Skip to content

Commit 5c29ec7

Browse files
authored
Merge pull request #22 from Pavlopoulos-Lab/v3-fable-auto
V3 fable auto
2 parents f5158c4 + eb7b090 commit 5c29ec7

271 files changed

Lines changed: 48605 additions & 67883 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main, v3]
6+
pull_request:
7+
8+
jobs:
9+
backend:
10+
runs-on: ubuntu-latest
11+
defaults:
12+
run: { working-directory: backend }
13+
steps:
14+
- uses: actions/checkout@v4
15+
- uses: astral-sh/setup-uv@v5
16+
- run: uv sync
17+
- run: uv run ruff check .
18+
- run: uv run ruff format --check .
19+
- run: uv run mypy app
20+
- run: uv run pytest
21+
22+
frontend:
23+
runs-on: ubuntu-latest
24+
defaults:
25+
run: { working-directory: frontend }
26+
steps:
27+
- uses: actions/checkout@v4
28+
- uses: actions/setup-node@v4
29+
with: { node-version: 22, cache: npm, cache-dependency-path: frontend/package-lock.json }
30+
- run: npm ci
31+
- run: npm run lint
32+
- run: npx prettier --check src
33+
- run: npx tsc -b --noEmit || npx tsc --noEmit
34+
- run: npm test -- --run
35+
36+
e2e:
37+
runs-on: ubuntu-latest
38+
needs: [backend, frontend]
39+
steps:
40+
- uses: actions/checkout@v4
41+
- uses: astral-sh/setup-uv@v5
42+
- uses: actions/setup-node@v4
43+
with: { node-version: 22, cache: npm, cache-dependency-path: frontend/package-lock.json }
44+
- run: cd backend && uv sync && (uv run uvicorn app.main:app --port 8000 &)
45+
- run: cd frontend && npm ci && npx playwright install --with-deps chromium
46+
- run: cd frontend && npm run test:e2e

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,4 @@ frontend/dist/
5252

5353
# Editors
5454
.DS_Store
55+
.playwright-cli/

.pre-commit-config.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
repos:
2+
- repo: https://github.com/astral-sh/ruff-pre-commit
3+
rev: v0.15.0
4+
hooks:
5+
- id: ruff-check
6+
args: [--fix]
7+
files: ^backend/
8+
- id: ruff-format
9+
files: ^backend/
10+
11+
- repo: local
12+
hooks:
13+
- id: eslint
14+
name: eslint
15+
language: system
16+
entry: bash -c 'cd frontend && npx eslint src'
17+
files: ^frontend/src/.*\.ts$
18+
pass_filenames: false
19+
- id: prettier
20+
name: prettier
21+
language: system
22+
entry: bash -c 'cd frontend && npx prettier --check src'
23+
files: ^frontend/src/
24+
pass_filenames: false

.serena/project.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,12 @@ project_name: "Arena3Dweb"
3131
# When using multiple languages, the first language server that supports a given file will be used for that file.
3232
# The first language is the default language and the respective language server will be used as a fallback.
3333
# Note that when using the JetBrains backend, language servers are not used and this list is correspondingly ignored.
34+
# R dropped: legacy code being deleted through the v3 migration, and its LSP
35+
# (R `languageserver` package) isn't installed — its failure aborted the whole
36+
# language-server manager. Active dev is TS (frontend) + Python (backend).
3437
languages:
35-
- r
38+
- typescript
39+
- python
3640

3741
# the encoding used by text files in the project
3842
# For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings

Arena3Dweb.Rproj

Lines changed: 0 additions & 13 deletions
This file was deleted.

CLAUDE.md

Lines changed: 34 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,20 @@
22

33
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
44

5-
## Active Migration
5+
Arena3Dweb is a web application for interactive 3D visualization of multilayered networks: **FastAPI backend** (Python, `uv`) + **Vite / TypeScript / Three.js frontend** (npm).
66

