diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 89ab9c7..1dd19e1 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -13,7 +13,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: [3.7,3.9]
+ python-version: ["3.8", "3.9", "3.10", "3.11"]
env:
JNML_HOME: "/home/runner/work/NeuroMLlite/NeuroMLlite/jNeuroML"
HDF5_DISABLE_VERSION_CHECK: 1
@@ -58,9 +58,9 @@ jobs:
cd pyNeuroML
git checkout $pynml_branch
pip install pandas==1.3.5
- pip install NEURON==7.8.2 # Specify version of neuron - 8.2.1 fails
+ pip install NEURON==8.2.2 # Specify version of neuron - 8.2.1 fails
#pip install -r requirements-dev.txt
- python setup.py install
+ pip install .
cd -
# Install latest jnml...
diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml
new file mode 100644
index 0000000..0fe16bc
--- /dev/null
+++ b/.github/workflows/python-publish.yml
@@ -0,0 +1,36 @@
+# This workflow will upload a Python Package using Twine when a release is created
+# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
+
+# This workflow uses actions that are not certified by GitHub.
+# They are provided by a third-party and are governed by
+# separate terms of service, privacy policy, and support
+# documentation.
+
+name: Upload Python Package
+
+on:
+ release:
+ types: [published]
+
+jobs:
+ deploy:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+ - name: Set up Python
+ uses: actions/setup-python@v3
+ with:
+ python-version: '3.x'
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install build
+ - name: Build package
+ run: python -m build
+ - name: Publish package
+ uses: pypa/gh-action-pypi-publish@release/v1
+ with:
+ user: __token__
+ password: ${{ secrets.PYPI_API_TOKEN }}
diff --git a/.gitignore b/.gitignore
index 4afa231..50bcaa0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -202,3 +202,11 @@ docs/_build
/examples/pyr_4_sym.cell.nml
*_eden.py
arm64
+/examples/Example4_PyNN.mdf
+*.mdf.json
+*.mdf.yaml
+/examples/Example6_PyNN.mdf
+/examples/Example7_Brunel2000.mdf
+/examples/Example3_Network.yaml
+/examples/SimExample3.yaml
+/examples/Example4_PyNN.mdf.1
diff --git a/docs/NeuroMLlite_specification.json b/docs/NeuroMLlite_specification.json
index 97948a1..48f192e 100644
--- a/docs/NeuroMLlite_specification.json
+++ b/docs/NeuroMLlite_specification.json
@@ -1,5 +1,5 @@
{
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"specification": {
"Network": {
"definition": "A Network containing multiple Population's, connected by Projection's and receiving Input's",
@@ -237,7 +237,7 @@
"description": "Unique identifier for this Population"
},
"size": {
- "type": "Union[EvaluableExpression, T, VT, ndarray, int, float, str]",
+ "type": "Union[EvaluableExpression, List, Dict, ndarray, int, float, str]",
"description": "The size of the population."
},
"component": {
@@ -366,11 +366,11 @@
"description": "type of projection: projection (default; standard chemical, event triggered), electricalProjection\n(for gap junctions) or continuousProjection (for analogue/graded synapses)"
},
"delay": {
- "type": "Union[EvaluableExpression, T, VT, ndarray, int, float, str]",
+ "type": "Union[EvaluableExpression, List, Dict, ndarray, int, float, str]",
"description": "Delay to use (default: 0)"
},
"weight": {
- "type": "Union[EvaluableExpression, T, VT, ndarray, int, float, str]",
+ "type": "Union[EvaluableExpression, List, Dict, ndarray, int, float, str]",
"description": "Weight to use (default: 1)"
},
"random_connectivity": {
@@ -395,7 +395,7 @@
"description": ""
},
"probability": {
- "type": "Union[EvaluableExpression, T, VT, ndarray, int, float, str]",
+ "type": "Union[EvaluableExpression, List, Dict, ndarray, int, float, str]",
"description": "Random probability of connection."
}
}
@@ -442,23 +442,23 @@
"description": "Population to target"
},
"cell_ids": {
- "type": "Union[EvaluableExpression, T, VT, ndarray, int, float, str]",
+ "type": "Union[EvaluableExpression, List, Dict, ndarray, int, float, str]",
"description": "Specific ids of _Cell_s to apply this input to (cannot be used with percentage"
},
"percentage": {
- "type": "float",
+ "type": "Union[EvaluableExpression, List, Dict, ndarray, int, float, str]",
"description": "Percentage of Cells to apply input to"
},
"number_per_cell": {
- "type": "Union[EvaluableExpression, T, VT, ndarray, int, float, str]",
+ "type": "Union[EvaluableExpression, List, Dict, ndarray, int, float, str]",
"description": "Number of individual inputs per selected Cell (default: 1)"
},
"segment_ids": {
- "type": "Union[EvaluableExpression, T, VT, ndarray, int, float, str]",
+ "type": "Union[EvaluableExpression, List, Dict, ndarray, int, float, str]",
"description": "Which segments to target (default: [0])"
},
"weight": {
- "type": "Union[EvaluableExpression, T, VT, ndarray, int, float, str]",
+ "type": "Union[EvaluableExpression, List, Dict, ndarray, int, float, str]",
"description": "Weight to use (default: 1)"
}
}
diff --git a/docs/NeuroMLlite_specification.yaml b/docs/NeuroMLlite_specification.yaml
index 654994c..c05d843 100644
--- a/docs/NeuroMLlite_specification.yaml
+++ b/docs/NeuroMLlite_specification.yaml
@@ -1,4 +1,4 @@
-version: NeuroMLlite v0.5.3
+version: NeuroMLlite v0.5.7
specification:
Network:
definition: A Network containing multiple Population's, connected by Projection's
@@ -178,7 +178,8 @@ specification:
type: str
description: Unique identifier for this Population
size:
- type: Union[EvaluableExpression, T, VT, ndarray, int, float, str]
+ type: Union[EvaluableExpression, List, Dict, ndarray, int, float,
+ str]
description: The size of the population.
component:
type: str
@@ -276,10 +277,12 @@ specification:
(for gap junctions) or continuousProjection (for analogue/graded
synapses)'
delay:
- type: Union[EvaluableExpression, T, VT, ndarray, int, float, str]
+ type: Union[EvaluableExpression, List, Dict, ndarray, int, float,
+ str]
description: 'Delay to use (default: 0)'
weight:
- type: Union[EvaluableExpression, T, VT, ndarray, int, float, str]
+ type: Union[EvaluableExpression, List, Dict, ndarray, int, float,
+ str]
description: 'Weight to use (default: 1)'
random_connectivity:
type: RandomConnectivity
@@ -298,7 +301,8 @@ specification:
type: str
description: ''
probability:
- type: Union[EvaluableExpression, T, VT, ndarray, int, float, str]
+ type: Union[EvaluableExpression, List, Dict, ndarray, int, float,
+ str]
description: Random probability of connection.
ConvergentConnectivity:
definition: A ConvergentConnectivity definition.
@@ -331,19 +335,24 @@ specification:
type: str
description: Population to target
cell_ids:
- type: Union[EvaluableExpression, T, VT, ndarray, int, float, str]
+ type: Union[EvaluableExpression, List, Dict, ndarray, int, float,
+ str]
description: Specific ids of _Cell_s to apply this input to (cannot
be used with percentage
percentage:
- type: float
+ type: Union[EvaluableExpression, List, Dict, ndarray, int, float,
+ str]
description: Percentage of Cells to apply input to
number_per_cell:
- type: Union[EvaluableExpression, T, VT, ndarray, int, float, str]
+ type: Union[EvaluableExpression, List, Dict, ndarray, int, float,
+ str]
description: 'Number of individual inputs per selected Cell (default:
1)'
segment_ids:
- type: Union[EvaluableExpression, T, VT, ndarray, int, float, str]
+ type: Union[EvaluableExpression, List, Dict, ndarray, int, float,
+ str]
description: 'Which segments to target (default: [0])'
weight:
- type: Union[EvaluableExpression, T, VT, ndarray, int, float, str]
+ type: Union[EvaluableExpression, List, Dict, ndarray, int, float,
+ str]
description: 'Weight to use (default: 1)'
diff --git a/docs/README.md b/docs/README.md
index a56c868..1833050 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,4 +1,4 @@
-# Specification of NeuroMLlite v0.5.3
+# Specification of NeuroMLlite v0.5.7
**Note: the NeuroMLlite specification is still in development! Subject to change...**
## Network
@@ -404,7 +404,7 @@ A Population definition.
size |
- Union[EvaluableExpression, T, VT, ndarray, int, float, str] |
+ Union[EvaluableExpression, List, Dict, ndarray, int, float, str] |
The size of the population. |
@@ -622,14 +622,14 @@ A Projection definition.
delay |
- Union[EvaluableExpression, T, VT, ndarray, int, float, str] |
+ Union[EvaluableExpression, List, Dict, ndarray, int, float, str] |
Delay to use (default: 0) |
weight |
- Union[EvaluableExpression, T, VT, ndarray, int, float, str] |
+ Union[EvaluableExpression, List, Dict, ndarray, int, float, str] |
Weight to use (default: 1) |
@@ -671,7 +671,7 @@ A RandomConnectivity definition.
probability |
- Union[EvaluableExpression, T, VT, ndarray, int, float, str] |
+ Union[EvaluableExpression, List, Dict, ndarray, int, float, str] |
Random probability of connection. |
@@ -748,35 +748,35 @@ An Input definition.
cell_ids |
- Union[EvaluableExpression, T, VT, ndarray, int, float, str] |
+ Union[EvaluableExpression, List, Dict, ndarray, int, float, str] |
Specific ids of Cells to apply this input to (cannot be used with percentage |
percentage |
- float |
+ Union[EvaluableExpression, List, Dict, ndarray, int, float, str] |
Percentage of Cells to apply input to |
number_per_cell |
- Union[EvaluableExpression, T, VT, ndarray, int, float, str] |
+ Union[EvaluableExpression, List, Dict, ndarray, int, float, str] |
Number of individual inputs per selected Cell (default: 1) |
segment_ids |
- Union[EvaluableExpression, T, VT, ndarray, int, float, str] |
+ Union[EvaluableExpression, List, Dict, ndarray, int, float, str] |
Which segments to target (default: [0]) |
weight |
- Union[EvaluableExpression, T, VT, ndarray, int, float, str] |
+ Union[EvaluableExpression, List, Dict, ndarray, int, float, str] |
Weight to use (default: 1) |
diff --git a/docs/conf.py b/docs/conf.py
index b6ff8df..0360d77 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -53,7 +53,7 @@
# space here is important since __version__ is used in generation of
# version_info also
if "__version__ =" in aline:
- version = aline.split("\"")[1]
+ version = aline.split('"')[1]
# The full version, including alpha/beta/rc tags.
release = version
diff --git a/docs/generate.py b/docs/generate.py
index 1cd6075..1c89d2b 100644
--- a/docs/generate.py
+++ b/docs/generate.py
@@ -2,7 +2,6 @@
if __name__ == "__main__":
-
net = neuromllite.Network(id="net")
doc = net.generate_documentation(format="markdown")
print(doc)
diff --git a/examples/Example10_Lorenz.json b/examples/Example10_Lorenz.json
index 49faf0d..5380a74 100644
--- a/examples/Example10_Lorenz.json
+++ b/examples/Example10_Lorenz.json
@@ -1,6 +1,6 @@
{
"Example10_Lorenz": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"notes": "Example 10: Lorenz",
"parameters": {
"N": 1,
diff --git a/examples/Example10_Lorenz.mdf.yaml b/examples/Example10_Lorenz.mdf.yaml
index 618c1e4..15b70bc 100644
--- a/examples/Example10_Lorenz.mdf.yaml
+++ b/examples/Example10_Lorenz.mdf.yaml
@@ -1,25 +1,32 @@
Example10_Lorenz:
- format: ModECI MDF v0.3
+ format: ModECI MDF v0.4
graphs:
Example10_Lorenz:
notes: 'Example 10: Lorenz'
nodes:
- lorenzPop_0:
+ lorenzPop:
parameters:
sigma:
- value: 10.0
+ value:
+ - 10.0
b:
- value: 2.67
+ value:
+ - 2.67
r:
- value: 28.0
+ value:
+ - 28.0
x0:
- value: 1.0
+ value:
+ - 1.0
y0:
- value: 1.0
+ value:
+ - 1.0
z0:
- value: 1.0
+ value:
+ - 1.0
sec:
- value: 1.0
+ value:
+ - 1.0
x:
default_initial_value: x0
time_derivative: ( sigma * (y - x) ) / sec
diff --git a/examples/Example11_Synapses.json b/examples/Example11_Synapses.json
index 0e158ac..e8a3ace 100644
--- a/examples/Example11_Synapses.json
+++ b/examples/Example11_Synapses.json
@@ -1,6 +1,6 @@
{
"Example11_Synapses": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"notes": "Example 11: synaptic properties",
"parameters": {
"input_amp": 0.23,
@@ -87,7 +87,7 @@
"stim": {
"input_source": "i_clamp",
"population": "pop0",
- "percentage": 100.0
+ "percentage": 100
}
}
}
diff --git a/examples/Example11_Synapses.net.nml b/examples/Example11_Synapses.net.nml
index ea27c89..34f2db2 100644
--- a/examples/Example11_Synapses.net.nml
+++ b/examples/Example11_Synapses.net.nml
@@ -1,5 +1,5 @@
- Generated by NeuroMLlite v0.5.3
+ Generated by NeuroMLlite v0.5.7
Generated network: Example11_Synapses
Generation seed: 1234
NeuroMLlite parameters:
diff --git a/examples/Example12.py b/examples/Example12.py
index c7d183b..adfcba0 100644
--- a/examples/Example12.py
+++ b/examples/Example12.py
@@ -1,5 +1,12 @@
from neuromllite import Network, Cell, InputSource, Population, Synapse
-from neuromllite import Projection, RandomConnectivity, Input, Simulation, RectangularRegion, RandomLayout
+from neuromllite import (
+ Projection,
+ RandomConnectivity,
+ Input,
+ Simulation,
+ RectangularRegion,
+ RandomLayout,
+)
import sys
################################################################################
@@ -11,21 +18,23 @@
net.seed = 1234
net.temperature = 32.0
-net.parameters = {"N": 20,
- "fractionE": 0.7,
- "weightInput": 0.7,
- "prob_e_e": 0.1,
- "prob_e_i": 0.9,
- "prob_i_e": 0.8,
- "prob_i_i": 0.3,
- "global_delay": 2}
-
-r1 = RectangularRegion(
- id="region1", x=0, y=0, z=0, width=1000, height=100, depth=1000
-)
+net.parameters = {
+ "N": 20,
+ "fractionE": 0.7,
+ "weightInput": 0.7,
+ "prob_e_e": 0.1,
+ "prob_e_i": 0.9,
+ "prob_i_e": 0.8,
+ "prob_i_i": 0.3,
+ "global_delay": 2,
+}
+
+r1 = RectangularRegion(id="region1", x=0, y=0, z=0, width=1000, height=100, depth=1000)
net.regions.append(r1)
-pyr_cell = Cell(id="pyr_4_sym", neuroml2_source_file="test_files/acnet2/pyr_4_sym.cell.nml")
+pyr_cell = Cell(
+ id="pyr_4_sym", neuroml2_source_file="test_files/acnet2/pyr_4_sym.cell.nml"
+)
net.cells.append(pyr_cell)
bask_cell = Cell(id="bask", neuroml2_source_file="test_files/acnet2/bask.cell.nml")
net.cells.append(bask_cell)
@@ -61,17 +70,24 @@
net.populations.append(pE)
net.populations.append(pI)
-syn_e_e = Synapse(id="AMPA_syn", neuroml2_source_file="test_files/acnet2/AMPA_syn.synapse.nml")
+syn_e_e = Synapse(
+ id="AMPA_syn", neuroml2_source_file="test_files/acnet2/AMPA_syn.synapse.nml"
+)
net.synapses.append(syn_e_e)
-syn_e_i = Synapse(id="AMPA_syn_inh", neuroml2_source_file="test_files/acnet2/AMPA_syn_inh.synapse.nml")
+syn_e_i = Synapse(
+ id="AMPA_syn_inh", neuroml2_source_file="test_files/acnet2/AMPA_syn_inh.synapse.nml"
+)
net.synapses.append(syn_e_i)
-syn_i_e = Synapse(id="GABA_syn", neuroml2_source_file="test_files/acnet2/GABA_syn.synapse.nml")
+syn_i_e = Synapse(
+ id="GABA_syn", neuroml2_source_file="test_files/acnet2/GABA_syn.synapse.nml"
+)
net.synapses.append(syn_i_e)
-syn_i_i = Synapse(id="GABA_syn_inh", neuroml2_source_file="test_files/acnet2/GABA_syn_inh.synapse.nml")
+syn_i_i = Synapse(
+ id="GABA_syn_inh", neuroml2_source_file="test_files/acnet2/GABA_syn_inh.synapse.nml"
+)
net.synapses.append(syn_i_i)
-
net.projections.append(
Projection(
id="projEE",
@@ -94,7 +110,6 @@
)
-
net.projections.append(
Projection(
id="projIE",
@@ -136,7 +151,7 @@
### Build Simulation object & save as JSON
sim = Simulation(
- id="Sim%s"%net.id,
+ id="Sim%s" % net.id,
network=new_file,
duration="1000",
seed="1111",
@@ -145,7 +160,7 @@
record_spikes={
pE.id: "*",
pI.id: "*",
- }
+ },
)
sim.to_json_file()
diff --git a/examples/Example12_MultiComp.json b/examples/Example12_MultiComp.json
index 8ab0a7a..899d352 100644
--- a/examples/Example12_MultiComp.json
+++ b/examples/Example12_MultiComp.json
@@ -1,6 +1,6 @@
{
"Example12_MultiComp": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"notes": "Example 12: Multicompartmental cells...",
"parameters": {
"N": 20,
@@ -113,7 +113,7 @@
"stim": {
"input_source": "poissonFiringSyn",
"population": "pop_pyr",
- "percentage": 100.0,
+ "percentage": 100,
"weight": "weightInput"
}
},
diff --git a/examples/Example1_TestNetwork.json b/examples/Example1_TestNetwork.json
index b6d0c4c..76a405a 100644
--- a/examples/Example1_TestNetwork.json
+++ b/examples/Example1_TestNetwork.json
@@ -1,6 +1,6 @@
{
"TestNetwork": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"notes": "A simple network with 2 populations & projection between them. No info yet on what the cells are so network can't be simulated.",
"populations": {
"pop0": {
diff --git a/examples/Example2_TestNetwork.json b/examples/Example2_TestNetwork.json
index b203682..42e386d 100644
--- a/examples/Example2_TestNetwork.json
+++ b/examples/Example2_TestNetwork.json
@@ -1,6 +1,6 @@
{
"Example2_TestNetwork": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"notes": "A simple network with 2 populations & projection between them. Cells are specified to be NeuroML 2 HH cell models & pre population is given a spiking input.",
"cells": {
"hhcell": {
@@ -71,7 +71,7 @@
"stim_pop0": {
"input_source": "poissonFiringSyn",
"population": "pop0",
- "percentage": 80.0
+ "percentage": 80
}
}
}
diff --git a/examples/Example2_TestNetwork.net.nml b/examples/Example2_TestNetwork.net.nml
index 4fa2e83..e1de4e8 100644
--- a/examples/Example2_TestNetwork.net.nml
+++ b/examples/Example2_TestNetwork.net.nml
@@ -1,5 +1,5 @@
- Generated by NeuroMLlite v0.5.3
+ Generated by NeuroMLlite v0.5.7
Generated network: Example2_TestNetwork
Generation seed: 1234
diff --git a/examples/Example3.py b/examples/Example3.py
index 67cda1d..58bf606 100644
--- a/examples/Example3.py
+++ b/examples/Example3.py
@@ -11,7 +11,8 @@
net.id = "Example3_Network"
net.notes = "Example 3: simple network with 2 populations of NeuroML2 cells, a projection between them and spiking input."
print(net)
-new_file = net.to_json_file()
+
+new_json_file = net.to_json_file()
################################################################################
### Build Simulation object & save as JSON
@@ -19,7 +20,7 @@
sim = Simulation(
id="SimExample3",
- network=new_file,
+ network=new_json_file,
duration="1000",
dt="0.025",
record_traces={"all": "*"},
diff --git a/examples/Example3_Network.json b/examples/Example3_Network.json
index b333ee4..a323ac5 100644
--- a/examples/Example3_Network.json
+++ b/examples/Example3_Network.json
@@ -1,6 +1,6 @@
{
"Example3_Network": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"notes": "Example 3: simple network with 2 populations of NeuroML2 cells, a projection between them and spiking input.",
"cells": {
"hhcell": {
@@ -71,7 +71,7 @@
"stim_pop0": {
"input_source": "poissonFiringSyn",
"population": "pop0",
- "percentage": 80.0
+ "percentage": 80
}
}
}
diff --git a/examples/Example3_Network.net.nml b/examples/Example3_Network.net.nml
index 4da93af..8993003 100644
--- a/examples/Example3_Network.net.nml
+++ b/examples/Example3_Network.net.nml
@@ -1,5 +1,5 @@
- Generated by NeuroMLlite v0.5.3
+ Generated by NeuroMLlite v0.5.7
Generated network: Example3_Network
Generation seed: 1234
diff --git a/examples/Example4.py b/examples/Example4.py
index 9ed8afb..d579f83 100644
--- a/examples/Example4.py
+++ b/examples/Example4.py
@@ -125,7 +125,7 @@
sim.to_json_file()
sim.network = net_yaml_file
-sim.to_yaml_file('%s.yaml'%sim.id)
+sim.to_yaml_file("%s.yaml" % sim.id)
sim.network = net_json_file # reverting, for call below...
diff --git a/examples/Example4_PyNN.json b/examples/Example4_PyNN.json
index 23ac327..69ae655 100644
--- a/examples/Example4_PyNN.json
+++ b/examples/Example4_PyNN.json
@@ -1,6 +1,6 @@
{
"Example4_PyNN": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"notes": "Example 4: a network with PyNN cells & inputs",
"parameters": {
"input_amp": 0.99
@@ -120,7 +120,7 @@
"stim": {
"input_source": "i_clamp",
"population": "pop0",
- "percentage": 50.0
+ "percentage": 50
}
}
}
diff --git a/examples/Example4_PyNN.net.nml b/examples/Example4_PyNN.net.nml
index 1acf9cd..20d156f 100644
--- a/examples/Example4_PyNN.net.nml
+++ b/examples/Example4_PyNN.net.nml
@@ -1,14 +1,14 @@
- Generated by NeuroMLlite v0.5.3
+ Generated by NeuroMLlite v0.5.7
Generated network: Example4_PyNN
Generation seed: 1234
NeuroMLlite parameters:
input_amp = 0.99
-
-
-
-
+
+
+
+
Example 4: a network with PyNN cells & inputs
diff --git a/examples/Example4_PyNN.yaml b/examples/Example4_PyNN.yaml
index 811518d..b9895fb 100644
--- a/examples/Example4_PyNN.yaml
+++ b/examples/Example4_PyNN.yaml
@@ -1,5 +1,5 @@
Example4_PyNN:
- version: NeuroMLlite v0.5.3
+ version: NeuroMLlite v0.5.7
notes: 'Example 4: a network with PyNN cells & inputs'
parameters:
input_amp: 0.99
@@ -88,4 +88,4 @@ Example4_PyNN:
stim:
input_source: i_clamp
population: pop0
- percentage: 50.0
+ percentage: 50
diff --git a/examples/Example6.py b/examples/Example6.py
index a03dde3..8fbf52e 100644
--- a/examples/Example6.py
+++ b/examples/Example6.py
@@ -6,7 +6,6 @@
def generate(ref="Example6_PyNN", add_inputs=True):
-
################################################################################
### Build new network
@@ -69,7 +68,6 @@ def generate(ref="Example6_PyNN", add_inputs=True):
layers = ["L23", "L4", "L5", "L6"]
for l in layers:
-
i = 3 - layers.index(l)
r = RectangularRegion(
id=l,
@@ -83,7 +81,6 @@ def generate(ref="Example6_PyNN", add_inputs=True):
net.regions.append(r)
for t in ["E", "I"]:
-
try:
import opencortex.utils.color as occ
@@ -223,7 +220,6 @@ def generate(ref="Example6_PyNN", add_inputs=True):
if __name__ == "__main__":
-
if "-noinputs" in sys.argv:
sim, net = generate("Example6_PyNN_noinputs", False)
else:
diff --git a/examples/Example6_PyNN.json b/examples/Example6_PyNN.json
index 782817b..90719f4 100644
--- a/examples/Example6_PyNN.json
+++ b/examples/Example6_PyNN.json
@@ -1,6 +1,6 @@
{
"Example6_PyNN": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"notes": "Another network for PyNN - work in progress...",
"parameters": {
"N_scaling": 0.005,
diff --git a/examples/Example6_PyNN.net.nml b/examples/Example6_PyNN.net.nml
index a3783c6..4fe9d45 100644
--- a/examples/Example6_PyNN.net.nml
+++ b/examples/Example6_PyNN.net.nml
@@ -1,5 +1,5 @@
- Generated by NeuroMLlite v0.5.3
+ Generated by NeuroMLlite v0.5.7
Generated network: Example6_PyNN
Generation seed: 1234
NeuroMLlite parameters:
@@ -8,7 +8,7 @@
input_weight = 0.1
layer_height = 400
width = 100
-
+
@@ -2779,7009 +2779,7009 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/Example6_PyNN_noinputs.json b/examples/Example6_PyNN_noinputs.json
index b07d755..a141bf4 100644
--- a/examples/Example6_PyNN_noinputs.json
+++ b/examples/Example6_PyNN_noinputs.json
@@ -1,6 +1,6 @@
{
"Example6_PyNN_noinputs": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"notes": "Another network for PyNN - work in progress...",
"parameters": {
"N_scaling": 0.005,
diff --git a/examples/Example6_PyNN_noinputs.net.nml b/examples/Example6_PyNN_noinputs.net.nml
index 5809fe1..acc00d0 100644
--- a/examples/Example6_PyNN_noinputs.net.nml
+++ b/examples/Example6_PyNN_noinputs.net.nml
@@ -1,5 +1,5 @@
- Generated by NeuroMLlite v0.5.3
+ Generated by NeuroMLlite v0.5.7
Generated network: Example6_PyNN_noinputs
Generation seed: 1234
NeuroMLlite parameters:
@@ -8,7 +8,7 @@
input_weight = 0.1
layer_height = 400
width = 100
-
+
@@ -1202,7096 +1202,7096 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/Example7.py b/examples/Example7.py
index 8914e69..0a080ad 100644
--- a/examples/Example7.py
+++ b/examples/Example7.py
@@ -14,7 +14,6 @@
def generate():
-
dt = 0.025
simtime = 1000
@@ -228,9 +227,7 @@ def generate():
if __name__ == "__main__":
-
if "-sweep" in sys.argv:
-
from neuromllite.sweep.ParameterSweep import *
sim, net = generate()
@@ -298,7 +295,6 @@ def generate():
plt.show()
if "-sweep2" in sys.argv:
-
sim, net = generate()
sim.record_traces = {}
@@ -372,7 +368,6 @@ def generate():
plt.show()
else:
-
sim, net = generate()
################################################################################
diff --git a/examples/Example7_Brunel2000.json b/examples/Example7_Brunel2000.json
index b307816..1876d95 100644
--- a/examples/Example7_Brunel2000.json
+++ b/examples/Example7_Brunel2000.json
@@ -1,6 +1,6 @@
{
"Example7_Brunel2000": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"notes": "Example 7: based on network of Brunel 2000",
"parameters": {
"g": 4,
diff --git a/examples/Example7_Brunel2000.net.nml b/examples/Example7_Brunel2000.net.nml
index a2e3f6a..767a913 100644
--- a/examples/Example7_Brunel2000.net.nml
+++ b/examples/Example7_Brunel2000.net.nml
@@ -1,5 +1,5 @@
- Generated by NeuroMLlite v0.5.3
+ Generated by NeuroMLlite v0.5.7
Generated network: Example7_Brunel2000
Generation seed: 1234
NeuroMLlite parameters:
@@ -14,7 +14,7 @@
tauRef = 2.0
tauSyn = 0.1
theta = 20.0
-
+
diff --git a/examples/Example8.py b/examples/Example8.py
index 2731db3..504f846 100644
--- a/examples/Example8.py
+++ b/examples/Example8.py
@@ -9,7 +9,7 @@
net.notes = "Example 8: general testing..."
net.seed = 7890
-net.temperature = 32.0
+net.temperature = 32
net.parameters = {"N": 10, "fractionE": 0.8, "weightInput": 1}
diff --git a/examples/Example8_Extension.json b/examples/Example8_Extension.json
index 38eea78..ca00411 100644
--- a/examples/Example8_Extension.json
+++ b/examples/Example8_Extension.json
@@ -1,6 +1,6 @@
{
"Example8_Extension": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"notes": "Example 8: general testing...",
"parameters": {
"N": 10,
@@ -57,7 +57,7 @@
"stim": {
"input_source": "poissonFiringSyn",
"population": "Epop",
- "percentage": 50.0,
+ "percentage": 50,
"weight": "weightInput"
}
},
diff --git a/examples/Example9_HindmarshRose.json b/examples/Example9_HindmarshRose.json
index f63356f..7792ec6 100644
--- a/examples/Example9_HindmarshRose.json
+++ b/examples/Example9_HindmarshRose.json
@@ -1,6 +1,6 @@
{
"Example9_HindmarshRose": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"notes": "Example 9: HindmarshRose",
"parameters": {
"N": 1,
diff --git a/examples/LEMS_SimExample3.xml b/examples/LEMS_SimExample3.xml
index 8f64f8c..c683160 100644
--- a/examples/LEMS_SimExample3.xml
+++ b/examples/LEMS_SimExample3.xml
@@ -2,7 +2,7 @@
diff --git a/examples/LEMS_SimExample4.xml b/examples/LEMS_SimExample4.xml
index 3de6589..449619e 100644
--- a/examples/LEMS_SimExample4.xml
+++ b/examples/LEMS_SimExample4.xml
@@ -2,7 +2,7 @@
diff --git a/examples/SimExample10.json b/examples/SimExample10.json
index c7c4731..3326ea9 100644
--- a/examples/SimExample10.json
+++ b/examples/SimExample10.json
@@ -1,6 +1,6 @@
{
"SimExample10": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"network": "Example10_Lorenz.json",
"duration": 10000.0,
"dt": 1.0,
diff --git a/examples/SimExample11.json b/examples/SimExample11.json
index 93717d6..e816096 100644
--- a/examples/SimExample11.json
+++ b/examples/SimExample11.json
@@ -1,6 +1,6 @@
{
"SimExample11": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"network": "Example11_Synapses.json",
"duration": 1000.0,
"dt": 0.01,
diff --git a/examples/SimExample12_MultiComp.json b/examples/SimExample12_MultiComp.json
index a627bcb..7833778 100644
--- a/examples/SimExample12_MultiComp.json
+++ b/examples/SimExample12_MultiComp.json
@@ -1,6 +1,6 @@
{
"SimExample12_MultiComp": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"network": "Example12_MultiComp.json",
"duration": 1000.0,
"dt": 0.025,
diff --git a/examples/SimExample3.json b/examples/SimExample3.json
index cf8b948..30e11d9 100644
--- a/examples/SimExample3.json
+++ b/examples/SimExample3.json
@@ -1,6 +1,6 @@
{
"SimExample3": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"network": "Example3_Network.json",
"duration": 1000.0,
"dt": 0.025,
diff --git a/examples/SimExample4.json b/examples/SimExample4.json
index 0692a20..309083d 100644
--- a/examples/SimExample4.json
+++ b/examples/SimExample4.json
@@ -1,6 +1,6 @@
{
"SimExample4": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"network": "Example4_PyNN.json",
"duration": 1000.0,
"dt": 0.01,
diff --git a/examples/SimExample4.yaml b/examples/SimExample4.yaml
index d142ce5..875fcf9 100644
--- a/examples/SimExample4.yaml
+++ b/examples/SimExample4.yaml
@@ -1,5 +1,5 @@
SimExample4:
- version: NeuroMLlite v0.5.3
+ version: NeuroMLlite v0.5.7
network: Example4_PyNN.yaml
duration: 1000.0
dt: 0.01
diff --git a/examples/SimExample6_PyNN.json b/examples/SimExample6_PyNN.json
index 764dd2f..a0686d6 100644
--- a/examples/SimExample6_PyNN.json
+++ b/examples/SimExample6_PyNN.json
@@ -1,6 +1,6 @@
{
"SimExample6_PyNN": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"network": "Example6_PyNN.json",
"duration": 100.0,
"dt": 0.025,
diff --git a/examples/SimExample7.json b/examples/SimExample7.json
index a4ed679..b827ae4 100644
--- a/examples/SimExample7.json
+++ b/examples/SimExample7.json
@@ -1,6 +1,6 @@
{
"SimExample7": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"network": "Example7_Brunel2000.json",
"duration": 1000.0,
"dt": 0.025,
diff --git a/examples/SimExample8.json b/examples/SimExample8.json
index d317ad4..e7924ab 100644
--- a/examples/SimExample8.json
+++ b/examples/SimExample8.json
@@ -1,6 +1,6 @@
{
"SimExample8": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"network": "Example8_Extension.json",
"duration": 1000.0,
"dt": 0.025,
diff --git a/examples/SimExample9.json b/examples/SimExample9.json
index 8d355b9..31eefa7 100644
--- a/examples/SimExample9.json
+++ b/examples/SimExample9.json
@@ -1,6 +1,6 @@
{
"SimExample9": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"network": "Example9_HindmarshRose.json",
"duration": 1000000.0,
"dt": 25.0,
diff --git a/examples/arbor/ArborExample.json b/examples/arbor/ArborExample.json
index f8dc49d..3b7acec 100644
--- a/examples/arbor/ArborExample.json
+++ b/examples/arbor/ArborExample.json
@@ -1,6 +1,6 @@
{
"ArborExample": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"notes": "Example for testing Arbor",
"parameters": {
"v_init": -50,
diff --git a/examples/arbor/ArborExample.py b/examples/arbor/ArborExample.py
index 5167798..03df74d 100644
--- a/examples/arbor/ArborExample.py
+++ b/examples/arbor/ArborExample.py
@@ -103,7 +103,7 @@
net.projections[0].random_connectivity = RandomConnectivity(probability=0.5)
-'''
+"""
net.synapses.append(Synapse(id='gabaSyn',
pynn_receptor_type='inhibitory',
pynn_synapse_type='cond_alpha',
@@ -116,10 +116,10 @@
synapse='gabaSyn',
delay=2,
weight=0.01))
-net.projections[1].random_connectivity=RandomConnectivity(probability=1)'''
+net.projections[1].random_connectivity=RandomConnectivity(probability=1)"""
net.inputs.append(
- Input(id="stim", input_source=input_source.id, population=p0.id, cell_ids=[1,2])
+ Input(id="stim", input_source=input_source.id, population=p0.id, cell_ids=[1, 2])
)
print(net.to_json())
@@ -141,7 +141,7 @@
sim.to_json_file()
sim.network = new_file_yaml
-sim.to_yaml_file('%s.yaml'%sim.id)
+sim.to_yaml_file("%s.yaml" % sim.id)
################################################################################
diff --git a/examples/arbor/ArborExample.yaml b/examples/arbor/ArborExample.yaml
index 9920bbb..f3d8586 100644
--- a/examples/arbor/ArborExample.yaml
+++ b/examples/arbor/ArborExample.yaml
@@ -1,5 +1,5 @@
ArborExample:
- version: NeuroMLlite v0.5.3
+ version: NeuroMLlite v0.5.7
notes: Example for testing Arbor
parameters:
v_init: -50
diff --git a/examples/arbor/SimArborExample.json b/examples/arbor/SimArborExample.json
index 3abbb01..ca27e3b 100644
--- a/examples/arbor/SimArborExample.json
+++ b/examples/arbor/SimArborExample.json
@@ -1,6 +1,6 @@
{
"SimArborExample": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"network": "ArborExample.json",
"duration": 100.0,
"dt": 0.01,
diff --git a/examples/arbor/SimArborExample.yaml b/examples/arbor/SimArborExample.yaml
index 5fdeeb4..6951a5b 100644
--- a/examples/arbor/SimArborExample.yaml
+++ b/examples/arbor/SimArborExample.yaml
@@ -1,5 +1,5 @@
SimArborExample:
- version: NeuroMLlite v0.5.3
+ version: NeuroMLlite v0.5.7
network: ArborExample.yaml
duration: 100.0
dt: 0.01
diff --git a/examples/clean.sh b/examples/clean.sh
index 0d3afdd..17ca103 100755
--- a/examples/clean.sh
+++ b/examples/clean.sh
@@ -1,4 +1,4 @@
mkdir ~/temp/dump
-mv -v report*txt *.pdf *.dat *.spikes *.gdf *.pkl *.hoc *.mod *~ *.log *nrn.py NET_*nml *brian.py *brian2.py *nest.py *pynn.py *definition.py *netpyne.py *moose.py *.nestml *.png *.ini *.svg *.pov *.gv *cell.json *synapse.json *main.json tmp* *csv ~/temp/dump
-rm -rf x86_64 i386 umac *.pyc *.c *.so *~ .*~
+mv -v report*txt *.pdf *.dat *.spikes *.gdf *.pkl *.hoc *.mod *~ *.log *nrn.py NET_*nml *brian.py *brian2.py *nest.py *pynn.py *definition.py *netpyne.py *moose.py *.nestml *.png *.ini *.svg *.pov *.gv *cell.json *synapse.json *main.json tmp* *csv *mdf.json *mdf.yaml *.mdf *eden.py ~/temp/dump
+rm -rf x86_64 i386 umac arm64 *.pyc *.c *.so __pycache__ *~ .*~
rm -rf ./test_files/test_inputs/x86_64 ./test_files/x86_64 ./spikeratetest/x86_64
diff --git a/examples/sonatatest/analyze_output.py b/examples/sonatatest/analyze_output.py
index 9e26ccf..f48a33c 100644
--- a/examples/sonatatest/analyze_output.py
+++ b/examples/sonatatest/analyze_output.py
@@ -5,7 +5,6 @@
from analyze_output_utils import plot_data
if __name__ == "__main__":
-
plot_data(
"output/membrane_potential.h5", "mV", "Membrane Potential", show_already=True
)
diff --git a/examples/sonatatest/analyze_output_utils.py b/examples/sonatatest/analyze_output_utils.py
index b9c8fad..fe0b264 100644
--- a/examples/sonatatest/analyze_output_utils.py
+++ b/examples/sonatatest/analyze_output_utils.py
@@ -16,7 +16,6 @@ def plot_data(reports_file, y_axis, title, show_already=True, max_num_traces=Non
pop_prefixes = {pop: "/report/%s/" % pop}
for pop in pop_prefixes:
-
gids = np.array(cellvar_h5["%smapping/gids" % pop_prefixes[pop]])
soma_locs = np.array(
diff --git a/examples/sonatatest/run_bmtk.py b/examples/sonatatest/run_bmtk.py
index 0964873..193efbc 100644
--- a/examples/sonatatest/run_bmtk.py
+++ b/examples/sonatatest/run_bmtk.py
@@ -4,7 +4,6 @@
def run(config_file, simulator):
-
if simulator == "NEURON":
from bmtk.simulator import bionet
@@ -25,5 +24,4 @@ def run(config_file, simulator):
if __name__ == "__main__":
-
run("config.json", "NEST")
diff --git a/examples/spikeratetest/SimSpikers.json b/examples/spikeratetest/SimSpikers.json
index 5229831..65b72b0 100644
--- a/examples/spikeratetest/SimSpikers.json
+++ b/examples/spikeratetest/SimSpikers.json
@@ -1,6 +1,6 @@
{
"SimSpikers": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"network": "Spikers.json",
"duration": 10000.0,
"dt": 0.025,
diff --git a/examples/spikeratetest/Spikers.json b/examples/spikeratetest/Spikers.json
index 8e24bd0..9ce401e 100644
--- a/examples/spikeratetest/Spikers.json
+++ b/examples/spikeratetest/Spikers.json
@@ -1,6 +1,6 @@
{
"Spikers": {
- "version": "NeuroMLlite v0.5.3",
+ "version": "NeuroMLlite v0.5.7",
"notes": "Example with spiking entities..",
"parameters": {
"N": 10,
@@ -85,18 +85,18 @@
"stim0": {
"input_source": "poissonFiringSyn",
"population": "pop0",
- "percentage": 50.0,
+ "percentage": 50,
"weight": "weightInput"
},
"stim1": {
"input_source": "iclamp1",
"population": "pop1",
- "percentage": 100.0
+ "percentage": 100
},
"stim2": {
"input_source": "iclamp1",
"population": "pop2",
- "percentage": 50.0
+ "percentage": 50
}
}
}
diff --git a/examples/test_files/.test.ex7.nmllite.pynnnest.omt b/examples/test_files/.test.ex7.nmllite.pynnnest.omt
index 21eccf3..91f7084 100644
--- a/examples/test_files/.test.ex7.nmllite.pynnnest.omt
+++ b/examples/test_files/.test.ex7.nmllite.pynnnest.omt
@@ -12,7 +12,7 @@ experiments:
path: ../SimExample7.expoisson.spikes
format: ID_TIME
ids: '*'
- tolerance: 0.00020894387195494345
+ tolerance: 0.0019478218091029704
spike_rate_inh_in:
observables:
@@ -21,7 +21,7 @@ experiments:
path: ../SimExample7.inpoisson.spikes
format: ID_TIME
ids: '*'
- tolerance: 0.0025532645162897097
+ tolerance: 0.004952617763644412
spike_rate_e:
observables:
@@ -30,7 +30,7 @@ experiments:
path: ../SimExample7.Epop.spikes
format: ID_TIME
ids: '*'
- tolerance: 0.00
+ tolerance: 0.02167593418697938
spike_rate_i:
observables:
@@ -39,4 +39,4 @@ experiments:
path: ../SimExample7.Ipop.spikes
format: ID_TIME
ids: '*'
- tolerance: 0.00
+ tolerance: 0.017234417194577856
diff --git a/examples/test_files/.test.validate.omt b/examples/test_files/.test.validate.omt
index 3f0f9e9..14ba677 100644
--- a/examples/test_files/.test.validate.omt
+++ b/examples/test_files/.test.validate.omt
@@ -1,5 +1,5 @@
# Script for running automated tests on OSB using Travis-CI, see https://github.com/OpenSourceBrain/osb-model-validation
# This test will validate all of the NeuroML 2 files in the current directory using: jnml -validate *.nml
-target: "*.nml"
+target: "../Example2_TestNetwork.net.nml ../Example3_Network.net.nml ../Example4_PyNN.net.nml ../Example6_PyNN.net.nml ../Example7_Brunel2000.net.nml ../Example12_MultiComp.net.nml *.nml"
engine: jNeuroML_validate
diff --git a/neuromllite/ArborHandler.py b/neuromllite/ArborHandler.py
index 2e0bd61..22792cb 100644
--- a/neuromllite/ArborHandler.py
+++ b/neuromllite/ArborHandler.py
@@ -16,7 +16,6 @@
class ArborHandler(DefaultNetworkHandler):
-
pops_vs_components = {}
proj_weights = {}
proj_delays = {}
@@ -42,7 +41,6 @@ def handle_document_start(self, id, notes):
print_v("Document: %s" % id)
def handle_network(self, network_id, notes, temperature=None):
-
print_v("Network: %s" % network_id)
if temperature:
print_v(" Temperature: " + temperature)
@@ -52,7 +50,6 @@ def handle_network(self, network_id, notes, temperature=None):
def handle_population(
self, population_id, component, size=-1, component_obj=None, properties={}
):
-
sizeInfo = " as yet unspecified size"
if size >= 0:
sizeInfo = ", size: " + str(size) + " cells"
@@ -107,7 +104,6 @@ def handle_projection(
synapse_obj=None,
pre_synapse_obj=None,
):
-
synInfo = ""
if synapse_obj:
synInfo += " (syn: %s)" % synapse_obj.__class__.__name__
@@ -164,7 +160,6 @@ def handle_connection(
delay=0,
weight=1,
):
-
self.print_connection_information(
projName, id, prePop, postPop, synapseType, preCellId, postCellId, weight
)
@@ -191,7 +186,6 @@ def handle_connection(
def finalise_projection(
self, projName, prePop, postPop, synapse=None, type="projection"
):
-
print_v(
"Projection finalising: "
+ projName
@@ -208,7 +202,6 @@ def finalise_projection(
def handle_input_list(
self, inputListId, population_id, component, size, input_comp_obj=None
):
-
self.print_input_information(inputListId, population_id, component, size)
if input_comp_obj:
print("Input comp: %s" % input_comp_obj)
@@ -228,7 +221,6 @@ def handle_input_list(
def handle_single_input(
self, inputListId, id, cellId, segId=0, fract=0.5, weight=1
):
-
population_id, component, input_comp_obj = self.input_info[inputListId]
print_v(
@@ -261,8 +253,6 @@ def finalise_document(self):
)
-
-
# Create a NeuroML recipe
class NeuroML_Arbor_Recipe(arbor.recipe):
def __init__(
@@ -289,11 +279,8 @@ def __init__(
self.input_info = input_info
self.input_lists = input_lists
-
def create_arbor_cell(self, cell, gid, pop_id, index):
-
if cell.arbor_cell == "cable_cell":
-
default_tree = arbor.segment_tree()
radius = (
evaluate(cell.parameters["radius"], self.nl_network.parameters)
@@ -323,21 +310,26 @@ def create_arbor_cell(self, cell, gid, pop_id, index):
decor.paint('"soma"', arbor.density(cell.parameters["mechanism"]))
- decor.place('"center"', arbor.spike_detector(0), "detector")
+ decor.place('"center"', arbor.threshold_detector(0), "detector")
for ip in self.input_info:
if self.input_info[ip][0] == pop_id:
- print_v("Stim: %s (%s) being placed on %s" % (ip,self.input_info[ip],pop_id))
+ print_v(
+ "Stim: %s (%s) being placed on %s"
+ % (ip, self.input_info[ip], pop_id)
+ )
for il in self.input_lists[ip]:
cellId, segId, fract, weight = il
if cellId == index:
- if self.input_info[ip][1] == 'i_clamp': # TODO: remove hardcoding of this...
+ if (
+ self.input_info[ip][1] == "i_clamp"
+ ): # TODO: remove hardcoding of this...
ic = arbor.iclamp(
self.nl_network.parameters["input_del"],
self.nl_network.parameters["input_dur"],
self.nl_network.parameters["input_amp"],
)
- print_v("Stim: %s on %s" % (ic,gid))
+ print_v("Stim: %s on %s" % (ic, gid))
decor.place('"center"', ic, "iclamp")
# (2) Mark location for synapse at the midpoint of branch 1 (the first dendrite).
@@ -345,7 +337,7 @@ def create_arbor_cell(self, cell, gid, pop_id, index):
# (4) Attach a single synapse.
decor.place('"synapse_site"', arbor.synapse("expsyn"), "syn")
- default_cell = arbor.cable_cell(default_tree, labels, decor)
+ default_cell = arbor.cable_cell(default_tree, labels=labels, decor=decor)
print_v("Created a new cell for gid %i: %s" % (gid, cell))
print_v("%s" % (default_cell))
@@ -384,7 +376,6 @@ def cell_description(self, gid):
)
return a_cell
-
# The kind method returns the type of cell with gid.
# Note: this must agree with the type returned by cell_description.
def cell_kind(self, gid):
@@ -452,10 +443,10 @@ def num_sources(self, gid):
# (9) Attach a generator to the first cell in the ring.
def event_generators(self, gid):
egs = []
- '''
+ """
if gid == 0:
sched = arbor.explicit_schedule([1])
- egs = [arbor.event_generator("syn", 0.1, sched)]'''
+ egs = [arbor.event_generator("syn", 0.1, sched)]"""
print_v("Getting event_generators for %s: %s" % (gid, egs))
return egs
diff --git a/neuromllite/BBPConnectomeReader.py b/neuromllite/BBPConnectomeReader.py
index ffa97b4..8e2478c 100644
--- a/neuromllite/BBPConnectomeReader.py
+++ b/neuromllite/BBPConnectomeReader.py
@@ -8,11 +8,9 @@
class BBPConnectomeReader(NetworkReaderX):
-
component_objects = {} # Store cell ids vs objects, e.g. NeuroML2 based object
def __init__(self, **parameters):
-
print_v("Creating BBPConnectomeReader with %s..." % parameters)
self.parameters = parameters
self.current_population = None
@@ -20,7 +18,6 @@ def __init__(self, **parameters):
self.post_pop = None
def parse(self, handler):
-
filename = os.path.abspath(self.parameters["filename"])
id = filename.split("/")[-1].split(".")[0]
@@ -87,7 +84,6 @@ def parse_dataset(self, d):
# Population
if self.current_population and d.name == "locations":
-
perc_cells = (
self.parameters["percentage_cells_per_pop"]
if "percentage_cells_per_pop" in self.parameters
@@ -180,7 +176,6 @@ def parse_dataset(self, d):
" There are %i cells in: %s" % (size, self.current_population)
)
for i in range(0, d.shape[0]):
-
if i < size:
row = d[i, :]
x = row[0]
@@ -198,7 +193,6 @@ def parse_dataset(self, d):
# Projection
elif self.pre_pop != None and self.post_pop != None:
-
proj_id = "Proj__%s__%s" % (self.pre_pop, self.post_pop)
synapse = "gaba"
if (
@@ -263,7 +257,6 @@ def parse_dataset(self, d):
if __name__ == "__main__":
-
filename = "test_files/cons_locs_pathways_mc0_Column.h5"
percentage_cells_per_pop = 1
diff --git a/neuromllite/BindsNETHandler.py b/neuromllite/BindsNETHandler.py
index 8f10a0e..6e9aee5 100644
--- a/neuromllite/BindsNETHandler.py
+++ b/neuromllite/BindsNETHandler.py
@@ -16,7 +16,6 @@
class BindsNETHandler(DefaultNetworkHandler):
-
pops_vs_components = {}
pops_vs_bn_layers = {}
@@ -46,7 +45,6 @@ def handle_document_start(self, id, notes):
print_v("Document: %s" % id)
def handle_network(self, network_id, notes, temperature=None):
-
print_v("Network: %s" % network_id)
if temperature:
print_v(" Temperature: " + temperature)
@@ -56,7 +54,6 @@ def handle_network(self, network_id, notes, temperature=None):
def handle_population(
self, population_id, component, size=-1, component_obj=None, properties={}
):
-
sizeInfo = " as yet unspecified size"
if size >= 0:
sizeInfo = ", size: " + str(size) + " cells"
@@ -103,7 +100,6 @@ def handle_projection(
synapse_obj=None,
pre_synapse_obj=None,
):
-
synInfo = ""
if synapse_obj:
synInfo += " (syn: %s)" % synapse_obj.__class__.__name__
@@ -160,7 +156,6 @@ def handle_connection(
delay=0,
weight=1,
):
-
self.print_connection_information(
projName, id, prePop, postPop, synapseType, preCellId, postCellId, weight
)
@@ -187,7 +182,6 @@ def handle_connection(
def finalise_projection(
self, projName, prePop, postPop, synapse=None, type="projection"
):
-
print_v(
"Projection finalising: "
+ projName
@@ -204,7 +198,6 @@ def finalise_projection(
def handle_input_list(
self, inputListId, population_id, component, size, input_comp_obj=None
):
-
self.print_input_information(inputListId, population_id, component, size)
if input_comp_obj:
print("Input comp: %s" % input_comp_obj)
@@ -223,7 +216,6 @@ def handle_input_list(
def handle_single_input(
self, inputListId, id, cellId, segId=0, fract=0.5, weight=1
):
-
population_id, component = self.input_info[inputListId]
print_v(
diff --git a/neuromllite/ConnectivityHandler.py b/neuromllite/ConnectivityHandler.py
index 81ba023..a33bc76 100644
--- a/neuromllite/ConnectivityHandler.py
+++ b/neuromllite/ConnectivityHandler.py
@@ -10,7 +10,6 @@
class ConnectivityHandler(DefaultNetworkHandler):
-
CUTOFF_INH_SYN_MV = -50 # erev below -50mV => inhibitory, above => excitatory
include_ext_inputs = False
@@ -44,11 +43,9 @@ class ConnectivityHandler(DefaultNetworkHandler):
input_comp_obj_ils = {}
def handle_document_start(self, id, notes):
-
print_v("Document: %s" % id)
def handle_network(self, network_id, notes, temperature=None):
-
print_v("Network: %s" % network_id)
self.network_id = network_id
@@ -88,7 +85,6 @@ def get_size_post_pop(self, projName):
return self.pop_sizes[self.proj_post_pops[projName]]
def get_reversal_potential_mV(self, synapse_obj):
-
if hasattr(synapse_obj, "erev"):
return convert_to_units(synapse_obj.erev, "mV")
@@ -99,7 +95,6 @@ def get_reversal_potential_mV(self, synapse_obj):
return None
def _get_gbase_nS(self, projName, return_orig_string_also=False):
-
gbase_nS = None
gbase = "???"
# print('Getting gbase for %s'%projName)
@@ -123,7 +118,6 @@ def _get_gbase_nS(self, projName, return_orig_string_also=False):
return gbase_nS
def _scale_individual_weight(self, weight, projName):
-
orig_weight = weight
if self.scale_by_post_pop_cond:
@@ -138,7 +132,6 @@ def _scale_individual_weight(self, weight, projName):
return weight
def _scale_population_weight(self, weight, projName):
-
orig_weight = weight
if self.scale_by_post_pop_size:
weight /= self.get_size_post_pop(projName)
@@ -155,7 +148,6 @@ def _scale_population_weight(self, weight, projName):
return weight
def handle_location(self, id, population_id, component, x, y, z):
-
pass
def handle_connection(
@@ -174,7 +166,6 @@ def handle_connection(
delay=0,
weight=1.0,
):
-
# print_v(" - Connection for %s, cell %i -> %i, w: %s"%(projName, preCellId, postCellId, weight))
self.proj_conns[projName] += 1
self.proj_tot_weight[projName] += weight
@@ -194,7 +185,6 @@ def handle_connection(
def finalise_projection(
self, projName, prePop, postPop, synapse=None, type="projection"
):
-
# weight = self.proj_tot_weight[projName]
# self.max_weight = max(self.max_weight, weight)
# self.min_weight = min(self.min_weight, weight)
diff --git a/neuromllite/DefaultNetworkHandler.py b/neuromllite/DefaultNetworkHandler.py
index 2e64ca8..6e27813 100644
--- a/neuromllite/DefaultNetworkHandler.py
+++ b/neuromllite/DefaultNetworkHandler.py
@@ -21,7 +21,6 @@
class DefaultNetworkHandler:
-
#
# Internal info method, can be reused in overriding classes for debugging
#
@@ -82,7 +81,6 @@ def print_input_information(self, inputName, population_id, component, size=-1):
# Should be overridden
#
def handle_document_start(self, id, notes):
-
print_v("Document: %s started..." % id)
if notes:
print_v(" Notes: " + notes)
@@ -91,14 +89,12 @@ def handle_document_start(self, id, notes):
# Should be overridden
#
def finalise_document(self):
-
print_v("Document ended...")
#
# Should be overridden to create network
#
def handle_network(self, network_id, notes, temperature=None):
-
print_v("Network: %s" % network_id)
if temperature:
print_v(" Temperature: " + temperature)
@@ -139,7 +135,6 @@ def handle_location(self, id, population_id, component, x, y, z):
self.print_location_information(id, population_id, component, x, y, z)
def finalise_population(self, population_id):
-
pass
#
@@ -157,7 +152,6 @@ def handle_projection(
synapse_obj=None,
pre_synapse_obj=None,
):
-
synInfo = ""
if synapse_obj:
synInfo += " (syn: %s)" % synapse_obj.__class__.__name__
@@ -198,7 +192,6 @@ def handle_connection(
delay=0,
weight=1,
):
-
self.print_connection_information(
projName, id, prePop, postPop, synapseType, preCellId, postCellId, weight
)
@@ -223,7 +216,6 @@ def handle_connection(
def finalise_projection(
self, projName, prePop, postPop, synapse=None, type="projection"
):
-
print_v(
"Projection: "
+ projName
@@ -240,7 +232,6 @@ def finalise_projection(
def handle_input_list(
self, inputListId, population_id, component, size, input_comp_obj=None
):
-
self.print_input_information(inputListId, population_id, component, size)
if size < 0:
@@ -255,7 +246,6 @@ def handle_input_list(
def handle_single_input(
self, inputListId, id, cellId, segId=0, fract=0.5, weight=1
):
-
print_v(
" Input: %s[%s], cellId: %i, seg: %i, fract: %f, weight: %f"
% (inputListId, id, cellId, segId, fract, weight)
diff --git a/neuromllite/GraphVizHandler.py b/neuromllite/GraphVizHandler.py
index 0b9f9ad..118fc06 100644
--- a/neuromllite/GraphVizHandler.py
+++ b/neuromllite/GraphVizHandler.py
@@ -27,7 +27,6 @@
class GraphVizHandler(ConnectivityHandler):
-
DEFAULT_POP_SHAPE = "ellipse"
EXC_POP_SHAPE = "ellipse"
INH_POP_SHAPE = "ellipse"
@@ -54,7 +53,6 @@ def __init__(
output_format="png",
view_on_render=True,
):
-
self.nl_network = nl_network
self.level = level
self.engine = engine
@@ -106,7 +104,6 @@ def print_settings(self):
print_v("**************************************")
def get_weight_fraction_and_line(self, w, max_w, min_w):
-
if max_w == min_w:
return 1.0, 1.0
# fractional weight, 0->1
@@ -122,7 +119,6 @@ def get_weight_fraction_and_line(self, w, max_w, min_w):
return fweight, lweight
def finalise_document(self):
-
max_abs_weight = {}
min_abs_weight = {}
@@ -137,7 +133,6 @@ def finalise_document(self):
min_abs_weight[t] = 1e100
if self.is_cell_level() and self.level <= -1:
-
for projName in self.proj_weights:
# ws = self.proj_individual_weights[projName]
ws = self.proj_individual_scaled_weights[projName]
@@ -151,7 +146,6 @@ def finalise_document(self):
)
for projName in self.proj_weights:
-
pre_pop = self.proj_pre_pops[projName]
post_pop = self.proj_post_pops[projName]
proj_type = self.proj_types[projName]
@@ -209,7 +203,6 @@ def finalise_document(self):
][pre_i][post_i]
if w != 0:
-
weight_used = w
cond_scale = None
@@ -279,17 +272,14 @@ def finalise_document(self):
self.graph.edge(pre_pop_i, post_pop_i)
else:
-
for projName in self.proj_tot_weight:
t = self.proj_types[projName]
if self.proj_tot_weight[projName] != 0:
-
weight_used = float(self.proj_tot_weight[projName])
weight_used = self._scale_population_weight(weight_used, projName)
if abs(weight_used) >= self.min_weight_to_show:
-
max_abs_weight[t] = max(max_abs_weight[t], abs(weight_used))
min_abs_weight[t] = min(min_abs_weight[t], abs(weight_used))
print_v(
@@ -316,17 +306,14 @@ def finalise_document(self):
)
for projName in self.proj_tot_weight:
-
proj_type = self.proj_types[projName]
if self.proj_tot_weight[projName] != 0:
-
# weight_used = self.proj_weights[projName]
weight_used = float(self.proj_tot_weight[projName])
weight_used = self._scale_population_weight(weight_used, projName)
if abs(weight_used) >= self.min_weight_to_show:
-
if max_abs_weight[proj_type] == min_abs_weight[proj_type]:
fweight = 1
lweight = 1
@@ -415,9 +402,7 @@ def finalise_document(self):
)
if self.level >= 5:
-
if self.proj_conns[projName] > 0:
-
pre_avg = (
float(self.proj_conns[projName])
/ self.pop_sizes[
@@ -490,7 +475,6 @@ def finalise_document(self):
)
def handle_network(self, network_id, notes, temperature=None):
-
print_v("Network: %s" % network_id)
self.network_id = network_id
@@ -570,7 +554,6 @@ def handle_population(
if self.level >= 3:
label += "
%s cell%s" % (size, "" if size == 1 else "s")
if self.level >= 4:
-
from neuroml import SpikeSourcePoisson
if component_obj and isinstance(component_obj, SpikeSourcePoisson):
@@ -592,7 +575,6 @@ def handle_population(
label += ">"
if properties and "region" in properties:
-
with self.graph.subgraph(name="cluster_%s" % properties["region"]) as c:
c.attr(color="#444444", fontcolor="#444444")
c.attr(label=properties["region"])
@@ -631,7 +613,6 @@ def handle_projection(
synapse_obj=None,
pre_synapse_obj=None,
):
-
shape = self.EXC_CONN_ARROW_SHAPE
line = "solid"
@@ -706,7 +687,6 @@ def handle_projection(
def finalise_projection(
self, projName, prePop, postPop, synapse=None, type="projection"
):
-
# weight = self.proj_tot_weight[projName]
# self.max_weight = max(self.max_weight, weight)
# self.min_weight = min(self.min_weight, weight)
@@ -715,19 +695,16 @@ def finalise_projection(
# print_v("Projection finalising: "+projName+" from "+prePop+" to "+postPop+" completed")
def finalise_input_source(self, inputListId):
-
if self.include_ext_inputs:
# self.print_input_information('FINAL: '+inputListId, self.pops_ils[inputListId], '...', self.sizes_ils[inputListId])
if self.level >= 2:
-
label = "<%s" % inputListId
if self.level >= 3:
size = self.sizes_ils[inputListId]
label += "
%s input%s" % (size, "" if size == 1 else "s")
if self.level >= 4:
-
from neuroml import PulseGenerator
from neuroml import TransientPoissonFiringSynapse
from neuroml import PoissonFiringSynapse
@@ -755,7 +732,6 @@ def finalise_input_source(self, inputListId):
if input_comp_obj and isinstance(
input_comp_obj, PoissonFiringSynapse
):
-
average_rate = convert_to_units(
input_comp_obj.average_rate, "Hz"
)
@@ -770,7 +746,6 @@ def finalise_input_source(self, inputListId):
if input_comp_obj and isinstance(
input_comp_obj, TransientPoissonFiringSynapse
):
-
start = convert_to_units(input_comp_obj.delay, "ms")
if start == int(start):
start = int(start)
diff --git a/neuromllite/MDFHandler.py b/neuromllite/MDFHandler.py
index e2b882c..b6bb48e 100644
--- a/neuromllite/MDFHandler.py
+++ b/neuromllite/MDFHandler.py
@@ -6,6 +6,8 @@
from neuromllite.DefaultNetworkHandler import DefaultNetworkHandler
from neuromllite.utils import print_v
+from neuromllite.NetworkGenerator import _extract_pynn_components_to_neuroml
+
from modelspec.utils import save_to_json_file
from modelspec.utils import save_to_yaml_file
from modelspec.utils import locate_file
@@ -14,6 +16,12 @@
import lems.api as lems # from pylems
+import numpy
+
+DEFAULT_CURRENT_INPUT_PORT = "synapses_i"
+SPIKE_INPUT_PORT_ID = "spike_input"
+WEIGHTED_SPIKE_INPUTS = "weighted_inputs"
+
class MDFHandler(DefaultNetworkHandler):
def __init__(self, nl_network):
@@ -23,15 +31,16 @@ def __init__(self, nl_network):
self.input_list_vs_comps = {}
self.input_list_vs_pops = {}
- def handle_document_start(self, id, notes):
+ self.pop_ids_vs_size = {}
- print_v("Parsing for PsyNeuLink export: %s" % id)
+ def handle_document_start(self, id, notes):
+ print_v("Parsing for MDF export: %s" % id)
self.id = id
self.mdf_info = {}
# from modeci_mdf import MODECI_MDF_VERSION
- MODECI_MDF_VERSION = "0.3"
+ MODECI_MDF_VERSION = "0.4"
self.mdf_info[self.id] = {}
self.mdf_info[self.id]["format"] = "ModECI MDF v%s" % MODECI_MDF_VERSION
@@ -40,7 +49,6 @@ def handle_document_start(self, id, notes):
self.pnl_additions = False
def finalise_document(self):
-
print_v("Writing file for...: %s" % self.id)
save_to_json_file(self.mdf_info, "%s.mdf.json" % self.id, indent=4)
@@ -48,7 +56,6 @@ def finalise_document(self):
"""save_to_json_file(self.mdf_info_hl, '%s.bids-mdf.highlevel.json'%self.id, indent=4)"""
def handle_network(self, network_id, notes, temperature=None):
-
print_v("Network: %s" % network_id)
self.network_id = network_id
@@ -64,12 +71,17 @@ def handle_network(self, network_id, notes, temperature=None):
self.mdf_info[self.id]["graphs"][network_id] = self.mdf_graph
- def _convert_value(self, val):
+ def _get_input_port_name(self, name):
+ if name == "in":
+ return SPIKE_INPUT_PORT_ID
+ else:
+ return name
+ def _convert_value(self, val):
funcs = ["exp"]
for f in funcs:
if "%s(" % f in val:
- val = val.replace("%s(" % f, "math.%s(" % f)
+ val = val.replace("%s(" % f, "numpy.%s(" % f)
val = evaluate(val) # catch if it's an int etc.
return val
@@ -77,7 +89,6 @@ def _convert_value(self, val):
def handle_population(
self, population_id, component, size=-1, component_obj=None, properties={}
):
-
sizeInfo = " as yet unspecified size"
if size >= 0:
sizeInfo = ", size: " + str(size) + " cells"
@@ -86,182 +97,456 @@ def handle_population(
else:
compInfo = ""
- print_v(
+ self.pop_ids_vs_size[population_id] = size
+
+ info = (
"Population: "
+ population_id
+ ", component: "
+ component
+ compInfo
+ sizeInfo
- + ", properties: %s"% properties
+ + ", properties: %s" % properties
)
+ print_v(" = %s" % info)
- if size >= 0:
- for i in range(size):
- node_id = "%s_%i" % (population_id, i)
-
- cell_comp = self.nl_network.get_child(component, "cells")
-
- if cell_comp is not None:
- node = self._comp_to_mdf_node(cell_comp, component, node_id, properties)
-
- self.mdf_graph["nodes"][node_id] = node
-
-
- def _comp_to_mdf_node(self, nmllite_comp, lems_comp_id, node, properties=None):
-
- base_dir = "./" # for now...
-
- node = {}
- if properties:
- node["metadata"] = properties
-
- node["parameters"] = {}
- node["input_ports"] = {}
- node["output_ports"] = {}
-
- if nmllite_comp.lems_source_file:
- print_v(" It's defined in custom lems..." )
- fname = locate_file(nmllite_comp.lems_source_file, base_dir)
- model = MDFHandler._load_lems_file_with_neuroml2_types(fname)
- lems_comp = model.components.get(lems_comp_id)
-
- elif hasattr(nmllite_comp,'neuroml2_cell'):
- print_v(" It's a cell..." )
- model = MDFHandler._get_lems_model_with_neuroml2_types()
- lems_comp = lems.Component(
- id_=nmllite_comp.id, type_=nmllite_comp.neuroml2_cell
- )
- for p in nmllite_comp.parameters:
- lems_comp.set_parameter(
- p,
- evaluate(
- nmllite_comp.parameters[p], self.nl_network.parameters
- ),
- )
-
- elif hasattr(nmllite_comp,'neuroml2_input'):
- print_v(" It's an input..." )
- model = MDFHandler._get_lems_model_with_neuroml2_types()
- lems_comp = lems.Component(
- id_=nmllite_comp.id, type_=nmllite_comp.neuroml2_input
- )
- for p in nmllite_comp.parameters:
- lems_comp.set_parameter(
- p,
- evaluate(
- nmllite_comp.parameters[p], self.nl_network.parameters
- ),
- )
-
- print_v("All LEMS comps in model: %s" % model.components.keys())
- print_v("This comp: %s" % lems_comp)
- comp_type_name = lems_comp.type
- lems_comp_type = model.component_types.get(comp_type_name)
- print_v("lems_comp_type: %s" % lems_comp_type)
- notes = "Cell: [%s] is defined in %s and in Lems is: %s" % (
- nmllite_comp,
- nmllite_comp.lems_source_file,
- lems_comp,
- )
-
- node["notes"] = notes
-
- for p in lems_comp.parameters:
- node["parameters"][p] = {
- "value": get_value_in_si(evaluate(lems_comp.parameters[p]))
- }
-
- for c in lems_comp_type.constants:
- node["parameters"][c.name] = {"value": get_value_in_si(c.value)}
-
- for sv in lems_comp_type.dynamics.state_variables:
- node["parameters"][sv.name] = {}
- if sv.exposure:
- node["output_ports"][sv.exposure] = {"value": sv.name}
-
- for dv in lems_comp_type.dynamics.derived_variables:
-
- print_v(
- "Converting: %s (exp: %s) = [%s] or [%s]"
- % (dv.name, dv.exposure, dv.value, dv.select)
- )
- if dv.name == "INPUT":
- node["input_ports"][dv.name] = {}
- else:
- if dv.value is not None:
- node["parameters"][dv.name] = {
- "value": self._convert_value(dv.value)
- }
- if dv.exposure:
- node["output_ports"][dv.exposure] = {
- "value": dv.name
- }
- if dv.select is not None:
- in_port = dv.select.replace("[*]/", "_")
- node["input_ports"][in_port] = {}
- node["parameters"][dv.name] = {"value": in_port}
-
- conditions = 0
- for eh in lems_comp_type.dynamics.event_handlers:
-
- print_v("Converting: %s (type: %s)" % (eh, type(eh)))
- if type(eh) == lems.OnStart:
- for a in eh.actions:
- if type(a) == lems.StateAssignment:
- node["parameters"][a.variable][
- "default_initial_value"
- ] = a.value
- if type(eh) == lems.OnCondition:
- test = (
- eh.test.replace(".gt.", ">")
- .replace(".geq.", ">=")
- .replace(".lt.", "<")
- .replace(".leq.", "<=")
- .replace(".eq.", "==")
- .replace(".and.", "and")
- )
- for a in eh.actions:
- if type(a) == lems.StateAssignment:
- if (
- not "conditions"
- in node["parameters"][a.variable]
- ):
- node["parameters"][a.variable][
- "conditions"
- ] = {}
-
- node["parameters"][a.variable]["conditions"][
- "condition_%i" % conditions
- ] = {"test": test, "value": a.value}
- conditions += 1
-
- for td in lems_comp_type.dynamics.time_derivatives:
- node["parameters"][td.variable][
- "time_derivative"
- ] = self._convert_value(td.value)
-
- return node
+ node_id = "%s" % (population_id)
+
+ cell_comp = self.nl_network.get_child(component, "cells")
+
+ if cell_comp is not None:
+ node = self._comp_to_mdf_node(
+ nmllite_comp=cell_comp,
+ lems_comp_id=component,
+ size=size,
+ properties=properties,
+ )
+
+ self.mdf_graph["nodes"][node_id] = node
+
+ def _comp_to_mdf_node(self, nmllite_comp, lems_comp_id, size=1, properties=None):
+ base_dir = "./" # for now...
+
+ node = {}
+
+ if properties:
+ node["metadata"] = properties
+
+ node["parameters"] = {}
+ node["input_ports"] = {}
+ node["output_ports"] = {}
+
+ if nmllite_comp.lems_source_file:
+ print_v(" It's a component defined in custom lems...")
+ fname = locate_file(nmllite_comp.lems_source_file, base_dir)
+ model = MDFHandler._load_lems_file_with_neuroml2_types(fname)
+ lems_comp = model.components.get(lems_comp_id)
+
+ elif (
+ hasattr(nmllite_comp, "neuroml2_cell")
+ and nmllite_comp.neuroml2_cell is not None
+ ):
+ print_v(
+ " It is a NeuroML2 cell (%s, %s)..."
+ % (nmllite_comp.id, nmllite_comp.neuroml2_cell)
+ )
+ model = MDFHandler._get_lems_model_with_neuroml2_types()
+ lems_comp = lems.Component(
+ id_=nmllite_comp.id, type_=nmllite_comp.neuroml2_cell
+ )
+ if nmllite_comp.parameters is not None:
+ for p in nmllite_comp.parameters:
+ lems_comp.set_parameter(
+ p,
+ evaluate(
+ nmllite_comp.parameters[p], self.nl_network.parameters
+ ),
+ )
+ elif nmllite_comp.neuroml2_source_file is not None:
+ print_v(
+ " It is a NeuroML2 cell (%s, %s)..."
+ % (nmllite_comp.id, nmllite_comp.neuroml2_source_file)
+ )
+ model = MDFHandler._get_lems_model_with_neuroml2_types()
+ lems_comp = lems.Component(
+ id_=nmllite_comp.id, type_=nmllite_comp.neuroml2_cell
+ )
+ if nmllite_comp.parameters is not None:
+ for p in nmllite_comp.parameters:
+ lems_comp.set_parameter(
+ p,
+ evaluate(
+ nmllite_comp.parameters[p], self.nl_network.parameters
+ ),
+ )
+
+ elif hasattr(nmllite_comp, "pynn_cell"):
+ print_v(" It's a PyNN cell...")
+
+ nml2_doc_temp = _extract_pynn_components_to_neuroml(self.nl_network)
+
+ model = MDFHandler._get_lems_model_with_neuroml2_types(nml2_doc_temp)
+
+ lems_comp = model.components[nmllite_comp.id]
+
+ for p in nmllite_comp.parameters:
+ lems_comp.set_parameter(
+ p,
+ evaluate(nmllite_comp.parameters[p], self.nl_network.parameters),
+ )
+
+ elif hasattr(nmllite_comp, "pynn_synapse_type"):
+ print_v(" It's a PyNN synapse...")
+ nml2_doc_temp = _extract_pynn_components_to_neuroml(self.nl_network)
+
+ model = MDFHandler._get_lems_model_with_neuroml2_types(nml2_doc_temp)
+
+ lems_comp = model.components[nmllite_comp.id]
+
+ for p in nmllite_comp.parameters:
+ lems_comp.set_parameter(
+ p,
+ evaluate(nmllite_comp.parameters[p], self.nl_network.parameters),
+ )
+
+ elif (
+ hasattr(nmllite_comp, "neuroml2_input")
+ and nmllite_comp.neuroml2_input is not None
+ ):
+ print_v(" It's a NeuroML input...")
+ model = MDFHandler._get_lems_model_with_neuroml2_types()
+ lems_comp = lems.Component(
+ id_=nmllite_comp.id, type_=nmllite_comp.neuroml2_input
+ )
+ for p in nmllite_comp.parameters:
+ lems_comp.set_parameter(
+ p,
+ evaluate(nmllite_comp.parameters[p], self.nl_network.parameters),
+ )
+
+ elif hasattr(nmllite_comp, "pynn_input"):
+ print_v(
+ " It's a PyNN input: %s - %s..."
+ % (nmllite_comp.id, nmllite_comp.pynn_input)
+ )
+
+ nml2_doc_temp = _extract_pynn_components_to_neuroml(self.nl_network)
+
+ model = MDFHandler._get_lems_model_with_neuroml2_types(nml2_doc_temp)
+
+ lems_comp = model.components[nmllite_comp.id]
+ """
+ for p in nmllite_comp.parameters:
+ lems_comp.set_parameter(
+ p,
+ evaluate(
+ nmllite_comp.parameters[p], self.nl_network.parameters
+ ),
+ )"""
+
+ else:
+ raise Exception(
+ "Can't determine the source of the component definition in: %s"
+ % nmllite_comp
+ )
+
+ print_v(
+ "All LEMS Components in known LEMS model: %s"
+ % sorted(list(model.components.keys()))
+ )
+ print_v(
+ "All LEMS ComponentTypes in known LEMS model: %s"
+ % sorted(list(model.component_types.keys()))
+ )
+ print_v("This LEMS comp: %s" % lems_comp)
+ comp_type_name = lems_comp.type
+ lems_comp_type = model.component_types.get(comp_type_name)
+ print_v("lems_comp_type: %s" % lems_comp_type)
+ notes = "Cell: [%s] is defined in %s and in Lems is: %s" % (
+ nmllite_comp,
+ nmllite_comp.lems_source_file,
+ lems_comp,
+ )
+
+ node["notes"] = notes
+
+ for p in lems_comp.parameters:
+ node["parameters"][p] = {
+ "value": [get_value_in_si(evaluate(lems_comp.parameters[p]))] * size
+ }
+
+ properties = self._get_all_elements_in_lems(lems_comp_type, model, "properties")
+ for prop in properties:
+ node["parameters"][prop.name] = {
+ "value": [get_value_in_si(evaluate(prop.default_value))] * size
+ }
+
+ # if lems_comp_types.is_or_extends()
+
+ consts = self._get_all_elements_in_lems(lems_comp_type, model, "constant")
+ for c in consts:
+ node["parameters"][c.name] = {"value": [get_value_in_si(c.value)] * size}
+
+ event_ports = self._get_all_elements_in_lems(
+ lems_comp_type, model, "event_port"
+ )
+ for ep in event_ports:
+ if ep.direction == "out":
+ node["parameters"][ep.name] = {"value": [0] * size}
+ node["output_ports"][ep.name] = {"value": ep.name}
+ elif ep.direction == "in":
+ ep_name = self._get_input_port_name(ep.name)
+ node["input_ports"][ep_name] = {"shape": [size], "reduce": "add"}
+
+ if hasattr(lems_comp_type, "dynamics"):
+ for sv in lems_comp_type.dynamics.state_variables:
+ node["parameters"][sv.name] = {}
+
+ for reg in lems_comp_type.dynamics.regimes:
+ node["parameters"]["ACTIVE_REGIME"] = {"value": [1] * size}
+ node["parameters"]["INACTIVE_REGIME"] = {"value": [0] * size}
+
+ reg_param = "REGIME_%s" % reg.name
+ # node["parameters"][reg_param] = {"value": 'ACTIVE_REGIME' if reg.initial else 'INACTIVE_REGIME'}
+
+ if not reg_param in node["parameters"]:
+ node["parameters"][reg_param] = {}
+ node["parameters"][reg_param]["value"] = reg_param
+ node["parameters"][reg_param]["default_initial_value"] = (
+ "ACTIVE_REGIME" if reg.initial else "INACTIVE_REGIME"
+ )
+
+ node["output_ports"][reg_param] = {"value": reg_param}
+
+ for td in reg.time_derivatives:
+ node["parameters"][td.variable][
+ "time_derivative"
+ ] = self._convert_value("%s * (%s)" % (reg_param, td.value))
+
+ for eh in reg.event_handlers:
+ print_v(
+ "Converting the event handler: %s (type: %s)" % (eh, type(eh))
+ )
+
+ if type(eh) == lems.OnCondition:
+ # TODO: remove when global t available
+ node["parameters"]["t"] = {
+ "default_initial_value": 0,
+ "time_derivative": "1",
+ }
+
+ test = "(%s == ACTIVE_REGIME) * (%s)" % (
+ reg_param,
+ self._replace_in_condition_test(eh.test),
+ )
+ # test = "%s == ACTIVE_REGIME" % (reg_param)
+ if not "conditions" in node["parameters"][reg_param]:
+ node["parameters"][reg_param]["conditions"] = {}
+
+ node["parameters"][reg_param]["conditions"][
+ "regime_exit_condition"
+ ] = {"test": test, "value": "INACTIVE_REGIME"}
+
+ for a in eh.actions:
+ if type(a) == lems.Transition:
+ reg_to_id = a.regime
+ print_v(
+ " Transition: %s -> %s" % (reg_param, reg_to_id)
+ )
+ reg_to_param = "REGIME_%s" % reg_to_id
+ if not reg_to_param in node["parameters"]:
+ node["parameters"][reg_to_param] = {}
+ reg_to = lems_comp_type.dynamics.regimes[reg_to_id]
+ if not "conditions" in node["parameters"][reg_to_param]:
+ node["parameters"][reg_to_param]["conditions"] = {}
+
+ node["parameters"][reg_to_param]["conditions"][
+ "regime_entry_condition"
+ ] = {"test": test, "value": "ACTIVE_REGIME"}
+
+ for eh in reg_to.event_handlers:
+ print_v(
+ "Converting an event handler: %s (type: %s)"
+ % (eh, type(eh))
+ )
+
+ if type(eh) == lems.OnEntry:
+ for a in eh.actions:
+ if type(a) == lems.StateAssignment:
+ if (
+ not "conditions"
+ in node["parameters"][a.variable]
+ ):
+ node["parameters"][a.variable][
+ "conditions"
+ ] = {}
+
+ node["parameters"][a.variable][
+ "conditions"
+ ]["entering_regime_%s" % reg_to_id] = {
+ "test": test,
+ "value": a.value,
+ }
+
+ if type(a) == lems.EventOut:
+ del node["parameters"][a.port]["value"]
+ node["parameters"][a.port] = {
+ "default_initial_value": [0] * size
+ }
+
+ if not "conditions" in node["parameters"][a.port]:
+ node["parameters"][a.port]["conditions"] = {}
+
+ node["parameters"][a.port]["conditions"][
+ "condition_%s_on" % a.port
+ ] = {"test": test, "value": 1}
+ node["parameters"][a.port]["conditions"][
+ "condition_%s_off" % a.port
+ ] = {"test": "%s > 0" % a.port, "value": 0}
+
+ for sv in lems_comp_type.dynamics.state_variables:
+ # node["parameters"][sv.name]["value"] = [0]*size
+
+ node["output_ports"][sv.name] = {"value": sv.name}
+ print_v("Adding %s as an output port"%sv.name)
+ if sv.exposure:
+ node["output_ports"][sv.exposure] = {"value": sv.name}
+
+ for dv in lems_comp_type.dynamics.derived_variables:
+ print_v(
+ "Converting derived variable: %s (exp: %s) = [%s] or [%s]"
+ % (dv.name, dv.exposure, dv.value, dv.select)
+ )
+ if dv.name == "INPUT":
+ node["input_ports"][dv.name] = {}
+ else:
+ if dv.value is not None:
+ dv_name = dv.name
+ node["parameters"][dv_name] = {
+ "value": self._convert_value(dv.value)
+ }
+ if dv.exposure:
+ node["output_ports"][dv.exposure] = {"value": dv_name}
+ if dv.select is not None:
+ in_port = dv.select.replace("[*]/", "_").replace("/", "_")
+ node["input_ports"][in_port] = {}
+ """ "shape": [size],
+ "reduce": "add","""
+
+ node["parameters"][dv.name] = {"value": in_port}
+
+ conditions = 0
+ for eh in lems_comp_type.dynamics.event_handlers:
+ print_v("Converting an event handler: %s (type: %s)" % (eh, type(eh)))
+
+ if type(eh) == lems.OnEvent:
+ ep_name = self._get_input_port_name(eh.port)
+ for a in eh.actions:
+ if type(a) == lems.StateAssignment:
+ if not "conditions" in node["parameters"][a.variable]:
+ node["parameters"][a.variable]["conditions"] = {}
+
+ to_check = ep_name
+ if to_check == SPIKE_INPUT_PORT_ID:
+ to_check = WEIGHTED_SPIKE_INPUTS
+ node["parameters"][a.variable]["conditions"][
+ "condition_%s_on_eh" % ep_name
+ ] = {"test": "%s > 0" % to_check, "value": a.value}
+
+ if type(eh) == lems.OnStart:
+ for a in eh.actions:
+ if type(a) == lems.StateAssignment:
+ node["parameters"][a.variable][
+ "default_initial_value"
+ ] = a.value
+ if "value" in node["parameters"][a.variable]:
+ node["parameters"][a.variable].pop("value")
+
+ if type(eh) == lems.OnCondition:
+ test = self._replace_in_condition_test(eh.test)
+
+ for a in eh.actions:
+ if type(a) == lems.StateAssignment:
+ if not "conditions" in node["parameters"][a.variable]:
+ node["parameters"][a.variable]["conditions"] = {}
+
+ node["parameters"][a.variable]["conditions"][
+ "condition_%i" % conditions
+ ] = {"test": test, "value": a.value}
+
+ if type(a) == lems.EventOut:
+ del node["parameters"][a.port]["value"]
+ node["parameters"][a.port] = {
+ "default_initial_value": [0] * size
+ }
+
+ if not "conditions" in node["parameters"][a.port]:
+ node["parameters"][a.port]["conditions"] = {}
+
+ node["parameters"][a.port]["conditions"][
+ "condition_%i_on" % conditions
+ ] = {"test": test, "value": 1}
+ node["parameters"][a.port]["conditions"][
+ "condition_%i_off" % conditions
+ ] = {"test": "%s > 0" % a.port, "value": 0}
+
+ conditions += 1
+
+ for td in lems_comp_type.dynamics.time_derivatives:
+ node["parameters"][td.variable][
+ "time_derivative"
+ ] = self._convert_value(td.value)
+
+ if not "default_initial_value" in node["parameters"][td.variable]:
+ node["parameters"][td.variable]["default_initial_value"] = [
+ 0
+ ] * size
+
+ return node
+
+ def _replace_in_condition_test(self, test):
+ return (
+ test.replace(".gt.", ">")
+ .replace(".geq.", ">=")
+ .replace(".lt.", "<")
+ .replace(".leq.", "<=")
+ .replace(".eq.", "==")
+ .replace(".and.", "and")
+ )
# TODO: move to pylems!
@classmethod
- def _get_all_children_in_lems(cls, component_type, model, child_type):
- c = []
+ def _get_all_elements_in_lems(cls, component_type, model, child_type):
+ ee = []
if child_type == "exposure":
- for e in component_type.exposures:
- c.append(e)
+ if hasattr(component_type, "exposures"):
+ for e in component_type.exposures:
+ ee.append(e)
+ elif child_type == "constant":
+ if hasattr(component_type, "constants"):
+ for c in component_type.constants:
+ ee.append(c)
+ elif child_type == "event_port":
+ if hasattr(component_type, "event_ports"):
+ for e in component_type.event_ports:
+ ee.append(e)
+ elif child_type == "properties":
+ if hasattr(component_type, "properties"):
+ for p in component_type.properties:
+ ee.append(p)
+ else:
+ raise Exception("Cannot get child of type: %s in LEMS model" % child_type)
- if component_type.extends:
+ if hasattr(component_type, "extends") and component_type.extends:
ect = model.component_types[component_type.extends]
- c.extend(cls._get_all_children_in_lems(ect, model, child_type))
+ ee.extend(cls._get_all_elements_in_lems(ect, model, child_type))
- return c
+ return ee
# TODO: move to pyneuroml!
@classmethod
- def _get_lems_model_with_neuroml2_types(cls):
-
+ def _get_lems_model_with_neuroml2_types(cls, nml_doc=None):
from pyneuroml.pynml import get_path_to_jnml_jar
from pyneuroml.pynml import read_lems_file
from lems.parser.LEMS import LEMSFileParser
@@ -290,12 +575,27 @@ def _get_lems_model_with_neuroml2_types(cls):
new_lems = jar.read("NeuroML2CoreTypes/Inputs.xml")
parser.parse(new_lems)
+ if nml_doc is not None:
+ import io
+
+ sf = io.StringIO()
+
+ from neuroml.writers import NeuroMLWriter
+
+ print(
+ "Adding nml elements from this doc to new lems model: %s"
+ % nml_doc.summary()
+ )
+
+ NeuroMLWriter.write(nml_doc, sf, close=False)
+ sf.seek(0)
+ parser.parse(sf.read())
+
return lems_model
# TODO: move to pyneuroml!
@classmethod
def _load_lems_file_with_neuroml2_types(cls, lems_filename):
-
from pyneuroml.pynml import read_lems_file
lems_model = cls._get_lems_model_with_neuroml2_types()
@@ -318,9 +618,122 @@ def handle_location(self, id, population_id, component, x, y, z):
pass
def finalise_population(self, population_id):
-
pass
+ def handle_projection(
+ self,
+ projName,
+ prePop,
+ postPop,
+ synapse,
+ hasWeights=False,
+ hasDelays=False,
+ type="projection",
+ synapse_obj=None,
+ pre_synapse_obj=None,
+ ):
+ synInfo = ""
+ if synapse_obj:
+ synInfo += " (syn: %s)" % synapse_obj.__class__.__name__
+
+ if pre_synapse_obj:
+ synInfo += " (pre comp: %s)" % pre_synapse_obj.__class__.__name__
+
+ print_v(
+ " = Projection: "
+ + projName
+ + " ("
+ + type
+ + ") from "
+ + prePop
+ + " to "
+ + postPop
+ + " with syn: "
+ + synapse
+ + synInfo
+ )
+
+ syn_node_id = "%s_%s" % (projName, synapse)
+ syn_node = {}
+
+ syn_comp = self.nl_network.get_child(synapse, "synapses")
+
+ print("Converting syn %s; %s" % (synapse_obj, syn_comp))
+
+ pre_pop_size = self.pop_ids_vs_size[prePop]
+ post_pop_size = self.pop_ids_vs_size[postPop]
+
+ syn_node = self._comp_to_mdf_node(
+ nmllite_comp=syn_comp,
+ lems_comp_id=synapse,
+ size=post_pop_size,
+ properties={},
+ )
+ if SPIKE_INPUT_PORT_ID in syn_node["input_ports"]:
+ syn_node["input_ports"][SPIKE_INPUT_PORT_ID]["shape"] = [pre_pop_size]
+ syn_node["parameters"][WEIGHTED_SPIKE_INPUTS] = {
+ "value": numpy.zeros([pre_pop_size, post_pop_size]).tolist()
+ }
+ syn_node["parameters"]["weight"] = {}
+ syn_node["parameters"]["weight"]["function"] = "MatMul"
+ syn_node["parameters"]["weight"]["args"] = {
+ "A": SPIKE_INPUT_PORT_ID,
+ "B": WEIGHTED_SPIKE_INPUTS,
+ }
+
+ self.mdf_graph["nodes"][syn_node_id] = syn_node
+
+ #### Edge pre_node -> syn
+
+ pre_node_id = prePop
+ pre_node = self.mdf_graph["nodes"][pre_node_id]
+
+ pre_syn_edge_id = "%s_TO_%s" % (pre_node_id, syn_node_id)
+ pre_syn_edge = {}
+ pre_syn_edge["name"] = pre_syn_edge_id
+
+ pre_ports = list(pre_node["output_ports"].keys())
+ pre_syn_edge["sender_port"] = (
+ "OUTPUT" if "OUTPUT" in pre_ports else pre_ports[0]
+ )
+
+ post_ports = list(syn_node["input_ports"].keys())
+ pre_syn_edge["receiver_port"] = (
+ "INPUT" if "INPUT" in post_ports else post_ports[0]
+ )
+ pre_syn_edge["sender"] = pre_node_id
+ pre_syn_edge["receiver"] = syn_node_id
+
+ self.mdf_graph["edges"][pre_syn_edge_id] = pre_syn_edge
+
+ #### Edge syn -> post_node
+
+ post_node_id = postPop
+ post_node = self.mdf_graph["nodes"][post_node_id]
+
+ syn_post_edge_id = "%s_TO_%s" % (syn_node_id, post_node_id)
+ syn_post_edge = {}
+ syn_post_edge["name"] = syn_post_edge_id
+
+ syn_ports = list(syn_node["output_ports"].keys())
+
+ syn_post_edge["sender_port"] = (
+ "OUTPUT"
+ if "OUTPUT" in syn_ports
+ else ("i" if "i" in syn_ports else syn_ports[0])
+ )
+
+ post_ports = list(post_node["input_ports"].keys())
+ syn_post_edge["receiver_port"] = (
+ "INPUT"
+ if "INPUT" in post_ports
+ else ("synapses_i" if "synapses_i" in post_ports else post_ports[0])
+ )
+ syn_post_edge["sender"] = syn_node_id
+ syn_post_edge["receiver"] = post_node_id
+
+ self.mdf_graph["edges"][syn_post_edge_id] = syn_post_edge
+
#
# Should be overridden to handle network connection
#
@@ -340,43 +753,41 @@ def handle_connection(
delay=0,
weight=1,
):
-
# self.print_connection_information(projName, id, prePop, postPop, synapseType, preCellId, postCellId, weight)
print_v(
- ">>>>>> Src cell: %d, seg: %f, fract: %f -> Tgt cell %d, seg: %f, fract: %f; weight %s, delay: %s ms"
+ ">>>>>> Src pop: %s, cell: %d, seg: %f, fract: %f -> Tgt pop %s, cell %d, seg: %f, fract: %f; syn: %s, weight %s, delay: %s ms"
% (
+ prePop,
preCellId,
preSegId,
preFract,
+ postPop,
postCellId,
postSegId,
postFract,
+ synapseType,
weight,
delay,
)
)
- pre_node_id = "%s_%i" % (prePop, preCellId)
- post_node_id = "%s_%i" % (postPop, postCellId)
- edge_id = "Edge %s to %s" % (pre_node_id, post_node_id)
- edge = {}
- edge["name"] = edge_id
- # edge['type'] = {}
- # edge['type']['NeuroML'] = synapseType
- # edge['parameters'] = {}
- # edge['functions'] = {}
- edge["sender_port"] = "OUTPUT"
- edge["receiver_port"] = "INPUT"
- edge["sender"] = pre_node_id
- edge["receiver"] = post_node_id
- edge["weight"] = weight
+ if preSegId != 0 or postSegId != 0:
+ raise Exception(
+ "MDF export does not support connections on anything other than segment id = 0"
+ )
- """edge['type'] = {
- "PNL": "MappingProjection",
- "generic": None
- }"""
+ syn_node_id = "%s_%s" % (projName, synapseType)
+ node = self.mdf_graph["nodes"][syn_node_id]
+ if WEIGHTED_SPIKE_INPUTS in node["parameters"]:
+ # Weight used inside input
+ node["parameters"][WEIGHTED_SPIKE_INPUTS]["value"][preCellId][
+ postCellId
+ ] = weight
+ print(node["parameters"][WEIGHTED_SPIKE_INPUTS]["value"])
- self.mdf_graph["edges"][edge_id] = edge
+ def _get_input_list_node_id(self, inputListId):
+ return "InputList_%s" % (inputListId)
+ # return "%s" % (inputListId)
#
# Should be overridden to create input source array
@@ -384,48 +795,62 @@ def handle_connection(
def handle_input_list(
self, inputListId, population_id, component, size, input_comp_obj=None
):
-
self.input_list_vs_comps[inputListId] = component
self.input_list_vs_pops[inputListId] = population_id
- #
- # Should be overridden to to connect each input to the target cell
- #
- def handle_single_input(
- self, inputListId, id, cellId, segId=0, fract=0.5, weight=1
- ):
- component = self.input_list_vs_comps[inputListId]
print_v(
- "Input: %s[%s], cellId: %i, seg: %i, fract: %f, weight: %f, component: %s"
- % (inputListId, id, cellId, segId, fract, weight, component)
+ "InputList: %s, population_id: %s, component: %s, size: %i, input_comp_obj: %s"
+ % (inputListId, population_id, component, size, input_comp_obj)
)
- node_id = "Input_%s_%i" % (inputListId, id)
+ node_id = self._get_input_list_node_id(inputListId)
comp = self.nl_network.get_child(component, "input_sources")
- node = self._comp_to_mdf_node(comp, component, node_id)
+ node = self._comp_to_mdf_node(nmllite_comp=comp, lems_comp_id=component, size=1)
# TODO: remove when global t available
- node['parameters']['t']={'default_initial_value': 0, 'time_derivative': '1'}
+ node["parameters"]["t"] = {"default_initial_value": 0, "time_derivative": "1"}
+
+ pop_size = self.pop_ids_vs_size[population_id]
+ node["parameters"]["weight"] = {"value": [0.0] * pop_size}
self.mdf_graph["nodes"][node_id] = node
pre_node_id = node_id
- post_node_id = "%s_%i" % (self.input_list_vs_pops[inputListId], cellId)
+ post_node_id = "%s" % population_id
edge_id = "Edge %s to %s" % (pre_node_id, post_node_id)
edge = {}
edge["name"] = edge_id
edge["sender_port"] = "i"
- edge["receiver_port"] = "synapses_i"
+ edge["receiver_port"] = DEFAULT_CURRENT_INPUT_PORT
edge["sender"] = pre_node_id
edge["receiver"] = post_node_id
- # Weight used inside input
- node['parameters']['weight']={'value': weight}
-
self.mdf_graph["edges"][edge_id] = edge
+ #
+ # Should be overridden to to connect each input to the target cell
+ #
+ def handle_single_input(
+ self, inputListId, id, cellId, segId=0, fract=0.5, weight=1
+ ):
+ if segId != 0:
+ raise Exception(
+ "MDF export does not support inputs on anything other than segment id = 0"
+ )
+
+ component = self.input_list_vs_comps[inputListId]
+ print_v(
+ "Input: %s[%s], cellId: %i, seg: %i, fract: %f, weight: %f, component: %s"
+ % (inputListId, id, cellId, segId, fract, weight, component)
+ )
+
+ node = self.mdf_graph["nodes"][self._get_input_list_node_id(inputListId)]
+
+ # Weight used inside input
+ node["parameters"]["weight"]["value"][cellId] = weight
+
#
# Should be overridden to to connect each input to the target cell
#
@@ -434,7 +859,6 @@ def finalise_input_source(self, inputName):
if __name__ == "__main__":
-
lems_model = MDFHandler._load_lems_file_with_neuroml2_types(
"../../git/MDF/examples/NeuroML/LEMS_SimIzhikevichTest.xml"
)
diff --git a/neuromllite/MatrixHandler.py b/neuromllite/MatrixHandler.py
index 868f002..de1c859 100644
--- a/neuromllite/MatrixHandler.py
+++ b/neuromllite/MatrixHandler.py
@@ -14,13 +14,11 @@
class MatrixHandler(ConnectivityHandler):
-
colormaps_used = []
weight_arrays_to_show = {}
def __init__(self, level=10, nl_network=None):
-
self.nl_network = nl_network
self.level = level
@@ -62,7 +60,6 @@ def _get_conn_label(self, template, pclass):
return label
def finalise_document(self):
-
entries = []
# print_v('Finals: %s -> %s'%(self.proj_pre_pops, self.proj_post_pops))
all_pops = []
@@ -144,7 +141,6 @@ def finalise_document(self):
] = "conductance * sign (nS)"
for projName in self.proj_weights:
-
pre_pop = self.proj_pre_pops[projName]
post_pop = self.proj_post_pops[projName]
proj_type = self.proj_types[projName]
@@ -174,7 +170,6 @@ def finalise_document(self):
)
if self.is_cell_level():
-
for pre_i in range(self.pop_sizes[pre_pop]):
for post_i in range(self.pop_sizes[post_pop]):
pre_pop_i = entries.index(
@@ -217,7 +212,6 @@ def finalise_document(self):
if abs(self.proj_tot_weight[projName]) != abs(
self.proj_weights[projName]
):
-
self.weight_arrays_to_show[
self._get_conn_label(matrix_single_conns, pclass)
][pre_pop_i][post_pop_i] += (
@@ -250,7 +244,6 @@ def finalise_document(self):
% (proj_type, weight_array.min(), weight_array.max())
)
if not (weight_array.max() == 0 and weight_array.min() == 0):
-
fig, ax = plt.subplots()
title = "%s" % (proj_type)
title2 = "%s" % (proj_type)
@@ -445,7 +438,6 @@ def handle_projection(
synapse_obj=None,
pre_synapse_obj=None,
):
-
weight = 1.0
self.proj_pre_pops[projName] = prePop
self.proj_post_pops[projName] = postPop
@@ -513,7 +505,6 @@ def handle_projection(
def finalise_projection(
self, projName, prePop, postPop, synapse=None, type="projection"
):
-
pass
# print_v("Projection finalising: "+projName+" -> "+prePop+" to "+postPop+" completed (%s; w: %s, conns: %s, tot w: %s)" % \
# (self.proj_types[projName], self.proj_weights[projName], self.proj_conns[projName], self.proj_tot_weight[projName]))
@@ -524,5 +515,4 @@ def finalise_projection(
input_comp_obj_ils = {}
def finalise_input_source(self, inputListId):
-
pass
diff --git a/neuromllite/NetworkGenerator.py b/neuromllite/NetworkGenerator.py
index 04be0dd..f057388 100644
--- a/neuromllite/NetworkGenerator.py
+++ b/neuromllite/NetworkGenerator.py
@@ -18,15 +18,17 @@
DEFAULT_SIMULATION_SEED = 5678
-
def __TEMP_CHECK_IF_SET(value):
"""
Should just be a check for None! Update in modelspec...
"""
- if value is None: return False
- if value == '': return False
+ if value is None:
+ return False
+ if value == "":
+ return False
return True
+
def _get_rng_for_network(nl_model):
"""
Get a random number generator and the seed used to generate it
@@ -66,7 +68,6 @@ def generate_network(
rng, seed = _get_rng_for_network(nl_model)
if nl_model.network_reader:
-
exec(
"from neuromllite.%s import %s"
% (nl_model.network_reader.type, nl_model.network_reader.type)
@@ -90,13 +91,16 @@ def generate_network(
if not p == "__builtins__":
notes += "\n %s = %s" % (p, nl_model.parameters[p])
handler.handle_document_start(nl_model.id, notes)
- temperature = "%sdegC" % nl_model.temperature if nl_model.temperature is not None else None
+ temperature = (
+ "%sdegC" % nl_model.temperature
+ if nl_model.temperature is not None
+ else None
+ )
handler.handle_network(nl_model.id, nl_model.notes, temperature=temperature)
nml2_doc_temp = _extract_pynn_components_to_neuroml(nl_model)
for c in nl_model.cells:
-
if c.neuroml2_source_file:
from pyneuroml import pynml
@@ -117,11 +121,10 @@ def generate_network(
)
synapse_objects[s.id] = nml2_doc.get_by_id(s.id)
- if hasattr(s, 'pynn_synapse') and s.pynn_synapse is not None:
+ if hasattr(s, "pynn_synapse") and s.pynn_synapse is not None:
synapse_objects[s.id] = nml2_doc_temp.get_by_id(s.id)
for p in nl_model.populations:
-
size = evaluate(p.size, nl_model.parameters)
properties = p.properties if p.properties else {}
@@ -136,7 +139,6 @@ def generate_network(
and not p.relative_layout
and not always_include_props
):
-
# If there are no positions (abstract network), and
# is added to , jLems doesn't like it... (it has difficulty
# interpreting pop0[0]/v, etc.)
@@ -197,7 +199,6 @@ def generate_network(
if include_connections:
for p in nl_model.projections:
-
type = p.type if p.type else "projection"
synapse_obj = (
@@ -242,7 +243,6 @@ def generate_network(
nl_model.parameters,
rng,
):
-
delay = (
evaluate(p.delay, nl_model.parameters, rng)
if p.delay
@@ -272,9 +272,7 @@ def generate_network(
conn_count += 1
if p.convergent_connectivity:
-
for post_i in range(len(pop_locations[p.postsynaptic])):
-
for count in range(int(p.convergent_connectivity.num_per_post)):
found = False
while not found:
@@ -322,7 +320,6 @@ def generate_network(
len(pop_locations[p.postsynaptic]),
)
):
-
# print_v("Adding connection %i with weight: %s, delay: %s"%(conn_count, weight, delay))
handler.handle_connection(
p.id,
@@ -347,7 +344,6 @@ def generate_network(
if include_inputs:
for input in nl_model.inputs:
-
handler.handle_input_list(
input.id,
input.population,
@@ -365,7 +361,11 @@ def generate_network(
% input
)
for i in input.cell_ids:
- weight = input.weight if input.weight else 1
+ weight = (
+ evaluate(input.weight, nl_model.parameters, rng)
+ if input.weight
+ else 1
+ )
if input.number_per_cell and input.segment_ids:
raise Exception(
@@ -389,7 +389,11 @@ def generate_network(
input_count,
i,
segId=seg_id,
- weight=evaluate(weight, nl_model.parameters),
+ weight=(
+ evaluate(input.weight, nl_model.parameters, rng)
+ if input.weight
+ else 1
+ ),
)
input_count += 1
@@ -401,9 +405,12 @@ def generate_network(
)
for i in range(len(pop_locations[input.population])):
flip = rng.random()
- weight = input.weight if input.weight else 1
- if flip * 100.0 < input.percentage:
-
+ weight = (
+ evaluate(input.weight, nl_model.parameters, rng)
+ if input.weight
+ else 1
+ )
+ if flip * 100.0 < evaluate(input.percentage, nl_model.parameters, rng):
if input.number_per_cell and input.segment_ids:
raise Exception(
"On input: %s, only one of number_per_cell or segment_ids is allowed"
@@ -426,7 +433,11 @@ def generate_network(
input_count,
i,
segId=seg_id,
- weight=evaluate(weight, nl_model.parameters),
+ weight=(
+ evaluate(input.weight, nl_model.parameters, rng)
+ if input.weight
+ else 1
+ ),
)
input_count += 1
@@ -502,12 +513,10 @@ def check_to_generate_or_run(argv, sim):
generate_and_run(sim, simulator="mdf")
elif "-nml" in argv or "-neuroml" in argv:
-
network = load_network(sim.network)
generate_neuroml2_from_network(network, simulation=sim, validate=True)
elif "-nmlh5" in argv or "-neuromlh5" in argv:
-
network = load_network(sim.network)
generate_neuroml2_from_network(
network, simulation=sim, validate=True, format="hdf5"
@@ -515,7 +524,6 @@ def check_to_generate_or_run(argv, sim):
else:
for a in argv:
-
if "-jnmlnetpyne" in a:
num_processors = 1
if len(a) > len("-jnmlnetpyne"):
@@ -527,7 +535,9 @@ def check_to_generate_or_run(argv, sim):
show_graph = True
if "-nogui" in argv:
show_graph = False
- generate_and_run(sim, simulator=a[1:], nogui= not show_graph) # Will not "run" obviously...
+ generate_and_run(
+ sim, simulator=a[1:], nogui=not show_graph
+ ) # Will not "run" obviously...
elif "matrix" in a: # e.g. -matrix2
generate_and_run(sim, simulator=a[1:]) # Will not "run" obviously...
@@ -548,7 +558,6 @@ def _extract_pynn_components_to_neuroml(nl_model, nml_doc=None):
for c in nl_model.cells:
if c.pynn_cell:
-
if nml_doc.get_by_id(c.id) == None:
import pyNN.neuroml
@@ -556,7 +565,6 @@ def _extract_pynn_components_to_neuroml(nl_model, nml_doc=None):
for p in cell_params:
cell_params[p] = evaluate(cell_params[p], nl_model.parameters)
for proj in nl_model.projections:
-
synapse = nl_model.get_child(proj.synapse, "synapses")
post_pop = nl_model.get_child(proj.postsynaptic, "populations")
if post_pop.component == c.id:
@@ -572,7 +580,8 @@ def _extract_pynn_components_to_neuroml(nl_model, nml_doc=None):
)
temp_cell = eval("pyNN.neuroml.%s(**cell_params)" % c.pynn_cell)
- if c.pynn_cell != "SpikeSourcePoisson":
+
+ if c.pynn_cell != "SpikeSourcePoisson" and c.pynn_cell != "HH_cond_exp":
temp_cell.default_initial_values["v"] = temp_cell.parameter_space[
"v_rest"
].base_value
@@ -583,7 +592,6 @@ def _extract_pynn_components_to_neuroml(nl_model, nml_doc=None):
for s in nl_model.synapses:
if nml_doc.get_by_id(s.id) == None:
-
if s.pynn_synapse_type and s.pynn_receptor_type:
import neuroml
@@ -606,7 +614,6 @@ def _extract_pynn_components_to_neuroml(nl_model, nml_doc=None):
nml_doc.alpha_curr_synapses.append(syn)
for i in nl_model.input_sources:
-
if i.pynn_input:
import pyNN.neuroml
@@ -673,7 +680,6 @@ def generate_neuroml2_from_network(
)
for i in nl_model.input_sources:
-
if i.lems_source_file:
fname = locate_file(i.lems_source_file, base_dir)
@@ -686,7 +692,7 @@ def generate_neuroml2_from_network(
for comp in model.components:
if i.id == comp.id:
print_v("Found a component: %s in %s" % (comp, fname))
- if hasattr(i, 'parameters') and len(i.parameters) > 0:
+ if hasattr(i, "parameters") and len(i.parameters) > 0:
for p in i.parameters:
comp.set_parameter(
p, evaluate(i.parameters[p], nl_model.parameters)
@@ -713,14 +719,13 @@ def generate_neuroml2_from_network(
if nml_doc.get_by_id(i.id) == None:
if i.neuroml2_source_file:
-
incl = neuroml.IncludeType(
locate_file(i.neuroml2_source_file, base_dir)
)
if not incl in nml_doc.includes:
nml_doc.includes.append(incl)
- if hasattr(i, 'neuroml2_input') and i.neuroml2_input is not None:
+ if hasattr(i, "neuroml2_input") and i.neuroml2_input is not None:
input_params = i.parameters if i.parameters else {}
# TODO make more generic...
@@ -745,7 +750,6 @@ def generate_neuroml2_from_network(
for c in nl_model.cells:
if c.neuroml2_source_file:
-
incl = neuroml.IncludeType(locate_file(c.neuroml2_source_file, base_dir))
found_cell = False
for cell in nml_doc.cells:
@@ -802,7 +806,6 @@ def generate_neuroml2_from_network(
nml_doc.includes.append(incl)
if c.neuroml2_cell:
-
cell_params = c.parameters if c.parameters else {}
# TODO make more generic...
if c.neuroml2_cell.lower() == "spikegenerator":
@@ -910,7 +913,6 @@ def generate_neuroml2_from_network(
extra_lems_components.export_to_file(extra_lems_file)
if validate and format == "xml":
-
from pyneuroml import pynml
success = pynml.validate_neuroml2(nml_file_name, verbose_validate=False)
@@ -998,7 +1000,6 @@ def _generate_neuron_files_from_neuroml(network, verbose=False, dir_for_mod_file
% (dir_for_mod_files, os.getcwd(), locations_mods_loaded_from)
)
try:
-
from neuron import load_mechanisms
if os.getcwd() == dir_for_mod_files:
@@ -1041,7 +1042,6 @@ def generate_and_run(
try:
if simulator == "NEURON": # NOT YET WORKING...
-
_generate_neuron_files_from_neuroml(network, dir_for_mod_files=target_dir)
from neuromllite.NeuronHandler import NeuronHandler
@@ -1060,7 +1060,6 @@ def generate_and_run(
)
elif simulator.lower() == "mdf":
-
from neuromllite.MDFHandler import MDFHandler
mdf_handler = MDFHandler(nl_network=network)
@@ -1068,7 +1067,6 @@ def generate_and_run(
generate_network(network, mdf_handler)
elif simulator.lower() == "psyneulink":
-
from neuromllite.PsyNeuLinkHandler import PsyNeuLinkHandler
pnl_handler = PsyNeuLinkHandler(nl_network=network)
@@ -1158,7 +1156,6 @@ def generate_value_array(node, index, context='{0}', param='value'):
print_v("Done with PsyNeuLink...")
elif simulator.lower() == "sonata":
-
target_simulator = "NEST"
from neuromllite.SonataHandler import SonataHandler
@@ -1173,7 +1170,6 @@ def generate_value_array(node, index, context='{0}', param='value'):
for c in network.cells:
if c.pynn_cell:
-
cell_params = {}
if c.parameters:
for p in c.parameters:
@@ -1254,7 +1250,7 @@ def generate_value_array(node, index, context='{0}', param='value'):
sim_file_info["inputs"] = {}
for input in sonata_handler.input_info:
- print('Handling: %s: %s'%(input, sonata_handler.input_info[input]))
+ print("Handling: %s: %s" % (input, sonata_handler.input_info[input]))
sim_file_info["inputs"][input] = {}
input_comp = sonata_handler.input_info[input][1]
c = temp_nml_doc.get_by_id(input_comp)
@@ -1320,12 +1316,10 @@ def run(config_file, simulator):
print_v("Done with Sonata...")
elif simulator.lower().startswith("graph"): # Will not "run" obviously...
-
from neuromllite.GraphVizHandler import GraphVizHandler, engines
try:
if simulator[-1].isalpha():
-
engine = engines[simulator[-1]]
level = int(simulator[5:-1])
else:
@@ -1339,7 +1333,9 @@ def run(config_file, simulator):
)
return
- handler = GraphVizHandler(level, engine=engine, nl_network=network, view_on_render = not nogui)
+ handler = GraphVizHandler(
+ level, engine=engine, nl_network=network, view_on_render=not nogui
+ )
generate_network(
network, handler, always_include_props=True, base_dir=base_dir
@@ -1348,7 +1344,6 @@ def run(config_file, simulator):
print_v("Done with GraphViz...")
elif simulator.lower().startswith("matrix"): # Will not "run" obviously...
-
from neuromllite.MatrixHandler import MatrixHandler
try:
@@ -1369,7 +1364,6 @@ def run(config_file, simulator):
print_v("Done with MatrixHandler...")
elif simulator == "BindsNET":
-
from neuromllite.BindsNETHandler import BindsNETHandler
import bindsnet
@@ -1434,7 +1428,6 @@ def run(config_file, simulator):
return traces, events
elif simulator == "Arbor":
-
from neuromllite.ArborHandler import ArborHandler
import arbor
@@ -1484,7 +1477,7 @@ def run(config_file, simulator):
# (12) Create a default execution context, domain decomposition and simulation
context = arbor.context()
decomp = arbor.partition_load_balance(arbor_recipe, context)
- sim = arbor.simulation(arbor_recipe, decomp, context)
+ sim = arbor.simulation(arbor_recipe, domains=decomp, context=context)
# (13) Set spike generators to record
sim.record(arbor.spike_recording.all)
@@ -1507,7 +1500,6 @@ def run(config_file, simulator):
for pop_id in trace_pop_indices_seg_ids:
indices = trace_pop_indices_seg_ids[pop_id].keys()
for index in indices:
-
filename = "%s.%s.%s.v.dat" % (simulation.id, pop_id, index)
# all_columns = []
gid = arbor_recipe.get_gid(pop_id, index)
@@ -1565,7 +1557,6 @@ def run(config_file, simulator):
return traces, events
elif simulator.startswith("PyNN"):
-
# _generate_neuron_files_from_neuroml(network)
simulator_name = simulator.split("_")[1].lower()
@@ -1575,7 +1566,6 @@ def run(config_file, simulator):
syn_cell_params = {}
for proj in network.projections:
-
synapse = network.get_child(proj.synapse, "synapses")
post_pop = network.get_child(proj.postsynaptic, "populations")
@@ -1633,7 +1623,6 @@ def run(config_file, simulator):
pynn_handler.set_receptor_types(receptor_types)
for input_source in network.input_sources:
-
# TODO: change this when noisyCurrentSource is integrated into the core of NeuroML
if input_source.pynn_input or input_source.lems_source_file:
pynn_handler.add_input_source(input_source, network)
@@ -1686,6 +1675,14 @@ def run(config_file, simulator):
events = {}
if not "NeuroML" in simulator:
+ # Temp! See https://github.com/NeuralEnsemble/PyNN/pull/762
+ def get_source_id(spiketrain):
+ if "source_id" in spiketrain.annotations:
+ return spiketrain.annotations["source_id"]
+ elif (
+ "channel_id" in spiketrain.annotations
+ ): # See https://github.com/NeuralEnsemble/PyNN/pull/762
+ return spiketrain.annotations["channel_id"]
for pop_id in trace_pop_indices_seg_ids:
pynn_pop = pynn_handler.populations[pop_id]
@@ -1748,8 +1745,8 @@ def run(config_file, simulator):
ff = open(filename, "w")
for spiketrain in spiketrains:
- source_id = spiketrain.annotations["source_id"]
- source_index = spiketrain.annotations["source_index"]
+ source_id = get_source_id(spiketrain)
+ source_index = pynn_pop.id_to_index(source_id)
if source_index in indices:
# print_v("Writing spike data for cell %s[%s] (gid: %i): %i spikes "%(pynn_pop.label,source_index, source_id, len(spiketrain)), self.verbose)
ref = "%s/%i/???" % (pynn_pop.label, source_index)
@@ -1766,7 +1763,6 @@ def run(config_file, simulator):
return traces, events
elif simulator == "NetPyNE":
-
if target_dir == None:
target_dir = "./"
@@ -1861,7 +1857,6 @@ def run(config_file, simulator):
preComp = netpyne_handler.pop_ids_vs_components[prePop]
for conn in netpyne_handler.connections[projName]:
-
(
pre_id,
pre_seg,
@@ -1883,7 +1878,6 @@ def run(config_file, simulator):
}
if ptype == "electricalProjection":
-
if weight != 1:
raise Exception(
"Cannot yet support inputs where weight !=1!"
@@ -2000,7 +1994,6 @@ def run(config_file, simulator):
or simulator == "jNeuroML_Brian2"
or simulator == "EDEN"
):
-
from pyneuroml.lems import generate_lems_file_for_neuroml
from pyneuroml import pynml
@@ -2046,7 +2039,6 @@ def run(config_file, simulator):
pops = network.populations
pops.sort(key=id)
for p in pops:
-
if p.id in spike_pop_indices:
pops_spike_save.append(p.id)
diff --git a/neuromllite/NeuronHandler.py b/neuromllite/NeuronHandler.py
index 854806d..3a426f4 100644
--- a/neuromllite/NeuronHandler.py
+++ b/neuromllite/NeuronHandler.py
@@ -15,7 +15,6 @@
class NeuronHandler(DefaultNetworkHandler):
-
h = hoc.HocObject()
globalPreSynId = 10000000
@@ -26,7 +25,6 @@ class NeuronHandler(DefaultNetworkHandler):
# Helper function for printing hoc before executing it
#
def executeHoc(self, command):
-
cmdPrefix = "hoc >>>>>>>>>>: "
if len(command) > 0:
@@ -37,7 +35,6 @@ def executeHoc(self, command):
# Overridden from NetworkHandler
#
def handlePopulation(self, population_id, component, size=-1, component_obj=None):
-
if size >= 0:
sizeInfo = ", size " + str(size) + " cells"
@@ -56,7 +53,6 @@ def handlePopulation(self, population_id, component, size=-1, component_obj=None
)
else:
-
print_v(
"Population: "
+ population_id
@@ -136,7 +132,6 @@ def handleProjection(
synapse_obj=None,
pre_synapse_obj=None,
):
-
print_v("Projection: " + projName + " from " + prePop + " to " + postPop)
#
@@ -158,7 +153,6 @@ def handleConnection(
delay=0,
weight=1,
):
-
# self.printConnectionInformation(projName, id, prePop, postPop, synapseType, preCellId, postCellId, localWeight)
print_v(
diff --git a/neuromllite/PsyNeuLinkHandler.py b/neuromllite/PsyNeuLinkHandler.py
index ad2e593..c0220f2 100644
--- a/neuromllite/PsyNeuLinkHandler.py
+++ b/neuromllite/PsyNeuLinkHandler.py
@@ -14,7 +14,6 @@
class PsyNeuLinkHandler(DefaultNetworkHandler):
-
bids_mdf_info = {}
bids_mdf_info["graphs"] = []
@@ -26,19 +25,16 @@ def __init__(self, nl_network):
self.nl_network = nl_network
def handle_document_start(self, id, notes):
-
print_v("Parsing for PsyNeuLink export: %s" % id)
self.id = id
def finalise_document(self):
-
print_v("Writing file for...: %s" % self.id)
save_to_json_file(self.bids_mdf_info, "%s.bids-mdf.json" % self.id, indent=4)
"""save_to_json_file(self.bids_mdf_info_hl, '%s.bids-mdf.highlevel.json'%self.id, indent=4)"""
def handle_network(self, network_id, notes, temperature=None):
-
print_v("Network: %s" % network_id)
self.network_id = network_id
@@ -71,7 +67,6 @@ def handle_network(self, network_id, notes, temperature=None):
def handle_population(
self, population_id, component, size=-1, component_obj=None, properties={}
):
-
sizeInfo = " as yet unspecified size"
if size >= 0:
sizeInfo = ", size: " + str(size) + " cells"
@@ -172,7 +167,6 @@ def handle_location(self, id, population_id, component, x, y, z):
pass
def finalise_population(self, population_id):
-
pass
#
@@ -194,7 +188,6 @@ def handle_connection(
delay=0,
weight=1,
):
-
# self.print_connection_information(projName, id, prePop, postPop, synapseType, preCellId, postCellId, weight)
print_v(
">>>>>> Src cell: %d, seg: %f, fract: %f -> Tgt cell %d, seg: %f, fract: %f; weight %s, delay: %s ms"
@@ -235,7 +228,6 @@ def handle_connection(
def handle_input_list(
self, inputListId, population_id, component, size, input_comp_obj=None
):
-
pass
#
@@ -244,7 +236,6 @@ def handle_input_list(
def handle_single_input(
self, inputListId, id, cellId, segId=0, fract=0.5, weight=1
):
-
print_v(
"Input: %s[%s], cellId: %i, seg: %i, fract: %f, weight: %f"
% (inputListId, id, cellId, segId, fract, weight)
diff --git a/neuromllite/PsyNeuLinkReader.py b/neuromllite/PsyNeuLinkReader.py
index fdc63ef..cc6eb80 100644
--- a/neuromllite/PsyNeuLinkReader.py
+++ b/neuromllite/PsyNeuLinkReader.py
@@ -7,14 +7,12 @@
class PsyNeuLinkReader(NetworkReader):
-
component_objects = {} # Store cell ids vs objects, e.g. NeuroML2 based object
PRE_SYN = "silentSyn"
POST_SYN = "rsDL"
def __init__(self, **parameters):
-
print_v("Creating PsyNeuLinkReader with %s..." % parameters)
self.parameters = parameters
self.current_population = None
@@ -27,7 +25,6 @@ def _generate_id(self, name):
)
def parse(self, handler):
-
FORMAT = "BIDS-MDF"
filename = os.path.abspath(self.parameters["filename"])
id = filename.split("/")[-1].split(".")[0]
@@ -266,7 +263,6 @@ def parse_dataset(self, d):
if __name__ == "__main__":
-
test_files = [
"../../neuroConstruct/osb/showcase/PsyNeuLinkShowcase/PsyNeuLink/model_with_simple_graph.json"
]
diff --git a/neuromllite/PyNNHandler.py b/neuromllite/PyNNHandler.py
index a87236b..d799153 100644
--- a/neuromllite/PyNNHandler.py
+++ b/neuromllite/PyNNHandler.py
@@ -14,7 +14,6 @@
class PyNNHandler(DefaultNetworkHandler):
-
populations = {}
projections = {}
input_sources = {}
@@ -80,11 +79,9 @@ def add_input_source(self, input_source, network):
# print(['%s (%s): %s'%(i, type(self.input_sources[i]),self.input_sources[i].simple_parameters()) for i in self.input_sources])
def handle_document_start(self, id, notes):
-
print_v("Document: %s" % id)
def handle_network(self, network_id, notes, temperature=None):
-
print_v("Network: %s" % network_id)
if temperature:
print_v(" Temperature: " + temperature)
@@ -94,7 +91,6 @@ def handle_network(self, network_id, notes, temperature=None):
def handle_population(
self, population_id, component, size=-1, component_obj=None, properties={}
):
-
sizeInfo = " as yet unspecified size"
if size >= 0:
sizeInfo = ", size: " + str(size) + " cells"
@@ -141,7 +137,6 @@ def handle_projection(
synapse_obj=None,
pre_synapse_obj=None,
):
-
synInfo = ""
if synapse_obj:
synInfo += " (syn: %s)" % synapse_obj.__class__.__name__
@@ -184,7 +179,6 @@ def handle_connection(
delay=0,
weight=1,
):
-
# self.print_connection_information(projName, id, prePop, postPop, synapseType, preCellId, postCellId, weight)
# print_v("Src cell: %d, seg: %f, fract: %f -> Tgt cell %d, seg: %f, fract: %f; weight %s, delay: %s ms" % (preCellId,preSegId,preFract,postCellId,postSegId,postFract, weight, delay))
@@ -199,7 +193,6 @@ def handle_connection(
def finalise_projection(
self, projName, prePop, postPop, synapse=None, type="projection"
):
-
print_v(
"Projection finalising: "
+ projName
@@ -233,7 +226,6 @@ def finalise_projection(
def handle_input_list(
self, inputListId, population_id, component, size, input_comp_obj=None
):
-
self.print_input_information(inputListId, population_id, component, size)
if size < 0:
@@ -250,7 +242,6 @@ def handle_input_list(
def handle_single_input(
self, inputListId, id, cellId, segId=0, fract=0.5, weight=1
):
-
# print_v("Input: %s[%s], cellId: %i, seg: %i, fract: %f, weight: %f" % (inputListId,id,cellId,segId,fract,weight))
population_id, component = self.input_info[inputListId]
diff --git a/neuromllite/SonataHandler.py b/neuromllite/SonataHandler.py
index e11f7d1..8f3b413 100644
--- a/neuromllite/SonataHandler.py
+++ b/neuromllite/SonataHandler.py
@@ -14,7 +14,6 @@
class SonataHandler(DefaultNetworkHandler):
-
positions = {}
pop_indices = {}
@@ -28,7 +27,6 @@ def __init__(self):
print_v("Initiating Sonata handler")
def handle_document_start(self, id, notes):
-
print_v("Parsing for Sonata export: %s" % id)
self.config_file_info = {}
@@ -64,7 +62,6 @@ def handle_document_start(self, id, notes):
self.circuit_file_info["networks"]["nodes"].append({})
def finalise_document(self):
-
print_v("Writing file...: %s" % id)
self.sonata_nodes.close()
@@ -97,7 +94,6 @@ def finalise_document(self):
save_to_json_file(self.circuit_file_info, "circuit_config.json", indent=2)
def handle_network(self, network_id, notes, temperature=None):
-
print_v("Network: %s" % network_id)
self.network_id = network_id
@@ -123,7 +119,6 @@ def handle_network(self, network_id, notes, temperature=None):
def handle_population(
self, population_id, component, size=-1, component_obj=None, properties={}
):
-
sizeInfo = " as yet unspecified size"
if size >= 0:
sizeInfo = ", size: " + str(size) + " cells"
@@ -159,7 +154,6 @@ def handle_population(
)
def handle_location(self, id, population_id, component, x, y, z):
-
if not population_id in self.positions:
self.positions[population_id] = np.array([[x, y, z]])
self.pop_indices[population_id] = np.array([id])
@@ -172,7 +166,6 @@ def handle_location(self, id, population_id, component, x, y, z):
)
def finalise_population(self, population_id):
-
self.sonata_nodes.create_dataset(
"nodes/%s/0/positions" % population_id, data=self.positions[population_id]
)
@@ -202,7 +195,6 @@ def finalise_population(self, population_id):
def handle_input_list(
self, inputListId, population_id, component, size, input_comp_obj=None
):
-
self.print_input_information(inputListId, population_id, component, size)
if size < 0:
@@ -219,7 +211,6 @@ def handle_input_list(
def handle_single_input(
self, inputListId, id, cellId, segId=0, fract=0.5, weight=1
):
-
print_v(
"Input: %s[%s], cellId: %i, seg: %i, fract: %f, weight: %f"
% (inputListId, id, cellId, segId, fract, weight)
diff --git a/neuromllite/SonataReader.py b/neuromllite/SonataReader.py
index 8371c07..a94615e 100644
--- a/neuromllite/SonataReader.py
+++ b/neuromllite/SonataReader.py
@@ -19,7 +19,6 @@
def _get_default_nest_syn(nml_doc):
-
if nml_doc.get_by_id(DEFAULT_NEST_SPIKE_SYN):
return nml_doc.get_by_id(DEFAULT_NEST_SPIKE_SYN)
@@ -90,7 +89,6 @@ class SonataReader(NetworkReader):
nml_includes = ["PyNN.xml"]
def __init__(self, **parameters):
-
print_v("Creating SonataReader with %s..." % parameters)
self.parameters = parameters
@@ -361,11 +359,9 @@ def parse(self, handler):
properties["color"] = color
if True or not "locations" in self.cell_info[sonata_pop]["0"]:
-
properties = {} ############# temp for LEMS...
if model_type != "virtual":
-
self.handler.handle_population(
nml_pop_id,
pop_comp,
@@ -379,7 +375,6 @@ def parse(self, handler):
self.cell_info[sonata_pop]["pop_map"] = {}
for i in self.cell_info[sonata_pop]["types"]:
-
pop = types_vs_pops[self.cell_info[sonata_pop]["types"][i]]
if not pop in self.cell_info[sonata_pop]["pop_count"]:
@@ -412,7 +407,6 @@ def parse(self, handler):
# Load simulation info into self.simulation_config
if self.simulation_config:
-
if self.simulation_config:
for m in self.simulation_config["manifest"]:
path = self.subs(self.simulation_config["manifest"][m])
@@ -505,7 +499,6 @@ def parse(self, handler):
node_set = info["node_set"]
if info["input_type"] == "current_clamp":
-
comp = "PG_%s" % input
self.input_comp_info[input][info["input_type"]][comp] = {
"amp": info["amp"],
@@ -514,7 +507,6 @@ def parse(self, handler):
}
for nml_pop_id in self.node_set_mappings[node_set]:
-
input_list_id = "il_%s_%s" % (input, nml_pop_id)
indices = self.node_set_mappings[node_set][nml_pop_id]
@@ -579,7 +571,6 @@ def parse(self, handler):
projections_created = []
for conn in self.conn_info:
-
pre_node = self.conn_info[conn]["pre_node"]
post_node = self.conn_info[conn]["post_node"]
@@ -663,7 +654,6 @@ def parse(self, handler):
if not pop_type_pre == "virtual":
if not proj_id in projections_created:
-
self.handler.handle_projection(
proj_id, pre_pop, post_pop, synapse
)
@@ -743,7 +733,6 @@ def parse_group(self, g):
self.conn_info[self.current_edge] = {}
if g._v_name == self.current_edge:
-
self.current_pre_node = g._v_name.split("_to_")[0]
self.current_post_node = g._v_name.split("_to_")[1]
# print(' Found edge %s -> %s'%(self.current_pre_node, self.current_post_node))
@@ -785,7 +774,6 @@ def parse_dataset(self, d):
elif (
self.current_sonata_pop
): # e.g. parent group is cortex with child datasets node_id etc.
-
if d.name == "node_group_id":
for i in range(0, d.shape[0]):
if not d[i] == 0:
@@ -857,7 +845,6 @@ def add_neuroml_components(self, nml_doc):
info["model_type"] == "point_process"
and model_template == "nest:iaf_psc_alpha"
):
-
is_nest = True
from neuroml import IF_curr_alpha
@@ -881,7 +868,6 @@ def add_neuroml_components(self, nml_doc):
info["model_type"] == "point_process"
and model_template == "NEURON_IntFire1"
):
-
contents = """
""" % (
@@ -901,7 +887,6 @@ def add_neuroml_components(self, nml_doc):
)
else:
-
from neuroml import IafRefCell
IafRefCell0 = IafRefCell(
@@ -947,7 +932,6 @@ def add_neuroml_components(self, nml_doc):
"level_of_detail" in dyn_params
and dyn_params["level_of_detail"] == "instanteneous"
):
-
contents = """
""" % (
@@ -1164,7 +1148,6 @@ def process_args():
def _get_nml_pop_id(quantity):
-
if "[" in quantity:
nml_pop = quantity.split("[")[0]
nml_index = int(quantity.split("[")[1].split("]")[0])
@@ -1177,7 +1160,6 @@ def _get_nml_pop_id(quantity):
def run(args):
-
print_v(
"Reading Sonata file: %s and generating network: %s"
% (args.sonata_config_file, args.network_reference)
@@ -1197,12 +1179,10 @@ def run(args):
print_v("Generated LEMS file to run network: %s" % (lems_file_name))
if args.jnml or args.neuron:
-
traces = None
events = None
if args.jnml:
-
from pyneuroml import pynml
traces, events = pynml.run_lems_with_jneuroml(
@@ -1213,7 +1193,6 @@ def run(args):
reload_events=True,
)
if args.neuron:
-
from pyneuroml import pynml
traces, events = pynml.run_lems_with_jneuroml_neuron(
@@ -1245,7 +1224,6 @@ def run(args):
nml_q_vs_node_id = {}
for nml_q in traces.keys():
-
if nml_q != "t":
nml_pop, nml_index = _get_nml_pop_id(nml_q)
(sonata_node, sonata_node_id) = sr.nml_ids_vs_gids[nml_pop][
@@ -1256,7 +1234,6 @@ def run(args):
ordered = sorted(nml_q_vs_node_id, key=nml_q_vs_node_id.get)
for nml_q in ordered:
-
if nml_q != "t":
v = traces[nml_q]
nml_pop, nml_index = _get_nml_pop_id(nml_q)
@@ -1273,7 +1250,6 @@ def run(args):
node_info[sonata_node]["gids"].append(sonata_node_id)
for sonata_node in node_info:
-
node_grp = h5file.create_group(report_grp, sonata_node)
mapping_grp = h5file.create_group(node_grp, "mapping")
@@ -1334,7 +1310,6 @@ def run(args):
def main(args=None):
-
if "-test" in sys.argv:
id = "9_cells"
id = "300_cells"
@@ -1368,7 +1343,6 @@ def main(args=None):
NeuroMLHdf5Writer.write(nml_doc,nml_file_name)
print('Written to: %s'%nml_file_name) """
else:
-
if args is None:
args = process_args()
run(args=args)
diff --git a/neuromllite/__init__.py b/neuromllite/__init__.py
index 33e64e0..ca81abc 100644
--- a/neuromllite/__init__.py
+++ b/neuromllite/__init__.py
@@ -1,6 +1,6 @@
import collections
-__version__ = "0.5.3"
+__version__ = "0.5.7"
# import pyNN
# import nest
@@ -41,6 +41,7 @@ def get_locations(self):
@modelspec.define
class NMLBase(Base):
"""Base class for NeuroML objects."""
+
notes: str = field(kw_only=True, default=None, validator=optional(instance_of(str)))
@@ -59,9 +60,14 @@ class Cell(NMLBase):
arbor_cell: Name of standard Arbor cell type
bindsnet_node: Name of standard BindsNET node
"""
+
id: str = field(validator=instance_of(str))
- parameters: Dict[str, Any] = field(default=None, validator=optional(instance_of(dict)))
- neuroml2_source_file: str = field(default=None, validator=optional(instance_of(str)))
+ parameters: Dict[str, Any] = field(
+ default=None, validator=optional(instance_of(dict))
+ )
+ neuroml2_source_file: str = field(
+ default=None, validator=optional(instance_of(str))
+ )
lems_source_file: str = field(default=None, validator=optional(instance_of(str)))
neuroml2_cell: str = field(default=None, validator=optional(instance_of(str)))
pynn_cell: str = field(default=None, validator=optional(instance_of(str)))
@@ -82,12 +88,22 @@ class Synapse(NMLBase):
pynn_synapse_type: The pynn synapse type. Valid values are: "curr_exp", "curr_alpha", "cond_exp", "cond_alpha".
pynn_receptor_type: The pynn receptor type. Valid values are: "excitatory", "inhibitory".
"""
+
id: str = field(validator=instance_of(str))
- parameters: Dict[str, Any] = field(default=None, validator=optional(instance_of(dict)))
- neuroml2_source_file: str = field(default=None, validator=optional(instance_of(str)))
+ parameters: Dict[str, Any] = field(
+ default=None, validator=optional(instance_of(dict))
+ )
+ neuroml2_source_file: str = field(
+ default=None, validator=optional(instance_of(str))
+ )
lems_source_file: str = field(default=None, validator=optional(instance_of(str)))
- pynn_synapse_type: str = field(default=None, validator=optional(in_(["curr_exp", "curr_alpha", "cond_exp", "cond_alpha"])))
- pynn_receptor_type: str = field(default=None, validator=optional(in_(["excitatory", "inhibitory"])))
+ pynn_synapse_type: str = field(
+ default=None,
+ validator=optional(in_(["curr_exp", "curr_alpha", "cond_exp", "cond_alpha"])),
+ )
+ pynn_receptor_type: str = field(
+ default=None, validator=optional(in_(["excitatory", "inhibitory"]))
+ )
@modelspec.define
@@ -103,9 +119,14 @@ class InputSource(NMLBase):
lems_source_file: File name of LEMS file defining the input source
pynn_input: Name of PyNN input
"""
+
id: str = field(validator=instance_of(str))
- parameters: Dict[str, Any] = field(default=None, validator=optional(instance_of(dict)))
- neuroml2_source_file: str = field(default=None, validator=optional(instance_of(str)))
+ parameters: Dict[str, Any] = field(
+ default=None, validator=optional(instance_of(dict))
+ )
+ neuroml2_source_file: str = field(
+ default=None, validator=optional(instance_of(str))
+ )
neuroml2_input: str = field(default=None, validator=optional(instance_of(str)))
lems_source_file: str = field(default=None, validator=optional(instance_of(str)))
pynn_input: str = field(default=None, validator=optional(instance_of(str)))
@@ -125,6 +146,7 @@ class RectangularRegion(NMLBase):
height: height of the rectangular region
depth: depth of the rectangular region
"""
+
id: str = field(validator=instance_of(str))
x: float = field(validator=instance_of(float), converter=convert2float)
y: float = field(validator=instance_of(float), converter=convert2float)
@@ -142,6 +164,7 @@ class RandomLayout(NMLBase):
Args:
region: Region in which to place population
"""
+
region: str = field(validator=instance_of(str))
@@ -156,6 +179,7 @@ class RelativeLayout(NMLBase):
y: y position relative to y coordinate of Region
z: z position relative to z coordinate of Region
"""
+
region: str = field(validator=instance_of(str))
x: float = field(validator=instance_of(float), converter=convert2float)
y: float = field(validator=instance_of(float), converter=convert2float)
@@ -172,6 +196,7 @@ class Location(NMLBase):
y: y coordinate of location
z: z coordinate of location
"""
+
x: float = field(validator=instance_of(float), converter=convert2float)
y: float = field(validator=instance_of(float), converter=convert2float)
z: float = field(validator=instance_of(float), converter=convert2float)
@@ -185,6 +210,7 @@ class SingleLocation(NMLBase):
Args:
location: Location of the single Cell.
"""
+
location: Location = field(validator=instance_of(Location))
@@ -202,13 +228,22 @@ class Population(NMLBase):
relative_layout: Position relative to RectangularRegion.
single_location: Explicit location of the one Cell in the population
"""
+
id: str = field(validator=instance_of(str))
size: ValueExprType = field(validator=instance_of(value_expr_types))
component: str = field(validator=instance_of(str))
- properties: Dict[str, Any] = field(default=None, validator=optional(instance_of(dict)))
- random_layout: RandomLayout = field(default=None, validator=optional(instance_of(RandomLayout)))
- relative_layout: RelativeLayout = field(default=None, validator=optional(instance_of(RelativeLayout)))
- single_location: SingleLocation = field(default=None, validator=optional(instance_of(SingleLocation)))
+ properties: Dict[str, Any] = field(
+ default=None, validator=optional(instance_of(dict))
+ )
+ random_layout: RandomLayout = field(
+ default=None, validator=optional(instance_of(RandomLayout))
+ )
+ relative_layout: RelativeLayout = field(
+ default=None, validator=optional(instance_of(RelativeLayout))
+ )
+ single_location: SingleLocation = field(
+ default=None, validator=optional(instance_of(SingleLocation))
+ )
def has_positions(self):
"""
@@ -235,6 +270,7 @@ class RandomConnectivity(NMLBase):
Args:
probability: Random probability of connection.
"""
+
probability: ValueExprType = field(validator=instance_of(value_expr_types))
@@ -243,6 +279,7 @@ class OneToOneConnector(NMLBase):
"""
A OneToOneConnector definition.
"""
+
pass
@@ -255,6 +292,7 @@ class ConvergentConnectivity(NMLBase):
Args:
num_per_post: Number per post-synaptic neuron.
"""
+
num_per_post: float = field(validator=instance_of(float), converter=convert2float)
@@ -278,17 +316,28 @@ class Projection(NMLBase):
one_to_one_connector: Connect cell index i in pre pop to cell index i in post pop for all i
"""
+
id: str = field(validator=instance_of(str))
presynaptic: str = field(validator=optional(instance_of(str)))
postsynaptic: str = field(validator=optional(instance_of(str)))
synapse: str = field(validator=optional(instance_of(str)))
pre_synapse: str = field(default=None, validator=optional(instance_of(str)))
type: str = field(default="projection", validator=optional(instance_of(str)))
- delay: ValueExprType = field(default=None, validator=optional(instance_of(value_expr_types)))
- weight: ValueExprType = field(default=None, validator=optional(instance_of(value_expr_types)))
- random_connectivity: RandomConnectivity = field(default=None, validator=optional(instance_of(RandomConnectivity)))
- convergent_connectivity: ConvergentConnectivity = field(default=None, validator=optional(instance_of(ConvergentConnectivity)))
- one_to_one_connector: OneToOneConnector = field(default=None, validator=optional(instance_of(OneToOneConnector)))
+ delay: ValueExprType = field(
+ default=None, validator=optional(instance_of(value_expr_types))
+ )
+ weight: ValueExprType = field(
+ default=None, validator=optional(instance_of(value_expr_types))
+ )
+ random_connectivity: RandomConnectivity = field(
+ default=None, validator=optional(instance_of(RandomConnectivity))
+ )
+ convergent_connectivity: ConvergentConnectivity = field(
+ default=None, validator=optional(instance_of(ConvergentConnectivity))
+ )
+ one_to_one_connector: OneToOneConnector = field(
+ default=None, validator=optional(instance_of(OneToOneConnector))
+ )
@modelspec.define
@@ -310,11 +359,21 @@ class Input(NMLBase):
id: str = field(validator=instance_of(str))
input_source: str = field(default=None, validator=optional(instance_of(str)))
population: str = field(default=None, validator=optional(instance_of(str)))
- cell_ids: ValueExprType = field(default="", validator=optional(instance_of(value_expr_types)))
- percentage: float = field(default=None, validator=optional(instance_of(float)), converter=convert2float)
- number_per_cell: ValueExprType = field(default="", validator=optional(instance_of(value_expr_types)))
- segment_ids: ValueExprType = field(default="", validator=optional(instance_of(value_expr_types)))
- weight: ValueExprType = field(default=None, validator=optional(instance_of(value_expr_types)))
+ cell_ids: ValueExprType = field(
+ default="", validator=optional(instance_of(value_expr_types))
+ )
+ percentage: ValueExprType = field(
+ default=None, validator=optional(instance_of(value_expr_types))
+ )
+ number_per_cell: ValueExprType = field(
+ default="", validator=optional(instance_of(value_expr_types))
+ )
+ segment_ids: ValueExprType = field(
+ default="", validator=optional(instance_of(value_expr_types))
+ )
+ weight: ValueExprType = field(
+ default=None, validator=optional(instance_of(value_expr_types))
+ )
@modelspec.define
@@ -326,8 +385,11 @@ class NetworkReader(NMLBase):
type: The type of NetworkReader
parameters: Dictionary of parameters for the NetworkReader
"""
+
type: str = field(default=None, validator=optional(instance_of(str)))
- parameters: Dict[str, Any] = field(default=None, validator=optional(instance_of(dict)))
+ parameters: Dict[str, Any] = field(
+ default=None, validator=optional(instance_of(dict))
+ )
@modelspec.define
@@ -349,16 +411,35 @@ class Simulation(NMLBase):
plots2D: Work in progress...
plots3D: Work in progress...
"""
+
id: str = field(validator=instance_of(str))
- version: str = field(default=f"NeuroMLlite v{__version__}", validator=optional(instance_of(str)), metadata={"omit_if_default": False})
+ version: str = field(
+ default=f"NeuroMLlite v{__version__}",
+ validator=optional(instance_of(str)),
+ metadata={"omit_if_default": False},
+ )
network: str = field(default=None, validator=optional(instance_of(str)))
- duration: float = field(default=None, validator=optional(instance_of(float)), converter=convert2float)
- dt: float = field(default=None, validator=optional(instance_of(float)), converter=convert2float)
- seed: int = field(default=None, validator=optional(instance_of(int)), converter=convert2int)
- record_traces: Dict[str, Any] = field(default=None, validator=optional(instance_of(dict)))
- record_spikes: Dict[str, Any] = field(default=None, validator=optional(instance_of(dict)))
- record_rates: Dict[str, Any] = field(default=None, validator=optional(instance_of(dict)))
- record_variables: Dict[str, Any] = field(default=None, validator=optional(instance_of(dict)))
+ duration: float = field(
+ default=None, validator=optional(instance_of(float)), converter=convert2float
+ )
+ dt: float = field(
+ default=None, validator=optional(instance_of(float)), converter=convert2float
+ )
+ seed: int = field(
+ default=None, validator=optional(instance_of(int)), converter=convert2int
+ )
+ record_traces: Dict[str, Any] = field(
+ default=None, validator=optional(instance_of(dict))
+ )
+ record_spikes: Dict[str, Any] = field(
+ default=None, validator=optional(instance_of(dict))
+ )
+ record_rates: Dict[str, Any] = field(
+ default=None, validator=optional(instance_of(dict))
+ )
+ record_variables: Dict[str, Any] = field(
+ default=None, validator=optional(instance_of(dict))
+ )
plots2D: Dict[str, Any] = field(default=None, validator=optional(instance_of(dict)))
plots3D: Dict[str, Any] = field(default=None, validator=optional(instance_of(dict)))
@@ -386,7 +467,9 @@ class Network(NMLBase):
"""
id: str = field(validator=instance_of(str))
- parameters: Dict[str, Any] = field(default=None, validator=optional(instance_of(dict)))
+ parameters: Dict[str, Any] = field(
+ default=None, validator=optional(instance_of(dict))
+ )
cells: List[Cell] = field(factory=list, validator=instance_of(list))
synapses: List[Synapse] = field(factory=list, validator=instance_of(list))
input_sources: List[InputSource] = field(factory=list, validator=instance_of(list))
@@ -394,14 +477,19 @@ class Network(NMLBase):
populations: List[Population] = field(factory=list, validator=instance_of(list))
projections: List[Projection] = field(factory=list, validator=instance_of(list))
inputs: List[Input] = field(factory=list, validator=instance_of(list))
- version: str = field(default=f"NeuroMLlite v{__version__}", validator=instance_of(str), metadata={"omit_if_default": False})
+ version: str = field(
+ default=f"NeuroMLlite v{__version__}",
+ validator=instance_of(str),
+ metadata={"omit_if_default": False},
+ )
seed: int = field(default=None, validator=optional(instance_of(int)))
- temperature: float = field(default=None, validator=optional(instance_of(float)), converter=convert2float)
+ temperature: float = field(
+ default=None, validator=optional(instance_of(float)), converter=convert2float
+ )
network_reader: NetworkReader = field(default=None)
if __name__ == "__main__":
-
net = Network(id="net")
doc = net.generate_documentation(format="markdown")
print(doc)
diff --git a/neuromllite/gui/NMLliteUI.py b/neuromllite/gui/NMLliteUI.py
index 70f9bb1..d54bbbb 100644
--- a/neuromllite/gui/NMLliteUI.py
+++ b/neuromllite/gui/NMLliteUI.py
@@ -2,8 +2,8 @@
from os.path import realpath
import sys
-from PyQt5.QtGui import *
-from PyQt5.QtWidgets import *
+from PyQt6.QtGui import *
+from PyQt6.QtWidgets import *
from matplotlib.backends.backend_qt5agg import FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
@@ -16,34 +16,31 @@
from neuromllite.utils import evaluate
from neuromllite.utils import print_v, print_
from neuromllite.utils import is_spiking_input_population
-from pyneuroml.pynml import get_next_hex_color
+from pyneuroml.utils.plot import get_next_hex_color
from functools import partial
class ParameterSpinBox(QDoubleSpinBox):
-
- value_type=float
+ value_type = float
def __init__(self, value, value_type=float):
-
super(QDoubleSpinBox, self).__init__()
self.value_type = value_type
self.setDecimals(18)
self.setMaximum(1e16)
self.setMinimum(-1e16)
- if self.value_type==int:
+ if self.value_type == int:
self.setSingleStep(1)
else:
self.setSingleStep(value / 20.0)
self.setValue(value_type(value))
-
- #print('ParameterSpinBox: %s/%s (%s/%s), %s'%(value, self.value(), value_type, type(self.value()),self.singleStep()))
+ # print('ParameterSpinBox: %s/%s (%s/%s), %s'%(value, self.value(), value_type, type(self.value()),self.singleStep()))
# TODO: handle a spinner on values like -60mV etc.
def textFromValue(self, value):
- return "%i" % value if self.value_type==int else "%s" % value
+ return "%i" % value if self.value_type == int else "%s" % value
# TODO: handle a spinner on values like -60mV etc.
def final_value(self):
@@ -51,7 +48,6 @@ def final_value(self):
class NMLliteUI(QWidget):
-
default_vals = {}
simulators = [
@@ -90,7 +86,6 @@ def updated_param(self, p):
self.update_simulation_json()
def update_network_json(self):
-
self.nmlliteNetText.clear()
try:
j = self.network.to_json()
@@ -99,7 +94,6 @@ def update_network_json(self):
self.nmlliteNetText.insertPlainText("Error parsing model: %s" % e)
def update_simulation_json(self):
-
self.nmlliteSimText.clear()
try:
j = self.simulation.to_json()
@@ -129,7 +123,6 @@ def add_tab(
toolbar=False,
options=False,
):
-
if name in self.all_tabs:
raise Exception("The name for a tab: %s is already taken!" % name)
@@ -170,13 +163,13 @@ def add_tab(
label = QLabel(
"An image will be generated here. Push the appropriate button on the left"
)
- label.setBackgroundRole(QPalette.Base)
- label.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
+ # label.setBackgroundRole(QPalette.Base)
+ # label.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
label.setScaledContents(True)
self.all_image_qlabels[name] = label
scrollArea = QScrollArea()
- scrollArea.setBackgroundRole(QPalette.Light)
+ # scrollArea.setBackgroundRole(QPalette.Light)
scrollArea.setWidget(label)
scrollArea.setVisible(True)
@@ -244,7 +237,6 @@ def get_value_entry(self, name, value, entry_map, value_type=float):
entry.textChanged.connect(self.updated_param)
else:
-
try:
entry = ParameterSpinBox(value, value_type)
entry_map[name] = entry
@@ -269,10 +261,10 @@ def get_value_entry(self, name, value, entry_map, value_type=float):
def dialog_popup(self, message):
dialog = QMessageBox()
- dialog.setIcon(QMessageBox.Warning)
+ dialog.setIcon(QMessageBox.Icon.Warning)
dialog.setWindowTitle("Message")
dialog.setText(message)
- dialog.exec_()
+ dialog.exec()
def __init__(self, nml_sim_file, parent=None):
"""Constructor for the GUI"""
@@ -301,7 +293,9 @@ def __init__(self, nml_sim_file, parent=None):
self.sim_base_dir = "."
if self.simulation.network is None:
- print_v(f"ERROR: The provided simulation file, {nml_sim_file}, does not refer to a network.")
+ print_v(
+ f"ERROR: The provided simulation file, {nml_sim_file}, does not refer to a network."
+ )
print_v("Please provide a NeuroMLlite simulation file.")
sys.exit(-1)
@@ -338,7 +332,6 @@ def __init__(self, nml_sim_file, parent=None):
self.plotTabs.addTab(self.heatmapTab, "Heatmap")
if self.simulation.plots2D is not None:
-
self.plot2DTab = QTabWidget()
self.plotTabs.addTab(self.plot2DTab, "2D plots")
@@ -352,7 +345,6 @@ def __init__(self, nml_sim_file, parent=None):
)
if self.simulation.plots3D is not None:
-
self.plot3DTab = QTabWidget()
self.plotTabs.addTab(self.plot3DTab, "3D plots")
@@ -542,7 +534,9 @@ def __init__(self, nml_sim_file, parent=None):
pval = self.network.seed
label = QLabel("Net generation seed")
paramLayout.addWidget(label, rows, 0)
- entry = self.get_value_entry("seed", pval, self.param_entries, value_type=int)
+ entry = self.get_value_entry(
+ "seed", pval, self.param_entries, value_type=int
+ )
paramLayout.addWidget(entry, rows, 1)
if self.network.temperature is not None:
@@ -602,8 +596,10 @@ def __init__(self, nml_sim_file, parent=None):
if sval is not None:
label = QLabel("%s" % s)
paramLayout.addWidget(label, rows, 0)
- value_type=int if s=='seed' else float
- entry = self.get_value_entry(s, sval, self.sim_entries,value_type=value_type)
+ value_type = int if s == "seed" else float
+ entry = self.get_value_entry(
+ s, sval, self.sim_entries, value_type=value_type
+ )
paramLayout.addWidget(entry, rows, 1)
rows += 1
@@ -753,7 +749,7 @@ def show3Dimage(self):
self.add_image(nml_view_file, self.IMAGE_3D_TAB)
def showGraph(self):
- """Generate graph buttom has been pressed"""
+ """Generate graph button has been pressed"""
print_v("Graph button was clicked.")
@@ -806,8 +802,8 @@ def update_net_sim(self):
"""Set the parameters in the network/simulation from the GUI values"""
for p in self.param_entries:
- #print("Updating: %s to %s (%s)" % (p, self.param_entries[p], type(self.param_entries[p])))
- if type(self.param_entries[p])==QLineEdit:
+ # print("Updating: %s to %s (%s)" % (p, self.param_entries[p], type(self.param_entries[p])))
+ if type(self.param_entries[p]) == QLineEdit:
v = self.param_entries[p].text()
else:
v = self.param_entries[p].final_value()
@@ -855,6 +851,7 @@ def runSimulation(self):
self.replotSimResults()
except Exception as e:
import traceback
+
print(traceback.format_exc())
self.dialog_popup("Error: %s" % e)
@@ -874,7 +871,6 @@ def _get_pop_size(self, pop_id):
return evaluate(pop.size, self.network.parameters)
def _get_pop_id_cell_id(self, quantity):
-
if "[" in quantity:
# e.g. Epop[5]/v
pop_id = quantity.split("[")[0]
@@ -887,7 +883,6 @@ def _get_pop_id_cell_id(self, quantity):
return pop_id, cell_id
def traceSelect(self):
-
print_v(
"traceSelect button was clicked. Traces shown: %s; colours: %s"
% (self.current_traces_shown, self.current_traces_colours)
@@ -896,7 +891,7 @@ def traceSelect(self):
dialog = QDialog(self)
dialog.setWindowTitle("Select which traces to plot")
- QBtn = QDialogButtonBox.Ok # | QDialogButtonBox.Cancel
+ QBtn = QDialogButtonBox.StandardButton.Ok # | QDialogButtonBox.Cancel
buttonBox = QDialogButtonBox(QBtn)
buttonBox.accepted.connect(dialog.accept)
@@ -926,11 +921,10 @@ def traceSelect(self):
count += 1
layout.addWidget(buttonBox, count, 1)
- dialog.exec_()
+ dialog.exec()
self.replotSimResults()
def traceSelectClicked(self, key):
-
cb = self.all_cbs[key]
# print('Clicked: %s, %s, key: %s'%(cb.text(),cb.isChecked(), key))
self.current_traces_shown[key] = cb.isChecked()
@@ -965,7 +959,6 @@ def _eval_at_all(self, expr, parameters, traces):
return ret_val
def replotSimResults(self):
-
simulator = str(self.simulatorComboBox.currentText())
self.traceSelectButton.setEnabled(True)
@@ -995,7 +988,6 @@ def replotSimResults(self):
heat_array = []
for key in sorted(self.current_traces.keys()):
-
if not key in self.current_traces_shown:
self.current_traces_shown[key] = True
@@ -1065,7 +1057,6 @@ def replotSimResults(self):
## Plot 2D
if self.simulation.plots2D is not None:
-
for plot2D in self.simulation.plots2D:
info = self.simulation.plots2D[plot2D]
fig = self.all_figures[plot2D]
@@ -1130,7 +1121,6 @@ def replotSimResults(self):
## Plot 3D
if self.simulation.plots3D is not None:
-
for plot3D in self.simulation.plots3D:
info = self.simulation.plots3D[plot3D]
fig = self.all_figures[plot3D]
@@ -1204,7 +1194,6 @@ def replotSimResults(self):
max_id = 0
for pop_id in sorted(ids_for_pop.keys()):
-
if pop_id in pop_colors:
c = pop_colors[pop_id]
else:
@@ -1329,11 +1318,10 @@ def main():
nmlui = NMLliteUI(nml_sim_file)
nmlui.show()
- sys.exit(app.exec_())
+ sys.exit(app.exec())
def usage():
-
from neuromllite import __version__ as version
MAIN_CLA = "nmllite-ui"
diff --git a/neuromllite/sweep/GenerateTests.py b/neuromllite/sweep/GenerateTests.py
index 69e2e6f..4dbc9e8 100644
--- a/neuromllite/sweep/GenerateTests.py
+++ b/neuromllite/sweep/GenerateTests.py
@@ -5,7 +5,6 @@
if __name__ == "__main__":
-
hhcell = Cell(
id="hhcell", neuroml2_source_file="../../examples/test_files/hhcell.cell.nml"
)
diff --git a/neuromllite/sweep/ParameterSweep.py b/neuromllite/sweep/ParameterSweep.py
index 64fbf2a..9130c89 100644
--- a/neuromllite/sweep/ParameterSweep.py
+++ b/neuromllite/sweep/ParameterSweep.py
@@ -45,7 +45,6 @@ def __init__(
show_plot_already=False,
peak_threshold=0,
):
-
self.sim = load_simulation_json(runner.nmllite_sim)
self.colormap = "jet"
@@ -119,7 +118,6 @@ def _rem_key(self, d, key):
return r
def _sweep(self, v, f, reference=""):
-
keys = list(v)
if len(keys) > 1:
@@ -159,7 +157,6 @@ def _get_sim_duration_ms(self, parameters):
return self.sim.duration
def _run_all(self):
-
import pp
ppservers = ()
@@ -173,7 +170,6 @@ def _run_all(self):
submitted = 0
for ref in self.report["Simulations"]:
-
report_here = self.report["Simulations"][ref]
params = report_here["parameters"]
@@ -333,7 +329,6 @@ def _run_all(self):
print_v("-------------------------------------------")
def run(self):
-
print_v("Running...")
self._sweep(self.vary, self.fixed)
self._run_all()
@@ -345,7 +340,6 @@ def run(self):
plt.savefig(self.save_plot_all_to, bbox_inches="tight")
if self.heatmap_all:
-
self.hm_fig, self.hm_ax = plt.subplots()
z = np.array(self.hm_z)
@@ -409,7 +403,6 @@ def run(self):
return self.report
def print_report(self):
-
print_v("--- REPORT:")
import json
@@ -424,7 +417,6 @@ def plotLines(
logx=False,
logy=False,
):
-
all_pvals = OrderedDict()
all_lines = OrderedDict()
@@ -490,7 +482,6 @@ def plotLines(
maxy = -1 * sys.float_info.max
for t in all_traces:
-
for ref in all_lines[t]:
print_v("Add data %s, %s" % (t, ref))
@@ -546,7 +537,6 @@ def plotLines(
def run_instance(runner, i, total, job_dir, params):
-
print(
"============================================================= \n\n"
+ " Instance (%s of %s): %s\n" % (i, total, params)
@@ -564,7 +554,6 @@ def run_instance(runner, i, total, job_dir, params):
class NeuroMLliteRunner:
def __init__(self, nmllite_sim, simulator="jNeuroML"):
-
real_sim = os.path.realpath(nmllite_sim)
print_v("Created NeuroMLliteRunner to run %s in %s" % (real_sim, simulator))
@@ -577,7 +566,6 @@ def __init__(self, nmllite_sim, simulator="jNeuroML"):
"""
def run_once(self, job_dir, **kwargs):
-
from neuromllite.utils import print_v
from neuromllite.utils import load_simulation_json, load_network_json
from neuromllite.NetworkGenerator import generate_and_run
@@ -621,7 +609,6 @@ def run_once(self, job_dir, **kwargs):
if __name__ == "__main__":
-
if "-2d" in sys.argv:
fixed = {"dt": 0.025}
vary = {
@@ -759,7 +746,6 @@ def run_once(self, job_dir, **kwargs):
plt.show()
elif "-run" in sys.argv:
-
simulator = "jNeuroML_NetPyNE"
simulator = "jNeuroML"
# simulator = 'PyNN_NEST'
diff --git a/neuromllite/test/sonata/test_sonata_reader.py b/neuromllite/test/sonata/test_sonata_reader.py
index 8a24b3d..97a906e 100644
--- a/neuromllite/test/sonata/test_sonata_reader.py
+++ b/neuromllite/test/sonata/test_sonata_reader.py
@@ -2,7 +2,6 @@
def main():
-
ids = ["5_cells_iclamp", "9_cells", "300_intfire", "300_cells"]
ids += ["sim_tests/intfire/one_cell_iclamp_nest/input"]
ids += ["sim_tests/intfire/ten_cells_iclamp_nest/input"]
diff --git a/neuromllite/test/test_base.py b/neuromllite/test/test_base.py
index 9fa4fbd..55c5f22 100644
--- a/neuromllite/test/test_base.py
+++ b/neuromllite/test/test_base.py
@@ -14,7 +14,6 @@
def get_example_network():
-
net = Network(id="net0", parameters={})
net.notes = "...."
@@ -43,7 +42,6 @@ def get_example_network():
def get_example_simulation():
-
id = "Sim0"
sim = Simulation(
id=id,
@@ -57,7 +55,6 @@ def get_example_simulation():
class TestCustomSaveLoad(unittest.TestCase):
def test_save_load_json(self):
-
@modelspec.define
class NewCell(Base):
"""
@@ -67,8 +64,11 @@ class NewCell(Base):
id: the cell id
neuroml2_source_file: The path to the source file
"""
+
id: str = field(validator=instance_of(str))
- neuroml2_source_file: str = field(default=None, validator=optional(instance_of(str)))
+ neuroml2_source_file: str = field(
+ default=None, validator=optional(instance_of(str))
+ )
@modelspec.define
class NewSynapse(Base):
@@ -80,8 +80,11 @@ class NewSynapse(Base):
neuroml2_source_file: The path to the source file
tested: A boolean attribute
"""
+
id: str = field(validator=instance_of(str))
- neuroml2_source_file: str = field(default=None, validator=optional(instance_of(str)))
+ neuroml2_source_file: str = field(
+ default=None, validator=optional(instance_of(str))
+ )
tested: bool = field(default=None, validator=optional(instance_of(bool)))
@modelspec.define
@@ -93,7 +96,10 @@ class NewRandomConnectivity(Base):
probability: Random probability of connection
"""
- probability: ValueExprType = field(default=None, validator=optional(instance_of(value_expr_types)))
+
+ probability: ValueExprType = field(
+ default=None, validator=optional(instance_of(value_expr_types))
+ )
@modelspec.define
class NewNetwork(Base):
@@ -110,22 +116,40 @@ class NewNetwork(Base):
parameters: Dictionary of global parameters for the network
random_connectivity: Use random connectivity
"""
+
id: str = field(validator=instance_of(str))
cells: List[NewCell] = field(factory=list)
synapses: List[NewSynapse] = field(factory=list)
version: str = field(default="NeuroMLlite 0.0", validator=instance_of(str))
seed: int = field(default=None, validator=optional(instance_of(int)))
stable: bool = field(default=None, validator=optional(instance_of(bool)))
- parameters: Dict[str, Any] = field(default=None, validator=optional(instance_of(dict)))
- random_connectivity: NewRandomConnectivity = field(default=None, validator=optional(instance_of(NewRandomConnectivity)))
- ee0: ValueExprType = field(default=None, validator=optional(instance_of(value_expr_types)))
- ee1: ValueExprType = field(default=None, validator=optional(instance_of(value_expr_types)))
- ee2: ValueExprType = field(default=None, validator=optional(instance_of(value_expr_types)))
- ee3: ValueExprType = field(default=None, validator=optional(instance_of(value_expr_types)))
- ee4: ValueExprType = field(default=None, validator=optional(instance_of(value_expr_types)))
- ee5: ValueExprType = field(default=None, validator=optional(instance_of(value_expr_types)))
- ee6: ValueExprType = field(default=None, validator=optional(instance_of(value_expr_types)))
-
+ parameters: Dict[str, Any] = field(
+ default=None, validator=optional(instance_of(dict))
+ )
+ random_connectivity: NewRandomConnectivity = field(
+ default=None, validator=optional(instance_of(NewRandomConnectivity))
+ )
+ ee0: ValueExprType = field(
+ default=None, validator=optional(instance_of(value_expr_types))
+ )
+ ee1: ValueExprType = field(
+ default=None, validator=optional(instance_of(value_expr_types))
+ )
+ ee2: ValueExprType = field(
+ default=None, validator=optional(instance_of(value_expr_types))
+ )
+ ee3: ValueExprType = field(
+ default=None, validator=optional(instance_of(value_expr_types))
+ )
+ ee4: ValueExprType = field(
+ default=None, validator=optional(instance_of(value_expr_types))
+ )
+ ee5: ValueExprType = field(
+ default=None, validator=optional(instance_of(value_expr_types))
+ )
+ ee6: ValueExprType = field(
+ default=None, validator=optional(instance_of(value_expr_types))
+ )
net = NewNetwork(id="netid", parameters={"size": 3, "name": None})
@@ -220,9 +244,7 @@ class NewNetwork(Base):
class TestBaseSaveLoad(unittest.TestCase):
def test_save_load_json(self):
-
for o in [get_example_simulation(), get_example_network()]:
-
str0 = str(o)
json0 = o.to_json()
@@ -250,9 +272,7 @@ def test_save_load_json(self):
self.assertEqual(json0, json1)
def test_save_load_pickle(self):
-
for o in [get_example_simulation(), get_example_network()]:
-
str0 = str(o)
json0 = o.to_json()
@@ -272,7 +292,6 @@ def test_save_load_pickle(self):
if __name__ == "__main__":
-
# Some tests
tc = TestCustomSaveLoad()
tc.test_save_load_json()
diff --git a/neuromllite/test/test_generate.py b/neuromllite/test/test_generate.py
index d32a5f0..18d6440 100644
--- a/neuromllite/test/test_generate.py
+++ b/neuromllite/test/test_generate.py
@@ -13,7 +13,6 @@
class TestGenerate(unittest.TestCase):
def get_example_simulation(self):
-
id = "Sim3"
sim = Simulation(
id=id,
@@ -25,7 +24,6 @@ def get_example_simulation(self):
return sim
def test_generate_nml(self):
-
sim = self.get_example_simulation()
network = load_network_json(sim.network)
diff --git a/neuromllite/test/test_utils.py b/neuromllite/test/test_utils.py
index aa2b4c7..9bc0fe0 100644
--- a/neuromllite/test/test_utils.py
+++ b/neuromllite/test/test_utils.py
@@ -16,7 +16,6 @@
class TestUtils(unittest.TestCase):
def test_pops_vs_cell_indices(self):
-
from neuromllite.utils import get_pops_vs_cell_indices_seg_ids
network = get_example_network()
@@ -26,7 +25,6 @@ def test_pops_vs_cell_indices(self):
sim.record_rates = {}
for recordSpec in [sim.record_traces, sim.record_spikes, sim.record_rates]:
-
print("Testing...")
recordSpec["all"] = "*"
pvi = get_pops_vs_cell_indices_seg_ids(recordSpec, network)
diff --git a/neuromllite/utils.py b/neuromllite/utils.py
index c64dee9..86c67e6 100644
--- a/neuromllite/utils.py
+++ b/neuromllite/utils.py
@@ -80,6 +80,14 @@ def load_network_yaml(filename):
return net
+def load_simulation(filename):
+ """
+ Load a NeuroMLlite simulation JSON/YAML file
+ """
+ if filename.endswith(".yaml") or filename.endswith(".yml"):
+ return load_simulation_yaml(filename)
+ else:
+ return load_simulation_json(filename)
def load_simulation_json(filename: str) -> Optional[dict]:
"""
@@ -109,7 +117,6 @@ def load_simulation_json(filename: str) -> Optional[dict]:
def get_pops_vs_cell_indices_seg_ids(recordSpec, network):
-
pvc = {}
if recordSpec is not None:
for p in recordSpec:
@@ -132,7 +139,6 @@ def get_pops_vs_cell_indices_seg_ids(recordSpec, network):
def _generate_cell_indices_seg_ids(pop_id, indices_segids, network):
-
a = {}
pop = network.get_child(pop_id, "populations")
@@ -159,7 +165,6 @@ def _generate_cell_indices_seg_ids(pop_id, indices_segids, network):
def is_spiking_input_population(population, network):
-
cell = network.get_child(population.component, "cells")
return is_spiking_input_cell(cell)
@@ -195,7 +200,6 @@ def create_new_model(
network_filename=None,
simulation_filename=None,
):
-
################################################################################
### Build a new network
@@ -208,7 +212,7 @@ def create_new_model(
################################################################################
### Add some regions
- if default_region:
+ if default_region is not None:
if type(default_region) == str:
r1 = RectangularRegion(
id=default_region, x=0, y=0, z=0, width=1000, height=100, depth=1000
@@ -241,9 +245,7 @@ def create_new_model(
properties={"color": color_for_default_population},
)
- if default_region:
- pop.region = default_region
-
+ if default_region is not None:
pop.random_layout = RandomLayout(region=default_region.id)
net.populations.append(pop)
@@ -263,7 +265,6 @@ def create_new_model(
### Add some inputs
if input_for_default_population:
-
net.input_sources.append(input_for_default_population)
net.inputs.append(
diff --git a/regenerateAndTest.sh b/regenerateAndTest.sh
index 0eaaef8..219d575 100755
--- a/regenerateAndTest.sh
+++ b/regenerateAndTest.sh
@@ -35,8 +35,8 @@ python Example4.py
python Example4.py -netpyne
if [[ "$CI" != "true" ]]; then
python Example4.py -pynnnest
+ python Example4.py -pynnnrn
fi
-python Example4.py -pynnnrn
#python Example4.py -pynnbrian # Not supported in python 3...
python Example4.py -jnmlnetpyne
python Example4.py -jnmlnrn
@@ -64,8 +64,8 @@ python Example7.py -jnmlnrn
python Example7.py -jnml
if [[ "$CI" != "true" ]]; then
python Example7.py -pynnnest
+ python Example7.py -pynnnrn
fi
-python Example7.py -pynnnrn
echo
echo "**** Running Example 8 ****"
diff --git a/setup.py b/setup.py
index 22bb74c..ba65143 100644
--- a/setup.py
+++ b/setup.py
@@ -20,7 +20,7 @@
long_description=open("README.md").read(),
long_description_content_type="text/markdown",
install_requires=[
- "libNeuroML>=0.4.0",
+ "libNeuroML>=0.5.1",
"pyyaml",
"numpy",
"tables",
@@ -32,11 +32,11 @@
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
"Natural Language :: English",
"Operating System :: OS Independent",
- "Programming Language :: Python :: 2.7",
- "Programming Language :: Python :: 3.5",
- "Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
"Topic :: Scientific/Engineering",
],
)