OSBModelValidation 0.2.18__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. OSBModelValidation-0.2.18.dist-info/METADATA +184 -0
  2. OSBModelValidation-0.2.18.dist-info/RECORD +98 -0
  3. OSBModelValidation-0.2.18.dist-info/WHEEL +5 -0
  4. OSBModelValidation-0.2.18.dist-info/entry_points.txt +2 -0
  5. OSBModelValidation-0.2.18.dist-info/top_level.txt +1 -0
  6. omv/__init__.py +8 -0
  7. omv/analyzers/__init__.py +21 -0
  8. omv/analyzers/activation.py +24 -0
  9. omv/analyzers/analyzer.py +80 -0
  10. omv/analyzers/dryrun.py +13 -0
  11. omv/analyzers/input_resistance.py +47 -0
  12. omv/analyzers/morphology.py +16 -0
  13. omv/analyzers/rates.py +97 -0
  14. omv/analyzers/resting.py +37 -0
  15. omv/analyzers/spikes.py +113 -0
  16. omv/analyzers/temperature.py +12 -0
  17. omv/analyzers/timeseries.py +57 -0
  18. omv/analyzers/utils/__init__.py +0 -0
  19. omv/analyzers/utils/filenode.py +73 -0
  20. omv/analyzers/utils/timeseries.py +293 -0
  21. omv/autogen.py +106 -0
  22. omv/common/__init__.py +0 -0
  23. omv/common/inout.py +154 -0
  24. omv/engines/__init__.py +53 -0
  25. omv/engines/arbor_.py +57 -0
  26. omv/engines/brian1.py +59 -0
  27. omv/engines/brian2_.py +57 -0
  28. omv/engines/eden_.py +63 -0
  29. omv/engines/engine.py +111 -0
  30. omv/engines/genesis.py +86 -0
  31. omv/engines/getarbor.py +15 -0
  32. omv/engines/getbrian1.py +42 -0
  33. omv/engines/getbrian2.py +17 -0
  34. omv/engines/geteden.py +17 -0
  35. omv/engines/getgenesis.py +56 -0
  36. omv/engines/getjlems.py +20 -0
  37. omv/engines/getjnml.py +48 -0
  38. omv/engines/getlibsbml.py +13 -0
  39. omv/engines/getmoose.py +15 -0
  40. omv/engines/getnest.py +62 -0
  41. omv/engines/getnetpyne.py +52 -0
  42. omv/engines/getneuroconstruct.py +31 -0
  43. omv/engines/getnml2.py +26 -0
  44. omv/engines/getnrn.py +60 -0
  45. omv/engines/getoctave.py +11 -0
  46. omv/engines/getpylems.py +13 -0
  47. omv/engines/getpyneuroml.py +14 -0
  48. omv/engines/getpynn.py +40 -0
  49. omv/engines/jlems.py +48 -0
  50. omv/engines/jneuroml.py +101 -0
  51. omv/engines/jneuromlbrian.py +65 -0
  52. omv/engines/jneuromlbrian2.py +61 -0
  53. omv/engines/jneuromleden.py +61 -0
  54. omv/engines/jneuromlmoose.py +63 -0
  55. omv/engines/jneuromlnetpyne.py +73 -0
  56. omv/engines/jneuromlnetpyne_np2.py +45 -0
  57. omv/engines/jneuromlnetpyne_np4.py +45 -0
  58. omv/engines/jneuromlnrn.py +78 -0
  59. omv/engines/jneuromlpynnnrn.py +75 -0
  60. omv/engines/jneuromlvalidate.py +62 -0
  61. omv/engines/jneuromlvalidatev1.py +58 -0
  62. omv/engines/moose_.py +86 -0
  63. omv/engines/nestsli.py +84 -0
  64. omv/engines/netpyne_.py +120 -0
  65. omv/engines/netpyne__np2.py +47 -0
  66. omv/engines/netpyne__np4.py +47 -0
  67. omv/engines/neuron_.py +205 -0
  68. omv/engines/octave.py +51 -0
  69. omv/engines/pylems.py +57 -0
  70. omv/engines/pylemsnml2.py +59 -0
  71. omv/engines/pynest.py +111 -0
  72. omv/engines/pyneuroconstruct.py +67 -0
  73. omv/engines/pyneuroml_.py +55 -0
  74. omv/engines/pyneuromlvalidatesbml.py +83 -0
  75. omv/engines/pyneuron.py +94 -0
  76. omv/engines/pynn.py +63 -0
  77. omv/engines/pynnbrian1.py +59 -0
  78. omv/engines/pynnbrian2.py +60 -0
  79. omv/engines/pynnnest.py +56 -0
  80. omv/engines/pynnneuroml.py +57 -0
  81. omv/engines/pynnneuron.py +94 -0
  82. omv/engines/utils/__init__.py +21 -0
  83. omv/engines/utils/genesis_utils.g +26 -0
  84. omv/engines/utils/wdir.py +15 -0
  85. omv/experiment.py +18 -0
  86. omv/find_tests.py +126 -0
  87. omv/omt_mep_parser.py +59 -0
  88. omv/omv_util.py +439 -0
  89. omv/parse_omt.py +118 -0
  90. omv/tally.py +112 -0
  91. omv/test/__init__.py +0 -0
  92. omv/test/test_rates.py +38 -0
  93. omv/test/test_types.py +29 -0
  94. omv/validation/__init__.py +0 -0
  95. omv/validation/rx_validator.py +35 -0
  96. omv/validation/utils.py +51 -0
  97. omv/validation/validate.py +53 -0
  98. omv/validation/validate_mep.py +15 -0
