Repository navigation
Python API
Everything the GUI Walkthrough does by point-and-click is mirrored by a single
synchronous Python class, golgi.Study. The API and the GUI act on the same on-disk project
state, so a study started in the browser can be continued from a script (and vice-versa), and a
script-built project opens cleanly in the GUI.
Use the API for notebook-based papers, batch parameter studies, CI regression tests, and as the unit of work that the Headless / HPC runners fan out.
import golgi
s = golgi.Study.create("/tmp/vagus_study")
s.import_nerve("nerve.stl")
s.set_mesh(use_epi=True, epi_thickness_um=50)
s.run_mesh()
s.set_electrodes([{"name": "bipolar @ 5 mm", "cuff_offset_mm": 5.0}])
s.run_fem()
s.run_fibers()
res = s.run_sweep(req)
s.export_bundle("/tmp/vagus_study.golgi")
s.close()Import is cheap.
import golgidoes not start Trame/VTK/PyVista — the heavy stack is imported lazily the first time you touch a compute method, sogolgi.Studyis fast to import in scripts and notebooks.
| Call | Description |
|---|---|
Study.create(project_dir, *, user="headless") |
Create a new project. Raises FileExistsError if the directory exists and is non-empty (it refuses to clobber an existing study). |
Study.open(project_dir, *, user="headless") |
Attach to an existing project. Loads the project's ui_state.json (if present) so the first compute call sees the same parameters the GUI would. Raises FileNotFoundError if the directory is missing. |
study.close() |
Release the headless context. Safe to call repeatedly. |
with Study.create(...) as s: ... |
Context-manager sugar — close() runs on exit. |
Read-only properties: study.project_dir (Path), study.user (str).
Every method is synchronous. Internally the async pipeline drivers are wrapped in asyncio.run,
so you call them from plain functions, scripts, and Jupyter cells without await.
The methods map one-to-one onto the pipeline stages. Call them in order; each
stage writes its artifacts under <project>/ and the next stage reads them back.
Load a nerve surface (STL / NAS / OBJ). Computes the global PCA frame, per-triangle surface
quality, and topology stats. scale_factor converts file units to metres (default 1e-3 = mm → m).
Returns a summary: {n_pts, n_tris, n_components, bbox_mm, watertight, q_median}.
Set mesh parameters in bulk (forwarded to project state). Common keys:
use_epi, epi_thickness_um, lc_endo_um, lc_epi_um, lc_muscle_um, lc_saline_um,
lc_silicone_um, lc_contact_um, lc_scar_um, decim_target_k, muscle_radial_pad_mm,
muscle_axial_pad_mm, muscle_dx_mm, muscle_dy_mm, muscle_dz_mm. See
Meshing and the Configuration Reference.
Replace the project's electrode designs. You may pass minimal dicts — just the fields you care
about (e.g. eid, name, cuff_offset_mm, electrode_type); every other field is filled from the
factory defaults, contact polarities/fractions are derived from the electrode type, the first design
becomes selected/active, and each design gets a Default FEM config. See
Electrodes & Cuff Designer for the electrode types and their
parameters.
s.set_electrodes([
{"name": "Tripolar @ 6 mm",
"electrode_type": "tripolar (anode-cathode-anode)",
"cuff_offset_mm": 6.0},
])Build a per-design TetGen mesh for every design. Outputs land in <project>/designs/<eid>/.
Returns {eid: path_to_nerve.msh}.
Solve the anisotropic FEM for every config in the project. Outputs land in
<project>/configs/<cid>/. Returns {cid: outputs_dir}. Requires run_mesh() first. See the
Finite-Element Solver page.
Generate curved 3-D fiber trajectories on the loaded nerve (Laplace solve + streamline integration +
cap detection + branch classification). Writes <project>/nerve_paths_fibers.npz and friends.
Returns {n_paths, n_branches, n_pts_total, branch_summary}. See
Fiber Populations & Trajectories.
Set fiber-generation parameters in bulk. Common keys: n_fibers, fiber_max_steps,
fiber_seed_end, fiber_cluster_eps_mm, fiber_cap_band_pct, fiber_min_rel_size_pct,
fiber_axial_normal_thresh, fiber_auto_detect_branches, fiber_method.
Run a parameter sweep — recruitment mode (activation across an amplitude axis) or threshold
mode (per-fiber activation threshold by bisection). Returns a SweepResult and writes it to the
project's sweep cache, tagged with the active config. See
Recruitment Sweeps & Selectivity for the request/result
schema.
| Call | Description |
|---|---|
study.export_bundle(out_zip) -> Path |
Pack the project into an integrity-hashed study bundle. The .golgi extension is conventional; the container is a zip. |
Study.import_bundle(zip_path, target_dir) -> Path (staticmethod)
|
Unpack a bundle into target_dir; returns the project directory. |
See Reproducible Study Bundles for the manifest format and replay
verification.
| Call | Description |
|---|---|
study.list_designs() -> list[dict] |
Per-cuff designs from the project's ui_state.json. |
study.list_configs() -> list[dict] |
Per-design FEM configs. |
Headless runs synthesise a headless user (local trust, no password) so the auth-gated pipeline
decorators run unchanged. The audit writer still fires — every headless
action lands in the same audit_fallback.jsonl the GUI writes, so headless runs show up in
golgi events / the Activity tab. Pass a different user= to create/open to attribute the run.
A complete load → mesh → electrodes → FEM → fibers → sweep → bundle script lives in
examples/recruitment_sweep.py
and is exercised by tests/test_headless_api.py. See Getting Started for a
walk-through.
Getting Started · Command-Line Interface · Headless / HPC · Pipeline Overview · Configuration Reference
golgi · open image-to-recruitment modeling of peripheral nerve stimulation · repository · issues · AGPL-3.0-or-later · data CC-BY-4.0
Get started
Tutorial
Build a model
Simulate & analyze
- Finite-Element Solver
- Fiber Populations & Trajectories
- Fiber Models & Activation
- Recruitment Sweeps & Selectivity
- Recording & CNAP
Share & reproduce
Scripting & scale
Reference
Research & project