7-
This repository is being migrated from R/Shiny to FastAPI + Vite + TypeScript + Three.js (npm).
8-
9-
- **`SPEC.md`** — architecture decisions, chosen stack, design patterns, API contract, and rationale. Read this first to understand why things are structured the way they are.
10-
- **`PLAN.md`** — phased implementation checklist with checkboxes. Check this to see what has been done and what remains before starting any work.
11-
- **`MIGRATION.md`** — maps each old R/Shiny file to its new equivalent; old files are deleted only after their replacement is tested.
12-
13-
If you are on the `v3` branch, the presence of old R/Shiny files (`server.R`, `functions/`, `views/`, `www/js/`) means those pieces have not been ported yet — they are the living specification for what the new code should do.
7+
The app was migrated from R/Shiny to this stack. All R/Shiny source is gone; the migration history lives in:
8+
- **`SPEC.md`** — architecture decisions, chosen stack, design patterns, API contract, and rationale.
9+
- **`PLAN.md`** — phased implementation checklist (essentially complete).
10+
- **`MIGRATION.md`** — old R/Shiny file → new equivalent map (all rows done).
1411

1512
## Running the App
1613

17-
### v3 (FastAPI + Vite — active development, `v3` branch)
18-
19-
**Backend:**
14+
**Backend** (package management via `uv` — no manual venv/pip):
2015
```bash
2116
cd backend
22-
python3 -m venv .venv
23-
source .venv/bin/activate
24-
pip install -r requirements.txt
25-
uvicorn app.main:app --reload # http://localhost:8000
17+
uv sync # installs deps + dev group into .venv
18+
uv run uvicorn app.main:app --reload # http://localhost:8000
2619
```
2720

2821
**Frontend:**
@@ -39,7 +32,7 @@ docker-compose up
3932

4033
**Backend tests:**
4134
```bash
42-
cd backend && pytest
35+
cd backend && uv run pytest
4336
```
4437

4538
**Frontend tests:**
@@ -48,63 +41,37 @@ cd frontend && npm test # Vitest unit tests
4841
cd frontend && npm run test:e2e # Playwright E2E
4942
```
5043

51-
**Lint / format:**
44+
**Lint / format / typecheck:**
5245
```bash
53-
cd backend && ruff check . && ruff format .
54-
cd frontend && npm run lint && npm run format
46+
cd backend && uv run ruff check . && uv run ruff format . && uv run mypy app
47+
cd frontend && npm run lint && npm run format && npx tsc --noEmit
5548
```
5649

57-
---
58-
59-
### v2 (R/Shiny — legacy, `main` branch)
60-
61-
**From RStudio:**
62-
1. Open `Arena3Dweb.Rproj`
63-
2. Open `server.R`, select "Run External", click "Run App"
50+
## Architecture Overview
6451

65-
**Via Docker:**
66-
```bash
67-
docker pull pavlopouloslab/arena3dweb
68-
docker run -p 3838:3838 pavlopouloslab/arena3dweb
69-
```
52+
### Backend (`backend/app/`)
53+
Stateless FastAPI — the frontend holds all scene state; the server validates input and runs the graph algorithms.
7054

71-
**From R CLI:**
72-
```r
73-
shiny::runApp('.')
74-
```
55+
- `main.py` — app + router registration; `config.py` — constants (limits, palettes, scale targets) served at `GET /api/config`.
56+
- `models/` — Pydantic request/response models (`network`, `layout`, `topology`, `session`, `attributes`).
57+
- `routers/` — one per endpoint: `config`, `network` (TSV upload), `layout`, `topology`, `session` (import/export), `external` (token-shared sessions), `attributes` (node/edge attribute files).
58+
- `services/` — logic: `parser` (TSV parse/validate), `graph` (igraph construction + scopes), `layouts` (11 layout algos), `clustering` (4 community algos, optional layout step), `topology` (Degree / Clustering Coefficient / Betweenness), `session`, `attributes`.
59+
- Algorithms use **python-igraph** — same C core as R's igraph, so layouts/clustering/topology port 1:1.
7560

76-
## Architecture Overview
61+
### Frontend (`frontend/src/`)
62+
- `main.ts` — entry point: fetch config → set up Three.js → mount canvas → wire panels + listeners → `animate()`. Exposes `window.__arena = { ctx, history }` as a Playwright test hook (the WebGL canvas is opaque to the a11y tree).
63+
- `three/``Scene`, `Layer`, `Node`, `Edge` classes on npm `three` r170; `runtime.ts` holds the shared mutable `ctx` (replaces v2 ambient globals); `constants.ts` static geometry/palette constants.
64+
- `actions/` — one module per domain (`network`, `layout`, `layer`, `node`, `edge`, `labels`, `themes`, `screen`, `canvas_controls`, `nav_controls`, `drag_controls`, `right_click_menu`, `session`). These mutate the object model + `ctx`.
65+
- `commands/``Command` interface + `CommandHistory` (undo/redo); `scene.ts` holds the concrete commands. Every scene mutation that should be undoable routes through a command.
66+
- `ui/` — one module per navbar panel (`home`, `file`, `layouts`, `scene`, `layer`, `node`, `edge`, `data`, `fps`, `help`), each filling its `#panel-*` pane with Bootstrap DOM and wiring controls to `actions`/`commands`.
67+
- `bus/` — typed `EventBus` singleton (returns unsubscribe fns); `store/` — typed `AppState` store. Together they replace the old Shiny input/output sync.
68+
- `api/client.ts` — hand-written typed client mirroring the Pydantic models.
7769

