├── .github
└── workflows
│ ├── ci.yml
│ ├── examples.yml
│ └── python-publish.yml
├── .gitignore
├── .readthedocs.yaml
├── LICENSE.lesser
├── MANIFEST.in
├── Makefile
├── README.md
├── ci
├── run-apitest.sh
└── run-examples-ghactions.sh
├── doc
├── Makefile
├── conf.py
├── index.rst
├── lems.base.rst
├── lems.dlems.rst
├── lems.model.rst
├── lems.parser.rst
├── lems.rst
├── lems.sim.rst
├── migrate_docstrings.sh
└── modules.rst
├── examples
├── MultiRunSimulation.xml
├── SimpleNetwork.xml
├── SimpleTest.xml
├── SingleSimulation.xml
├── apitest.py
├── apitest2.py
├── apitest3.py
├── bounce-conditional.xml
├── elecdims.xml
├── ex2dims.xml
├── example1.xml
├── example10_Q10.xml
├── example2.xml
├── example3.xml
├── example4.xml
├── example5.xml
├── example6.xml
├── example7.xml
├── example8.xml
├── example9.xml
├── hhaltgate.xml
├── hhcell.xml
├── hhchannel.xml
├── hhmodels.xml
├── loadtest.py
├── misciaf.xml
└── spikegenerators.xml
├── lems
├── __init__.py
├── api.py
├── base
│ ├── __init__.py
│ ├── base.py
│ ├── errors.py
│ ├── map.py
│ ├── stack.py
│ └── util.py
├── dlems
│ ├── __init__.py
│ └── exportdlems.py
├── model
│ ├── __init__.py
│ ├── component.py
│ ├── dynamics.py
│ ├── fundamental.py
│ ├── model.py
│ ├── simulation.py
│ └── structure.py
├── parser
│ ├── LEMS.py
│ ├── __init__.py
│ └── expr.py
├── run.py
├── sim
│ ├── __init__.py
│ ├── build.py
│ ├── recording.py
│ ├── runnable.py
│ └── sim.py
└── test
│ ├── NeuroML2CoreTypes
│ ├── Cells.xml
│ ├── Channels.xml
│ ├── Inputs.xml
│ ├── Networks.xml
│ ├── NeuroML2CoreTypes.xml
│ ├── NeuroMLCoreCompTypes.xml
│ ├── NeuroMLCoreDimensions.xml
│ ├── PyNN.xml
│ ├── Simulation.xml
│ └── Synapses.xml
│ ├── hhcell_resaved2.xml
│ ├── reg_test_20.py
│ ├── test_exposure_listing.xml
│ ├── test_load_write.py
│ ├── test_misc.py
│ ├── test_parser.py
│ └── test_units.py
├── man
└── man1
│ ├── README.md
│ └── pylems.1
├── pyproject.toml
└── setup.cfg
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on:
4 | push:
5 | branches: [ master, development, experimental, test* ]
6 | pull_request:
7 | branches: [ master, development, experimental, test* ]
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: ${{ matrix.runs-on }}
13 | strategy:
14 | fail-fast: false
15 | matrix:
16 | python-version: ["3.9", "3.10", "3.11", "3.12"]
17 | runs-on: [ubuntu-latest, windows-latest, macos-latest]
18 |
19 | steps:
20 | - uses: actions/checkout@v4
21 |
22 | - name: Set up Python ${{ matrix.python-version }}
23 | uses: actions/setup-python@v5
24 | with:
25 | python-version: ${{ matrix.python-version }}
26 |
27 | - name: Install dependencies
28 | run: |
29 | python -m pip install --upgrade pip
30 | python -m pip install pytest pytest-cov
31 |
32 | - name: Checkout NeuroML2
33 | uses: actions/checkout@v4
34 | with:
35 | repository: NeuroML/NeuroML2
36 | ref: development
37 | path: NeuroML2
38 |
39 | - name: Build package
40 | run: |
41 | pip install .
42 |
43 | - name: Test with pytest
44 | run: |
45 | pytest --cov=lems
46 |
47 | - name: Test examples
48 | run: |
49 | ./ci/run-examples-ghactions.sh
50 |
51 | - name: Test API tests
52 | run: |
53 | ./ci/run-apitest.sh
54 |
55 | - name: Final version info
56 | run: |
57 | pip list
58 |
59 | - name: Lint with flake8
60 | run: |
61 | # Install flake
62 | python -m pip install flake8
63 | # stop the build if there are Python syntax errors or undefined names
64 | flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
65 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
66 | flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
67 |
--------------------------------------------------------------------------------
/.github/workflows/examples.yml:
--------------------------------------------------------------------------------
1 | # Check that examples are same in pylems and in jlems
2 | name: Check LEMS examples
3 |
4 | on:
5 | push:
6 | branches: [ master, development, experimental ]
7 |
8 | jobs:
9 | verify:
10 |
11 | runs-on: ubuntu-latest
12 |
13 | steps:
14 | - uses: actions/checkout@v4
15 | - uses: nelonoel/branch-name@v1.0.1
16 |
17 | # https://stackoverflow.com/questions/58033366/how-to-get-current-branch-within-github-actions
18 | - name: Extract branch name
19 | shell: bash
20 | run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
21 | id: extract_branch
22 |
23 | - name: Checkout jlems
24 | uses: actions/checkout@v4
25 | with:
26 | repository: LEMS/jLEMS
27 | ref: ${{ steps.extract_branch.outputs.branch }}
28 | path: jlems
29 |
30 | - name: check examples
31 | run: |
32 | for ex in "example1.xml" "example2.xml" "example3.xml" "example4.xml" "example5.xml" "example6.xml" "example7.xml" "example8.xml" "bounce-conditional.xml" ; do
33 |
34 | if ! diff -ur "examples/$ex" "jlems/src/test/resources/$ex" ; then
35 | echo "Example file $ex is not identical"
36 | exit -1
37 | fi
38 | done
39 |
--------------------------------------------------------------------------------
/.github/workflows/python-publish.yml:
--------------------------------------------------------------------------------
1 | # This workflow will upload a Python Package using Twine when a release is created
2 | # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
3 |
4 | # This workflow uses actions that are not certified by GitHub.
5 | # They are provided by a third-party and are governed by
6 | # separate terms of service, privacy policy, and support
7 | # documentation.
8 |
9 | name: Upload Python Package
10 |
11 | on:
12 | release:
13 | types: [published]
14 |
15 | jobs:
16 | deploy:
17 |
18 | runs-on: ubuntu-latest
19 |
20 | steps:
21 | - uses: actions/checkout@v4
22 | - name: Set up Python
23 | uses: actions/setup-python@v5
24 | with:
25 | python-version: '3.x'
26 | - name: Install dependencies
27 | run: |
28 | python -m pip install --upgrade pip
29 | pip install build
30 | - name: Build package
31 | run: python -m build
32 | - name: Publish package
33 | uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
34 | with:
35 | user: __token__
36 | password: ${{ secrets.PYPI_API_TOKEN }}
37 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.tar.gz
2 | /MANIFEST
3 | *.dat
4 | results
5 | test*.sh
6 | build
7 | *~
8 | doc/_build
9 | *.pyc
10 | *.pyo
11 | .project
12 | .ropeproject
13 | .pydevproject
14 | comp_*
15 | /lems/test/hhcell_resaved3.xml
16 | /lems/__init__$py.class
17 | *PyLEMS.egg-info
18 | /dist
19 | *ken.sh
20 | *.whl
21 |
--------------------------------------------------------------------------------
/.readthedocs.yaml:
--------------------------------------------------------------------------------
1 | version: 2
2 |
3 | build:
4 | os: ubuntu-22.04
5 | tools:
6 | python: "3.11"
7 |
8 |
9 | sphinx:
10 | configuration: doc/conf.py
11 |
12 | python:
13 | install:
14 | - method: pip
15 | path: .
16 | extra_requirements:
17 | - doc
18 |
19 |
--------------------------------------------------------------------------------
/LICENSE.lesser:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
167 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include README.md
2 | include examples/*.xml
3 | include examples/*.py
4 | include LICENSE.lesser
5 | recursive-include man *.1
6 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | all: lems-code lems-doc
2 |
3 | JLEMSPATH = ../jLEMS
4 | JLEMSBIN = lems
5 | TIME = /usr/bin/time -f '%E s'
6 | BENCHFILE = ../NeuroML2/NeuroML2CoreTypes/LEMS_NML2_Ex2_Izh.xml
7 |
8 | lems-code:
9 |
10 | lems-doc:
11 | mkdir -p doc/epydoc
12 | epydoc -v -o doc/epydoc lems
13 |
14 | clean:
15 | find . -name "*.pyc" | xargs rm -f
16 | find . -name "*.pyo" | xargs rm -f
17 | find . -name "__pycache__" | xargs rm -rf
18 | rm -rf doc/epydoc/*
19 |
20 | example1:
21 | pylems examples/example1.xml
22 |
23 | example2:
24 | pylems examples/example2.xml
25 |
26 | example3:
27 | pylems examples/example3.xml
28 |
29 | example4:
30 | pylems examples/example4.xml
31 |
32 | example5:
33 | pylems examples/example5.xml
34 |
35 | example6:
36 | pylems examples/example6.xml
37 |
38 | example7:
39 | pylems examples/example7.xml
40 |
41 | example8:
42 | pylems examples/example8.xml
43 |
44 | example9:
45 | pylems examples/example9.xml
46 |
47 | ex0:
48 | pylems examples/LEMS_NML2_Ex0.xml
49 |
50 | nmlex0:
51 | pylems ../NeuroML2/NeuroML2CoreTypes/LEMS_NML2_Ex0_IaF.xml
52 |
53 | nmlex1:
54 | pylems ../NeuroML2/NeuroML2CoreTypes/LEMS_NML2_Ex1_HH.xml
55 |
56 | nmlex2:
57 | pylems ../NeuroML2/NeuroML2CoreTypes/LEMS_NML2_Ex2_Izh.xml
58 |
59 | nmlex3:
60 | pylems ../NeuroML2/NeuroML2CoreTypes/LEMS_NML2_Ex3_Net.xml
61 |
62 | run: example1
63 |
64 | bench:
65 | @echo "Java"
66 | env LEMS_HOME=${JLEMSPATH} ${TIME} ${JLEMSPATH}/${JLEMSBIN} ${BENCHFILE} -nogui 2>&1 > /dev/null
67 |
68 | @echo "CPython 2 (no optimizations)"
69 | @${TIME} python pylems -nogui ${BENCHFILE} > /dev/null
70 |
71 | @echo "CPython 2 (with optimizations)"
72 | @${TIME} python -O pylems -nogui ${BENCHFILE} > /dev/null
73 |
74 | @echo "PyPy"
75 | @${TIME} pypy pylems -nogui ${BENCHFILE} > /dev/null
76 |
77 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## PyLEMS
2 |
3 | [](https://github.com/LEMS/pylems/actions/workflows/ci.yml)
4 | [](https://github.com/LEMS/pylems/actions/workflows/examples.yml)
5 | [](https://pylems.readthedocs.io/en/latest/?badge=latest)
6 | [](https://pypi.org/project/pylems/)
7 |
8 | A [LEMS](http://lems.github.io/LEMS) simulator written in Python which can be used to run NeuroML2 models (see [here](https://docs.neuroml.org/Userdocs/Software/pyLEMS.html)).
9 |
10 | For more about PyLEMS see:
11 |
12 | Michael Vella, Robert C. Cannon, Sharon Crook, Andrew P. Davison, Gautham Ganapathy, Hugh P. C. Robinson, R. Angus Silver and Padraig Gleeson,
13 | **libNeuroML and PyLEMS: using Python to combine procedural and declarative modeling approaches in computational neuroscience**
14 | [Frontiers in Neuroinformatics 2014](http://journal.frontiersin.org/Journal/10.3389/fninf.2014.00038/abstract), doi: 10.3389/fninf.2014.00038
15 |
16 | _**PLEASE CITE THE PAPER ABOVE IF YOU USE PYLEMS!**_
17 |
18 | For more details on LEMS see:
19 |
20 | Robert C. Cannon, Padraig Gleeson, Sharon Crook, Gautham Ganapathy, Boris Marin, Eugenio Piasini and R. Angus Silver,
21 | **LEMS: A language for expressing complex biological models in concise and hierarchical form and its use in underpinning NeuroML 2**,
22 | [Frontiers in Neuroinformatics 2014](http://journal.frontiersin.org/Journal/10.3389/fninf.2014.00079/abstract), doi: 10.3389/fninf.2014.00079
23 |
24 | ### Installation
25 |
26 | A stable version of PyLEMS is [available on PyPI](https://pypi.python.org/pypi/PyLEMS) using [pip](https://pip.pypa.io/en/latest/installing.html):
27 |
28 | ```
29 | pip install pylems
30 | ```
31 |
32 | Alternatively, you can obtain the latest version with
33 |
34 | ```
35 | git clone https://github.com/LEMS/pylems.git
36 | cd pylems
37 | git checkout development # optional
38 | pip install .
39 | ```
40 |
41 | ### Usage as a LEMS model simulator
42 |
43 | ```
44 | pylems [options] LEMS_file
45 | ```
46 |
47 | **Options**
48 |
49 | - -I/-include path - Adds a directory to the model file include search path
50 |
51 | ### Examples
52 |
53 | **NeuroML examples (from https://github.com/NeuroML/NeuroML2/tree/development/NeuroML2CoreTypes)**
54 |
55 | - Example 0 -- Working
56 | - Example 1 -- Working
57 | - Example 2 -- Working
58 | - Example 3 -- Working
59 | - Example 4 -- Not working (Unsupported in PyLEMS: KSChannel)
60 | - Example 5 -- Working
61 | - Example 6 -- Working
62 | - Example 7 -- Working
63 | - Example 8 -- Working
64 | - Example 9 -- Working
65 | - Example 10 -- Working
66 | - Example 11 -- Working
67 | - Example 12 -- Not working (Unsupported in PyLEMS: Property)
68 | - Example 13 -- Working
69 | - Example 14 -- Not working (Unsupported in PyLEMS: Property)
70 | - Example 15 -- Working
71 | - Example 16 -- Working (apart from spikeArray)
72 | - Example 17 -- Working
73 | - Example 18 -- Working
74 |
75 | **LEMS examples (in directory examples)**
76 |
77 | - example1.xml -- Working
78 | - example2.xml -- Working
79 | - example3.xml -- Working
80 | - example4.xml -- Not working (Unsupported in PyLEMS: KSChannel)
81 | - example5.xml -- Not working (Unsupported in PyLEMS: KSChannel)
82 | - example6.xml -- Working
83 |
84 | TODO: Rest of examples require an update to the `` element, i.e. use `` not ``, to work in PyLEMS
85 |
86 | **LEMS elements that do not work**
87 |
88 | - KSChannel
89 | - Property
90 | - XPath based parameters - PathParameter
91 | - Assertions
92 |
93 | **Tasks TODO**
94 |
95 | - Implement flattening
96 | - Decouple events from runnables
97 | - Improve dimension-checking on expressions.
98 |
99 | This code is distributed under the terms of the GNU Lesser General Public License.
100 |
101 |
102 |
--------------------------------------------------------------------------------
/ci/run-apitest.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2023 LEMS contributors
4 | # Author: Ankur Sinha
5 | # File : run-apitest.sh
6 | #
7 | # Run api tests on GitHub actions
8 |
9 | python examples/apitest.py
10 | python examples/apitest2.py
11 | python examples/loadtest.py
12 |
13 | # Update NeuroML2 path for CI
14 | if [ "$CI" = "true" ]; then
15 | if [ "$RUNNER_OS" = "macOS" ]; then
16 | sed -i '' 's|../NeuroML2|./NeuroML2|g' lems/dlems/exportdlems.py;
17 | else
18 | sed -i 's|../NeuroML2|./NeuroML2|g' lems/dlems/exportdlems.py;
19 | fi
20 | fi
21 | python lems/dlems/exportdlems.py
--------------------------------------------------------------------------------
/ci/run-examples-ghactions.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2023 LEMS contributors
4 | # Author: Ankur Sinha
5 | # File : run-examples-ghactions.sh
6 | #
7 | # Run tests on GitHub actions
8 |
9 | mkdir results
10 |
11 | ### Try running "standard" LEMS examples
12 | echo "Running standard LEMS examples"
13 | pylems examples/example1.xml -nogui
14 | pylems examples/example2.xml -nogui
15 | pylems examples/example3.xml -nogui
16 | #pylems examples/example4.xml -nogui # Not working (Unsupported in PyLEMS: KSChannel)
17 | #pylems examples/example5.xml -nogui # Not working (Unsupported in PyLEMS: KSChannel)
18 | pylems examples/example6.xml -nogui
19 | pylems examples/bounce-conditional.xml -nogui
20 | # Rest of examples require an update to the element, i.e. use not , to work in PyLEMS
21 |
22 | ### Try running NeuroML 2 examples
23 | echo "Running NeuroML2 examples"
24 | pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex0_IaF.xml -nogui
25 | pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex1_HH.xml -nogui
26 | pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex2_Izh.xml -nogui
27 | pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex3_Net.xml -nogui
28 | #pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex4_KS.xml -nogui # Not working (Unsupported in PyLEMS: KSChannel)
29 | pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex5_DetCell.xml -nogui
30 | pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex6_NMDA.xml -nogui
31 | pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex7_STP.xml -nogui
32 | pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex8_AdEx.xml -nogui
33 | pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex9_FN.xml -nogui
34 | #pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex10_Q10.xml -nogui
35 | pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex11_STDP.xml -nogui
36 |
37 | pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex13_Instances.xml -nogui
38 |
39 | #pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex15_CaDynamics.xml -nogui
40 |
41 | #pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex17_Tissue.xml -nogui
42 | #pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex18_GHK.xml -nogui # Mismatch...
43 |
--------------------------------------------------------------------------------
/doc/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | PAPER =
8 | BUILDDIR = _build
9 |
10 | # Internal variables.
11 | PAPEROPT_a4 = -D latex_paper_size=a4
12 | PAPEROPT_letter = -D latex_paper_size=letter
13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
14 | # the i18n builder cannot share the environment and doctrees with the others
15 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
16 |
17 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
18 |
19 | help:
20 | @echo "Please use \`make ' where is one of"
21 | @echo " html to make standalone HTML files"
22 | @echo " dirhtml to make HTML files named index.html in directories"
23 | @echo " singlehtml to make a single large HTML file"
24 | @echo " pickle to make pickle files"
25 | @echo " json to make JSON files"
26 | @echo " htmlhelp to make HTML files and a HTML help project"
27 | @echo " qthelp to make HTML files and a qthelp project"
28 | @echo " devhelp to make HTML files and a Devhelp project"
29 | @echo " epub to make an epub"
30 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
31 | @echo " latexpdf to make LaTeX files and run them through pdflatex"
32 | @echo " text to make text files"
33 | @echo " man to make manual pages"
34 | @echo " texinfo to make Texinfo files"
35 | @echo " info to make Texinfo files and run them through makeinfo"
36 | @echo " gettext to make PO message catalogs"
37 | @echo " changes to make an overview of all changed/added/deprecated items"
38 | @echo " linkcheck to check all external links for integrity"
39 | @echo " doctest to run all doctests embedded in the documentation (if enabled)"
40 |
41 | clean:
42 | -rm -rf $(BUILDDIR)/*
43 |
44 | html:
45 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
46 | @echo
47 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
48 |
49 | dirhtml:
50 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
51 | @echo
52 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
53 |
54 | singlehtml:
55 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
56 | @echo
57 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
58 |
59 | pickle:
60 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
61 | @echo
62 | @echo "Build finished; now you can process the pickle files."
63 |
64 | json:
65 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
66 | @echo
67 | @echo "Build finished; now you can process the JSON files."
68 |
69 | htmlhelp:
70 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
71 | @echo
72 | @echo "Build finished; now you can run HTML Help Workshop with the" \
73 | ".hhp project file in $(BUILDDIR)/htmlhelp."
74 |
75 | qthelp:
76 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
77 | @echo
78 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \
79 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
80 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/PyLEMS.qhcp"
81 | @echo "To view the help file:"
82 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PyLEMS.qhc"
83 |
84 | devhelp:
85 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
86 | @echo
87 | @echo "Build finished."
88 | @echo "To view the help file:"
89 | @echo "# mkdir -p $$HOME/.local/share/devhelp/PyLEMS"
90 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/PyLEMS"
91 | @echo "# devhelp"
92 |
93 | epub:
94 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
95 | @echo
96 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
97 |
98 | latex:
99 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
100 | @echo
101 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
102 | @echo "Run \`make' in that directory to run these through (pdf)latex" \
103 | "(use \`make latexpdf' here to do that automatically)."
104 |
105 | latexpdf:
106 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
107 | @echo "Running LaTeX files through pdflatex..."
108 | $(MAKE) -C $(BUILDDIR)/latex all-pdf
109 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
110 |
111 | text:
112 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
113 | @echo
114 | @echo "Build finished. The text files are in $(BUILDDIR)/text."
115 |
116 | man:
117 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
118 | @echo
119 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
120 |
121 | texinfo:
122 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
123 | @echo
124 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
125 | @echo "Run \`make' in that directory to run these through makeinfo" \
126 | "(use \`make info' here to do that automatically)."
127 |
128 | info:
129 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
130 | @echo "Running Texinfo files through makeinfo..."
131 | make -C $(BUILDDIR)/texinfo info
132 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
133 |
134 | gettext:
135 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
136 | @echo
137 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
138 |
139 | changes:
140 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
141 | @echo
142 | @echo "The overview file is in $(BUILDDIR)/changes."
143 |
144 | linkcheck:
145 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
146 | @echo
147 | @echo "Link check complete; look for any errors in the above output " \
148 | "or in $(BUILDDIR)/linkcheck/output.txt."
149 |
150 | doctest:
151 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
152 | @echo "Testing of doctests in the sources finished, look at the " \
153 | "results in $(BUILDDIR)/doctest/output.txt."
154 |
--------------------------------------------------------------------------------
/doc/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # PyLEMS documentation build configuration file, created by
4 | # sphinx-quickstart on Wed Mar 21 08:17:12 2012.
5 | #
6 | # This file is execfile()d with the current directory set to its containing dir.
7 | #
8 | # Note that not all possible configuration values are present in this
9 | # autogenerated file.
10 | #
11 | # All configuration values have a default; values that are commented out
12 | # serve to show the default.
13 |
14 | import sys
15 | import os
16 |
17 | # If extensions (or modules to document with autodoc) are in another directory,
18 | # add these directories to sys.path here. If the directory is relative to the
19 | # documentation root, use os.path.abspath to make it absolute, like shown here.
20 | # sys.path.insert(0, os.path.abspath('.'))
21 |
22 | sys.path.insert(0, os.path.abspath("../lems"))
23 | sys.path.insert(0, os.path.abspath(".."))
24 |
25 | # -- General configuration -----------------------------------------------------
26 |
27 | # If your documentation needs a minimal Sphinx version, state it here.
28 | # needs_sphinx = '1.0'
29 |
30 | # Add any Sphinx extension module names here, as strings. They can be extensions
31 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
32 | extensions = [
33 | "sphinx.ext.autodoc",
34 | "sphinx.ext.doctest",
35 | "sphinx.ext.todo",
36 | "sphinxcontrib.bibtex",
37 | ]
38 |
39 | bibtex_bibfiles = ["refs.bib"]
40 |
41 | # Include TODOs in docs
42 | todo_include_todos = True
43 |
44 | # Add any paths that contain templates here, relative to this directory.
45 | templates_path = ["_templates"]
46 |
47 | # The suffix of source filenames.
48 | source_suffix = ".rst"
49 |
50 | # The encoding of source files.
51 | # source_encoding = 'utf-8-sig'
52 |
53 | # The master toctree document.
54 | master_doc = "index"
55 |
56 | # General information about the project.
57 | project = "PyLEMS"
58 | copyright = "2023, LEMS authors and contributors"
59 |
60 | # The version info for the project you're documenting, acts as replacement for
61 | # |version| and |release|, also used in various other places throughout the
62 | # built documents.
63 | #
64 | # The short X.Y version.
65 | version = ""
66 | for aline in open("../lems/__init__.py"):
67 | # space here is important since __version__ is used in generation of
68 | # version_info also
69 | if "__version__ =" in aline:
70 | version = aline.split('"')[1]
71 | # The full version, including alpha/beta/rc tags.
72 | release = version
73 |
74 | # The language for content autogenerated by Sphinx. Refer to documentation
75 | # for a list of supported languages.
76 | # language = None
77 |
78 | # There are two options for replacing |today|: either, you set today to some
79 | # non-false value, then it is used:
80 | # today = ''
81 | # Else, today_fmt is used as the format for a strftime call.
82 | # today_fmt = '%B %d, %Y'
83 |
84 | # List of patterns, relative to source directory, that match files and
85 | # directories to ignore when looking for source files.
86 | exclude_patterns = ["_build"]
87 |
88 | # The reST default role (used for this markup: `text`) to use for all documents.
89 | # default_role = None
90 |
91 | # If true, '()' will be appended to :func: etc. cross-reference text.
92 | # add_function_parentheses = True
93 |
94 | # If true, the current module name will be prepended to all description
95 | # unit titles (such as .. function::).
96 | # add_module_names = True
97 |
98 | # If true, sectionauthor and moduleauthor directives will be shown in the
99 | # output. They are ignored by default.
100 | # show_authors = False
101 |
102 | # The name of the Pygments (syntax highlighting) style to use.
103 | pygments_style = "sphinx"
104 |
105 | # A list of ignored prefixes for module index sorting.
106 | # modindex_common_prefix = []
107 |
108 |
109 | # -- Options for HTML output ---------------------------------------------------
110 |
111 | # The theme to use for HTML and HTML Help pages. See the documentation for
112 | # a list of builtin themes.
113 | html_theme = "nature"
114 |
115 | # Theme options are theme-specific and customize the look and feel of a theme
116 | # further. For a list of options available for each theme, see the
117 | # documentation.
118 | # html_theme_options = {}
119 |
120 | # Add any paths that contain custom themes here, relative to this directory.
121 | # html_theme_path = []
122 |
123 | # The name for this set of Sphinx documents. If None, it defaults to
124 | # " v documentation".
125 | # html_title = None
126 |
127 | # A shorter title for the navigation bar. Default is the same as html_title.
128 | # html_short_title = None
129 |
130 | # The name of an image file (relative to this directory) to place at the top
131 | # of the sidebar.
132 | html_logo = ""
133 |
134 | # The name of an image file (within the static path) to use as favicon of the
135 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
136 | # pixels large.
137 | # html_favicon = None
138 |
139 | # Add any paths that contain custom static files (such as style sheets) here,
140 | # relative to this directory. They are copied after the builtin static files,
141 | # so a file named "default.css" will overwrite the builtin "default.css".
142 | html_static_path = ["_static"]
143 |
144 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
145 | # using the given strftime format.
146 | # html_last_updated_fmt = '%b %d, %Y'
147 |
148 | # If true, SmartyPants will be used to convert quotes and dashes to
149 | # typographically correct entities.
150 | # html_use_smartypants = True
151 |
152 | # Custom sidebar templates, maps document names to template names.
153 | # html_sidebars = {}
154 |
155 | # Additional templates that should be rendered to pages, maps page names to
156 | # template names.
157 | # html_additional_pages = {}
158 |
159 | # If false, no module index is generated.
160 | # html_domain_indices = True
161 |
162 | # If false, no index is generated.
163 | # html_use_index = True
164 |
165 | # If true, the index is split into individual pages for each letter.
166 | # html_split_index = False
167 |
168 | # If true, links to the reST sources are added to the pages.
169 | # html_show_sourcelink = True
170 |
171 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
172 | # html_show_sphinx = True
173 |
174 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
175 | # html_show_copyright = True
176 |
177 | # If true, an OpenSearch description file will be output, and all pages will
178 | # contain a tag referring to it. The value of this option must be the
179 | # base URL from which the finished HTML is served.
180 | # html_use_opensearch = ''
181 |
182 | # This is the file name suffix for HTML files (e.g. ".xhtml").
183 | # html_file_suffix = None
184 |
185 | # Output file base name for HTML help builder.
186 | htmlhelp_basename = "pylemsdoc"
187 |
188 |
189 | # -- Options for LaTeX output --------------------------------------------------
190 |
191 | # The paper size ('letterpaper' or 'a4paper').
192 | #'papersize': 'letterpaper',
193 |
194 | # The font size ('10pt', '11pt' or '12pt').
195 | #'pointsize': '10pt',
196 |
197 | # Additional stuff for the LaTeX preamble.
198 | #'preamble': '',
199 | latex_elements = {}
200 |
201 | # Grouping the document tree into LaTeX files. List of tuples
202 | # (source start file, target name, title, author, documentclass [howto/manual]).
203 | latex_documents = [
204 | (
205 | "index",
206 | "pylems.tex",
207 | "PyLEMS Documentation",
208 | "LEMS authors and contributors",
209 | "manual",
210 | ),
211 | ]
212 |
213 | # The name of an image file (relative to this directory) to place at the top of
214 | # the title page.
215 | # latex_logo = None
216 |
217 | # For "manual" documents, if this is true, then toplevel headings are parts,
218 | # not chapters.
219 | # latex_use_parts = False
220 |
221 | # If true, show page references after internal links.
222 | # latex_show_pagerefs = False
223 |
224 | # If true, show URL addresses after external links.
225 | # latex_show_urls = False
226 |
227 | # Documents to append as an appendix to all manuals.
228 | # latex_appendices = []
229 |
230 | # If false, no module index is generated.
231 | # latex_domain_indices = True
232 |
233 |
234 | # -- Options for manual page output --------------------------------------------
235 |
236 | # One entry per manual page. List of tuples
237 | # (source start file, name, description, authors, manual section).
238 | man_pages = [
239 | ("index", "PyLEMS", "PyLEMS Documentation", ["LEMS authors and contributors"], 1)
240 | ]
241 |
242 | # If true, show URL addresses after external links.
243 | # man_show_urls = False
244 |
245 |
246 | # -- Options for Texinfo output ------------------------------------------------
247 |
248 | # Grouping the document tree into Texinfo files. List of tuples
249 | # (source start file, target name, title, author,
250 | # dir menu entry, description, category)
251 | texinfo_documents = [
252 | (
253 | "index",
254 | "PyLEMS",
255 | "PyLEMS Documentation",
256 | "LEMS authors and contributors",
257 | "PyLEMS",
258 | "This package provides PyLEMS for working with LEMS.",
259 | "Miscellaneous",
260 | ),
261 | ]
262 |
263 | # Documents to append as an appendix to all manuals.
264 | # texinfo_appendices = []
265 |
266 | # If false, no module index is generated.
267 | # texinfo_domain_indices = True
268 |
269 | # How to display URL addresses: 'footnote', 'no', or 'inline'.
270 | # texinfo_show_urls = 'footnote'
271 |
--------------------------------------------------------------------------------
/doc/index.rst:
--------------------------------------------------------------------------------
1 | PyLEMS: documentation
2 | ==========================
3 |
4 | Welcome to the PyLEMS API documentation.
5 | For more information on LEMS, please see: http://lems.github.io/LEMS/
6 |
7 | User documentation
8 | ************************
9 |
10 | .. toctree::
11 | :maxdepth: 3
12 |
13 | modules
14 |
15 |
--------------------------------------------------------------------------------
/doc/lems.base.rst:
--------------------------------------------------------------------------------
1 | lems.base package
2 | =================
3 |
4 | Submodules
5 | ----------
6 |
7 | lems.base.base module
8 | ---------------------
9 |
10 | .. automodule:: lems.base.base
11 | :members:
12 | :undoc-members:
13 | :show-inheritance:
14 |
15 | lems.base.errors module
16 | -----------------------
17 |
18 | .. automodule:: lems.base.errors
19 | :members:
20 | :undoc-members:
21 | :show-inheritance:
22 |
23 | lems.base.map module
24 | --------------------
25 |
26 | .. automodule:: lems.base.map
27 | :members:
28 | :undoc-members:
29 | :show-inheritance:
30 |
31 | lems.base.stack module
32 | ----------------------
33 |
34 | .. automodule:: lems.base.stack
35 | :members:
36 | :undoc-members:
37 | :show-inheritance:
38 |
39 | lems.base.util module
40 | ---------------------
41 |
42 | .. automodule:: lems.base.util
43 | :members:
44 | :undoc-members:
45 | :show-inheritance:
46 |
47 | Module contents
48 | ---------------
49 |
50 | .. automodule:: lems.base
51 | :members:
52 | :undoc-members:
53 | :show-inheritance:
54 |
--------------------------------------------------------------------------------
/doc/lems.dlems.rst:
--------------------------------------------------------------------------------
1 | lems.dlems package
2 | ==================
3 |
4 | Submodules
5 | ----------
6 |
7 | lems.dlems.exportdlems module
8 | -----------------------------
9 |
10 | .. automodule:: lems.dlems.exportdlems
11 | :members:
12 | :undoc-members:
13 | :show-inheritance:
14 |
15 | Module contents
16 | ---------------
17 |
18 | .. automodule:: lems.dlems
19 | :members:
20 | :undoc-members:
21 | :show-inheritance:
22 |
--------------------------------------------------------------------------------
/doc/lems.model.rst:
--------------------------------------------------------------------------------
1 | lems.model package
2 | ==================
3 |
4 | Submodules
5 | ----------
6 |
7 | lems.model.component module
8 | ---------------------------
9 |
10 | .. automodule:: lems.model.component
11 | :members:
12 | :undoc-members:
13 | :show-inheritance:
14 |
15 | lems.model.dynamics module
16 | --------------------------
17 |
18 | .. automodule:: lems.model.dynamics
19 | :members:
20 | :undoc-members:
21 | :show-inheritance:
22 |
23 | lems.model.fundamental module
24 | -----------------------------
25 |
26 | .. automodule:: lems.model.fundamental
27 | :members:
28 | :undoc-members:
29 | :show-inheritance:
30 |
31 | lems.model.model module
32 | -----------------------
33 |
34 | .. automodule:: lems.model.model
35 | :members:
36 | :undoc-members:
37 | :show-inheritance:
38 |
39 | lems.model.simulation module
40 | ----------------------------
41 |
42 | .. automodule:: lems.model.simulation
43 | :members:
44 | :undoc-members:
45 | :show-inheritance:
46 |
47 | lems.model.structure module
48 | ---------------------------
49 |
50 | .. automodule:: lems.model.structure
51 | :members:
52 | :undoc-members:
53 | :show-inheritance:
54 |
55 | Module contents
56 | ---------------
57 |
58 | .. automodule:: lems.model
59 | :members:
60 | :undoc-members:
61 | :show-inheritance:
62 |
--------------------------------------------------------------------------------
/doc/lems.parser.rst:
--------------------------------------------------------------------------------
1 | lems.parser package
2 | ===================
3 |
4 | Submodules
5 | ----------
6 |
7 | lems.parser.LEMS module
8 | -----------------------
9 |
10 | .. automodule:: lems.parser.LEMS
11 | :members:
12 | :undoc-members:
13 | :show-inheritance:
14 |
15 | lems.parser.expr module
16 | -----------------------
17 |
18 | .. automodule:: lems.parser.expr
19 | :members:
20 | :undoc-members:
21 | :show-inheritance:
22 |
23 | Module contents
24 | ---------------
25 |
26 | .. automodule:: lems.parser
27 | :members:
28 | :undoc-members:
29 | :show-inheritance:
30 |
--------------------------------------------------------------------------------
/doc/lems.rst:
--------------------------------------------------------------------------------
1 | lems package
2 | ============
3 |
4 | Subpackages
5 | -----------
6 |
7 | .. toctree::
8 | :maxdepth: 4
9 |
10 | lems.base
11 | lems.dlems
12 | lems.model
13 | lems.parser
14 | lems.sim
15 |
16 | Submodules
17 | ----------
18 |
19 | lems.api module
20 | ---------------
21 |
22 | .. automodule:: lems.api
23 | :members:
24 | :undoc-members:
25 | :show-inheritance:
26 |
27 | lems.run module
28 | ---------------
29 |
30 | .. automodule:: lems.run
31 | :members:
32 | :undoc-members:
33 | :show-inheritance:
34 |
35 | Module contents
36 | ---------------
37 |
38 | .. automodule:: lems
39 | :members:
40 | :undoc-members:
41 | :show-inheritance:
42 |
--------------------------------------------------------------------------------
/doc/lems.sim.rst:
--------------------------------------------------------------------------------
1 | lems.sim package
2 | ================
3 |
4 | Submodules
5 | ----------
6 |
7 | lems.sim.build module
8 | ---------------------
9 |
10 | .. automodule:: lems.sim.build
11 | :members:
12 | :undoc-members:
13 | :show-inheritance:
14 |
15 | lems.sim.recording module
16 | -------------------------
17 |
18 | .. automodule:: lems.sim.recording
19 | :members:
20 | :undoc-members:
21 | :show-inheritance:
22 |
23 | lems.sim.runnable module
24 | ------------------------
25 |
26 | .. automodule:: lems.sim.runnable
27 | :members:
28 | :undoc-members:
29 | :show-inheritance:
30 |
31 | lems.sim.sim module
32 | -------------------
33 |
34 | .. automodule:: lems.sim.sim
35 | :members:
36 | :undoc-members:
37 | :show-inheritance:
38 |
39 | Module contents
40 | ---------------
41 |
42 | .. automodule:: lems.sim
43 | :members:
44 | :undoc-members:
45 | :show-inheritance:
46 |
--------------------------------------------------------------------------------
/doc/migrate_docstrings.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # Script for migrating from epydoc to Sphinx style docstrings.
4 | #
5 | # WARNING: THIS SCRIPT MODIFIES FILES IN PLACE. BE SURE TO BACKUP THEM BEFORE
6 | # RUNNING IT.
7 |
8 | DIRECTORY=$1
9 |
10 | SED=`which gsed gnused sed`
11 |
12 | for value in $SED
13 | do
14 | SED=${value}
15 | break
16 | done
17 |
18 | if [ ! $DIRECTORY ]; then
19 | echo "Usage: ./migrate_docstrings.sh "
20 | exit 1
21 | fi
22 |
23 | OLD_VALUES[0]='@type'
24 | OLD_VALUES[1]='@keyword'
25 | OLD_VALUES[2]='@param'
26 | OLD_VALUES[3]='@return'
27 | OLD_VALUES[4]='@rtype'
28 | OLD_VALUES[5]='L{\([^}]\+\)}'
29 | OLD_VALUES[6]='C{\(int\|float\|str\|list\|tuple\|dict\|bool\|None\|generator\|object\)}'
30 | OLD_VALUES[7]='@\(ivar\|cvar\|var\)'
31 | OLD_VALUES[8]='@raise'
32 | OLD_VALUES[9]='@author'
33 | OLD_VALUES[10]='@organization'
34 | OLD_VALUES[11]='@contact'
35 |
36 | NEW_VALUES[0]=':type'
37 | NEW_VALUES[1]=':keyword'
38 | NEW_VALUES[2]=':param'
39 | NEW_VALUES[3]=':return'
40 | NEW_VALUES[4]=':rtype'
41 | NEW_VALUES[5]=':class:`\1`'
42 | NEW_VALUES[6]='``\1``'
43 | NEW_VALUES[7]=':\1'
44 | NEW_VALUES[8]=':raises'
45 | NEW_VALUES[9]=':codeauthor'
46 | NEW_VALUES[10]=':organization'
47 | NEW_VALUES[11]=':contact'
48 |
49 | for (( i = 0 ; i < ${#OLD_VALUES[@]} ; i++ ))
50 | do
51 | old_value=${OLD_VALUES[$i]}
52 | new_value=${NEW_VALUES[$i]}
53 |
54 | cmd="find ${DIRECTORY} -name '*.py' -type f -print0 | xargs -0 ${SED} -i -e 's/${old_value}/${new_value}/g'"
55 |
56 | echo "Migrating: ${old_value} -> ${new_value}"
57 | eval "$cmd"
58 | done
59 |
--------------------------------------------------------------------------------
/doc/modules.rst:
--------------------------------------------------------------------------------
1 | lems
2 | ====
3 |
4 | .. toctree::
5 | :maxdepth: 4
6 |
7 | lems
8 |
--------------------------------------------------------------------------------
/examples/MultiRunSimulation.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/examples/SimpleNetwork.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/examples/SimpleTest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/examples/SingleSimulation.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/examples/apitest.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 |
3 | import lems.api as lems
4 |
5 | model = lems.Model()
6 |
7 | model.add(lems.Dimension("voltage", m=1, l=3, t=-3, i=-1))
8 | model.add(lems.Dimension("time", t=1))
9 | model.add(lems.Dimension("capacitance", m=-1, l=-2, t=4, i=2))
10 |
11 | model.add(lems.Unit("milliVolt", "mV", "voltage", -3))
12 | model.add(lems.Unit("milliSecond", "ms", "time", -3))
13 | model.add(lems.Unit("microFarad", "uF", "capacitance", -12))
14 |
15 | iaf1 = lems.ComponentType("iaf1")
16 | model.add(iaf1)
17 |
18 | iaf1.add(lems.Parameter("threshold", "voltage"))
19 | iaf1.add(lems.Parameter("refractoryPeriod", "time"))
20 | iaf1.add(lems.Parameter("capacitance", "capacitance"))
21 |
22 | model.add(lems.Component("celltype_a", "iaf1"))
23 |
24 | fn = "/tmp/model.xml"
25 | model.export_to_file(fn)
26 |
27 | print("----------------------------------------------")
28 | print(open(fn, "r").read())
29 | print("----------------------------------------------")
30 |
31 | print("Written generated LEMS to %s" % fn)
32 |
33 | from lems.base.util import validate_lems
34 |
35 | validate_lems(fn)
36 |
--------------------------------------------------------------------------------
/examples/apitest2.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 |
3 | import lems.api as lems
4 |
5 | model = lems.Model()
6 |
7 | model.add(lems.Dimension("voltage", m=1, l=3, t=-3, i=-1))
8 | model.add(lems.Dimension("time", t=1))
9 | model.add(lems.Dimension("capacitance", m=-1, l=-2, t=4, i=2))
10 |
11 | model.add(lems.Unit("milliVolt", "mV", "voltage", -3))
12 | model.add(lems.Unit("milliSecond", "ms", "time", -3))
13 | model.add(lems.Unit("microFarad", "uF", "capacitance", -12))
14 |
15 | iaf1 = lems.ComponentType("iaf1")
16 | model.add(iaf1)
17 |
18 | iaf1.add(lems.Parameter("threshold", "voltage"))
19 | iaf1.add(lems.Parameter("reset", "voltage"))
20 | iaf1.add(lems.Parameter("refractoryPeriod", "time"))
21 | iaf1.add(lems.Parameter("capacitance", "capacitance"))
22 | iaf1.add(lems.Exposure("vexp", "voltage"))
23 | dp = lems.DerivedParameter("range", "threshold - reset", "voltage")
24 | iaf1.add(dp)
25 |
26 | iaf1.dynamics.add(lems.StateVariable("v", "voltage", "vexp"))
27 | iaf1.dynamics.add(lems.DerivedVariable("v2", dimension="voltage", value="v*2"))
28 | cdv = lems.ConditionalDerivedVariable("v_abs", "voltage")
29 | cdv.add(lems.Case("v .geq. 0", "v"))
30 | cdv.add(lems.Case("v .lt. 0", "-1*v"))
31 | iaf1.dynamics.add(cdv)
32 |
33 |
34 | model.add(lems.Component("celltype_a", iaf1.name))
35 | model.add(lems.Component("celltype_b", iaf1.name, threshold="20mV"))
36 |
37 | fn = "/tmp/model.xml"
38 | model.export_to_file(fn)
39 |
40 | print("----------------------------------------------")
41 | print(open(fn, "r").read())
42 | print("----------------------------------------------")
43 |
44 | print("Written generated LEMS to %s" % fn)
45 |
46 | from lems.base.util import validate_lems
47 |
48 | validate_lems(fn)
49 |
--------------------------------------------------------------------------------
/examples/apitest3.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 |
3 | import lems.api as lems
4 |
5 | model = lems.Model()
6 |
7 | model.add(lems.Include("test.xml"))
8 |
9 | model.add(lems.Dimension("voltage", m=1, l=3, t=-3, i=-1))
10 | model.add(lems.Dimension("time", t=1))
11 | model.add(lems.Dimension("capacitance", m=-1, l=-2, t=4, i=2))
12 |
13 | model.add(lems.Unit("milliVolt", "mV", "voltage", -3))
14 | model.add(lems.Unit("milliSecond", "ms", "time", -3))
15 | model.add(lems.Unit("microFarad", "uF", "capacitance", -12))
16 |
17 | iaf1 = lems.ComponentType("iaf1")
18 | model.add(iaf1)
19 |
20 | iaf1.add(lems.Parameter("threshold", "voltage"))
21 | iaf1.add(lems.Parameter("reset", "voltage"))
22 | iaf1.add(lems.Parameter("refractoryPeriod", "time"))
23 | iaf1.add(lems.Parameter("capacitance", "capacitance"))
24 | iaf1.add(lems.Exposure("vexp", "voltage"))
25 | dp = lems.DerivedParameter("range", "threshold - reset", "voltage")
26 | iaf1.add(dp)
27 |
28 | iaf1.dynamics.add(lems.StateVariable("v", "voltage", "vexp"))
29 | iaf1.dynamics.add(lems.DerivedVariable("v2", dimension="voltage", value="v*2"))
30 | cdv = lems.ConditionalDerivedVariable("v_abs", "voltage")
31 | cdv.add(lems.Case("v .geq. 0", "v"))
32 | cdv.add(lems.Case("v .lt. 0", "-1*v"))
33 | iaf1.dynamics.add(cdv)
34 |
35 |
36 | model.add(lems.Component("celltype_a", iaf1.name))
37 | model.add(lems.Component("celltype_b", iaf1.name, threshold="20mV"))
38 |
39 | fn = "/tmp/model.xml"
40 | model.export_to_file(fn)
41 |
42 | print("----------------------------------------------")
43 | print(open(fn, "r").read())
44 | print("----------------------------------------------")
45 |
46 | print("Written generated LEMS to %s" % fn)
47 |
48 | from lems.base.util import validate_lems
49 |
50 | validate_lems(fn)
51 |
--------------------------------------------------------------------------------
/examples/bounce-conditional.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/examples/elecdims.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/examples/ex2dims.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/examples/example1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
--------------------------------------------------------------------------------
/examples/example10_Q10.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/examples/example2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/examples/example3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/examples/example4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
--------------------------------------------------------------------------------
/examples/example5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
--------------------------------------------------------------------------------
/examples/example6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/examples/example7.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/examples/example8.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/examples/example9.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
--------------------------------------------------------------------------------
/examples/hhaltgate.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/examples/hhcell.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/examples/hhchannel.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/examples/hhmodels.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/examples/loadtest.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 |
3 | from lems.model.model import Model
4 | import sys
5 |
6 | model = Model()
7 |
8 | file_name = "examples/hhcell.xml"
9 | # file_name = '../NeuroML2/NeuroML2CoreTypes/LEMS_NML2_Ex0_IaF.xml'
10 | # file_name = '../NeuroML2/NeuroML2CoreTypes/LEMS_NML2_Ex3_Net.xml'
11 | # file_name = '../org.neuroml.import/src/test/resources/BIOMD0000000185_LEMS.xml'
12 |
13 | if len(sys.argv) == 2:
14 | file_name = sys.argv[1]
15 |
16 | model.import_from_file(file_name)
17 |
18 | fn = "/tmp/hhmodel.xml"
19 | model.export_to_file(fn)
20 |
21 | print("----------------------------------------------")
22 | print(open(fn, "r").read())
23 | print("----------------------------------------------")
24 |
25 | print("Written generated LEMS to %s" % fn)
26 |
27 | from lems.base.util import validate_lems
28 |
29 | validate_lems(fn)
30 |
--------------------------------------------------------------------------------
/examples/misciaf.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/examples/spikegenerators.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/lems/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | :author: Gautham Ganapathy
3 | :organization: LEMS (https://github.com/organizations/LEMS)
4 | """
5 |
6 | import logging
7 |
8 | try:
9 | import importlib.metadata
10 |
11 | __version__ = importlib.metadata.version("PyLEMS")
12 | except ImportError:
13 | import importlib_metadata
14 |
15 | __version__ = importlib_metadata.version("PyLEMS")
16 |
17 | logger = logging.getLogger("LEMS")
18 |
19 | __schema_version__ = "0.7.6"
20 | __schema_branch__ = "development"
21 | __schema_location__ = (
22 | "https://raw.githubusercontent.com/LEMS/LEMS/{0}/Schemas/LEMS/LEMS_v{1}.xsd".format(
23 | __schema_branch__, __schema_version__
24 | )
25 | )
26 |
--------------------------------------------------------------------------------
/lems/api.py:
--------------------------------------------------------------------------------
1 | """
2 | PyLEMS API module.
3 |
4 | :author: Gautham Ganapathy
5 | :organization: LEMS (https://github.com/organizations/LEMS)
6 | """
7 |
8 | from lems.model.fundamental import *
9 | from lems.model.structure import *
10 | from lems.model.dynamics import *
11 | from lems.model.simulation import *
12 | from lems.model.component import *
13 | from lems.model.model import Model
14 |
--------------------------------------------------------------------------------
/lems/base/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | :author: Gautham Ganapathy
3 | :organization: LEMS (https://github.com/organizations/LEMS)
4 | """
5 |
--------------------------------------------------------------------------------
/lems/base/base.py:
--------------------------------------------------------------------------------
1 | """
2 | PyLEMS base class.
3 |
4 | :author: Gautham Ganapathy
5 | :organization: LEMS (https://github.com/organizations/LEMS)
6 | """
7 |
8 | import copy
9 |
10 |
11 | class LEMSBase(object):
12 | """
13 | Base object for PyLEMS.
14 | """
15 |
16 | def copy(self):
17 | return copy.deepcopy(self)
18 |
19 | def toxml(self):
20 | return ""
21 |
--------------------------------------------------------------------------------
/lems/base/errors.py:
--------------------------------------------------------------------------------
1 | """
2 | Error classes.
3 |
4 | :author: Gautham Ganapathy
5 | :organization: LEMS (https://github.com/organizations/LEMS)
6 | """
7 |
8 |
9 | class LEMSError(Exception):
10 | """
11 | Base exception class.
12 | """
13 |
14 | def __init__(self, message, *params, **key_params):
15 | """
16 | Constructor
17 |
18 | :param message: Error message.
19 | :type message: string
20 |
21 | :param params: Optional arguments for formatting.
22 | :type params: list
23 |
24 | :param key_params: Named arguments for formatting.
25 | :type key_params: dict
26 | """
27 |
28 | self.message = None
29 | """ Error message
30 |
31 | :type: string """
32 |
33 | if params:
34 | if key_params:
35 | self.message = message.format(*params, **key_params)
36 | else:
37 | self.message = message.format(*params)
38 | else:
39 | if key_params:
40 | self.message = message(**key_params)
41 | else:
42 | self.message = message
43 |
44 | def __str__(self):
45 | """
46 | Returns the error message string.
47 |
48 | :return: The error message
49 | :rtype: string
50 | """
51 |
52 | return self.message
53 |
54 |
55 | class StackError(LEMSError):
56 | """
57 | Exception class to signal errors in the Stack class.
58 | """
59 |
60 | pass
61 |
62 |
63 | class ParseError(LEMSError):
64 | """
65 | Exception class to signal errors found during parsing.
66 | """
67 |
68 | pass
69 |
70 |
71 | class ModelError(LEMSError):
72 | """
73 | Exception class to signal errors in creating the model.
74 | """
75 |
76 | pass
77 |
78 |
79 | class SimBuildError(LEMSError):
80 | """
81 | Exception class to signal errors in building the simulation.
82 | """
83 |
84 | pass
85 |
86 |
87 | class SimError(LEMSError):
88 | """
89 | Exception class to signal errors in simulation.
90 | """
91 |
92 | pass
93 |
--------------------------------------------------------------------------------
/lems/base/map.py:
--------------------------------------------------------------------------------
1 | """
2 | Map class.
3 |
4 | :author: Gautham Ganapathy
5 | :organization: LEMS (https://github.com/organizations/LEMS)
6 | """
7 |
8 | from lems.base.base import LEMSBase
9 |
10 |
11 | class Map(dict, LEMSBase):
12 | """
13 | Map class.
14 |
15 | Same as dict, but iterates over values.
16 | """
17 |
18 | def __init__(self, *params, **key_params):
19 | """
20 | Constructor.
21 | """
22 |
23 | dict.__init__(self, *params, **key_params)
24 |
25 | def __iter__(self):
26 | """
27 | Returns an iterator.
28 | """
29 |
30 | return iter(self.values())
31 |
--------------------------------------------------------------------------------
/lems/base/stack.py:
--------------------------------------------------------------------------------
1 | """
2 | Stack class.
3 |
4 | :author: Gautham Ganapathy
5 | :organization: LEMS (https://github.com/organizations/LEMS)
6 | """
7 |
8 | from lems.base.base import LEMSBase
9 | from lems.base.errors import StackError
10 |
11 |
12 | class Stack(LEMSBase):
13 | """
14 | Basic stack implementation.
15 | """
16 |
17 | def __init__(self):
18 | """
19 | Constructor.
20 | """
21 |
22 | self.stack = []
23 | """ List used to store the stack contents.
24 |
25 | :type: list """
26 |
27 | def push(self, val):
28 | """
29 | Pushed a value onto the stack.
30 |
31 | :param val: Value to be pushed.
32 | :type val: *
33 | """
34 |
35 | self.stack = [val] + self.stack
36 |
37 | def pop(self):
38 | """
39 | Pops a value off the top of the stack.
40 |
41 | :return: Value popped off the stack.
42 | :rtype: *
43 |
44 | :raises StackError: Raised when there is a stack underflow.
45 | """
46 |
47 | if self.stack:
48 | val = self.stack[0]
49 | self.stack = self.stack[1:]
50 | return val
51 | else:
52 | raise StackError("Stack empty")
53 |
54 | def top(self):
55 | """
56 | Returns the value off the top of the stack without popping.
57 |
58 | :return: Value on the top of the stack.
59 | :rtype: *
60 |
61 | :raises StackError: Raised when there is a stack underflow.
62 | """
63 |
64 | if self.stack:
65 | return self.stack[0]
66 | else:
67 | raise StackError("Stack empty")
68 |
69 | def is_empty(self):
70 | """
71 | Checks if the stack is empty.
72 |
73 | :return: True if the stack is empty, otherwise False.
74 | :rtype: Boolean
75 | """
76 |
77 | return self.stack == []
78 |
79 | def __str__(self):
80 | """
81 | Returns a string representation of the stack.
82 |
83 | @note: This assumes that the stack contents are capable of generating
84 | string representations.
85 | """
86 |
87 | if len(self.stack) == 0:
88 | s = "[]"
89 | else:
90 | s = "[" + str(self.stack[0])
91 | for i in range(1, len(self.stack)):
92 | s += ", " + str(self.stack[i])
93 | s += "]"
94 | return s
95 |
96 | def __repr__(self):
97 | return self.__str__()
98 |
--------------------------------------------------------------------------------
/lems/base/util.py:
--------------------------------------------------------------------------------
1 | """
2 | PyLEMS utility classes / functions
3 |
4 | :author: Gautham Ganapathy
5 | :organization: LEMS (https://github.com/organizations/LEMS)
6 | """
7 |
8 | from lems import __schema_location__
9 |
10 |
11 | id_counter = 0
12 |
13 |
14 | def make_id():
15 | global id_counter
16 | id_counter = id_counter + 1
17 | return "__id_{0}__".format(id_counter)
18 |
19 |
20 | def merge_maps(m, base):
21 | """
22 | Merge in undefined map entries from given map.
23 |
24 | :param m: Map to be merged into.
25 | :type m: lems.util.Map
26 |
27 | :param base: Map to be merged into.
28 | :type base: lems.util.Map
29 | """
30 |
31 | for k in base.keys():
32 | if k not in m:
33 | m[k] = base[k]
34 |
35 |
36 | def merge_lists(l, base):
37 | """
38 | Merge in undefined list entries from given list.
39 |
40 | :param l: List to be merged into.
41 | :type l: list
42 |
43 | :param base: List to be merged into.
44 | :type base: list
45 | """
46 |
47 | for i in base:
48 | if i not in l:
49 | l.append(i)
50 |
51 |
52 | def validate_lems(file_name):
53 | from lxml import etree
54 |
55 | try:
56 | from urllib2 import urlopen # Python 2
57 | except:
58 | from urllib.request import urlopen # Python 3
59 |
60 | schema_file = urlopen(__schema_location__)
61 | xmlschema = etree.XMLSchema(etree.parse(schema_file))
62 | print("Validating {0} against {1}".format(file_name, schema_file.geturl()))
63 | xmlschema.assertValid(etree.parse(file_name))
64 | print("It's valid!")
65 |
--------------------------------------------------------------------------------
/lems/dlems/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | :author: Padraig Gleeson
3 | :organization: LEMS (https://github.com/organizations/LEMS)
4 | """
5 |
--------------------------------------------------------------------------------
/lems/dlems/exportdlems.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | """
3 | Exporter for dLEMS (formerly SOM). See https://github.com/borismarin/som-codegen
4 |
5 | :author: Boris Marin
6 | """
7 |
8 | import sys
9 | import re
10 | import json
11 | from collections import OrderedDict
12 |
13 | from lems.model.model import Model
14 | from lems.sim.build import order_derived_variables, order_derived_parameters
15 | from lems.model.dynamics import OnStart
16 | from lems.model.dynamics import OnCondition
17 | from lems.model.dynamics import StateAssignment
18 |
19 | SI_PREF = {"p": 1e-12, "n": 1e-9, "u": 1e-6, "m": 1e-3, "c": 1e-2}
20 |
21 |
22 | def to_si(model, unit_str):
23 | return str(model.get_numeric_value(unit_str))
24 |
25 |
26 | def comp2sign(cond):
27 | ret = "???"
28 | if cond in ("gt", "geq"):
29 | ret = "+"
30 | elif cond in ("lt", "leq"):
31 | ret = "-"
32 | elif cond == "eq":
33 | ret = "0"
34 | return ret
35 |
36 |
37 | def has_display(disp, pop):
38 | pop = re.compile(pop)
39 | # iterate over plots/dumps pertaining to current element
40 | quants = [li.parameters["quantity"] for li in disp.children]
41 | return any([pop.search(q) for q in quants])
42 |
43 |
44 | def any_svs_plotted(disp, svs):
45 | s = lambda x: x[x.rfind("/") + 1 :]
46 | return any([s(li.parameters["quantity"]) in svs for li in disp.children])
47 |
48 |
49 | def inequality_to_condition(ineq):
50 | r = re.compile("(.+)(?:\.([glneqt]+)\.)(.+)")
51 | s = r.search(ineq)
52 | expr = "".join([s.group(1).strip(), " - (", s.group(3).strip() + ")"])
53 | sign = comp2sign(s.group(2))
54 | return (expr, sign)
55 |
56 |
57 | def export_component(model, comp, sim_comp, parent_pop="", file_name=None):
58 | comp_type = model.component_types[comp.type]
59 |
60 | dlems = OrderedDict()
61 | dlems["name"] = comp.id
62 | params = OrderedDict()
63 |
64 | for p in comp.parameters.keys():
65 | params[p] = to_si(model, comp.parameters[p])
66 |
67 | for p in order_derived_parameters(comp_type):
68 | params[p] = to_si(model, comp_type.derived_parameters[p])
69 |
70 | for c in comp_type.constants.keys():
71 | params[c] = to_si(model, comp_type.constants[c].value)
72 | dlems["parameters"] = params
73 |
74 | dyn = comp_type.dynamics
75 | dvs = OrderedDict()
76 | for dv in order_derived_variables(dyn):
77 | val = dyn.derived_variables[dv].value
78 | if val is not None:
79 | dvs[dv] = val
80 | else:
81 | dvs[dv] = "0"
82 |
83 | dlems["state_functions"] = dvs
84 |
85 | tds = OrderedDict()
86 |
87 | for td in dyn.time_derivatives:
88 | tds[td.variable] = td.value
89 |
90 | dlems["dynamics"] = tds
91 |
92 | svs = OrderedDict()
93 | for sv in dyn.state_variables:
94 | for eh in dyn.event_handlers:
95 | if isinstance(eh, OnStart):
96 | for action in eh.actions:
97 | if isinstance(action, StateAssignment):
98 | if action.variable == sv.name:
99 | svs[sv.name] = action.value
100 | if not sv.name in svs:
101 | svs[sv.name] = "0"
102 |
103 | dlems["state"] = svs
104 |
105 | evs = []
106 | count_cond = 0
107 |
108 | for eh in dyn.event_handlers:
109 | if isinstance(eh, OnCondition):
110 | ev = OrderedDict()
111 | ev["name"] = "condition_%i" % count_cond
112 | (cond, dir) = inequality_to_condition(eh.test)
113 | ev["condition"] = cond
114 | ev["direction"] = dir
115 | effect = OrderedDict()
116 | state_effects = OrderedDict()
117 | for action in eh.actions:
118 | if isinstance(action, StateAssignment):
119 | state_effects[action.variable] = action.value
120 | effect["state"] = state_effects
121 | ev["effect"] = effect
122 | evs.append(ev)
123 | count_cond += 1
124 |
125 | dlems["events"] = evs
126 |
127 | dlems["t_start"] = "0"
128 | dlems["t_end"] = to_si(model, sim_comp.parameters["length"])
129 | dlems["dt"] = to_si(model, sim_comp.parameters["step"])
130 |
131 | disps = []
132 |
133 | for d in sim_comp.children:
134 | if (
135 | d.type == "Display"
136 | and has_display(d, parent_pop)
137 | and any_svs_plotted(d, svs.keys())
138 | ):
139 | di = OrderedDict()
140 | abax = OrderedDict()
141 | abax["min"] = d.parameters["xmin"]
142 | abax["max"] = d.parameters["xmax"]
143 |
144 | orax = OrderedDict()
145 | orax["min"] = d.parameters["ymin"]
146 | orax["max"] = d.parameters["ymax"]
147 |
148 | curves = []
149 | for li in d.children:
150 | cur = OrderedDict()
151 | s = li.parameters["quantity"]
152 | x = s[s.rfind("/") + 1 :]
153 | cur["abscissa"] = "t"
154 | cur["ordinate"] = x
155 | cur["colour"] = li.parameters["color"]
156 | px = re.search("([cmunp])s", li.parameters["timeScale"], re.IGNORECASE)
157 | py = re.search("([cmunp])+\w", li.parameters["scale"], re.IGNORECASE)
158 | try:
159 | scale_x = SI_PREF[px.group()[0]]
160 | except (KeyError, AttributeError) as e:
161 | scale_x = 1
162 | try:
163 | scale_y = SI_PREF[py.group()[0]]
164 | except (KeyError, AttributeError) as e:
165 | scale_y = 1
166 | # dlems is currently concerned with state var plots only
167 | if cur["ordinate"] in svs:
168 | curves.append(cur)
169 |
170 | abax = {k: str(scale_x * float(v)) for (k, v) in abax.items()}
171 | orax = {k: str(scale_y * float(v)) for (k, v) in orax.items()}
172 | di["abscissa_axis"] = abax
173 | di["ordinate_axis"] = orax
174 |
175 | di["curves"] = curves
176 | disps.append(di)
177 |
178 | elif d.type == "OutputFile":
179 | dlems["dump_to_file"] = d.parameters["fileName"]
180 | for dd in d.children:
181 | s = dd.parameters["quantity"]
182 |
183 | dlems["display"] = disps
184 |
185 | dlems_file_name = file_name
186 | if dlems_file_name is None:
187 | dlems_file_name = "comp_%s.json" % comp.id
188 |
189 | dlems_file = open(dlems_file_name, "w")
190 |
191 | dlems_file.write(json.dumps(dlems, indent=4, separators=(",", ": ")))
192 |
193 | dlems_file.close()
194 |
195 | reopen = open(dlems_file_name, "r")
196 | print(reopen.read())
197 | reopen.close()
198 |
199 | print("Written to %s" % dlems_file_name)
200 |
201 |
202 | if __name__ == "__main__":
203 | model = Model()
204 |
205 | try:
206 | lems_file = sys.argv[1]
207 | except:
208 | lems_file = "../NeuroML2/LEMSexamples/LEMS_NML2_Ex9_FN.xml"
209 | model.add_include_directory("../NeuroML2/NeuroML2CoreTypes")
210 |
211 | print("Importing LEMS file from: %s" % lems_file)
212 | model.import_from_file(lems_file)
213 |
214 | target = model.targets[0]
215 |
216 | sim_comp = model.components[target]
217 |
218 | target_net = sim_comp.parameters["target"]
219 |
220 | target_comp = model.components[target_net]
221 |
222 | if target_comp.type == "network":
223 | for child in target_comp.children:
224 | if child.type == "population":
225 | comp = model.components[child.parameters["component"]]
226 |
227 | export_component(model, comp, sim_comp, child.id)
228 | else:
229 | export_component(model, target_comp, sim_comp)
230 |
--------------------------------------------------------------------------------
/lems/model/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | :author: Gautham Ganapathy
3 | :organization: LEMS (https://github.com/organizations/LEMS)
4 | """
5 |
--------------------------------------------------------------------------------
/lems/model/fundamental.py:
--------------------------------------------------------------------------------
1 | """
2 | Dimension and Unit definitions in terms of the fundamental SI units.
3 |
4 | :author: Gautham Ganapathy
5 | :organization: LEMS (https://github.com/organizations/LEMS)
6 | """
7 |
8 | from lems.base.base import LEMSBase
9 |
10 |
11 | class Include(LEMSBase):
12 | """
13 | Include another LEMS file.
14 | """
15 |
16 | def __init__(self, filename):
17 | """
18 | Constructor.
19 |
20 | :param filename: Name of the file.
21 | :type name: str
22 |
23 | """
24 |
25 | self.file = filename
26 | """ Name of the file.
27 |
28 | :type: str """
29 |
30 | def toxml(self):
31 | """
32 | Exports this object into a LEMS XML object
33 | """
34 |
35 | return '' % self.file
36 |
37 |
38 | class Dimension(LEMSBase):
39 | """
40 | Stores a dimension in terms of the seven fundamental SI units.
41 | """
42 |
43 | def __init__(self, name, description="", **params):
44 | """
45 | Constructor.
46 |
47 | :param name: Name of the dimension.
48 | :type name: str
49 |
50 | :param params: Key arguments specifying powers for each of the
51 | seven fundamental SI dimensions.
52 | :type params: dict()
53 | """
54 |
55 | self.name = name
56 | """ Name of the dimension.
57 |
58 | :type: str """
59 |
60 | self.m = params["m"] if "m" in params else 0
61 | """ Power for the mass dimension.
62 |
63 | :type: int """
64 |
65 | self.l = params["l"] if "l" in params else 0
66 | """ Power for the length dimension.
67 |
68 | :type: int """
69 |
70 | self.t = params["t"] if "t" in params else 0
71 | """ Power for the time dimension.
72 |
73 | :type: int """
74 |
75 | self.i = params["i"] if "i" in params else 0
76 | """ Power for the electic current dimension.
77 |
78 | :type: int """
79 |
80 | self.k = params["k"] if "k" in params else 0
81 | """ Power for the temperature dimension.
82 |
83 | :type: int """
84 |
85 | self.n = params["n"] if "n" in params else 0
86 | """ Power for the quantity dimension.
87 |
88 | :type: int """
89 |
90 | self.j = params["j"] if "j" in params else 0
91 | """ Power for the luminous intensity dimension.
92 |
93 | :type: int """
94 |
95 | self.description = description
96 | """ Description of this dimension.
97 |
98 | :type: str """
99 |
100 | def toxml(self):
101 | """
102 | Exports this object into a LEMS XML object
103 | """
104 |
105 | return (
106 | '"
115 | )
116 |
117 |
118 | class Unit(LEMSBase):
119 | """
120 | Stores a unit definition.
121 | """
122 |
123 | def __init__(
124 | self, name, symbol, dimension, power=0, scale=1.0, offset=0.0, description=""
125 | ):
126 | """
127 | Constructor.
128 |
129 | See instance variable documentation for more details on parameters.
130 | """
131 |
132 | self.name = name
133 | """ Name of the unit.
134 |
135 | :type: str """
136 |
137 | self.symbol = symbol
138 | """ Symbol for the unit.
139 |
140 | :type: str """
141 |
142 | self.dimension = dimension
143 | """ Dimension for the unit.
144 |
145 | :type: str """
146 |
147 | self.power = power
148 | """ Scaling by power of 10.
149 |
150 | :type: int """
151 |
152 | self.scale = scale
153 | """ Scaling.
154 |
155 | :type: float """
156 |
157 | self.offset = offset
158 | """ Offset for non-zero units.
159 |
160 | :type: float """
161 |
162 | self.description = description
163 | """ Description of this unit.
164 |
165 | :type: str """
166 |
167 | def toxml(self):
168 | """
169 | Exports this object into a LEMS XML object
170 | """
171 |
172 | # Probably name should be removed altogether until its usage is decided, see
173 | # https://github.com/LEMS/LEMS/issues/4
174 | # '''(' name = "{0}"'.format(self.name) if self.name else '') +\'''
175 |
176 | return (
177 | ""
189 | )
190 |
--------------------------------------------------------------------------------
/lems/model/simulation.py:
--------------------------------------------------------------------------------
1 | """
2 | Simulation specification classes.
3 |
4 | :author: Gautham Ganapathy
5 | :organization: LEMS (https://github.com/organizations/LEMS)
6 | """
7 |
8 | from lems.base.base import LEMSBase
9 | from lems.base.errors import ModelError
10 | from lems.base.map import Map
11 |
12 |
13 | class Run(LEMSBase):
14 | """
15 | Stores the description of an object to be run according to an independent
16 | variable (usually time).
17 | """
18 |
19 | def __init__(self, component, variable, increment, total):
20 | """
21 | Constructor.
22 |
23 | See instance variable documentation for information on parameters.
24 | """
25 |
26 | self.component = component
27 | """ Name of the target component to be run according to the
28 | specification given for an independent state variable.
29 |
30 | :type: str """
31 |
32 | self.variable = variable
33 | """ The name of an independent state variable according to which the
34 | target component will be run.
35 |
36 | :type: str """
37 |
38 | self.increment = increment
39 | """ Increment of the state variable on each step.
40 |
41 | :type: str """
42 |
43 | self.total = total
44 | """ Final value of the state variable.
45 |
46 | :type: str """
47 |
48 | def toxml(self):
49 | """
50 | Exports this object into a LEMS XML object
51 | """
52 |
53 | return (
54 | ''.format(
55 | self.component, self.variable, self.increment, self.total
56 | )
57 | )
58 |
59 |
60 | class Record(LEMSBase):
61 | """
62 | Stores the parameters of a statement.
63 | """
64 |
65 | def __init__(self, quantity, scale=None, color=None, id=None):
66 | """
67 | Constructor.
68 |
69 | See instance variable documentation for information on parameters.
70 | """
71 |
72 | self.id = ""
73 | """ Id of the quantity
74 |
75 | :type: str """
76 |
77 | self.quantity = quantity
78 | """ Path to the quantity to be recorded.
79 |
80 | :type: str """
81 |
82 | self.scale = scale
83 | """ Text parameter to be used for scaling the quantity before display.
84 |
85 | :type: str """
86 |
87 | self.color = color
88 | """ Text parameter to be used to specify the color for display.
89 |
90 | :type: str """
91 |
92 | self.id = id
93 | """ Text parameter to be used to specify an id for the record
94 |
95 | :type: str """
96 |
97 | def toxml(self):
98 | """
99 | Exports this object into a LEMS XML object
100 | """
101 |
102 | return ''.format(
103 | self.quantity, self.scale, self.color, self.id
104 | )
105 |
106 |
107 | class EventRecord(LEMSBase):
108 | """
109 | Stores the parameters of an statement.
110 | """
111 |
112 | def __init__(self, quantity, eventPort):
113 | """
114 | Constructor.
115 |
116 | See instance variable documentation for information on parameters.
117 | """
118 |
119 | self.id = ""
120 | """ Id of the quantity
121 |
122 | :type: str """
123 |
124 | self.quantity = quantity
125 | """ Path to the quantity to be recorded.
126 |
127 | :type: str """
128 |
129 | self.eventPort = eventPort
130 | """ eventPort to be used for the event record
131 |
132 | :type: str """
133 |
134 | def toxml(self):
135 | """
136 | Exports this object into a LEMS XML object
137 | """
138 |
139 | return ''.format(
140 | self.quantity, self.eventPort
141 | )
142 |
143 |
144 | class DataOutput(LEMSBase):
145 | """
146 | Generic data output specification class.
147 | """
148 |
149 | def __init__(self):
150 | """
151 | Constuctor.
152 | """
153 |
154 | pass
155 |
156 |
157 | class DataDisplay(DataOutput):
158 | """
159 | Stores specification for a data display.
160 | """
161 |
162 | def __init__(self, title, data_region):
163 | """
164 | Constuctor.
165 |
166 | See instance variable documentation for information on parameters.
167 | """
168 |
169 | DataOutput.__init__(self)
170 |
171 | self.title = title
172 | """ Title for the display.
173 |
174 | :type: string """
175 |
176 | self.data_region = data_region
177 | """ Display position
178 |
179 | :type: string """
180 |
181 | self.time_scale = 1
182 | """ Time scale
183 |
184 | :type: Number """
185 |
186 | def toxml(self):
187 | """
188 | Exports this object into a LEMS XML object
189 | """
190 |
191 | return ''.format(
192 | self.title, self.data_region
193 | )
194 |
195 |
196 | class DataWriter(DataOutput):
197 | """
198 | Stores specification for a data writer.
199 | """
200 |
201 | def __init__(self, path, file_name):
202 | """
203 | Constuctor.
204 |
205 | See instance variable documentation for information on parameters.
206 | """
207 |
208 | DataOutput.__init__(self)
209 |
210 | self.path = path
211 | """ Path to the quantity to be saved to file.
212 |
213 | :type: string """
214 |
215 | self.file_name = file_name
216 | """ Text parameter to be used for the file name
217 |
218 | :type: string """
219 |
220 | def toxml(self):
221 | """
222 | Exports this object into a LEMS XML object
223 | """
224 |
225 | return ''.format(
226 | self.path, self.file_name
227 | )
228 |
229 | def __str__(self):
230 | return "DataWriter, path: {0}, fileName: {1}".format(self.path, self.file_name)
231 |
232 |
233 | class EventWriter(DataOutput):
234 | """
235 | Stores specification for an event writer.
236 | """
237 |
238 | def __init__(self, path, file_name, format):
239 | """
240 | Constuctor.
241 |
242 | See instance variable documentation for information on parameters.
243 | """
244 |
245 | DataOutput.__init__(self)
246 |
247 | self.path = path
248 | """ Path to the quantity to be saved to file.
249 |
250 | :type: string """
251 |
252 | self.file_name = file_name
253 | """ Text parameter to be used for the file name
254 |
255 | :type: string """
256 |
257 | self.format = format
258 | """ Text parameter to be used for the format
259 |
260 | :type: string """
261 |
262 | def toxml(self):
263 | """
264 | Exports this object into a LEMS XML object
265 | """
266 |
267 | return ''.format(
268 | self.path, self.file_name, self.format
269 | )
270 |
271 | def __str__(self):
272 | return "EventWriter, path: {0}, fileName: {1}, format: {2}".format(
273 | self.path, self.file_name, self.format
274 | )
275 |
276 |
277 | class Simulation(LEMSBase):
278 | """
279 | Stores the simulation-related attributes of a component-type.
280 | """
281 |
282 | def __init__(self):
283 | """
284 | Constructor.
285 | """
286 |
287 | self.runs = Map()
288 | """ Map of runs in this dynamics regime.
289 |
290 | :type: Map(string, lems.model.simulation.Run) """
291 |
292 | self.records = Map()
293 | """ Map of recorded variables in this dynamics regime.
294 |
295 | :type: Map(string, lems.model.simulation.Record """
296 |
297 | self.event_records = Map()
298 | """ Map of recorded events in this dynamics regime.
299 |
300 | :type: Map(string, lems.model.simulation.EventRecord """
301 |
302 | self.data_displays = Map()
303 | """ Map of data displays mapping titles to regions.
304 |
305 | :type: Map(string, string) """
306 |
307 | self.data_writers = Map()
308 | """ Map of recorded variables to data writers.
309 |
310 | :type: Map(string, lems.model.simulation.DataWriter """
311 |
312 | self.event_writers = Map()
313 | """ Map of recorded variables to event writers.
314 |
315 | :type: Map(string, lems.model.simulation.EventWriter """
316 |
317 | def add_run(self, run):
318 | """
319 | Adds a runnable target component definition to the list of runnable
320 | components stored in this context.
321 |
322 | :param run: Run specification
323 | :type run: lems.model.simulation.Run
324 | """
325 |
326 | self.runs[run.component] = run
327 |
328 | def add_record(self, record):
329 | """
330 | Adds a record object to the list of record objects in this dynamics
331 | regime.
332 |
333 | :param record: Record object to be added.
334 | :type record: lems.model.simulation.Record
335 | """
336 |
337 | self.records[record.quantity] = record
338 |
339 | def add_event_record(self, event_record):
340 | """
341 | Adds an eventrecord object to the list of event_record objects in this dynamics
342 | regime.
343 |
344 | :param event_record: EventRecord object to be added.
345 | :type event_record: lems.model.simulation.EventRecord
346 | """
347 |
348 | self.event_records[event_record.quantity] = event_record
349 |
350 | def add_data_display(self, data_display):
351 | """
352 | Adds a data display to this simulation section.
353 |
354 | :param data_display: Data display to be added.
355 | :type data_display: lems.model.simulation.DataDisplay
356 | """
357 |
358 | self.data_displays[data_display.title] = data_display
359 |
360 | def add_data_writer(self, data_writer):
361 | """
362 | Adds a data writer to this simulation section.
363 |
364 | :param data_writer: Data writer to be added.
365 | :type data_writer: lems.model.simulation.DataWriter
366 | """
367 |
368 | self.data_writers[data_writer.path] = data_writer
369 |
370 | def add_event_writer(self, event_writer):
371 | """
372 | Adds an event writer to this simulation section.
373 |
374 | :param event_writer: event writer to be added.
375 | :type event_writer: lems.model.simulation.EventWriter
376 | """
377 |
378 | self.event_writers[event_writer.path] = event_writer
379 |
380 | def add(self, child):
381 | """
382 | Adds a typed child object to the simulation spec.
383 |
384 | :param child: Child object to be added.
385 | """
386 |
387 | if isinstance(child, Run):
388 | self.add_run(child)
389 | elif isinstance(child, Record):
390 | self.add_record(child)
391 | elif isinstance(child, EventRecord):
392 | self.add_event_record(child)
393 | elif isinstance(child, DataDisplay):
394 | self.add_data_display(child)
395 | elif isinstance(child, DataWriter):
396 | self.add_data_writer(child)
397 | elif isinstance(child, EventWriter):
398 | self.add_event_writer(child)
399 | else:
400 | raise ModelError("Unsupported child element")
401 |
402 | def toxml(self):
403 | """
404 | Exports this object into a LEMS XML object
405 | """
406 |
407 | chxmlstr = ""
408 |
409 | for run in self.runs:
410 | chxmlstr += run.toxml()
411 |
412 | for record in self.records:
413 | chxmlstr += record.toxml()
414 |
415 | for event_record in self.event_records:
416 | chxmlstr += event_record.toxml()
417 |
418 | for data_display in self.data_displays:
419 | chxmlstr += data_display.toxml()
420 |
421 | for data_writer in self.data_writers:
422 | chxmlstr += data_writer.toxml()
423 |
424 | for event_writer in self.event_writers:
425 | chxmlstr += event_writer.toxml()
426 |
427 | if chxmlstr:
428 | xmlstr = "" + chxmlstr + ""
429 | else:
430 | xmlstr = ""
431 |
432 | return xmlstr
433 |
--------------------------------------------------------------------------------
/lems/parser/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | :author: Gautham Ganapathy
3 | :organization: LEMS (https://github.com/organizations/LEMS)
4 | """
5 |
--------------------------------------------------------------------------------
/lems/run.py:
--------------------------------------------------------------------------------
1 | """
2 | Command line simulation driver.
3 |
4 | :author: Gautham Ganapathy
5 | :organization: LEMS (https://github.com/organizations/LEMS)
6 | """
7 |
8 | import argparse
9 |
10 | from lems.model.model import Model
11 | from lems.sim.build import SimulationBuilder
12 | from lems.model.simulation import DataDisplay, DataWriter
13 |
14 |
15 | dlems_info = "dLEMS (distilled LEMS in JSON format, see https://github.com/borismarin/som-codegen)"
16 |
17 |
18 | def process_args():
19 | """
20 | Parse command-line arguments.
21 | """
22 | parser = argparse.ArgumentParser()
23 |
24 | parser.add_argument(
25 | "-I",
26 | type=str,
27 | metavar="",
28 | action="append",
29 | help="Directory to be searched for included files",
30 | )
31 |
32 | parser.add_argument(
33 | "lems_file", type=str, metavar="", help="LEMS file to be simulated"
34 | )
35 |
36 | parser.add_argument(
37 | "-nogui",
38 | action="store_true",
39 | help="If this is specified, just parse & simulate the model, but don't show any plots",
40 | )
41 |
42 | parser.add_argument(
43 | "-dlems",
44 | action="store_true",
45 | help="If this is specified, export the LEMS file as " + dlems_info,
46 | )
47 |
48 | return parser.parse_args()
49 |
50 |
51 | def run(file_path, include_dirs=[], dlems=False, nogui=False):
52 | """
53 | Function for running from a script or shell.
54 | """
55 | import argparse
56 |
57 | args = argparse.Namespace()
58 | args.lems_file = file_path
59 | args.I = include_dirs
60 | args.dlems = dlems
61 | args.nogui = nogui
62 | main(args=args)
63 |
64 |
65 | def main(args=None):
66 | """
67 | Program entry point.
68 | """
69 |
70 | if args is None:
71 | args = process_args()
72 |
73 | print("Parsing and resolving model: " + args.lems_file)
74 | model = Model()
75 | if args.I is not None:
76 | for dir in args.I:
77 | model.add_include_directory(dir)
78 | model.import_from_file(args.lems_file)
79 |
80 | resolved_model = model.resolve()
81 |
82 | print("Building simulation")
83 | sim = SimulationBuilder(resolved_model).build()
84 | # sim.dump("Afterbuild:")
85 |
86 | if args.dlems:
87 | print("Exporting as: " + dlems_info)
88 |
89 | from lems.dlems.exportdlems import export_component
90 |
91 | target = model.targets[0]
92 |
93 | sim_comp = model.components[target]
94 |
95 | target_net = sim_comp.parameters["target"]
96 |
97 | target_comp = model.components[target_net]
98 |
99 | dlems_file_name = args.lems_file.replace(".xml", ".json")
100 | if dlems_file_name == args.lems_file:
101 | dlems_file_name = args.lems_file + ".json"
102 |
103 | if target_comp.type == "network":
104 | for child in target_comp.children:
105 | if child.type == "population":
106 | comp = model.components[child.parameters["component"]]
107 |
108 | export_component(
109 | model, comp, sim_comp, child.id, file_name=dlems_file_name
110 | )
111 | else:
112 | export_component(model, sim_comp, target_comp)
113 |
114 | else:
115 | print("Running simulation")
116 | sim.run()
117 | process_simulation_output(sim, model, args)
118 |
119 |
120 | fig_count = 0
121 |
122 |
123 | def process_simulation_output(sim, model, options):
124 |
125 | print("Processing results")
126 | rq = []
127 | for rn in sim.runnables:
128 | rq.append(sim.runnables[rn])
129 |
130 | file_times = {}
131 | file_outs = {}
132 |
133 | display_order = {}
134 | file_column_order = {}
135 |
136 | simulation = model.components[model.targets[0]]
137 | for c in simulation.children:
138 | if c.type == "Display":
139 | display_order[c.parameters["title"]] = []
140 | for l in c.children:
141 | display_order[c.parameters["title"]].append(l.parameters["quantity"])
142 |
143 | if c.type == "OutputFile":
144 | file_column_order[c.parameters["fileName"]] = []
145 | for f in c.children:
146 | file_column_order[c.parameters["fileName"]].append(
147 | f.parameters["quantity"]
148 | )
149 |
150 | recordings = {}
151 |
152 | while rq != []:
153 | runnable = rq[0]
154 | rq = rq[1:]
155 | for c in runnable.children:
156 | rq.append(runnable.children[c])
157 | for child in runnable.array:
158 | rq.append(child)
159 |
160 | if runnable.recorded_variables:
161 | for recording in runnable.recorded_variables:
162 | if isinstance(recording.data_output, DataDisplay):
163 | data_output = recording.data_output
164 | if not options.nogui:
165 | if data_output.title not in recordings:
166 | recordings[data_output.title] = {}
167 |
168 | recordings[data_output.title][recording.full_path] = recording
169 | elif isinstance(recording.data_output, DataWriter):
170 | data_output = recording.data_output
171 | times = []
172 | vals = []
173 | for x, y in recording.values:
174 | times.append(x)
175 | vals.append(y)
176 | file_times[data_output.file_name] = times
177 | if data_output.file_name not in file_outs:
178 | file_outs[data_output.file_name] = {}
179 |
180 | file_outs[data_output.file_name][recording.full_path] = vals
181 | else:
182 | raise Exception(
183 | "Invalid output type - " + str(type(recording.data_output))
184 | )
185 |
186 | for file_out_name in file_column_order.keys():
187 | times = file_times[file_out_name]
188 | vals = file_outs[file_out_name]
189 | print(
190 | "Going to save {0}x{1} data points to file {2}".format(
191 | len(times), len(vals.keys()), file_out_name
192 | )
193 | )
194 | file_out = open(file_out_name, "w")
195 | i = 0
196 |
197 | for time in times:
198 | file_out.write("{0} ".format(time))
199 | columns = file_column_order[file_out_name]
200 | for column in columns:
201 | val = vals[column]
202 | file_out.write("{0} ".format(val[i]))
203 |
204 | file_out.write("\n")
205 | i += 1
206 |
207 | file_out.close()
208 |
209 | if not options.nogui:
210 | for display in display_order.keys():
211 | lines = display_order[display]
212 | recordings_here = recordings[display]
213 | for line in lines:
214 | plot_recording(recordings_here[line])
215 |
216 | if fig_count > 0:
217 | import matplotlib.pyplot as pylab
218 |
219 | pylab.show()
220 |
221 |
222 | class Display:
223 | def __init__(self, fig):
224 | self.fig = fig
225 | self.plots = list()
226 | self.legend = list()
227 |
228 |
229 | displays = {}
230 |
231 |
232 | def plot_recording(recording):
233 | import matplotlib.pyplot as pylab
234 | import numpy
235 |
236 | global fig_count
237 |
238 | data_output = recording.data_output
239 | recorder = recording.recorder
240 |
241 | x = numpy.empty(len(recording.values))
242 | y = numpy.empty(len(recording.values))
243 | i = 0
244 | for xv, yv in recording.values:
245 | x[i] = xv / data_output.timeScale
246 | y[i] = yv / recorder.scale
247 | i = i + 1
248 |
249 | if data_output.title in displays:
250 | fig = displays[data_output.title].fig
251 | else:
252 | fig_count = fig_count + 1
253 | fig = fig_count
254 | displays[data_output.title] = Display(fig)
255 |
256 | f = pylab.figure(fig)
257 | pylab.title(data_output.title)
258 |
259 | pylab.figure(fig)
260 | p = pylab.subplot(111)
261 | p.patch.set_facecolor("#7f7f7f")
262 | (plot,) = pylab.plot(x, y, color=recorder.color, label=recorder.quantity)
263 | displays[data_output.title].plots.append(plot)
264 | displays[data_output.title].legend.append(recorder.id)
265 | pylab.legend(displays[data_output.title].plots, displays[data_output.title].legend)
266 |
--------------------------------------------------------------------------------
/lems/sim/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | :author: Gautham Ganapathy
3 | :organization: LEMS (https://github.com/organizations/LEMS)
4 | """
5 |
--------------------------------------------------------------------------------
/lems/sim/recording.py:
--------------------------------------------------------------------------------
1 | """
2 | Recording class(es).
3 |
4 | :author: Gautham Ganapathy
5 | :organization: LEMS (https://github.com/organizations/LEMS)
6 | """
7 |
8 | from lems.base.base import LEMSBase
9 |
10 |
11 | class Recording(LEMSBase):
12 | """
13 | Stores details of a variable recording across a single simulation run.
14 | """
15 |
16 | def __init__(self, variable, full_path, data_output, recorder):
17 | self.variable = variable
18 |
19 | self.full_path = full_path
20 |
21 | self.data_output = data_output
22 |
23 | self.recorder = recorder
24 |
25 | self.values = []
26 |
27 | def __str__(self):
28 | return "Recording: {0} ({1}), {2}, size: {3}".format(
29 | self.variable, self.full_path, self.recorder, len(self.values)
30 | )
31 |
32 | def __repr__(self):
33 | return self.__str__()
34 |
35 | def add_value(self, time, value):
36 | self.values.append((time, value))
37 |
--------------------------------------------------------------------------------
/lems/sim/sim.py:
--------------------------------------------------------------------------------
1 | """
2 | Simulation.
3 |
4 | :author: Gautham Ganapathy
5 | :organization: LEMS (https://github.com/organizations/LEMS)
6 | """
7 |
8 | from lems.base.base import LEMSBase
9 | from lems.base.errors import SimError
10 |
11 | import heapq
12 |
13 |
14 | class Simulation(LEMSBase):
15 | """
16 | Simulation class.
17 | """
18 |
19 | debug = False
20 |
21 | def __init__(self):
22 | """
23 | Constructor.
24 | """
25 |
26 | self.runnables = {}
27 | """ Dictionary of runnable components in this simulation.
28 |
29 | :type: dict(string, lems.sim.runnable.Runnable) """
30 |
31 | self.run_queue = []
32 | """ Priority of pairs of (time-to-next run, runnable).
33 |
34 | :type: list((Integer, lems.sim.runnable.Runnable)) """
35 |
36 | self.event_queue = []
37 | """ List of posted events.
38 |
39 | :type: list(lems.sim.sim.Event) """
40 |
41 | def add_runnable(self, runnable):
42 | """
43 | Adds a runnable component to the list of runnable components in
44 | this simulation.
45 |
46 | :param runnable: A runnable component
47 | :type runnable: lems.sim.runnable.Runnable
48 | """
49 |
50 | if runnable.id in self.runnables:
51 | raise SimError("Duplicate runnable component {0}".format(runnable.id))
52 |
53 | self.runnables[runnable.id] = runnable
54 |
55 | def init_run(self):
56 | self.current_time = 0
57 | for id in self.runnables:
58 | self.runnables[id].do_startup()
59 | heapq.heappush(self.run_queue, (0, self.runnables[id]))
60 |
61 | def step(self):
62 | current_time = self.current_time
63 |
64 | if self.run_queue == []:
65 | return False
66 |
67 | (current_time, runnable) = heapq.heappop(self.run_queue)
68 | time = current_time
69 | while time == current_time:
70 | next_time = current_time + runnable.single_step(runnable.time_step)
71 |
72 | if next_time > current_time:
73 | heapq.heappush(self.run_queue, (next_time, runnable))
74 |
75 | if self.run_queue == []:
76 | break
77 | (time, runnable) = heapq.heappop(self.run_queue)
78 |
79 | if time > current_time:
80 | heapq.heappush(self.run_queue, (time, runnable))
81 |
82 | self.current_time = current_time
83 |
84 | if self.run_queue == []:
85 | return False
86 | else:
87 | return True
88 |
89 | def run(self):
90 | """
91 | Runs the simulation.
92 | """
93 |
94 | self.init_run()
95 | if self.debug:
96 | self.dump("AfterInit: ")
97 | # print("++++++++++++++++ Time: %f"%self.current_time)
98 | while self.step():
99 | # self.dump("Time: %f"%self.current_time)
100 | # print("++++++++++++++++ Time: %f"%self.current_time)
101 | pass
102 |
103 | def push_state(self):
104 | for id in self.runnables:
105 | self.runnables[id].push_state()
106 |
107 | def pop_state(self):
108 | for id in self.runnables:
109 | self.runnables[id].pop_state()
110 |
111 | def enable_plasticity(self):
112 | for id in self.runnables:
113 | self.runnables[id].plastic = True
114 |
115 | def disable_plasticity(self):
116 | for id in self.runnables:
117 | self.runnables[id].plastic = False
118 |
119 | def dump_runnable(self, runnable, prefix="."):
120 | r = runnable
121 | print("{0}............... {1} ({2})".format(prefix, r.id, r.component.type))
122 | print(prefix + str(r))
123 | ignores = ["Display", "Line", "OutputColumn", "OutputFile", "Simulation"]
124 | verbose = r.component.type not in ignores
125 | if verbose:
126 | if r.instance_variables:
127 | print("{0} Instance variables".format(prefix))
128 | for vn in r.instance_variables:
129 | print("{0} {1} = {2}".format(prefix, vn, r.__dict__[vn]))
130 | if r.derived_variables:
131 | print("{0} Derived variables".format(prefix))
132 | for vn in r.derived_variables:
133 | print("{0} {1} = {2}".format(prefix, vn, r.__dict__[vn]))
134 |
135 | if verbose:
136 | keys = list(r.__dict__.keys())
137 | keys.sort()
138 | print("{0} Keys for {1}".format(prefix, r.id))
139 | for k in keys:
140 | key_str = str(r.__dict__[k])
141 | if len(key_str) > 0 and not key_str == "[]" and not key_str == "{}":
142 | print("{0} {1} -> {2}".format(prefix, k, key_str))
143 |
144 | if r.array:
145 | for c in r.array:
146 | self.dump_runnable(c, prefix + " .")
147 | if r.uchildren:
148 | for cn in r.uchildren:
149 | self.dump_runnable(r.uchildren[cn], prefix + " .")
150 |
151 | def dump(self, prefix=""):
152 | print("Runnables:")
153 | for id in self.runnables:
154 | self.dump_runnable(self.runnables[id], prefix)
155 |
156 |
157 | class Event:
158 | """
159 | Stores data associated with an event.
160 | """
161 |
162 | def __init__(self, from_id, to_id):
163 | self.from_id = from_id
164 | """ ID of the source runnable for this event.
165 |
166 | :type: Integer """
167 |
168 | self.to_id = to_id
169 | """ ID of the destination runnable for this event.
170 |
171 | :type: Integer """
172 |
--------------------------------------------------------------------------------
/lems/test/NeuroML2CoreTypes/NeuroML2CoreTypes.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/lems/test/NeuroML2CoreTypes/NeuroMLCoreCompTypes.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
--------------------------------------------------------------------------------
/lems/test/NeuroML2CoreTypes/NeuroMLCoreDimensions.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
--------------------------------------------------------------------------------
/lems/test/NeuroML2CoreTypes/Simulation.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/lems/test/hhcell_resaved2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/lems/test/reg_test_20.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """
3 | Regression test for https://github.com/LEMS/pylems/issues/20
4 |
5 | File: reg_test_20.py
6 |
7 | Copyright 2023 LEMS contributors
8 | Author: Ankur Sinha
9 | """
10 |
11 |
12 | import unittest
13 | import os
14 | import textwrap
15 | import tempfile
16 | import typing
17 |
18 | from lems.run import run as lems_run
19 |
20 |
21 | class TestIssue20Regression(unittest.TestCase):
22 |
23 | """Regression test for issue #20
24 |
25 | PyLEMS does not initialise initMembPotential correctly.
26 | """
27 |
28 | def test_initMembPotential_init(self):
29 | """Test for https://github.com/LEMS/pylems/issues/20"""
30 | initmembpot = -20.000000000000000000000
31 | reg_20_nml = textwrap.dedent(
32 | """
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | |
60 |
61 | """.format(
62 | initmembpot
63 | )
64 | )
65 | nml_file = tempfile.NamedTemporaryFile(mode="w+b")
66 | nml_file.write(str.encode(reg_20_nml))
67 | nml_file.flush()
68 |
69 | reg_20_xml = textwrap.dedent(
70 | """
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 | """.format(
86 | nml_file.name
87 | )
88 | )
89 |
90 | xml_file = tempfile.NamedTemporaryFile(mode="w+b")
91 | xml_file.write(str.encode(reg_20_xml))
92 | xml_file.flush()
93 |
94 | # TODO: replace this with pynml's extract LEMS files function when that has
95 | # been merged and released. We won't need to carry a copy of the coretypes
96 | # then.
97 | coretype_files_dir = (
98 | os.path.dirname(os.path.abspath(__file__)) + "/NeuroML2CoreTypes"
99 | )
100 | lems_run(xml_file.name, include_dirs=[coretype_files_dir])
101 |
102 | # Deletes the files also
103 | nml_file.close()
104 | xml_file.close()
105 |
106 | with open("reg_20.dat", "r") as res:
107 | for line in res:
108 | ln = line.split()
109 | time = float(ln[0])
110 | value = float(ln[1])
111 | assert time == 0
112 | self.assertAlmostEqual(value, initmembpot / 1000.0, delta=0.01)
113 | # We only want to check the first line
114 | break
115 | os.remove("reg_20.dat")
116 |
--------------------------------------------------------------------------------
/lems/test/test_exposure_listing.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/lems/test/test_load_write.py:
--------------------------------------------------------------------------------
1 | """
2 | Unit tests for loading/writing
3 |
4 | """
5 |
6 | import unittest
7 | from lems.model.model import Model
8 |
9 |
10 | class TestLoadWrite(unittest.TestCase):
11 | def test_load_write_xml(self):
12 | model = Model()
13 | file_name = "lems/test/hhcell_resaved2.xml"
14 | model.import_from_file(file_name)
15 | file_name2 = "lems/test/hhcell_resaved3.xml"
16 | model.export_to_file(file_name2)
17 |
18 | print("----------------------------------------------")
19 | print(open(file_name2, "r").read())
20 | print("----------------------------------------------")
21 |
22 | print("Written generated LEMS to %s" % file_name2)
23 |
24 | from lems.base.util import validate_lems
25 |
26 | validate_lems(file_name2)
27 |
28 | def test_load_get_dom(self):
29 | model = Model()
30 | file_name = "lems/test/hhcell_resaved2.xml"
31 | model.import_from_file(file_name)
32 | dom0 = model.export_to_dom()
33 |
--------------------------------------------------------------------------------
/lems/test/test_misc.py:
--------------------------------------------------------------------------------
1 | """
2 | Misc tests.
3 |
4 | File: test_misc.py
5 |
6 | Copyright 2023 LEMS contributors
7 | Author: Ankur Sinha
8 | """
9 |
10 |
11 | import unittest
12 | import os
13 | from lems.model.model import Model
14 |
15 |
16 | class TestExposure(unittest.TestCase):
17 |
18 | """Test getting exposures from LEMS models"""
19 |
20 | def test_exposure_getters(self):
21 | model = Model(include_includes=True, fail_on_missing_includes=True)
22 | file_name = (
23 | os.path.dirname(os.path.abspath(__file__)) + "/test_exposure_listing.xml"
24 | )
25 | model.import_from_file(file_name)
26 | exp_list = model.list_exposures()
27 | for c, es in exp_list.items():
28 | # iaf1 defines v as an exposure
29 | if c.id == "example_iaf1_cell":
30 | self.assertTrue("v" in es)
31 | # iaf2 extends iaf1 and so should inherit v
32 | if c.id == "example_iaf2_cell":
33 | self.assertTrue("v" in es)
34 |
35 | paths = model.list_recording_paths_for_exposures(substring="", target="net1")
36 | self.assertTrue("net1/p1[0]/v" in paths)
37 | self.assertTrue("net1/p1[1]/v" in paths)
38 | self.assertTrue("net1/p1[2]/v" in paths)
39 | self.assertTrue("net1/p1[3]/v" in paths)
40 | self.assertTrue("net1/p1[4]/v" in paths)
41 | self.assertTrue("net1/p2[0]/v" in paths)
42 |
43 |
44 | if __name__ == "__main__":
45 | unittest.main()
46 |
--------------------------------------------------------------------------------
/lems/test/test_parser.py:
--------------------------------------------------------------------------------
1 | """
2 | Unit tests for Parser
3 |
4 | """
5 |
6 |
7 | import unittest
8 | from lems.parser.expr import ExprParser
9 |
10 |
11 | class TestParser(unittest.TestCase):
12 | def test_parser(self):
13 | x = 0.5
14 |
15 | exprs = {}
16 | exprs["x"] = "{x}"
17 | exprs["exp(x)"] = "(exp {x})"
18 |
19 | all = False
20 | all = True
21 |
22 | if all:
23 | exprs[
24 | "(R * temperature / (zCa * F)) * log(caConcExt / caConc)"
25 | ] = "(* (/ (* {R} {temperature}) (* {zCa} {F})) (log (/ {caConcExt} {caConc})))"
26 | exprs[
27 | "( (V - ((V^3) / 3)) - W + I) / SEC"
28 | ] = "(/ (+ (- (- {V} (/ (^ {V} {3.0}) {3.0})) {W}) {I}) {SEC})"
29 | exprs[
30 | "(V - (V^3) / 3 - W + I) / SEC"
31 | ] = "(/ (- {V} (+ (- (/ (^ {V} {3.0}) {3.0}) {W}) {I})) {SEC})"
32 | exprs["120+300"] = "(+ {120.0} {300.0})"
33 | exprs["12e-22"] = "{1.2e-21}"
34 | exprs["1e+22"] = "{1e+22}"
35 | exprs["1-1E+2+2"] = "(+ (- {1.0} {100.0}) {2.0})"
36 | exprs["5.0E-11"] = "{5e-11}"
37 | exprs["a + (b + c) * d"] = "(+ {a} (* (+ {b} {c}) {d}))"
38 | exprs["1 + (exp(x))"] = "(+ {1.0} (exp {x}))"
39 | exprs["exp(x)"] = "(exp {x})"
40 | exprs["x / y * z"] = "(* (/ {x} {y}) {z})"
41 | exprs["x / (y) * z"] = "(* (/ {x} {y}) {z})"
42 | exprs["(y - z) + t"] = "(+ (- {y} {z}) {t})"
43 | exprs["x + (y) - z"] = "(- (+ {x} {y}) {z})"
44 | exprs["exp(v*2)"] = "(exp (* {v} {2.0}))"
45 | exprs["exp(-x)"] = "(exp (- {0.0} {x}))"
46 | exprs["sin(y)"] = "(sin {y})"
47 | exprs["H(y)"] = "(H {y})"
48 | exprs["a / b"] = "(/ {a} {b})"
49 | exprs["a / (b)"] = "(/ {a} {b})"
50 |
51 | exprs[
52 | "(120 + 300/( (exp ((V + 55)/9)) + (exp ((V + 65)/(-16)))))"
53 | ] = "(+ {120.0} (/ {300.0} (+ (exp (/ (+ {V} {55.0}) {9.0})) (exp (/ (+ {V} {65.0}) (- {0.0} {16.0}))))))"
54 |
55 | exprs[
56 | "(43.4 - 42.6/(1.0 + (exp ((V + 68.1)/(-20.5)))))"
57 | ] = "(- {43.4} (/ {42.6} (+ {1.0} (exp (/ (+ {V} {68.1}) (- {0.0} {20.5}))))))"
58 |
59 | exprs[
60 | "(2.64 - 2.52/(1.0 + (exp ((V+120)/(-25)))))"
61 | ] = "(- {2.64} (/ {2.52} (+ {1.0} (exp (/ (+ {V} {120.0}) (- {0.0} {25.0}))))))"
62 |
63 | exprs[
64 | "(1.34 / (1.0 + (exp ((V + 62.9)/(-10)))) * (1.5 + 1.0/(1.0 + (exp ((V+34.9)/3.6)))))"
65 | ] = "(* (/ {1.34} (+ {1.0} (exp (/ (+ {V} {62.9}) (- {0.0} {10.0}))))) (+ {1.5} (/ {1.0} (+ {1.0} (exp (/ (+ {V} {34.9}) {3.6}))))))"
66 |
67 | for expr in exprs.keys():
68 | self.parse_expr(expr, exprs[expr])
69 |
70 | bad_exprs = {}
71 | bad_exprs["exxp(x)"] = "(exxp {x})"
72 | bad_exprs["ln(x)"] = "(ln {x})" # Use log instead!!
73 |
74 | for expr in bad_exprs.keys():
75 | self.parse_expr(expr, bad_exprs[expr], True)
76 |
77 | def parse_expr(self, expr, val, should_fail=False):
78 | print("\n--- Parsing %s, checking against %s" % (expr, val))
79 | ep = ExprParser(expr)
80 | try:
81 | pt = ep.parse()
82 | print("Expr: %s " % expr)
83 | print("Parsed as: %s " % (str(pt)))
84 | print("Expected : %s " % (val))
85 | print("Math : %s " % (pt.to_python_expr()))
86 |
87 | assert str(pt) == val
88 | print("Success")
89 | except Exception as e:
90 | if not should_fail:
91 | print("Exception thrown %s" % e)
92 | assert 1 == 2
93 | else:
94 | print("Successfully failed")
95 |
96 |
97 | if __name__ == "__main__":
98 | TestParser().test_parser()
99 |
--------------------------------------------------------------------------------
/lems/test/test_units.py:
--------------------------------------------------------------------------------
1 | """
2 | Unit tests for Unit/Dimension handling
3 |
4 |
5 | """
6 |
7 |
8 | import unittest
9 | from lems.model.fundamental import Dimension, Unit
10 | from lems.model.model import Model
11 |
12 |
13 | class TestUnitParsing(unittest.TestCase):
14 | def get_model(self):
15 | model = Model()
16 |
17 | model.add(Dimension("voltage", m=1, l=3, t=-3, i=-1))
18 | model.add(Dimension("time", t=1))
19 | model.add(Dimension("capacitance", m=-1, l=-2, t=4, i=2))
20 | model.add(Dimension("conductanceDensity", m="-1", l="-4", t="3", i="2"))
21 | model.add(Dimension("temperature", k=1))
22 |
23 | model.add(Unit("volt", "V", "voltage", 0))
24 | model.add(Unit("milliVolt", "mV", "voltage", -3))
25 | model.add(Unit("milliSecond", "ms", "time", -3))
26 | model.add(Unit("microFarad", "uF", "capacitance", -12))
27 | model.add(Unit("mS_per_cm2", "mS_per_cm2", "conductanceDensity", 1))
28 |
29 | model.add(Unit("Kelvin", "K", "temperature", 0))
30 | model.add(Unit("celsius", "degC", "temperature", 0, offset=273.15))
31 |
32 | model.add(Unit("hour", "hour", "time", scale=3600))
33 | model.add(Unit("min", "min", "time", scale=60))
34 |
35 | return model
36 |
37 | def check_num_val(self, unit_str, val, dimension=None):
38 | val2 = self.get_model().get_numeric_value(unit_str, dimension)
39 | print(
40 | "Ensuring %s returns %f in SI units of %s; it returns %f"
41 | % (unit_str, val, dimension, val2)
42 | )
43 | self.assertAlmostEqual(val, val2)
44 |
45 | def test_parse_units(self):
46 | self.check_num_val("-60mV", -0.06, "voltage")
47 | self.check_num_val("1V", 1, "voltage")
48 | self.check_num_val("10 K", 10)
49 | self.check_num_val("0 K", 0)
50 | self.check_num_val("0 degC", 273.15)
51 | self.check_num_val("-40 degC", 233.15)
52 |
53 | self.check_num_val("1.1e-2 ms", 0.000011, "time")
54 | self.check_num_val("5E-24", 5e-24)
55 | self.check_num_val("1.1ms", 0.0011)
56 | self.check_num_val("-60mV", -0.060)
57 | self.check_num_val("-60", -60)
58 | self.check_num_val("1.1e-2 ms", 0.000011)
59 |
60 | self.check_num_val("10.5 mS_per_cm2", 105, "conductanceDensity")
61 | self.check_num_val("10.5 mS_per_cm2", 105)
62 |
63 | self.check_num_val("1 hour", 3600)
64 | self.check_num_val("30 min", 30 * 60)
65 |
--------------------------------------------------------------------------------
/man/man1/README.md:
--------------------------------------------------------------------------------
1 | # pylems.1
2 |
3 |
4 | Generated using `help2man `__ from `pylems -h` output:
5 |
6 | ```
7 | $ help2man -n "LEMS interpreter implemented in Python" --version-string="0.5.8" -N pylems -S "https://lems.github.io" -o pylems.1
8 | ```
9 |
10 | On Linux systems, this file would go into `/usr/share/man/man1`.
11 | The file can be locally viewed without installation using `man -l pylems.1`.
12 |
--------------------------------------------------------------------------------
/man/man1/pylems.1:
--------------------------------------------------------------------------------
1 | .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.5.
2 | .TH PYLEMS "1" "November 2021" "https://lems.github.io" "User Commands"
3 | .SH NAME
4 | pylems \- LEMS interpreter implemented in Python
5 | .SH DESCRIPTION
6 | usage: pylems [\-h] [\-I ] [\-nogui] [\-dlems]
7 | .SS "positional arguments:"
8 | .TP
9 |
10 | LEMS file to be simulated
11 | .SS "options:"
12 | .TP
13 | \fB\-h\fR, \fB\-\-help\fR
14 | show this help message and exit
15 | .TP
16 | \fB\-I\fR
17 | Directory to be searched for included files
18 | .TP
19 | \fB\-nogui\fR
20 | If this is specified, just parse & simulate the model,
21 | but don't show any plots
22 | .TP
23 | \fB\-dlems\fR
24 | If this is specified, export the LEMS file as dLEMS
25 | (distilled LEMS in JSON format, see
26 | https://github.com/borismarin/som\-codegen)
27 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["setuptools"]
3 | build-backend = "setuptools.build_meta"
4 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [metadata]
2 | name = PyLEMS
3 | version = 0.6.7
4 | author = PyLEMS authors and contributors
5 | author_email = gautham@lisphacker.org, p.gleeson@gmail.com
6 | maintainer_email = p.gleeson@gmail.com
7 | url = https://github.com/LEMS/pylems
8 | description = A Python library for working with the Low Entropy Model Specification language (LEMS)
9 | long_description = file: README.md
10 | long_description_content_type=text/markdown
11 | classifiers =
12 | Intended Audience :: Science/Research
13 | License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
14 | Natural Language :: English
15 | Operating System :: OS Independent
16 | Programming Language :: Python :: 3.8
17 | Programming Language :: Python :: 3.9
18 | Programming Language :: Python :: 3.10
19 | Programming Language :: Python :: 3.11
20 | Programming Language :: Python :: 3.12
21 | Topic :: Scientific/Engineering
22 | license = LGPL-3.0-only
23 |
24 | [options]
25 | install_requires =
26 | lxml
27 | typing; python_version<"3.5"
28 |
29 | packages = find:
30 |
31 | [options.packages.find]
32 | where = .
33 | include = lems*
34 |
35 | [options.entry_points]
36 | console_scripts =
37 | pylems = lems.run:main
38 |
39 |
40 | [options.extras_require]
41 | doc =
42 | sphinxcontrib-bibtex
43 |
44 | [flake8]
45 | # ignore:
46 | # spacing around operators, comment blocks, in argument lists
47 | # lines too long
48 | ignore = E501,E502,F403,F405,E231,E228,E225,E226,E265,E261
49 |
--------------------------------------------------------------------------------