Skip to content

Commit bfd89d3

Browse files
authored
Merge pull request #25 from Pavlopoulos-Lab/v3
Migration to v3 (typescript + python)
2 parents 2fea85f + b7542a2 commit bfd89d3

291 files changed

Lines changed: 53089 additions & 67084 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: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,18 @@ vignettes/*.pdf
3838
# R Environment Variables
3939
.Renviron
4040
Arena3Dweb.Rproj
41+
42+
# Python
43+
backend/.venv/
44+
__pycache__/
45+
*.pyc
46+
.mypy_cache/
47+
.ruff_cache/
48+
49+
# Node
50+
frontend/node_modules/
51+
frontend/dist/
52+
53+
# Editors
54+
.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/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/cache
2+
/project.local.yml

.serena/project.yml

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# the name by which the project can be referenced within Serena
2+
project_name: "Arena3Dweb"
3+
4+
5+
# list of languages for which language servers are started; choose from:
6+
# al angular ansible bash clojure
7+
# cpp cpp_ccls crystal csharp csharp_omnisharp
8+
# dart elixir elm erlang fortran
9+
# fsharp go groovy haskell haxe
10+
# hlsl html java json julia
11+
# kotlin lean4 lua luau markdown
12+
# matlab msl nix ocaml pascal
13+
# perl php php_phpactor powershell python
14+
# python_jedi python_ty r rego ruby
15+
# ruby_solargraph rust scala scss solidity
16+
# svelte swift systemverilog terraform toml
17+
# typescript typescript_vts vue yaml zig
18+
# (This list may be outdated. For the current list, see values of Language enum here:
19+
# https://github.com/oraios/serena/blob/main/src/solidlsp/ls_config.py
20+
# For some languages, there are alternative language servers, e.g. csharp_omnisharp, ruby_solargraph.)
21+
# Note:
22+
# - For C, use cpp
23+
# - For JavaScript, use typescript
24+
# - For Angular projects, use angular (subsumes typescript+html; requires `npm install` in the project root)
25+
# - For Svelte projects, use svelte (subsumes typescript/javascript for .svelte projects; requires npm)
26+
# - For SCSS / Sass / plain CSS, use scss (some-sass-language-server handles all three)
27+
# - For Free Pascal/Lazarus, use pascal
28+
# Special requirements:
29+
# Some languages require additional setup/installations.
30+
# See here for details: https://oraios.github.io/serena/01-about/020_programming-languages.html#language-servers
31+
# When using multiple languages, the first language server that supports a given file will be used for that file.
32+
# The first language is the default language and the respective language server will be used as a fallback.
33+
# 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).
37+
languages:
38+
- typescript
39+
- python
40+
41+
# the encoding used by text files in the project
42+
# For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings
43+
encoding: "utf-8"
44+
45+
# line ending convention to use when writing source files.
46+
# Possible values: unset (use global setting), "lf", "crlf", or "native" (platform default)
47+
# This does not affect Serena's own files (e.g. memories and configuration files), which always use native line endings.
48+
line_ending:
49+
50+
# The language backend to use for this project.
51+
# If not set, the global setting from serena_config.yml is used.
52+
# Valid values: LSP, JetBrains
53+
# Note: the backend is fixed at startup. If a project with a different backend
54+
# is activated post-init, an error will be returned.
55+
language_backend:
56+
57+
# whether to use project's .gitignore files to ignore files
58+
ignore_all_files_in_gitignore: true
59+
60+
# advanced configuration option allowing to configure language server-specific options.
61+
# Maps the language key to the options.
62+
# Have a look at the docstring of the constructors of the LS implementations within solidlsp (e.g., for C# or PHP) to see which options are available.
63+
# No documentation on options means no options are available.
64+
ls_specific_settings: {}
65+
66+
# list of additional workspace folder paths for cross-package reference support (e.g. in monorepos).
67+
# Paths can be absolute or relative to the project root.
68+
# Each folder is registered as an LSP workspace folder, enabling language servers to discover
69+
# symbols and references across package boundaries.
70+
# Currently supported for: TypeScript.
71+
# Example:
72+
# additional_workspace_folders:
73+
# - ../sibling-package
74+
# - ../shared-lib
75+
additional_workspace_folders: []
76+
77+
# list of additional paths to ignore in this project.
78+
# Same syntax as gitignore, so you can use * and **.
79+
# Note: global ignored_paths from serena_config.yml are also applied additively.
80+
ignored_paths: []
81+
82+
# whether the project is in read-only mode
83+
# If set to true, all editing tools will be disabled and attempts to use them will result in an error
84+
# Added on 2025-04-18
85+
read_only: false
86+
87+
# list of tool names to exclude.
88+
# This extends the existing exclusions (e.g. from the global configuration)
89+
# Find the list of tools here: https://oraios.github.io/serena/01-about/035_tools.html
90+
excluded_tools: []
91+
92+
# list of tools to include that would otherwise be disabled (particularly optional tools that are disabled by default).
93+
# This extends the existing inclusions (e.g. from the global configuration).
94+
# Find the list of tools here: https://oraios.github.io/serena/01-about/035_tools.html
95+
included_optional_tools: []
96+
97+
# fixed set of tools to use as the base tool set (if non-empty), replacing Serena's default set of tools.
98+
# This cannot be combined with non-empty excluded_tools or included_optional_tools.
99+
# Find the list of tools here: https://oraios.github.io/serena/01-about/035_tools.html
100+
fixed_tools: []
101+
102+
# list of mode names that are to be activated by default, overriding the setting in the global configuration.
103+
# The full set of modes to be activated is base_modes (from global config) + default_modes + added_modes.
104+
# If the setting is undefined/empty, the default_modes from the global configuration (serena_config.yml) apply.
105+
# Otherwise, this overrides the setting from the global configuration (serena_config.yml).
106+
# Therefore, you can set this to [] if you do not want the default modes defined in the global config to apply
107+
# for this project.
108+
# This setting can, in turn, be overridden by CLI parameters (--mode).
109+
# See https://oraios.github.io/serena/02-usage/050_configuration.html#modes
110+
default_modes:
111+
112+
# list of mode names to be activated additionally for this project, e.g. ["query-projects"]
113+
# The full set of modes to be activated is base_modes (from global config) + default_modes + added_modes.
114+
# See https://oraios.github.io/serena/02-usage/050_configuration.html#modes
115+
added_modes:
116+
117+
# initial prompt for the project. It will always be given to the LLM upon activating the project
118+
# (contrary to the memories, which are loaded on demand).
119+
initial_prompt: ""
120+
121+
# time budget (seconds) per tool call for the retrieval of additional symbol information
122+
# such as docstrings or parameter information.
123+
# This overrides the corresponding setting in the global configuration; see the documentation there.
124+
# If null or missing, use the setting from the global configuration.
125+
symbol_info_budget:
126+
127+
# list of regex patterns which, when matched, mark a memory entry as read‑only.
128+
# Extends the list from the global configuration, merging the two lists.
129+
read_only_memory_patterns: []
130+
131+
# list of regex patterns for memories to completely ignore.
132+
# Matching memories will not appear in list_memories or activate_project output
133+
# and cannot be accessed via read_memory or write_memory.
134+
# To access ignored memory files, use the read_file tool on the raw file path.
135+
# Extends the list from the global configuration, merging the two lists.
136+
# Example: ["_archive/.*", "_episodes/.*"]
137+
ignored_memory_patterns: []

AGENTS.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
Arena3D is a web application for interactive 3D visualization of multilayered networks: **FastAPI backend** (Python, `uv`) + **Vite / TypeScript / Three.js frontend** (npm).
6+
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).
11+
12+
## Rules for Agents
13+
14+
- **Never push to remote.** Commit only when explicitly asked, one commit per feature.
15+
- **Always use the `token-saviour` skill** — and the tools/skills it routes to across its layers — wherever it makes sense.
16+
- **When a plan is active** (e.g. a `PLAN*.md` file): one feature per commit, tick the checkboxes as you go, and verify each feature at runtime before moving to the next.
17+
- **Before every commit**: run the build, lint, typecheck, and the relevant test suite (see commands below). Verify UI/UX changes at runtime with Playwright.
18+
- **Keep responses concise** — summarize rather than dumping full files, to stay within output token limits.
19+
20+
## Running the App
21+
22+
**Backend** (package management via `uv` — no manual venv/pip):
23+
```bash
24+
cd backend
25+
uv sync # installs deps + dev group into .venv
26+
uv run uvicorn app.main:app --reload # http://localhost:8000
27+
```
28+
29+
**Frontend:**
30+
```bash
31+
cd frontend
32+
npm install
33+
npm run dev # http://localhost:5173 — /api proxied to localhost:8000
34+
```
35+
36+
**Both together (Docker):**
37+
```bash
38+
docker-compose up
39+
```
40+
41+
**Backend tests:**
42+
```bash
43+
cd backend && uv run pytest
44+
```
45+
46+
**Frontend tests:**
47+
```bash
48+
cd frontend && npm test # Vitest unit tests
49+
cd frontend && npm run test:e2e # Playwright E2E
50+
```
51+
52+
**Lint / format / typecheck:**
53+
```bash
54+
cd backend && uv run ruff check . && uv run ruff format . && uv run mypy app
55+
cd frontend && npm run lint && npm run format && npx tsc --noEmit
56+
```
57+
58+
## Architecture Overview
59+
60+
### Backend (`backend/app/`)
61+
Stateless FastAPI — the frontend holds all scene state; the server validates input and runs the graph algorithms.
62+
63+
- `main.py` — app + router registration; `config.py` — constants (limits, palettes, scale targets) served at `GET /api/config`.
64+
- `models/` — Pydantic request/response models (`network`, `layout`, `topology`, `session`, `attributes`).
65+
- `routers/` — one per endpoint: `config`, `network` (TSV upload), `layout`, `topology`, `session` (import/export), `external` (token-shared sessions), `attributes` (node/edge attribute files).
66+
- `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`.
67+
- Algorithms use **python-igraph** — same C core as R's igraph, so layouts/clustering/topology port 1:1.
68+
69+
### Frontend (`frontend/src/`)
70+
- `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).
71+
- `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.
72+
- `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`.
73+
- `commands/``Command` interface + `CommandHistory` (undo/redo); `scene.ts` holds the concrete commands. Every scene mutation that should be undoable routes through a command.
74+
- `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`.
75+
- `bus/` — typed `EventBus` singleton (returns unsubscribe fns); `store/` — typed `AppState` store. Together they replace the old Shiny input/output sync.
76+
- `api/client.ts` — hand-written typed client mirroring the Pydantic models.
77+
78+
### Communication
79+
- **Frontend → backend**: `api.*` calls to `/api/*` (network parse, layout, topology, session, attributes).
80+
- **Within frontend**: components emit/subscribe on the `EventBus` and read/write the `store`; the render loop reacts to `ctx` flags (`renderInterLayerEdgesFlag`, label flags, etc.).
81+
82+
### Network Data Model
83+
- Networks upload as TSV with mandatory columns `SourceNode`, `SourceLayer`, `TargetNode`, `TargetLayer` (optional: `Weight`, `Channel`, edge color columns).
84+
- Node/edge attribute files add per-node color/size/url/description and per-edge (optionally per-channel) color.
85+
- 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.

Arena3Dweb.Rproj

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

CHANGELOG.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Changelog
2+
3+
## [3.0.0] - 2026-07-08
4+
5+
Full rewrite: migrated from R/Shiny to a **FastAPI (Python) backend + Vite / TypeScript / Three.js frontend**. Algorithms (layouts, clustering, topology) ported 1:1 via python-igraph.
6+
7+
### Added
8+
9+
- **Satellite view** — minimap overview of the scene (hidden layers excluded).
10+
- **Command-pattern undo/redo** — granular history for scene mutations.
11+
- **Token-shared sessions** — hand off a session to another app via `?session=` URL (`POST /api/external`).
12+
- **Export Image** — button to export the scene as PNG.
13+
- Reproducible node scatter (seeded), 60 FPS render loop as default, redesigned UI (side-drawer panels).
14+
15+
### Changed
16+
17+
- **Zoom to cursor** — mouse-wheel zoom anchors at the pointer instead of the scene center.
18+
19+
### Fixed
20+
21+
- **Undraggable layers when zoomed in** — orthographic drag ray rejected planes sitting behind its origin; layers froze at high zoom despite hover working.
22+
23+
## [2.0.0] - 2023-04-13
24+
25+
Initial public release — Arena3D, an **R/Shiny + Three.js** web app for interactive 3D visualization of multilayered networks.
26+
27+
- Interactive 3D rendering of multilayer networks (Three.js via R/Shiny).
28+
- TSV network upload; layer / node / edge styling.
29+
- Layout algorithms, community clustering, and topology metrics on the graph.
30+
- Session import / export.
31+
32+
## [1.0.0] - 2008-11-28
33+
34+
The now retired legacy Arena3D standalone desktop application written in Java.

CLAUDE.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# CLAUDE.md
2+
3+
See **[AGENTS.md](AGENTS.md)**.
4+
5+
Guidance for coding agents working in this repository lives there, so that every agent — Claude Code,
6+
Codex, and others — reads the same file.

0 commit comments

Comments
 (0)