78-
This is an **R/Shiny + Three.js** web application for interactive 3D visualization of multilayered networks.
79-
80-
### R/Shiny Layer (backend)
81-
- `global.R` — loaded once; imports libraries
82-
- `ui.R` — loads all JS/CSS, defines the navbar tab layout (Home, File, Layer Selection & Layouts, Scene Actions, Layer Actions, Node Actions, Edge Actions, View Data, FPS, Help)
83-
- `server.R` — wires all `observeEvent` handlers; calls `initializeServerApp()` on startup
84-
- `views/` — one R file per UI tab (e.g. `file.R`, `layer.R`), each exporting a `generate*Div()` function
85-
- `functions/` — server-side logic split by domain:
86-
- `input.R` — network file upload and validation
87-
- `init.R` — app startup: pushes global constants to JS, attaches download handler
88-
- `js_handling.R` — helpers to sync JS state back to Shiny inputs
89-
- `render.R` — modal/error/warning rendering
90-
- `general.R`, `reset.R`, `edges.R`, `vr.R` — domain-specific handlers
91-
- `igraph/` — layout, clustering, topology metric calculations using igraph
92-
- `config/` — R-side variables (`global_variables.R`, `server_variables.R`, `static_variables.R`, `ui_variables.R`)
93-
94-
### JavaScript Layer (frontend, `www/js/`)
95-
- **Three.js** (`three/three.js`) — core 3D rendering engine; `matrix4.js` and `drag_controls.js` are Three.js add-ons
96-
- **Classes** (`classes/`) — `Scene`, `Layer`, `Node`, `Edge` — OOP wrappers around Three.js objects
97-
- **Object actions** (`object_actions/`) — functions for each entity type: `screen.js`, `network.js`, `layout.js`, `layer.js`, `node.js`, `edge.js`, `labels.js`, `themes.js`, `canvas_controls.js`, `right_click_menu.js`
98-
- **Shiny bridge**`rshiny_handlers.js` registers all `Shiny.addCustomMessageHandler("handler_*", ...)` callbacks; `rshiny_update.js` sends data from JS back to Shiny
99-
- **Config** (`config/`) — `global_variables.js` (runtime globals initialized from R via `handler_initializeGlobals`), `static_variables.js` (constants like color palettes, geometry sizes)
100-
- `general.js` — utility functions; `event_listeners.js` — mouse/keyboard events; `on_page_load.js` — Three.js canvas setup
101-
102-
### R ↔ JS Communication Pattern
103-
- **R → JS**: `session$sendCustomMessage("handler_*", payload)` in R calls the registered handler in `rshiny_handlers.js`
104-
- **JS → R**: Shiny input updates (e.g. `Shiny.setInputValue`) trigger `observeEvent` handlers in `server.R`
105-
- Constants (MAX_LAYERS, MAX_EDGES, MAX_CHANNELS, channel colors) are defined in R config and pushed to JS globals at startup via `handler_initializeGlobals`
70+
### Communication
71+
- **Frontend → backend**: `api.*` calls to `/api/*` (network parse, layout, topology, session, attributes).
72+
- **Within frontend**: components emit/subscribe on the `EventBus` and read/write the `store`; the render loop reacts to `ctx` flags (`renderInterLayerEdgesFlag`, label flags, etc.).
10673

10774
### Network Data Model
108-
- Networks are uploaded as TSV with mandatory columns: `SourceNode`, `SourceLayer`, `TargetNode`, `TargetLayer` (optional: `Weight`, `Channel`, edge color columns)
109-
- Sessions are exported/imported as JSON containing full node/edge/layer state
110-
- The REST API endpoint accepts a URL parameter to load a network directly from an external application
75+
- Networks upload as TSV with mandatory columns `SourceNode`, `SourceLayer`, `TargetNode`, `TargetLayer` (optional: `Weight`, `Channel`, edge color columns).
76+
- Node/edge attribute files add per-node color/size/url/description and per-edge (optionally per-channel) color.
77+
- Sessions export/import as JSON with full node/edge/layer/scene state. `POST /api/external` returns a token URL so another app can hand off a session.

Dockerfile

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,20 @@
1-
FROM r-base
2-
#Description of the image
3-
LABEL description="Arena3Dweb docker image"
4-
LABEL maintainer="Fotis Baltoumas<baltoumas@fleming.gr>"
5-
LABEL version="2.0"
6-
#set the timezone
7-
ENV TZ Europe/Athens
8-
#copy the Rprofile.site file and containing the shiny port and CRAN repo url
9-
COPY Rprofile.site /usr/lib/R/etc/
1+
# Production image: nginx serves static Vite build, proxies /api to uvicorn.
2+
FROM node:22-slim AS frontend-build
3+
WORKDIR /build
4+
COPY frontend/package.json frontend/package-lock.json ./
5+
RUN npm ci
6+
COPY frontend/ ./
7+
RUN npm run build
108

11-
# install required R packages
12-
RUN R -e 'install.packages(c("shiny","shinyjs","shinythemes","igraph","RColorBrewer","jsonlite","tidyr"))'
9+
FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim
10+
WORKDIR /app
11+
RUN apt-get update && apt-get install -y --no-install-recommends nginx && rm -rf /var/lib/apt/lists/*
12+
COPY backend/pyproject.toml backend/uv.lock ./
13+
RUN uv sync --frozen --no-group dev
14+
COPY backend/app ./app
15+
COPY nginx/nginx.conf /etc/nginx/nginx.conf
16+
COPY --from=frontend-build /build/dist /usr/share/nginx/html
1317

14-
# copy the Arena3Dweb directory to the VM
15-
COPY ./Arena3Dweb/ /root/Arena3DWeb/
16-
17-
RUN R -e 'install.packages(c("DT", "fst"))'
18-
19-
#expose the shiny port
20-
EXPOSE 3838
21-
22-
#set the default command to run, ie "R"
23-
CMD ["R", "-e", "shiny::runApp('/root/Arena3DWeb/')"]
18+
EXPOSE 8080
19+
# ponytail: sh -c instead of a supervisor; two processes, container dies if nginx dies
20+
CMD ["sh", "-c", "uv run uvicorn app.main:app --host 127.0.0.1 --port 8000 & exec nginx -g 'daemon off;'"]

MIGRATION.md

Lines changed: 0 additions & 112 deletions
This file was deleted.

0 commit comments

Comments
 (0)