@@ -0,0 +1,184 @@
1
+ Metadata-Version: 2.1
2
+ Name: OSBModelValidation
3
+ Version: 0.2.18
4
+ Summary: Open Source Brain Model validation
5
+ Home-page: https://github.com/OpenSourceBrain/osb-model-validation
6
+ Author: Boris Marin, Padraig Gleeson
7
+ Author-email: borismarin@gmail.com
8
+ License: LGPL-3.0-only
9
+ Classifier: Intended Audience :: Science/Research
10
+ Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
11
+ Classifier: Natural Language :: English
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3.7
14
+ Classifier: Programming Language :: Python :: 3.8
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Topic :: Scientific/Engineering
19
+ Description-Content-Type: text/markdown
20
+ Requires-Dist: PyYAML
21
+ Requires-Dist: numpy
22
+ Requires-Dist: pyrx
23
+ Requires-Dist: docopt
24
+ Requires-Dist: pathlib ; python_version < "3.4"
25
+ Requires-Dist: importlib-metadata ; python_version < "3.8"
26
+
27
+ [![Continuous builds](https://github.com/OpenSourceBrain/osb-model-validation/actions/workflows/ci.yml/badge.svg)](https://github.com/OpenSourceBrain/osb-model-validation/actions/workflows/ci.yml)
28
+ [![PyPI](https://img.shields.io/pypi/v/osb-model-validation)](https://pypi.org/project/osb-model-validation/)
29
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/osb-model-validation)](https://pypi.org/project/osb-model-validation/)
30
+ [![GitHub](https://img.shields.io/github/license/OpenSourceBrain/osb-model-validation)](https://github.com/OpenSourceBrain/osb-model-validation/blob/master/LICENSE.lesser)
31
+ [![GitHub pull requests](https://img.shields.io/github/issues-pr/OpenSourceBrain/osb-model-validation)](https://github.com/OpenSourceBrain/osb-model-validation/pulls)
32
+ [![GitHub issues](https://img.shields.io/github/issues/OpenSourceBrain/osb-model-validation)](https://github.com/OpenSourceBrain/osb-model-validation/issues)
33
+ [![Gitter](https://badges.gitter.im/NeuroML/community.svg)](https://gitter.im/NeuroML/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
34
+ ------------------------------------------
35
+
36
+ # OSB Model Validation
37
+
38
+ Tools for automated model validation in [Open Source Brain](http://www.opensourcebrain.org) projects, which can also be used for testing model behaviour on many [simulation engines](https://github.com/OpenSourceBrain/osb-model-validation/tree/master/omv/engines) both:
39
+
40
+ - on your local machine when developing models
41
+ - on [GitHub Actions](https://github.com/features/actions), to ensure tests pass on every commit.
42
+
43
+ To see this framework in action, click on some of the green buttons below:
44
+
45
+ | OSB project | Tests on GitHub Actions | Test workflow script |
46
+ |----------|:-------------:|:------:|
47
+ |[FitzHugh Nagumo](http://www.opensourcebrain.org/projects/fitzhugh-nagumo-fitzhugh-1969) | [![Continuous build using OMV](https://github.com/OpenSourceBrain/FitzHugh-Nagumo/actions/workflows/omv-ci.yml/badge.svg)](https://github.com/OpenSourceBrain/FitzHugh-Nagumo/actions/workflows/omv-ci.yml) | [omv-ci.yml](https://github.com/OpenSourceBrain/FitzHugh-Nagumo/blob/master/.github/workflows/omv-ci.yml) |
48
+ |[Auditory cortex network](http://www.opensourcebrain.org/projects/acnet2)| [![Continuous build using OMV](https://github.com/OpenSourceBrain/ACnet2/actions/workflows/omv-ci.yml/badge.svg)](https://github.com/OpenSourceBrain/ACnet2/actions/workflows/omv-ci.yml) | [omv-ci.yml](https://github.com/OpenSourceBrain/ACnet2/blob/master/.github/workflows/omv-ci.yml) |
49
+ | [SBML Showcase](http://www.opensourcebrain.org/projects/sbmlshowcase)| [![Continuous build using OMV](https://github.com/OpenSourceBrain/sbmlshowcase/actions/workflows/omv-ci.yml/badge.svg)](https://github.com/OpenSourceBrain/sbmlshowcase/actions/workflows/omv-ci.yml) | [omv-ci.yml](https://github.com/OpenSourceBrain/sbmlshowcase/blob/master/.github/workflows/omv-ci.yml) |
50
+
51
+ This framework has been used to test the 30+ NeuroML and PyNN models described in the [Open Source Brain paper (Gleeson et al. 2019)](https://www.cell.com/neuron/fulltext/S0896-6273(19)30444-1), and [many more](https://github.com/OpenSourceBrain/.github/blob/main/testsheet/README.md).
52
+
53
+ ## Installation
54
+
55
+ Quick system-wide install:
56
+
57
+ ``` bash
58
+ pip install osb-model-validation
59
+ ```
60
+
61
+ Or you can install from cloned repository (preferably in a virtual environment):
62
+
63
+ ``` bash
64
+ git clone https://github.com/OpenSourceBrain/osb-model-validation.git
65
+ cd osb-model-validation
66
+ pip install .
67
+ ```
68
+
69
+ ## Instructions
70
+
71
+ Any _Open Source Brain_ project can have automated testing incorporated.
72
+ For an overview of the various Open Source Brain projects with OMV tests, see https://github.com/OpenSourceBrain/.github/blob/main/testsheet/README.md (note not all of these use OMV yet).
73
+
74
+ Setting up validation for a model and simulation written in NeuroML2/LEMS requires two additional steps:
75
+
76
+ - write a <b>M</b>odel <b>E</b>mergent <b>P</b>roperties (_mep_) file.
77
+ - write the corresponding <b>O</b>SB <b>M</b>odel <b>T</b>est (_omt_) file.
78
+
79
+
80
+ ### Write MEP files
81
+
82
+ Depending on the size of your model, you can run validation on the full fledged model, or you can create smaller stripped down versions that test particular aspects of the model.
83
+ Here is an example LEMS file for the FitzHugh-Nagumo model on Open Source Brain: [LEMS_FitzHugNagamo.xml](https://github.com/OpenSourceBrain/FitzHugh-Nagumo/blob/master/NeuroML2/LEMS_FitzHughNagumo.xml).
84
+
85
+ ``` yaml
86
+ # Script for running automated tests on OSBrain, see https://github.com/OpenSourceBrain/osb-model-validation
87
+
88
+ system: The Fitzhugh-Nagumo model, classical parameters
89
+
90
+ experiments:
91
+ experiment 1, free run:
92
+ expected:
93
+ spike times: [2.24, 39.82, 76.53, 113.24, 149.94, 186.65, 223.36, 260.07, 296.78, 333.49, 370.2]
94
+ ```
95
+
96
+ MEP files include information on what is expected from the simulation run.
97
+ OMV will run the simulation based on the OMT files (which we'll see below), and compare the output to the information provided in MEP files.
98
+ Multiple _experiments_ can be mentioned in the MEP file, and each project can have multiple MEP files.
99
+
100
+ The MEP file for the FitzHugh-Nagumo model is [here](https://github.com/OpenSourceBrain/FitzHugh-Nagumo/blob/master/fhn.mep).
101
+ It includes a single experiment, with the expected spike times that the simulation run should generate.
102
+
103
+ ### Writing OMT files
104
+
105
+ OMT files include information on simulating the model for validation.
106
+ The FitzHugh-Nagumo model on Open Source Brain includes multiple OMT files that can be seen [here](https://github.com/OpenSourceBrain/FitzHugh-Nagumo/tree/master/NeuroML2).
107
+
108
+ - Each OMT file specifies a _target_ file, which is the LEMS simulation file to be run.
109
+
110
+ - Each OMT file specifies an _engine_ that OMV supports.
111
+ Engines are simulators that OMV should use to run the model. See [here](https://github.com/OpenSourceBrain/osb-model-validation/tree/master/omv/engines) for the current list.
112
+ For example, the [.test.fhn.jnml.omt](https://github.com/OpenSourceBrain/FitzHugh-Nagumo/blob/master/NeuroML2/.test.fhn.jnml.omt) file uses the `jNeuroML` engine, which implies that the model should be run using plain jNeuroML (and not any of the simulators that jNeuroML supports, like NEURON).
113
+
114
+ ``` yaml
115
+ # Script for running automated tests on OSB, see https://github.com/OpenSourceBrain/osb-model-validation
116
+
117
+ target: LEMS_FitzHughNagumo.xml
118
+ engine: jNeuroML
119
+ mep: ../fhn.mep
120
+ experiments:
121
+ experiment 1, free run:
122
+ observables:
123
+ spike times:
124
+ file:
125
+ path: ./fhn.dat
126
+ columns: [0,1]
127
+ scaling: [1000, 1]
128
+ spike detection:
129
+ method: derivative
130
+ tolerance: 2.185696883946938e-16
131
+ ```
132
+
133
+ - Each OMT file specifies the MEP file that the output of its simulation run should be compared to.
134
+ In this case, we use the same MEP file for all OMT files.
135
+
136
+ - Finally, like MEP files, OMT files also include _experiments_.
137
+ The names of the experiments in the OMT files must correspond to those used in the MEP files, so that OMV knows what section of the OMT and MEP files are related to each other.
138
+ In each experiment, we specify our _observables_, which are to be compared to the information provided in the MEP file.
139
+ Here, we inform OMV that we are observing _spike times_, which will be recorded by the simulation run in `fhn.dat`.
140
+ We also inform OMV what columns of this file the information is to be extracted from, and if these columns need to be scaled before they are compared to the data provided in the MEP file.
141
+ Finally, while simulations can save spike times directly and OMV will compare these to the MEP file, if the simulation is recording membrane potentials, OMV can also be asked to detect spikes from this data using the _spike detection_ section.
142
+ The _tolerance_ key tells OMV what the acceptable difference between the expected and observed data values is.
143
+
144
+ This is the OMT file to validate the same model using the `jNeuroML_NEURON` engine: [.test.fhn.jnmlnrn.omt](https://github.com/OpenSourceBrain/FitzHugh-Nagumo/blob/master/NeuroML2/.test.fhn.jnmlnrn.omt).
145
+ It uses the same MEP file, and observes the same recorded information.
146
+ It only tells OMV to use a different simulation engine:
147
+
148
+ ``` yaml
149
+ # Script for running automated tests on OSB, see https://github.com/OpenSourceBrain/osb-model-validation
150
+
151
+ target: LEMS_FitzHughNagumo.xml
152
+ engine: jNeuroML_NEURON
153
+ mep: ../fhn.mep
154
+ experiments:
155
+ experiment 1, free run:
156
+ observables:
157
+ spike times:
158
+ file:
159
+ path: ./fhn.dat
160
+ columns: [0,1]
161
+ scaling: [1000, 1]
162
+ spike detection:
163
+ method: derivative
164
+ tolerance: 0
165
+ ```
166
+ ### Running validation tests locally
167
+
168
+ If you have installed OMV successfully, you can now run all the OMV tests locally, by running this command:
169
+
170
+ omv all
171
+
172
+ Adding the `-V` flag prints more details on successful/failed runs. Learn more about the options that `omv` can take by running `omv --help`.
173
+
174
+ To see what [engines](https://github.com/OpenSourceBrain/osb-model-validation/tree/master/omv/engines) are currently installed (and what their versions are) type:
175
+
176
+ omv list -V
177
+
178
+ Running validation tests locally ensures that you can quickly check if any changes you have made to the model cause changes to its specific outcomes.
179
+ Since you can run the validation with different [engines](https://github.com/OpenSourceBrain/osb-model-validation/tree/master/omv/engines) to use different simulators, this also allows you to quickly verify that your model gives similar results using these different tools.
180
+
181
+
182
+ ### Running tests automatically on GitHub Actions
183
+
184
+ To use OMV with GHA, copy an existing configuration file, e.g. https://github.com/OpenSourceBrain/ACnet2/blob/master/.github/workflows/omv-ci.yml and place it in the required repository.
@@ -0,0 +1,98 @@
1
+ omv/__init__.py,sha256=49azS5RmLVlyUgahfuNDLANpz_xQ0lfw1LQ_vhLPVik,221
2
+ omv/autogen.py,sha256=k866pebE7LMrsdknVEP7FT-f7ZmwMIL5jX36EzechlU,3097
3
+ omv/experiment.py,sha256=FL76vNGdLLoblGnouRJrNjDFj2ci7WZ0yLSpPEtFXaA,624
4
+ omv/find_tests.py,sha256=U4H4PJswWf24YGIhzVCUr6RaRiM-5dAEpNgQVuvJY30,3873
5
+ omv/omt_mep_parser.py,sha256=of9FY4my7VA8QSKFQTiGoB_aUNV-DKs_GPw8qZGmjXg,1844
6
+ omv/omv_util.py,sha256=cFqU6zSlKYZC_j0re-lyqef8MTINdt2nzhM8QmLChmc,14466
7
+ omv/parse_omt.py,sha256=lZeHkUkgqEOk0adsmx8yQvHjdOq9YPG4mMPcrlFbTXM,4260
8
+ omv/tally.py,sha256=mMr-b-24nGNSIvmUSQdeXIP8W8JvtcJd_Dk5kSSi1go,3536
9
+ omv/analyzers/__init__.py,sha256=5QS2b80PQTa_keGnYlW3z_C7JxZDt6qd5zEEDSG03SA,843
10
+ omv/analyzers/activation.py,sha256=ZZncQ17Uvqgm4mzBZ3Js9uF0ZHyhP9N4ZiWMAZCps8o,830
11
+ omv/analyzers/analyzer.py,sha256=WdG5FPHOSW3kpjHcQLeo4j_G0qJdAyYWwVPvBOj0TqY,2583
12
+ omv/analyzers/dryrun.py,sha256=tSXGhunJX7giFa9Atiagbki2-qS_Fxvo_NayJHUBuOA,397
13
+ omv/analyzers/input_resistance.py,sha256=VbYryoRob-1FrvBgjzeG2VuLF-zXHDw7o5xZwbFiSSM,1587
14
+ omv/analyzers/morphology.py,sha256=gceVlkaD7czG8RyQuFUNzRECKUkx8tAYzSvV5O9RkvY,530
15
+ omv/analyzers/rates.py,sha256=ya3ARBc5dvEjmQzWqR-CpYJJopa4J5jMSsfxFg-4qdQ,3722
16
+ omv/analyzers/resting.py,sha256=7C0d5hsVmJd08wSUsICFI76nvngER7H62n9-QOLMNyY,1270
17
+ omv/analyzers/spikes.py,sha256=-C00aax6cSSVDfjw0yImmQRkXGA9REyxRUhdfH1xIqs,4373
18
+ omv/analyzers/temperature.py,sha256=PYI6KYTk-LRKl8LDskwdL9uykdExA7Kc2iVd4FzwC6A,330
19
+ omv/analyzers/timeseries.py,sha256=Y5nvJ-wyD-fFwK7L-gPyRFIaL0MITT_PIauJcd9vh7Y,1943
20
+ omv/analyzers/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
+ omv/analyzers/utils/filenode.py,sha256=qJfxzEuOPPEvWmkuZMsk-Lx_XyRoB_eYdLAbZZj0m30,2119
22
+ omv/analyzers/utils/timeseries.py,sha256=q9vupQWfCK--p3ZxiHcG-tX8PqzXBKFH-1u6hKdoB3c,8505
23
+ omv/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
+ omv/common/inout.py,sha256=UKMtWI_8GS5F360Ucam3EqHI8bF95pHH7qwkspQ86RA,3877
25
+ omv/engines/__init__.py,sha256=MkDTljoYQ-uut_WCLbvhedCI02jLif77kVmOEByQ3-s,2229
26
+ omv/engines/arbor_.py,sha256=OzeZUFUzXMbfmmSmlr3mwYdYFo-DGnt6a3v7R0ixlTU,1675
27
+ omv/engines/brian1.py,sha256=GAzZ7KCzeI25SVx6n8oytQOHGW5bdvM2ZSNjhLngJso,1732
28
+ omv/engines/brian2_.py,sha256=ehDduB9eH_da-l6ilkv1ixgbvyMqd4h2lbyCvdA2kRU,1699
29
+ omv/engines/eden_.py,sha256=k_tw6AE--1_Maa8CT1UZoWAaI2iN25U5FAVj8yS8sBk,1832
30
+ omv/engines/engine.py,sha256=QGCjiAv6XZ1fVaVOfEh85VfaAONysywI_KlS158VSDs,3460
31
+ omv/engines/genesis.py,sha256=EO12AvkBCLVxtdpKsFrcH1A6gYjG5GilTvbHOyn9HbI,2868
32
+ omv/engines/getarbor.py,sha256=q9Vp8du64fqTgqJvBqIkdeh4QdAh5v57VB4Oy-bMuJg,347
33
+ omv/engines/getbrian1.py,sha256=RkFzxSVw8l0y4nz_Jlibvdh6sPXG5zBZL5EJJNtc6J8,1492
34
+ omv/engines/getbrian2.py,sha256=VPh1ZwUpH3OPGj-P0a_DnWuwI_rpAa63WBZowFkgrXY,393
35
+ omv/engines/geteden.py,sha256=hMdmMgwvCM_8NUeSswz_pwvQxVuqth_XVv0DYyhSPEE,392
36
+ omv/engines/getgenesis.py,sha256=Q0TG0dy2U-rTYCeqPsP8ZqqK9YglHIoXMN_gN2-lEAo,2342
37
+ omv/engines/getjlems.py,sha256=9z3BSN6DBVrNiHotMN51N5ayW0qn8azUAVl7Kd20Jpo,613
38
+ omv/engines/getjnml.py,sha256=clKR4Sq9i_HQ7yqkp4Wrpcgc1ZkHeLTd2Idc8eGLKmI,1464
39
+ omv/engines/getlibsbml.py,sha256=Wr9lgf2WXaw8NXICY5CI-ry_p0bQEX8aB91JTWzihGU,358
40
+ omv/engines/getmoose.py,sha256=33eObTqFLB62w0Zz7O_WdL4K89j9BOp9qYx5BL8S_Sg,339
41
+ omv/engines/getnest.py,sha256=YH1UtPsy7LSJhVcqSDN_lqcWHfnDpkrutjAaSOjBiak,1967
42
+ omv/engines/getnetpyne.py,sha256=zYb9V-0MMw9iN9jbMEWDS5Aoheev3wUnm7v7m5SNtGA,1647
43
+ omv/engines/getneuroconstruct.py,sha256=797-0SmRw4NixmGz7Z7em_6lvrK4KRSlKyBiK8M1-HA,850
44
+ omv/engines/getnml2.py,sha256=UtpvetXojFuv_GbNNwZCsORnwdfnr9L3ZeELykZ11gU,744
45
+ omv/engines/getnrn.py,sha256=go95qPZLTx-HI3p61zRWjey-YKlb8x7rJkXKAQcXs0k,2025
46
+ omv/engines/getoctave.py,sha256=GvNyE_4vqYkSPfhfvco3NuVBR3P8lvIaaR42R8fLAtU,231
47
+ omv/engines/getpylems.py,sha256=0D8otZ_iE6bwICDm1QMkdOeMSU4cfFGkPbwm2SOH37k,301
48
+ omv/engines/getpyneuroml.py,sha256=X16_GQftMwEQsLTRU8b85Pd8L9LRay7jPkFXyhuxZbI,382
49
+ omv/engines/getpynn.py,sha256=Ykk2e5fi4RBWJcbrvntUqXU_VySibtOg36lJkBtV5iI,1342
50
+ omv/engines/jlems.py,sha256=WxSjJhlV3AQMPHWsGCrdPCUO_hO3SACk0mPNtq8tKcI,1604
51
+ omv/engines/jneuroml.py,sha256=uxxZaQCAG2p8Oi2V-O2RQUX1PJbQtmpIy1YrtNRp6Io,3412
52
+ omv/engines/jneuromlbrian.py,sha256=zpdSzjrjQbJdIH_NCwam89xLk9zIz30SlViTk9SO6e4,2379
53
+ omv/engines/jneuromlbrian2.py,sha256=WqGuuXaEpcW1vgaW_b9vus_i3df_40iwjs3njApkf2Q,2351
54
+ omv/engines/jneuromleden.py,sha256=uRdlTGxg9RbVw-DlLtlmKRx1i3GHrYcdCJ9SnUv0R_U,2285
55
+ omv/engines/jneuromlmoose.py,sha256=6CyuJKuZ4T7W30GchRQHsJLTltSITAQwPXcZSuIgPsk,2323
56
+ omv/engines/jneuromlnetpyne.py,sha256=zBOK-WcnkzCCNA1ZU_Btz7Pd8Ljh5pDL7IbwJVmHYgk,2704
57
+ omv/engines/jneuromlnetpyne_np2.py,sha256=w_jdkS_5hn92pO0JCfR2Pw6V6chgCPhBusv1VqjbFek,1622
58
+ omv/engines/jneuromlnetpyne_np4.py,sha256=R4wH-611YzGozA0cQwg6xB62aeM5g4KTE9sctAdlNQc,1622
59
+ omv/engines/jneuromlnrn.py,sha256=N6gavalu0IvF4mYKJbYbCv9aNUbTjcdUSylmE5fOg_I,2741
60
+ omv/engines/jneuromlpynnnrn.py,sha256=kq6wXkXWHyb1CrHbLelafC3NedzF8UYQSkfKsdofFfA,2734
61
+ omv/engines/jneuromlvalidate.py,sha256=aiFUDPkdatiCyYD93IBeYpuA6zG-ZLpyAnN4qsufe3U,2016
62
+ omv/engines/jneuromlvalidatev1.py,sha256=PrvuNa9T4rqZ-uKFc6IUXOHKxjeVqAqLs74y0sVilg4,1736
63
+ omv/engines/moose_.py,sha256=cjql6L0bW42m6KeZ_Fj84FZ88x5Xly63eEhxBioPJXg,2731
64
+ omv/engines/nestsli.py,sha256=qdKl_B-0HZVBqWaBNoRKb3ksz1WRlZ49Z6AvE9v_Ih8,2573
65
+ omv/engines/netpyne_.py,sha256=Fd-kf2Ehdjp702HmC0KlYniFOFyk6t33-8QJJSQqtOI,4007
66
+ omv/engines/netpyne__np2.py,sha256=57RbGs3xF3yBoqfQSEzvzquqziF5hBGO-XqtRKn2Z2k,1706
67
+ omv/engines/netpyne__np4.py,sha256=-VJW_QO2tDIiQ8PgmnhZuSwp_Dq5TQg48mC0S8TL2v8,1706
68
+ omv/engines/neuron_.py,sha256=OP3L7NS02Q5huiyc9GMIHlwienlSEVyNKOWcuZo16qU,7775
69
+ omv/engines/octave.py,sha256=W4UIudYOXC0np1z8_-81Keb9dNz0PB7IwLZrNAYF3Zk,1558
70
+ omv/engines/pylems.py,sha256=8P-adh3IPoGf7qr1ppq7g5avuMyg1NYFw_eu7ztW8Ps,1793
71
+ omv/engines/pylemsnml2.py,sha256=kQz2_mL5WpQhi1F10xKF6wJa6ZSRamEzjiVXbB9EA08,1912
72
+ omv/engines/pynest.py,sha256=FUPvn6YEvOaqROZSh5vNjh3DZc65vC2FbbuopDDkW78,3990
73
+ omv/engines/pyneuroconstruct.py,sha256=ZKXai5wiXwyH0Z21vfqN3RWy8GtE7IZUQyfGJvNdSAk,2127
74
+ omv/engines/pyneuroml_.py,sha256=1AWEinFnG47QaU5eQlK50Z4F1xqn3zr7bNfL0ynjW_s,1591
75
+ omv/engines/pyneuromlvalidatesbml.py,sha256=sBYw22RhMCEm9r1aiK_KcLQGxC9WDdaLNs4CZ-N-6tE,2628
76
+ omv/engines/pyneuron.py,sha256=LSv4hrWg3xX5555eHeGTvZcfOqnZqGppjHOhQDlrhCc,3263
77
+ omv/engines/pynn.py,sha256=4u1TG1g3RviiILZkfsxkEY39GYaZ7Wf9hnIC2bcvT2E,1977
78
+ omv/engines/pynnbrian1.py,sha256=aYBW8vbNxdse_AXAfK7Z2qiTd6O_vwi1J3nzMRTfyN8,2147
79
+ omv/engines/pynnbrian2.py,sha256=I3de3ujzXyEn-4dtXg2rsN7UwVz9PLNX5OSdXj7cXes,2166
80
+ omv/engines/pynnnest.py,sha256=u5WSj6malHYsBfegfHxkKv7H8QDJK9znhG3CG2vCNPE,1941
81
+ omv/engines/pynnneuroml.py,sha256=z61S-l4rZUdz1i4GD15wFsEfROtiJx4WLICp3M4KmHY,1863
82
+ omv/engines/pynnneuron.py,sha256=wMTHtvHMkoV2bqa1XfgaFzSScn0cE4khQPZLedKgnyY,3339
83
+ omv/engines/utils/__init__.py,sha256=eCOOobo9f1a5i6i9KYNVSm4KFJXwvB_dpqjHp8pQVaM,467
84
+ omv/engines/utils/genesis_utils.g,sha256=qMVW7OOrDISL77bNs2LZqKLNSUfLn_wOZ4rFgFPBWNc,656
85
+ omv/engines/utils/wdir.py,sha256=brpR7ALHkc4SbzwE8gcAA-wPnWIZo9J9ezah-00Tx0Q,350
86
+ omv/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
87
+ omv/test/test_rates.py,sha256=14-0Vt5faXefprcBo_Dlaq33Xdpa-Z5XkHnSpD98gGU,1012
88
+ omv/test/test_types.py,sha256=X8jg9meh44XM8uscca5xzO_S_3NZkc3WF8lVF_04Hg8,786
89
+ omv/validation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
90
+ omv/validation/rx_validator.py,sha256=TiT-zgc4fqoqx4BUvBBfKWKnJn5FrCv5LrAL_fRA02o,916
91
+ omv/validation/utils.py,sha256=vDAdiaZ82LIqoDGx24o8yOgw4xP1ZA_EenrtI4xiuHE,1759
92
+ omv/validation/validate.py,sha256=608ZX0uIMLDgJ7_VA09nh5t97dfywuaNeuTCBpATqx4,1758
93
+ omv/validation/validate_mep.py,sha256=BXZSGNgA64vAFY5SuhbsLH7G59ULQ58gr_NTaToS1R0,380
94
+ OSBModelValidation-0.2.18.dist-info/METADATA,sha256=zF6g5hpW6ioxW_mfKW073ENA7zGpYogRUbU3LdsslU4,10811
95
+ OSBModelValidation-0.2.18.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
96
+ OSBModelValidation-0.2.18.dist-info/entry_points.txt,sha256=FKthTyVC1g5PLxsbjWuZSpt6SshM-j_0i2RP97lTvr0,42
97
+ OSBModelValidation-0.2.18.dist-info/top_level.txt,sha256=6hVto0LMiELtSSMCGQNxFZpO6i5ZGdaheiuSYNpxvsk,4
98
+ OSBModelValidation-0.2.18.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.43.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ omv = omv.omv_util:main
omv/__init__.py ADDED
@@ -0,0 +1,8 @@
1
+ try:
2
+ import importlib.metadata
3
+
4
+ __version__ = importlib.metadata.version("OSBModelValidation")
5
+ except ImportError:
6
+ import importlib_metadata
7
+
8
+ __version__ = importlib_metadata.version("OSBModelValidation")
@@ -0,0 +1,21 @@
1
+ from omv.analyzers.spikes import SpikeAnalyzer
2
+ from omv.analyzers.rates import RateAnalyzer
3
+ from omv.analyzers.dryrun import DryRunAnalyzer
4
+ from omv.analyzers.resting import RestingAnalyzer
5
+ from omv.analyzers.morphology import MorphologyAnalyzer
6
+ from omv.analyzers.temperature import TemperatureAnalyzer
7
+ from omv.analyzers.activation import ActivationVariableAnalyzer
8
+ from omv.analyzers.input_resistance import InputResAnalyzer
9
+ from omv.analyzers.timeseries import TimeSeriesAnalyzer
10
+
11
+ OMVAnalyzers = {
12
+ "spike times": SpikeAnalyzer,
13
+ "spike rate": RateAnalyzer,
14
+ "dry": DryRunAnalyzer,
15
+ "resting": RestingAnalyzer,
16
+ "morphology": MorphologyAnalyzer,
17
+ "temperature": TemperatureAnalyzer,
18
+ "activation variables": ActivationVariableAnalyzer,
19
+ "input resistance": InputResAnalyzer,
20
+ "timeseries": TimeSeriesAnalyzer,
21
+ }
@@ -0,0 +1,24 @@
1
+ from omv.analyzers.analyzer import OMVAnalyzer
2
+ from omv.analyzers.utils import timeseries as ts
3
+ from omv.analyzers.utils import filenode as fn
4
+ from omv.common.inout import inform
5
+
6
+
7
+ class ActivationVariableAnalyzer(OMVAnalyzer):
8
+ def parse_observable(self):
9
+ if "file" in self.observable:
10
+ f = fn.FileNodeHelper(self.observable["file"], self.omt_root)
11
+ inform(
12
+ "Activation variable from file",
13
+ self.observable["file"],
14
+ indent=1,
15
+ verbosity=1,
16
+ )
17
+ return f.get_timeseries()
18
+
19
+ def __call__(self):
20
+ obs = self.parse_observable()
21
+ allin = ts.all_within_bounds(obs, (0, 1))
22
+ if not allin:
23
+ inform("Activation variable outside of (0,1) interval: ", obs, indent=1)
24
+ return allin
@@ -0,0 +1,80 @@
1
+ from omv.analyzers.utils.timeseries import *
2
+ from omv.common.inout import inform
3
+
4
+
5
+ class OMVAnalyzer(object):
6
+ def __init__(self, observable, expected, engine, omt_root, mep_root):
7
+ self.engine = engine
8
+ self.observable = observable
9
+ self.expected = expected
10
+ self.omt_root = omt_root
11
+ self.mep_root = mep_root
12
+ self.before_running()
13
+
14
+ def before_running(self):
15
+ pass
16
+
17
+ def parse_expected(self):
18
+ pass
19
+
20
+ def parse_observable(self):
21
+ pass
22
+
23
+ def __call__(self):
24
+ try:
25
+ obs = self.parse_observable()
26
+ if obs is None:
27
+ inform("Could not determine observed values")
28
+ return False
29
+ if isinstance(obs, list):
30
+ for o in obs:
31
+ if not o:
32
+ inform("Could not determine observed values")
33
+ return False
34
+
35
+ exp = self.parse_expected()
36
+
37
+ if exp is None:
38
+ inform("Could not determine expected values, value None")
39
+ return False
40
+ if isinstance(exp, list):
41
+ for e in exp:
42
+ if not e:
43
+ inform("Could not determine expected values")
44
+ return False
45
+ except IOError as e:
46
+ inform(
47
+ "Input/output error when\
48
+ checking for observable data: %s"
49
+ % e
50
+ )
51
+ return False
52
+
53
+ try:
54
+ tolerance = float(self.observable["tolerance"])
55
+ except (TypeError, KeyError): # observable can be None
56
+ tolerance = 1e-1
57
+
58
+ are_close, best_tol = compare_arrays((obs, exp), tolerance)
59
+
60
+ if not are_close:
61
+ pretty_obs, pretty_exp = pretty_print_copypaste(obs, exp)
62
+ inform(
63
+ "Comparison of \n\
64
+ (observed data): %s\n\
65
+ and\n\
66
+ (expected data): %s\n\
67
+ failed against tolerance %g"
68
+ % (pretty_obs, pretty_exp, tolerance)
69
+ )
70
+ if best_tol:
71
+ inform("A better tolerance to try is: ", best_tol, indent=1)
72
+ else:
73
+ if best_tol and best_tol < tolerance:
74
+ inform(
75
+ "Passed, but an even better tolerance might be: %s, as opposed to: %s (diff: %s)"
76
+ % (best_tol, tolerance, (tolerance - best_tol)),
77
+ indent=3,
78
+ verbosity=1,
79
+ )
80
+ return are_close
@@ -0,0 +1,13 @@
1
+ from omv.analyzers.analyzer import OMVAnalyzer
2
+ from omv.common.inout import inform
3
+
4
+
5
+ class DryRunAnalyzer(OMVAnalyzer):
6
+ def __init__(self, ost, expected, engine, omt_root, mep_root):
7
+ inform(
8
+ "No mep file specified. Will only run simulation using: ", engine, indent=1
9
+ )
10
+ self.engine = engine
11
+
12
+ def __call__(self):
13
+ return not self.engine.returncode
@@ -0,0 +1,47 @@
1
+ from omv.analyzers.analyzer import OMVAnalyzer
2
+ from omv.analyzers.utils import timeseries as ts
3
+ from omv.analyzers.utils import filenode as fn
4
+ from omv.common.inout import inform
5
+
6
+
7
+ class InputResAnalyzer(OMVAnalyzer):
8
+ """
9
+ Input resistance
10
+ """
11
+
12
+ def parseOMT(self, to_parse):
13
+ f = fn.FileNodeHelper(to_parse["file_Vm"], self.omt_root)
14
+ f_i = fn.FileNodeHelper(to_parse["file_VC_i"], self.omt_root)
15
+ inform(
16
+ "Calculating input resistance from files:",
17
+ (f.filename, f_i.filename),
18
+ indent=1,
19
+ verbosity=1,
20
+ )
21
+ h_voltage = to_parse.get("holding voltage", -70.0)
22
+ cmd_voltage = to_parse.get("command voltage", -80.0)
23
+ h_window = to_parse.get("holding window", [0.0, 0.0])
24
+ cmd_window = to_parse.get("command window", [0.0, 0.0])
25
+
26
+ # h_window = [float(t) for t in to_parse.get('holding window', [0., 0.])[0].split()]
27
+ # cmd_window = [float(t) for t in to_parse.get('command window', [0., 0.])[0].split()]
28
+ inform(
29
+ "Time wondow used for detection of current injections:",
30
+ (h_window, cmd_window),
31
+ indent=2,
32
+ verbosity=1,
33
+ )
34
+ input_resistance = ts.input_resistance(
35
+ f.get_timeseries(),
36
+ f_i.get_timeseries(),
37
+ h_window,
38
+ cmd_window,
39
+ (h_voltage, cmd_voltage),
40
+ )
41
+ return input_resistance
42
+
43
+ def parse_expected(self):
44
+ return self.expected
45
+
46
+ def parse_observable(self):
47
+ return self.parseOMT(self.observable)
@@ -0,0 +1,16 @@
1
+ from omv.analyzers.analyzer import OMVAnalyzer
2
+
3
+
4
+ class MorphologyAnalyzer(OMVAnalyzer):
5
+ def before_running(self):
6
+ if "total area" in self.expected:
7
+ base = self.observable.get("base section", "cell[0]")
8
+ self.query = self.engine.query_area(base)
9
+
10
+ def parse_expected(self):
11
+ return self.expected["total area"]
12
+
13
+ def parse_observable(self):
14
+ area = float(self.engine.fetch_query(self.query))
15
+ scale = float(self.observable.get("scaling", 1))
16
+ return scale * area
omv/analyzers/rates.py ADDED
@@ -0,0 +1,97 @@
1
+ from omv.analyzers.spikes import SpikeAnalyzer
2
+ from omv.analyzers.utils import timeseries as ts
3
+ from omv.common.inout import inform
4
+ from os import getcwd
5
+
6
+
7
+ class RateAnalyzer(SpikeAnalyzer):
8
+ def parse_spike_rates(self, to_parse):
9
+ if isinstance(to_parse, float) or isinstance(to_parse, int):
10
+ rate = to_parse
11
+
12
+ elif "file" in to_parse or "spiketimes file" in to_parse:
13
+ spikes = []
14
+ if not self.f.exists():
15
+ inform(
16
+ "ERROR! Datafile %s does not exist (relative to %s)!"
17
+ % (self.f.filename, getcwd()),
18
+ indent=2,
19
+ verbosity=0,
20
+ underline="-",
21
+ )
22
+ spikes = None
23
+ elif not self.f.has_changed():
24
+ inform(
25
+ "ERROR! Datafile %s has not changed!" % self.f.filename,
26
+ indent=2,
27
+ verbosity=0,
28
+ underline="-",
29
+ )
30
+ spikes = None
31
+ elif self.f.has_changed():
32
+ if "file" in to_parse:
33
+ try:
34
+ tv = self.f.get_timeseries()
35
+ except Exception as e:
36
+ inform(
37
+ "ERROR! Could not read spikes from datafile %s (%s)!"
38
+ % (self.f.filename, e),
39
+ indent=2,
40
+ verbosity=0,
41
+ underline="-",
42
+ )
43
+ spikes = []
44
+ return spikes
45
+ inform("Reading timeseries from: ", self.f, indent=1, verbosity=1)
46
+ if "spike detection" in to_parse:
47
+ sd = to_parse["spike detection"]
48
+ method = sd.get("method", "threshold")
49
+ threshold = float(sd.get("threshold", 0))
50
+ inform(
51
+ "Detecting spikes with method: ",
52
+ method,
53
+ indent=2,
54
+ verbosity=1,
55
+ )
56
+ spikes = ts.spikes_from_timeseries(
57
+ tv, method=method, threshold=threshold
58
+ )
59
+ else: # file contains spike times
60
+ spikes = tv
61
+
62
+ elif "spiketimes file" in to_parse:
63
+ inform("Reading spiketimes from: ", self.f, indent=1, verbosity=1)
64
+
65
+ spikes = self.f.get_spike_times()
66
+
67
+ if "method" in to_parse:
68
+ method = to_parse["method"]
69
+ if "start_time" in to_parse:
70
+ start_time = to_parse["start_time"]
71
+ else:
72
+ start_time = 0
73
+ if "end_time" in to_parse:
74
+ end_time = to_parse["end_time"]
75
+ else:
76
+ end_time = float("inf")
77
+ rate = ts.get_spike_rate(spikes, method, start_time, end_time)
78
+
79
+ else:
80
+ rate = ts.get_spike_rate(spikes)
81
+ else:
82
+ inform(
83
+ "ERROR! Preexistent datafile %s has not been updated!"
84
+ % self.f.filename,
85
+ indent=2,
86
+ verbosity=0,
87
+ underline="-",
88
+ )
89
+ rate = -1
90
+
91
+ return rate
92
+
93
+ def parse_expected(self):
94
+ return self.parse_spike_rates(self.expected)
95
+
96
+ def parse_observable(self):
97
+ return self.parse_spike_rates(self.observable)
@@ -0,0 +1,37 @@
1
+ from omv.analyzers.analyzer import OMVAnalyzer
2
+ from omv.analyzers.utils import timeseries as ts
3
+ from omv.analyzers.utils import filenode as fn
4
+ from omv.common.inout import inform
5
+
6
+
7
+ class RestingAnalyzer(OMVAnalyzer):
8
+ def parse_resting(self, to_parse):
9
+ if isinstance(to_parse, (int, float)):
10
+ resting = to_parse
11
+ inform(
12
+ "Explicit resting potential specified:", to_parse, indent=1, verbosity=1
13
+ )
14
+ elif "file" in to_parse:
15
+ f = fn.FileNodeHelper(to_parse["file"], self.omt_root)
16
+ inform(
17
+ "Calculating resting potential from file:",
18
+ f.filename,
19
+ indent=1,
20
+ verbosity=1,
21
+ )
22
+ window = to_parse.get("average last", 1)
23
+ if window > 1:
24
+ inform(
25
+ "Number of final points taken for averaging:",
26
+ window,
27
+ indent=2,
28
+ verbosity=1,
29
+ )
30
+ resting = ts.average_resting(f.get_timeseries(), window)
31
+ return resting
32
+
33
+ def parse_expected(self):
34
+ return self.parse_resting(self.expected)
35
+
36
+ def parse_observable(self):
37
+ return self.parse_resting(self.observable)