Skip to content

Latest commit

 

History

277 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation


Governed clinical imaging workflows, research experimentation, and agent-assisted medical reasoning.


RadSysX is a medical imaging and analysis platform with two distinct product surfaces:

  • clinical: the governed migration target, built around FastAPI contracts, worklist-driven launch, opaque viewer sessions, audited workflow state, and a dedicated OHIF viewer runtime.
  • research: the experimentation surface for prototype workflows, a LangGraph/deepagents-based multi-agent stack, MCP/FHIR integrations, and imaging/AI exploration that is explicitly not the clinical source of truth.

The two surfaces are not interchangeable. The repo also includes an Electron desktop fast path that opens directly into OHIF local DICOM mode and runs the local clinical shell without the Docker/nginx/Orthanc composition required for full governed archive validation.

Platform Overview

The current repo contains both:

  • a governed clinical platform with backend-authoritative workflow state and OHIF as the only supported clinical viewer
  • a research stack with direct chat, multi-agent orchestration, MCP tool integration, and BiomedParse-oriented imaging/AI experimentation

That distinction is intentional. The clinical path is the migration target; the research path remains useful, but it does not define clinical architecture.

Current State

The current clinical baseline on this branch is:

  • FastAPI is the backend authority for clinical auth, launch, workspace, report, AI, derived-result, and audit workflows.
  • OHIF is the only supported clinical viewer runtime.
  • The old Next.js /viewer fallback route is removed.
  • Backend-issued signed cookies provide local seeded clinical identity until institutional auth replaces them.
  • Derived DICOM writeback stays backend-mediated through STOW.
  • The local stack is designed to run as one origin through nginx, frontend, viewer, backend, and Orthanc.
  • The OHIF app exposes /viewer/fhir-viewer for FHIR R4 ImagingStudy/DocumentReference discovery and SMART on FHIR EHR launch with PKCE.
  • The desktop app starts FastAPI, Next.js, and a local OHIF viewer bridge under one localhost origin for a no-Docker local run path, opening OHIF first with local import ready, keeping the visible app name as RadSysX, and including a backend-governed RadSysX AI voice panel in the OHIF right sidebar.
  • The desktop app enables native local file/folder selection plus browser drag-and-drop fallback for backend-owned local imaging import of DICOM, DICOMDIR, NIFTI .nii/.nii.gz/paired .hdr+.img, NRRD .nrrd, ZIP archives containing supported files, and common image files, with safe imported-study asset summaries, backend-mediated NIFTI slice previews/common-image previews including TIFF SVG header previews, NRRD header/voxel metrics, and deterministic technical analysis for local analysis readiness.

