Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,6 @@ __pycache__
/src/worm2d/neuromlLocal/testc302SigSim/*.dat
/src/worm2d/neuromlLocal/testc302SigSim/testc302NervousSystem
/src/worm2d/neuromlLocal/testc302SigSim/report.txt
/synchere.sh
/wheelhouse
/tests/test_files/test_py_cpp
185 changes: 185 additions & 0 deletions HISTORY.md

Large diffs are not rendered by default.

54 changes: 52 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,54 @@
# Worm2D
Simulator of 2D worm body models

Work in progress. Latest verison of this code can be found here: https://github.com/openworm/CE_locomotion/tree/test_stable
Worm2D is a neuromechanical simulator of *C. elegans* locomotion. This is an initiative of the [OpenWorm project](https://www.openworm.org). It is based on earlier work on development of 2D worm neuromechanical models of Netta Cohen and team, as well as Dr. Eduardo J. Izquiredo, Dr. Erick Olivares and Prof. Randall Beer (See [HISTORY.md](HISTORY.md)).

Worm2D is a hybrid C++/Python package: C++ binaries implement the physics, nervous system, and evolutionary search, while Python handles configuration, binary dispatch, and post-run analysis/plotting.


## Build & Install

The package uses [scikit-build-core](https://scikit-build-core.readthedocs.io/) with CMake. nlohmann-json is bundled as a header at `src/cpp/nlohmann/json.hpp` — no system package needed.

Install in editable mode (builds C++ and installs Python package):

```bash
pip install -e .[all]
```

The `[all]` extra pulls in `[neuroml]` (pyNeuroML, NEURON<9.0) and `[dev]` (ruff, pytest, ipywidgets, OSBModelValidation, modelspec).

## Running Tests

Quick test (runs after `pip install -e .`):

```bash
python tests/test.py # runs a single optimisation run & saves output to exampleRun folder, see below
```

![Example](exampleRun/ExampleActivity.png)


Full test suite (cleans prior run folders, then runs all model variants and OMV tests):

```bash
./test_all.sh # full
./test_all.sh -q # quick (skips OMV and most model-specific tests)
```

Individual test scripts in `tests/` and `src/worm2d/` follow the naming pattern `test<ModelVariant>.py`. Run any directly:

```bash
cd tests
python testW2DCE.py
```


## CLI

After install, the `worm2d` command is available:

```bash
worm2d -f <outputFolder> [-E] [-O <modelName>] [-T <modelFolder>] [...]
```

Key flags: `-E` / `--doEvol` runs the evolutionary search; `-f` specifies the output folder (required); `-O` sets the model name when using the `Worm2D` binary family.
Binary file added exampleRun/ExampleActivity.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added exampleRunW2DCE/ExampleActivity.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions test_all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,10 @@ if [ "$quick_test" == 0 ]; then


omv test -V .test.example.omt #Izq original test.example.mep
omv test -V .test.W2DCEa.omt #main_osc.cpp test.example.mep
omv test -V .test.W2DCEanm.omt #main_osc.cpp test.W2DCEanm.mep, as W2DCEa but origMusc=False
omv test -V .test.W2DCEanm2.omt ${OMV_ARGS}
omv test -V .test.W2DCE.omt
omv test -V .test.W2DCEs.omt

fi
Binary file added testruns/exW2DCEa/ExampleActivity.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added testruns/exW2DCEanm/ExampleActivity.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added testruns/exW2DCEanm2/ExampleActivity.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added testruns/exW2DCEanm2_1/ExampleActivity.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added testruns/exW2DCEs/ExampleActivity.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions tests/.test.W2DCE.mep
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
system: Testing activity of some neurons

experiments:
Test:
expected:
spike times: [0.405, 8.555]
Test2:
expected:
spike times: [0.405, 8.655]
Test3:
expected:
spike times: [0.455, 8.655]
18 changes: 18 additions & 0 deletions tests/.test.W2DCE.omt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Framework for running automated tests on Open Source Brain
# See https://github.com/OpenSourceBrain/osb-model-validation for more details

target: testW2DCE.py
engine: Brian2 # This installs Brian2, but all we really need is a Python environment to run the script in
mep: .test.W2DCE.mep
experiments:
Test:
observables:
spike times:
file:
path: ../exampleRunW2DCE/act.dat
columns: [0,3]
scaling: [1, 1]
spike detection:
method: threshold
threshold: 2
tolerance: 0
18 changes: 18 additions & 0 deletions tests/.test.W2DCEa.omt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Framework for running automated tests on Open Source Brain
# See https://github.com/OpenSourceBrain/osb-model-validation for more details

target: testW2DCEa.py
engine: Brian2 # This installs Brian2, but all we really need is a Python environment to run the script in
mep: .test.example.mep
experiments:
Test:
observables:
spike times:
file:
path: ../testruns/exW2DCEa/act.dat
columns: [0,3]
scaling: [1, 1]
spike detection:
method: threshold
threshold: 2
tolerance: 0
6 changes: 6 additions & 0 deletions tests/.test.W2DCEanm.mep
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
system: Testing activity of some neurons

experiments:
Test:
expected:
spike times: [0.405, 5.955, 11.155, 16.155, 21.105, 26.105]
18 changes: 18 additions & 0 deletions tests/.test.W2DCEanm.omt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Framework for running automated tests on Open Source Brain
# See https://github.com/OpenSourceBrain/osb-model-validation for more details

target: testW2DCEanm.py
engine: Brian2 # This installs Brian2, but all we really need is a Python environment to run the script in
mep: .test.W2DCEanm.mep
experiments:
Test:
observables:
spike times:
file:
path: ../testruns/exW2DCEanm/act.dat
columns: [0,3]
scaling: [1, 1]
spike detection:
method: threshold
threshold: 2
tolerance: 0
9 changes: 9 additions & 0 deletions tests/.test.W2DCEanm2.mep
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
system: Testing activity of some neurons

experiments:
Test:
expected:
spike times: [8.21, 11.56, 14.96, 18.36, 21.76, 25.16, 28.61, 32.01]
Test2:
expected:
spike times: [9.06, 13.01, 16.96, 20.91, 24.86, 28.81]
29 changes: 29 additions & 0 deletions tests/.test.W2DCEanm2.omt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Framework for running automated tests on Open Source Brain
# See https://github.com/OpenSourceBrain/osb-model-validation for more details

target: testW2DCEanm2.py
engine: Brian2 # This installs Brian2, but all we really need is a Python environment to run the script in
mep: .test.W2DCEanm2.mep
experiments:
Test:
observables:
spike times:
file:
path: ../testruns/exW2DCEanm2/act.dat
columns: [0,3]
scaling: [1, 1]
spike detection:
method: threshold
threshold: 2
tolerance: 0
Test2:
observables:
spike times:
file:
path: ../testruns/exW2DCEanm2_1/act.dat
columns: [0,3]
scaling: [1, 1]
spike detection:
method: threshold
threshold: 2
tolerance: 0
6 changes: 6 additions & 0 deletions tests/.test.W2DCEs.mep
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
system: Testing activity of some neurons

experiments:
Test:
expected:
spike times: [0.555, 2.305]
18 changes: 18 additions & 0 deletions tests/.test.W2DCEs.omt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Framework for running automated tests on Open Source Brain
# See https://github.com/OpenSourceBrain/osb-model-validation for more details

target: testW2DCEs.py
engine: Brian2 # This installs Brian2, but all we really need is a Python environment to run the script in
mep: .test.W2DCEs.mep
experiments:
Test:
observables:
spike times:
file:
path: ../testruns/exW2DCEs/act.dat
columns: [0,3]
scaling: [1, 1]
spike detection:
method: threshold
threshold: 2
tolerance: 0
27 changes: 27 additions & 0 deletions tests/testW2DCE.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from worm2d import run

run(
simduration=20,
simtransient=0,
popSize=96,
RandSeed=1233,
maxGens=10,
modelName="W2DCE",
modelFolder="Worm2D",
# inputFolderName="exampleRunW2Dosc_t1",
outputFolderName="../exampleRunW2DCE",
# outputFolderName="exampleRunW2Dosc_t1_nml",
doEvol=True,
overwrite=True,
checkPointInterval=5,
reRand=True,
doPlotEvol=True,
doNML=False,
# doCPT=True,
evo_type="EvoCE",
AvgSpeed=0.0001,
# SRType = "SR_TRANS_STRETCH"
doTestRun=True,
doOrigMuscInput=True,
SRZeroGainsType=1,
)
23 changes: 23 additions & 0 deletions tests/testW2DCEa.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from worm2d import run

run(
simduration=30,
simtransient=0,
popSize=96,
RandSeed=1233,
modelName="W2DCE",
modelFolder="Worm2D",
outputFolderName="../testruns/exW2DCEa",
doEvol=True,
overwrite=True,
checkPointInterval=5,
doOrigMuscInput=True,
evo_type="EvoCE",
doTestRun=False,
SRZeroGainsType=1,
doReverse=0,
fitType=0,
AvgSpeed=0.0001,
inputInd=2,
debug=False,
)
23 changes: 23 additions & 0 deletions tests/testW2DCEanm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from worm2d import run

run(
simduration=30,
simtransient=0,
popSize=96,
RandSeed=1233,
modelName="W2DCE",
modelFolder="Worm2D",
outputFolderName="../testruns/exW2DCEanm",
doEvol=True,
overwrite=True,
checkPointInterval=5,
doOrigMuscInput=False,
evo_type="EvoCE",
doTestRun=False,
SRZeroGainsType=1,
doReverse=0,
fitType=0,
AvgSpeed=0.0001,
inputInd=2,
debug=False,
)
48 changes: 48 additions & 0 deletions tests/testW2DCEanm2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from worm2d import run
from worm2d.helper_funcs import get_worm_json, write_worm_json, delete_directory

outputFolderName = "../testruns/exW2DCEanm2"
outputFolderName_2 = "../testruns/exW2DCEanm2_1"
origFolderName = "../testruns/exW2DCEanm"


# x = 0.1
delete_directory(outputFolderName_2)
delete_directory(outputFolderName)
json_data = get_worm_json(origFolderName)
# json_data['evolvable_ranges']['evotag_2']["active"] = False
write_worm_json(outputFolderName, json_data)

args = dict(
modelFolder="Worm2D", # folder containing the compiled C++ binary code
modelName="W2DSR", # rerun using the generic json loaded model
maxGens=5, # number of generations to run
popSize=10,
doEvol=True,
# inputFolderName=origFolderName, # input folder
# outputFolderName=outputFolderName, # output folder
overwrite=True, # allow overwrite of output folder
# randInitState=True, #use fixed initial conditions from JSON file
# doTestRun=True, #run a single simple simulation
reRand=True,
RandSeed=900351,
)

args["outputFolderName"] = outputFolderName
run(**args)


json_data = get_worm_json(origFolderName)
json_data["evolvable_ranges"]["ns_cells_bias_0"]["active"] = False
json_data["evolvable_ranges"]["ns_chemcons_1"]["active"] = False
json_data["evolvable_ranges"]["DA_0_1_tau"] = {
"active": True,
"lower_limit": 0.1,
"upper_limit": 2.5,
"name": "DA_tau",
}
json_data["nervous_system"]["cells"]["DA_0"]["tau"]["evotag"] = "DA_0_1_tau"
json_data["nervous_system"]["cells"]["DA_1"]["tau"]["evotag"] = "DA_0_1_tau"
write_worm_json(outputFolderName_2, json_data)
args["outputFolderName"] = outputFolderName_2
run(**args) #
25 changes: 25 additions & 0 deletions tests/testW2DCEs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from worm2d import run

run(
simduration=20,
simtransient=0,
popSize=96,
RandSeed=1233,
maxGens=5,
modelName="W2DCE",
modelFolder="Worm2D",
outputFolderName="../testruns/exW2DCEs",
doEvol=True,
overwrite=True,
checkPointInterval=5,
reRand=True,
doPlotEvol=True,
doNML=False,
# doCPT=True,
evo_type="EvoCE",
AvgSpeed=0.0001,
# SRType = "SR_TRANS_STRETCH"
doTestRun=True,
doOrigMuscInput=True,
SRZeroGainsType=1,
)
Loading