The current research/agent baseline still includes:

  • backend/radsysx.py for multi-agent orchestration
  • backend/chat_interface.py for direct LLM chat
  • backend/mcp/* for MCP/FHIR tooling and server installation
  • backend/biomedparse_api.py for research imaging analysis APIs

Those capabilities remain part of RadSysX, but they are not the clinical source of truth.

Clinical Workflow

  1. POST /api/auth/local-login
  2. GET /api/auth/session
  3. Open /worklist
  4. POST /api/imaging/launch
  5. Open /viewer/?launch=...
  6. GET /api/imaging/launch/resolve
  7. OHIF binds to the returned runtime and same-origin DICOMweb roots
  8. GET /api/studies/{studyUid}/workspace
  9. Persist reports, AI jobs, derived results, and audit through backend contracts
  10. Persist uploaded derived DICOM through POST /api/derived-results/stow

FHIR Viewer

/viewer/fhir-viewer is a separate SMART on FHIR entry into the RadSysX OHIF shell. A standard EHR launch supplies opaque iss and launch parameters; the public SMART client ID comes from RADSYSX_FHIR_CLIENT_ID at viewer build time or a client_id launch parameter. The FHIR server remains the metadata authority and must allow the RadSysX browser origin through CORS.

The route resolves FHIR R4 ImagingStudy and DocumentReference resources into OHIF studies while keeping access tokens in session storage. Do not place patient identifiers, FHIR payloads, or access tokens in its URL. SMART authorization does not create a governed RadSysX session, so report persistence, audit, derived-result writeback, and STOW remain unavailable until an explicit backend contract connects those authorities.

Optional viewer-build settings are:

  • RADSYSX_FHIR_SERVER_URL
  • RADSYSX_FHIR_CLIENT_ID
  • RADSYSX_FHIR_SCOPE (defaults to launch openid fhirUser patient/*.read)

Architecture

Clinical authority

  • backend/server.py
  • backend/clinical/*
  • backend/clinical/local_imaging.py
  • backend/tests/test_clinical_platform.py

Research and agent stack

  • backend/radsysx.py
  • backend/chat_interface.py
  • backend/mcp/*
  • backend/biomedparse_api.py
  • backend/tools/*

Shared browser clinical package

  • packages/clinical-web/*

Next.js shell

  • frontend/app/login/page.tsx
  • frontend/app/worklist/page.tsx
  • frontend/app/page.tsx

Dedicated OHIF viewer

  • viewer/scripts/build-ohif-dist.mjs
  • viewer/assets/radsysx-bootstrap.js
  • viewer/assets/radsysx-fhir-extension.js
  • viewer/assets/radsysx-ohif-extension.js
  • viewer/assets/radsysx-ohif-mode.js
  • viewer/assets/radsysx-viewer.css
  • viewer/vendor/ohif-fhir-viewer/*

Electron desktop fast path

  • desktop/src/main.mjs
  • desktop/src/preload.cjs
  • desktop/scripts/launch.mjs
  • desktop/scripts/bootstrap.mjs
  • desktop/scripts/doctor.mjs

Local one-origin stack

  • docker-compose.yml
  • deploy/clinical-stack/*

Research and Agent Capabilities

Multi-agent orchestration

The research surface still includes a LangGraph/deepagents-style multi-agent stack in backend/radsysx.py, with a supervisor coordinating specialist agents for:

  1. pharmacist reasoning
  2. researcher/literature workflows
  3. medical analyst workflows

Chat and MCP

The repo still supports:

  • direct chat via backend/chat_interface.py
  • MCP-backed tool discovery and execution
  • FHIR-oriented MCP tools in backend/mcp/fhir_server.py
  • MCP installation flows in backend/mcp/installer.py

Research imaging and AI

Research-only imaging/AI experimentation still includes:

  • BiomedParse-oriented APIs in backend/biomedparse_api.py
  • prototype imaging upload/analyze routes in the Next.js research surface
  • legacy viewer components kept for experimentation and parity work, not as the clinical viewer target

Key Endpoints

Clinical

  • GET /api/auth/session
  • POST /api/auth/local-login
  • POST /api/auth/logout
  • GET /api/platform/config
  • GET /api/worklist
  • POST /api/imaging/launch
  • GET /api/imaging/launch/resolve
  • POST /api/local-imaging/import
  • GET /api/local-imaging/studies/{studyUid}/assets
  • GET /api/local-imaging/studies/{studyUid}/analysis
  • GET /api/local-imaging/studies/{studyUid}/assets/{assetId}/preview
  • GET /api/studies/{studyUid}/workspace
  • POST /api/reports/draft
  • POST /api/ai/jobs
  • POST /api/derived-results
  • POST /api/derived-results/stow
  • GET /api/audit/studies/{studyUid}

Research / agent

  • POST /process
  • POST /stream
  • GET /stream
  • POST /chat
  • POST /chat/stream
  • GET /tools
  • POST /execute_tool
  • POST /fhir/tool
  • GET /mcp/status
  • POST /mcp/toggle
  • POST /mcp/install

Runtime Modes

Mode is controlled by RADSYSX_APP_MODE:

  • research
  • pilot
  • clinical

Rules:

  • Only research may expose experimental upload/analyze flows.
  • pilot and clinical use the clinical FastAPI surface and OHIF viewer flow.
  • Governed flows must not send DICOM bytes directly from the browser to third-party AI services.

Environment

The most important clinical env vars are:

  • RADSYSX_APP_MODE
  • RADSYSX_AUTH_MODE
  • RADSYSX_CLINICAL_API_SECRET
  • RADSYSX_SESSION_SECRET
  • RADSYSX_SESSION_COOKIE_SECURE
  • RADSYSX_VIEWER_BASE_URL
  • RADSYSX_VIEWER_BASE_PATH
  • RADSYSX_DICOMWEB_PUBLIC_BASE_URL
  • RADSYSX_LOCAL_IMAGING_ENABLED
  • RADSYSX_LOCAL_IMAGING_STORAGE_DIR
  • RADSYSX_ORTHANC_DICOMWEB_URL
  • RADSYSX_ORTHANC_USERNAME
  • RADSYSX_ORTHANC_PASSWORD
  • RADSYSX_FHIR_SERVER_URL
  • RADSYSX_FHIR_CLIENT_ID
  • RADSYSX_FHIR_SCOPE
  • NEXT_PUBLIC_RADSYSX_APP_MODE
  • NEXT_PUBLIC_BACKEND_URL
  • NEXT_PUBLIC_VIEWER_BASE_URL

Desktop-only knobs:

  • RADSYSX_DESKTOP_PORT
  • RADSYSX_DESKTOP_BACKEND_PORT
  • RADSYSX_DESKTOP_FRONTEND_PORT
  • RADSYSX_DESKTOP_DICOMWEB_TARGET
  • RADSYSX_DESKTOP_SKIP_BOOTSTRAP

Research-only integrations such as MCP/FHIR tools and BiomedParse still exist, but they do not define the clinical architecture.

Host Assumptions

The preferred development and validation host is now native Linux.

Operational guidance:

  • use native Linux Python, Node, npm, and Docker Engine / Compose
  • avoid WSL-specific path assumptions or Windows-only toolchain shims
  • do not rely on temporary PYTHONPATH hacks or undeclared global dependencies
  • prefer a repo-local .venv plus workspace-installed Node dependencies
  • when starting work in a fresh chat on the Linux machine, do a short recon first, then wait for the user's report from the first Linux app test pass before making deeper code changes

Local Development

Prerequisites

  • Python 3.12 if you need one interpreter for both the clinical and research/backend installs
  • Python 3.13 is acceptable for the clinical bootstrap path only
  • Node.js 24+
  • npm
  • Docker Engine with Compose plugin if you want the one-origin stack

Install

python3 -m venv .venv
. .venv/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install -r backend/requirements-clinical.txt
npm install --legacy-peer-deps

Backend dependencies should be installed into .venv, not into ad hoc machine-local paths. Node dependencies should be installed from the repo root so the workspace-managed root package-lock.json remains authoritative. backend/requirements-clinical.txt is the governed clinical bootstrap set. backend/requirements.txt remains the broader research/agent dependency set and may carry tighter interpreter constraints than the clinical slice.

The FHIR/SMART data-source slice is pinned in viewer/vendor/ohif-fhir-viewer/UPSTREAM.md; normal viewer builds are network-independent and do not fetch moving upstream code.

Run the desktop app fast path

On a fresh clone, the shortest local path is:

npm run desktop

desktop is the user-facing local launcher. It checks the desktop bootstrap, runs the cross-platform bootstrap helper if setup is incomplete, then opens Electron directly to OHIF's local DICOM loader at /viewer/local. The lower-level desktop:bootstrap helper creates or reuses .venv, installs backend/requirements-ai.txt (clinical base plus Gemini/OpenAI transports, the native NVIDIA adapter and DeepAgents/LangGraph) with the venv Python, installs workspace Node dependencies from the root lockfile, and runs the desktop doctor. Use Python 3.12 for this lane. Keep the older full research requirements in a separate environment. For an existing install, npm run desktop -- --check-only or npm run desktop:bootstrap -- --check checks the actual venv imports, pinned dependencies and pip check without reinstalling dependencies. Nested npm installs retain the persisted install-script policy from .npmrc; an unmatched environment-only policy stops bootstrap with an actionable error. Use npm run desktop:run only when intentionally bypassing the launcher.

Live assistant: Gemini or OpenAI

The OHIF sidebar offers gemini-3.8-live-extended-thinking and gpt-realtime-2.1-mini through the local FastAPI backend. Both support low reasoning/thinking, asynchronous app tools, voice transcription/playback, selected-viewport images, reversible viewer/report drafts and reviewed report saves. Research delegates default to bounded Gemini 3.8 Flash workers; operators may opt into NVIDIA NIM PubMed research through the same DeepAgents/LangGraph runtime. Choosing a conversation provider does not switch the research provider. Separate BioMedParse/MedGemma inference and new segmentation masks are not part of this release.

  1. Run npm run desktop and open Settings → API keys in the RadSysX AI panel. Enter and save your own Gemini key, OpenAI key, or both. Saving refreshes provider availability without restarting; the first connection verifies provider access. Keys are sent only to the local backend for encrypted storage, and are never displayed again or saved in browser storage/history. Replacing or removing a key ends your active assistant sessions and tasks.
  2. Open a synthetic/deidentified study. The key settings distinguish your saved key, an app-configured key, and not configured. Removing a saved key explicitly returns that provider to an app-configured key when one exists.
  3. In Chat → Voice, select the provider, confirm the displayed content is synthetic or deidentified, then connect. If the initial catalog loaded before local sign-in, use Retry setup first. This records your declaration, not an automated deidentification result. Changing provider ends the old session and requires fresh confirmation.
  4. After Connected, enable the microphone or send text to the voice provider. Independent text chat and research are described below. To discuss what is visible, click Share active image and wait for image sharing on · image sent. The panel names the active image; capture covers that selected viewport, at up to one JPEG frame per second. The whole app, sidebar and other windows are outside this capture.
  5. Ask for a viewer action, image explanation, or public research. Review a proposed durable report save or deletion before applying it. Local-only DICOM must be imported/associated through the worklist before saving a report.

Text without voice: confirm synthetic/deidentified data, type your question, then choose Send for a discussion or Research for an explicit literature search. No Gemini Live or OpenAI Realtime connection is required. Settings → Text & research models selects the standard Gemini/NVIDIA or signed-in ChatGPT/Codex model. The request includes your question and neutral case/series metadata, not image pixels or patient records. Describe relevant findings in your question; this path does not inspect scans. Connect voice separately starts a new voice conversation. Jobs show progress, cancellation and saved results.

ChatGPT subscription: in Settings, choose Sign in with ChatGPT, continue in the official browser flow, then select ChatGPT / Codex subscription and an account-available model under Text & research models. Sign-in preserves your existing model until you save. Uses your plan’s Codex allowance for text/public PubMed research; Realtime voice remains separately API-key billed. Credentials stay in an isolated OS-keyring account. See the subscription runbook for setup, limits and validation.

The sidebar separates Chat, Research, and Jev review. Chat discusses the case; Research shows literature answers and collapsed source lists. Optional voice setup is behind the header Voice button. From a completed PubMed result, choose Review evidence with Jev to enter a dedicated review view. Select the unchanged cited passages, inspect their abstracts, confirm public/synthetic text, then explicitly start Jev. Results show abstract-support judgments with execution receipts under details. Empty previews explain why Jev has not run and offer Prepare review again. It does not analyze image pixels.

Literature research cards show the recorded provider/model and worker steps, including waiting for the model, searching PubMed and preparing the answer. Completed, timed-out and cancelled jobs stay visible in history. Model configuration alone does not mean a job is running. Desktop activation evidence separates local checks from hosted-provider results.

Microphone mute, stop speaking, stop sharing, research cancellation, and end-session are distinct controls. A study/capture-target change stops sharing and requires a fresh declaration. Transcripts, cited results, and action receipts stay in local history until deleted; raw audio, frames, and private reasoning are not retained. Clinical mode disables this initial synthetic/deidentified cloud lane. RADSYSX_AI_ENABLED=false disables it elsewhere; RADSYSX_GEMINI_VOICE optionally selects a supported voice (default Puck).

Speech may arrive faster than it plays. The viewer buffers up to 60 seconds at normal speed; barge-in and Stop speaking immediately discard unheard speech. Reaching the hard buffer limit stops the reply and suggests asking for a shorter one. The synthetic Electron playback check is node desktop/scripts/ui-import-smoke.mjs --local-start --audio-playback; it does not use a cloud provider or physical microphone.

For operator-managed configuration, the ignored repo-root .env.ai file still accepts RADSYSX_GEMINI_API_KEY and RADSYSX_OPENAI_API_KEY; exported values take precedence over the file. A signed-in user's saved key takes precedence over that app configuration for that user alone. Never commit .env.ai, use a NEXT_PUBLIC_* key, or distribute personal credentials. Saved keys are encrypted in the backend database using a random local master key in the private .ai-secrets directory alongside the SQLite database; RADSYSX_AI_KEY_STORE_DIR can select another private directory. Protect that directory and the database together when moving an installation. A missing or unreadable master key disables affected saved credentials rather than falling back to someone else's key. Cloud credentials are not included in the source or built frontend.

Configuration is not proof of provider access: missing credentials, quota exhaustion, rejected model access, or connection failures appear in the sidebar. The model is never silently substituted. npm run desktop:doctor reports voice-provider, research-provider/model, NVIDIA and Jev configuration without contacting those services. Gemini microphone input is 16 kHz PCM16; OpenAI input and both providers' output are 24 kHz PCM16. OpenAI interruption uses actual playback receipts to truncate unheard speech. A lost OpenAI browser or provider connection resets the upstream conversation and cancels pending work; fresh context includes bounded prior user text. Generated assistant speech remains local history because its playback cannot be confirmed after connection loss. Actions and media are never replayed.

npm run desktop:smoke:ai-live uses an explicitly guarded synthetic provider through the real Electron/WebSocket/capture path, including audio while two delayed research jobs run. node desktop/scripts/ai-live-smoke.mjs --openai checks the OpenAI session/audio profile with the same synthetic bridge. npm run desktop:smoke:ai-viewer exercises the real sidebar and OHIF commands on synthetic DICOM. These checks do not prove cloud inference or physical microphone/speaker acceptance. The implementation contract and evidence track those separately.

The desktop runtime, bootstrap, doctor, and smoke helpers resolve the repo-local Python venv using the host OS path convention: .venv/bin/python on Unix-like systems and .venv/Scripts/python.exe on Windows. Set RADSYSX_DESKTOP_PYTHON=/path/to/python when you need to force a specific interpreter.

This path is intentionally no-Docker. It is enough for seeded login, native local file/folder selection with direct Electron-main upload to the backend, browser drag-and-drop import, local import of DICOM/DICOMDIR/NIFTI .nii/.nii.gz/paired .hdr+.img/NRRD .nrrd/ZIP archives containing supported files/common image files including extensionless and multi-study DICOMDIR companion files, local worklist registration, local DICOM metadata/frame serving for imported DICOM studies, backend-mediated axial/coronal/sagittal NIFTI slice previews, common image previews including TIFF SVG header previews, NRRD header/voxel metrics, deterministic technical analysis, opaque launch/session resolution, OHIF rendering of imported DICOM from the first screen, workspace/report/AI/audit contract work, and local app use. Full Orthanc-backed DICOMweb retrieval, advanced archive behavior, and durable STOW validation still belong to the compose stack unless you set RADSYSX_DESKTOP_DICOMWEB_TARGET to a local archive.

By default Electron starts at /viewer/local, so the first visible screen is OHIF's native local DICOM loader. DICOM files load directly through OHIF's dicomlocal data source at /viewer/dicomlocal without a governed launch token or clinical workspace panel. NIFTI/NRRD/image/ZIP assets remain available through the local worklist inspection and analysis path. The OHIF right sidebar includes a RadSysX AI tab with live voice, an unsent local composer, and @ attachments referencing actual OHIF measurements and existing segmentations.

The desktop launcher builds the frontend production shell on first launch, writes a small ignored stamp under frontend/.next/, and reuses that build while the same-origin public API/viewer settings match. This keeps the local app from rebuilding just because it chooses a fallback localhost port. Force a rebuild with RADSYSX_DESKTOP_REBUILD_FRONTEND=1 npm run desktop. For live frontend UI development, use:

npm run desktop:dev-frontend

For a quick launcher contract check:

npm run desktop:smoke:launch

That smoke runs the same user-facing launcher path as npm run desktop: bootstrap check first, then service-ready Electron startup with the OHIF-first default retained, using a short cross-platform auto-shutdown timer. The desktop:smoke:local-start check is the UI assertion that samples /viewer/local, confirms there is no RadSysX intermediate card or governed launch, and verifies local-DICOM OHIF rendering.

For a quick startup and cleanup check:

npm run desktop:smoke

For the first-screen OHIF local import/render check:

npm run desktop:smoke:local-start

That smoke starts Electron on /viewer/local, verifies OHIF's local file/folder controls are visible without a RadSysX bootstrap card, verifies the document title is RadSysX, loads a synthetic DICOM through OHIF's local file input, routes to /viewer/dicomlocal?datasources=dicomlocal, asserts that OHIF paints a nonblank canvas without a governed launch, and checks the RadSysX AI sidebar composer with voice and @ ROI/segmentation controls.

For the first-screen OHIF drag/drop import/render check:

npm run desktop:smoke:local-start-drop

That smoke starts Electron on the same OHIF local screen, drops a synthetic DICOM directly onto it, forwards the drop into OHIF's local file input, routes to /viewer/dicomlocal?datasources=dicomlocal, and asserts that OHIF paints a nonblank canvas with the RadSysX title and RadSysX AI sidebar composer, without a governed launch.

For the first-screen NIFTI/NRRD/image-only fallback check:

npm run desktop:smoke:local-start-nondicom

That smoke starts from the same OHIF local screen, then verifies NIFTI/NRRD/image/ZIP fixtures remain usable through /worklist local asset inspection, preview loading, NIFTI slice-axis switching, and backend technical analysis without exposing an OHIF viewer action for non-DICOM assets.

For a stronger no-Docker import/use check:

npm run desktop:smoke:import

That smoke starts the desktop runtime on high local ports, generates synthetic PHI-free DICOMDIR, DICOM, .nii, .nii.gz, paired .hdr/.img, .nrrd, ZIP with supported NIFTI/PNG members, PNG, JPEG, and TIFF files, imports them through the one-origin local bridge, verifies worklist registration, imported-study asset summaries/previews/analysis, local DICOMweb discovery, and opaque viewer launch, then shuts the desktop runtime down.

For a hydrated UI-level import check:

npm run desktop:smoke:ui-import

That smoke starts the same no-Docker runtime, drives the Electron worklist UI through the local bridge, drops synthetic DICOMDIR/DICOM/NIFTI .nii/.nii.gz/paired .hdr+.img, NRRD .nrrd, ZIP with supported NIFTI/PNG members, plus PNG/JPEG/TIFF files onto the import panel, verifies imported rows, inspects local assets, changes a NIFTI preview to a coronal slice, runs backend technical analysis, and shuts down.

For a native file picker bridge check:

npm run desktop:smoke:picker-files-import

That smoke drives the hydrated worklist Import files action through the Electron preload IPC bridge with smoke-injected individual fixture file paths. Electron main uploads those selected files directly to the backend import endpoint with the existing session cookie, so the renderer receives only the backend import response. It proves the file picker button, backend import, local inspection, NIFTI preview controls, and technical analysis path without automating the actual operating-system file dialog.

For a native folder picker bridge check:

npm run desktop:smoke:picker-import

That smoke drives the hydrated worklist Import folder action through the Electron preload IPC bridge and main-process recursive file collector with smoke-injected test paths. Electron main uploads the selected files directly to the backend import endpoint with the existing session cookie, so the renderer receives only the backend import response. It proves the folder picker bridge, backend import, local inspection, NIFTI preview controls, and technical analysis path without automating the actual operating-system file dialog.

For a larger native picker import check:

npm run desktop:smoke:picker-large-import

That variant adds an 8 MiB synthetic NIFTI volume to the picker fixture folder and verifies import, preview, and technical analysis through the same direct Electron-main upload path.

For a many-file native picker import check:

npm run desktop:smoke:picker-many-import

That variant adds a nested folder of 32 additional extensionless DICOM instances to the picker fixture folder and verifies recursive collection, import of 44 accepted files after ZIP expansion into 2 local studies, DICOM asset summary, and technical analysis through the same direct Electron-main upload path.

For an imported-DICOM viewer handoff check:

npm run desktop:smoke:viewer-launch

That smoke imports synthetic local DICOM/DICOMDIR data through the hydrated worklist, opens the governed OHIF viewer, verifies the opaque launch resolves under /viewer/, confirms the launch token is stripped from the browser URL, checks that viewer-origin local DICOMweb/workspace requests can find the imported study, and asserts that OHIF paints a nonblank canvas for the synthetic DICOM. It proves viewer handoff, local DICOMweb binding, and a basic imported-DICOM render path, not full diagnostic pixel-rendering parity across real-world archives.

Install the full backend/runtime dependency set

If you want one local Python environment that can exercise both the governed clinical backend and the broader research/agent surface, use Python 3.12 and then install the full backend set:

. .venv/bin/activate
python3 -m pip install -r backend/requirements.txt

Run backend directly

. .venv/bin/activate
python3 backend/server.py

Run the research shell directly

export RADSYSX_APP_MODE=research
export NEXT_PUBLIC_RADSYSX_APP_MODE=research
. .venv/bin/activate
python3 backend/server.py

In a second terminal:

npm run dev --workspace frontend

Use the workspace script from the repo root rather than invoking next dev directly inside frontend/.

Focused backend checks

. .venv/bin/activate
python3 -m compileall backend/clinical backend/server.py backend/radsysx.py
python3 -m pytest backend/tests/test_clinical_platform.py

Frontend and viewer checks

npm run type-check --workspace frontend
npm run type-check --workspace viewer
npm run build --workspace viewer

Run the local one-origin stack

Set explicit Orthanc credentials first:

export RADSYSX_ORTHANC_USERNAME=local-user
export RADSYSX_ORTHANC_PASSWORD=local-pass
docker compose up --build

This compose stack validates the governed clinical surface only. It does not install or exercise the full research/agent backend dependency set. Use http://localhost:3000 through nginx for governed validation. The raw viewer dev server on port 3001 is only an internal asset server and is not a supported clinical entry point. The governed viewer launch should resolve under /viewer/ so OHIF static assets stay mounted beneath the viewer base path.

Recommended whole-runtime validation order

If you need to test both RadSysX surfaces on the same Linux host, use Python 3.12 and run:

  1. python3 -m venv .venv
  2. . .venv/bin/activate
  3. python3 -m pip install --upgrade pip
  4. python3 -m pip install -r backend/requirements.txt
  5. npm install --legacy-peer-deps
  6. npm run desktop -- --check-only
  7. npm run desktop:doctor
  8. npm run desktop:smoke:launch
  9. npm run desktop:smoke
  10. npm run desktop:smoke:local-start
  11. npm run desktop:smoke:local-start-drop
  12. npm run desktop:smoke:local-start-nondicom
  13. npm run desktop:smoke:import
  14. npm run desktop:smoke:ui-import
  15. npm run desktop:smoke:picker-files-import
  16. npm run desktop:smoke:picker-import
  17. npm run desktop:smoke:picker-large-import
  18. npm run desktop:smoke:picker-many-import
  19. npm run desktop:smoke:viewer-launch
  20. python3 -m compileall backend/clinical backend/server.py backend/radsysx.py
  21. python3 -m pytest backend/tests/test_clinical_platform.py
  22. npm run type-check --workspace frontend
  23. npm run build --workspace frontend
  24. npm run type-check --workspace viewer
  25. npm run build --workspace viewer
  26. Start the research surface directly with RADSYSX_APP_MODE=research python3 backend/server.py plus NEXT_PUBLIC_RADSYSX_APP_MODE=research npm run dev --workspace frontend
  27. Separately validate the governed clinical surface with docker compose up --build

First Linux Validation Pass

On the new Linux host, the first useful runtime checkpoint is:

  1. run npm run desktop and confirm the app opens straight into OHIF local mode at /viewer/local
  2. run npm run desktop -- --check-only, npm run desktop:doctor, npm run desktop:smoke:launch, npm run desktop:smoke, npm run desktop:smoke:local-start, npm run desktop:smoke:local-start-drop, npm run desktop:smoke:local-start-nondicom, npm run desktop:smoke:import, npm run desktop:smoke:ui-import, npm run desktop:smoke:picker-files-import, npm run desktop:smoke:picker-import, npm run desktop:smoke:picker-large-import, npm run desktop:smoke:picker-many-import, and npm run desktop:smoke:viewer-launch
  3. run the focused backend and viewer checks
  4. attempt the actual app flow on Linux
  5. report what happened before widening the code-change scope

That first report should ideally cover desktop startup, backend startup, frontend startup, viewer build/load, login, worklist, viewer launch, and compose-stack behavior if Docker is available.

Public routes:

Guidance

The authoritative contributor guidance is:

The current execution checklist for the next clinical tranche is:

Near-Term Roadmap

The next major clinical tasks are:

  1. Keep docs and runtime guidance aligned with the shipped RadSysX architecture.
  2. Deepen the RadSysX OHIF extension/mode implementation.
  3. Wire OHIF measurement tracking and segmentation into governed SR/SEG export and reload flows.
  4. Validate the full local nginx + frontend + viewer + backend + Orthanc stack end to end.
  5. Move from seeded local identity to institutional identity/context.

Security-patched viewer build

Use Node.js 24+ and Git. The viewer now rebuilds pinned OHIF source with audited dependency updates; the npm package prebuilt bundle is not shipped. viewer/ohif-build/ holds the upstream commit, reviewed patch, and separate frozen pnpm lockfile. npm run build --workspace viewer prepares an ignored viewer/.cache/ checkout on the first run (network access required) and reuses matching builds afterward. Run npm audit and npm run audit:ohif --workspace viewer to check both dependency trees. See the build contract.

Security remediation and verification details are in SECURITY_REMEDIATION.md. OHIF OIDC now requires authorization-code flow with PKCE; implicit-flow configurations must migrate.

Explicit public evidence evaluation

The standalone evidence-review runbook documents private public/synthetic PubMed capture, Jev/Gemini/NIM replay, blind references and comparative reports. Run .venv/bin/python -m backend.evidence_review --help. The CLI remains independent of live conversation and never changes assistant answers. The sidebar now offers a separate explicit Review evidence with Jev action on completed PubMed research cards; see the sidebar implementation runbook. Preview the exact claims and original abstracts, exclude claims as needed, and confirm public/synthetic text before TypeSafe receives anything. Saved claim-level judgments and resolved-model receipts establish what ran; the Settings configuration row alone does not. Clinical mode disables its network commands; local report/validation commands need no credentials. Software completion does not imply human-quality or live-provider acceptance.

NVIDIA NIM is available for explicit evidence evaluation and opt-in PubMed research. Set backend-only RADSYSX_NVIDIA_API_KEY, RADSYSX_RESEARCH_PROVIDER=nvidia_nim and an exact RADSYSX_NIM_RESEARCH_MODEL to select NIM research; these environment settings supply the default when the account has no saved choice. In Settings → Text & research models, choose Gemini or NVIDIA NIM and an exact model from the dropdown. NVIDIA lists every ID returned by its hosted catalog, with a refresh control. Saving persists the choice for the signed-in account and ends its active sessions/tasks; the next text or research request uses it. Catalog membership does not verify tool support or access. The model catalog is .venv/bin/python -m backend.evidence_review models --provider nvidia_nim. See the NIM runbook for tested models, limits and failure evidence.

Attach an image to Codex Chat or Research

With a ChatGPT/Codex model selected, confirm synthetic/deidentified data and choose Active viewport in the composer’s Images selector, then Send with images or Research. A fresh snapshot includes visible measurement overlays. Clients without study sharing retain Attach current view and its removable preview. The selected model must advertise image input. This works without Realtime. Saved image receipts record what was submitted; pixels are not saved in RadSysX history. See the subscription runbook.

Share a study with your Codex model

In the AI sidebar, select your ChatGPT/Codex model in Settings, confirm synthetic/deidentified data, then choose Whole reading view or Active series · all frames in Images. Let AI use viewer tools separately permits native navigation and reversible edits. Send with images or Research inventories and captures fresh pixels automatically; no Prepare step or voice connection is needed. Delivery counts and Stop/Take over remain beside the composer. Real gpt-6-astra acceptance on 2026-09-23 delivered all 34 synthetic frames and correctly identified a random marker visible only in the pixels; see the study runbook.

The native OpenMed adaptations add scoped technical metadata, literal report structuring, and richer PubMed abstracts/search receipts to the existing tool paths. They do not install NER models or provide clinical validation.

The study card shows acknowledged frame delivery, actions, Stop and Take over. Partial series coverage remains visible and requires explicit Continue review. Saving a report still requires review. See the implementation and acceptance record.

About

AI Powered Radiology Assistant

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages