Repository: LEMS/pylems (language: python)

Issue:
docs: add man page
Just adding a man page for completeness---takes output from `pylems -h`.
typing package should not be installed in python 3.5+
According to https://pypi.org/project/typing/#description:

> For package maintainers, it is preferred to use typing;python_version<"3.5" if your package requires it to support earlier Python versions. This will avoid shadowing the stdlib typing module when your package is installed via pip install -t . on Python 3.5 or later.

Introduced in 64bf0a7043c3e1597b199b25c2a93c8f41ec8be5, the typing package shadows the python native typing package present in 3.5+ and can result in `AttributeError: type object 'Callable' has no attribute '_abc_registry'` errors when installing certain dependency combinations. See https://github.com/python/typing/issues/573


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml
new file mode 100644
index 0000000..7f23ed5
--- /dev/null
+++ b/.github/workflows/examples.yml
@@ -0,0 +1,38 @@
+# Check that examples are same in pylems and in jlems
+name: Check LEMS examples
+
+on:
+  push:
+    branches:  [ master, development, experimental ]
+
+jobs:
+  verify:
+
+    runs-on: ubuntu-latest
+
+    steps:
+    - uses: actions/checkout@v2
+    - uses: nelonoel/branch-name@v1.0.1
+
+    # https://stackoverflow.com/questions/58033366/how-to-get-current-branch-within-github-actions
+    - name: Extract branch name
+      shell: bash
+      run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
+      id: extract_branch
+
+    - name: Checkout jlems
+      uses: actions/checkout@v2
+      with:
+        repository: LEMS/jLEMS
+        ref: ${{ steps.extract_branch.outputs.branch }}
+        path: jlems
+
+    - name: check examples
+      run: |
+        for ex in "example1.xml" "example2.xml" "example3.xml" "example4.xml" "example5.xml" "example6.xml" "example7.xml" "example8.xml" "bounce-conditional.xml" ; do
+
+          if ! diff -ur "examples/$ex" "jlems/src/test/resources/$ex" ; then
+            echo "Example file $ex is not identical"
+            exit -1
+          fi
+        done
diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml
new file mode 100644
index 0000000..3bfabfc
--- /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@v2
+    - name: Set up Python
+      uses: actions/setup-python@v2
+      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@27b31702a0e7fc50959f5ad993c78deac1bdfc29
+      with:
+        user: __token__
+        password: ${{ secrets.PYPI_API_TOKEN }}
diff --git a/README.md b/README.md
index f54b5eb..3c837b5 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-## PyLEMS 
+## PyLEMS
 
-[![Documentation Status](https://readthedocs.org/projects/pylems/badge/?version=latest)](https://pylems.readthedocs.io/en/latest/?badge=latest)
+[![Build](https://github.com/LEMS/pylems/actions/workflows/ci.yml/badge.svg)](https://github.com/LEMS/pylems/actions/workflows/ci.yml) [![Documentation Status](https://readthedocs.org/projects/pylems/badge/?version=latest)](https://pylems.readthedocs.io/en/latest/?badge=latest)
 
 
 A LEMS (http://lems.github.io/LEMS) simulator written in Python which can be used to run NeuroML2 (http://neuroml.org/neuroml2.php) models.
@@ -13,10 +13,10 @@ Michael Vella, Robert C. Cannon, Sharon Crook, Andrew P. Davison, Gautham Ganapa
 
 _**PLEASE CITE THE PAPER ABOVE IF YOU USE PYLEMS!**_
 
-For more details on LEMS see: 
+For more details on LEMS see:
 
-Robert C. Cannon, Padraig Gleeson, Sharon Crook, Gautham Ganapathy, Boris Marin, Eugenio Piasini and R. Angus Silver, 
-**LEMS: A language for expressing complex biological models in concise and hierarchical form and its use in underpinning NeuroML 2**, 
+Robert C. Cannon, Padraig Gleeson, Sharon Crook, Gautham Ganapathy, Boris Marin, Eugenio Piasini and R. Angus Silver,
+**LEMS: A language for expressing complex biological models in concise and hierarchical form and its use in underpinning NeuroML 2**,
 [Frontiers in Neuroinformatics 2014](http://journal.frontiersin.org/Journal/10.3389/fninf.2014.00079/abstract), doi: 10.3389/fninf.2014.00079
 
 
@@ -33,7 +33,7 @@ To install as root:
 Alternatively, you can obtain the latest version with
 
     git clone https://github.com/LEMS/pylems.git
-    cd pylems 
+    cd pylems
     git checkout development   # optional
     sudo python setup.py install
 
@@ -81,9 +81,9 @@ Alternatively, you can obtain the latest version with
 - example5.xml --  Not working (Unsupported in PyLEMS: KSChannel)
 - example6.xml --  Working
 -- TODO: Rest of examples require an update to the `<Simulation>` element,
-   i.e. use `<Simulation...>` not `<SimulationSet...>`, to work in PyLEMS 
+   i.e. use `<Simulation...>` not `<SimulationSet...>`, to work in PyLEMS
+
 
-      
 **LEMS elements that do not work**
 
 - KSChannel
@@ -105,5 +105,3 @@ pylems is integrated with the the [Travis Continuous Integration service](http:/
 [![Build Status](https://travis-ci.com/LEMS/pylems.png?branch=master)](https://travis-ci.com/LEMS/pylems)
 
 This code is distributed under the terms of the GNU Lesser General Public License.
-
-
diff --git a/ci/run-examples-ghactions.sh b/ci/run-examples-ghactions.sh
index 8d54972..0379765 100755
--- a/ci/run-examples-ghactions.sh
+++ b/ci/run-examples-ghactions.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 
 # Copyright 2021 LEMS contributors
-# Author: Ankur Sinha <sanjay DOT ankur AT gmail DOT com> 
+# Author: Ankur Sinha <sanjay DOT ankur AT gmail DOT com>
 # File : run-examples-ghactions.sh
 #
 # Run tests on GitHub actions
@@ -16,6 +16,7 @@ echo "Running standard LEMS examples"
 #./pylems examples/example4.xml -nogui     # Not working (Unsupported in PyLEMS: KSChannel)
 #./pylems examples/example5.xml -nogui     # Not working (Unsupported in PyLEMS: KSChannel)
 ./pylems examples/example6.xml -nogui
+./pylems examples/bounce-conditional.xml -nogui
 # Rest of examples require an update to the <Simulation> element, i.e. use <Simulation...> not <SimulationSet...>, to work in PyLEMS
 
 ###      Try running NeuroML 2 examples
diff --git a/doc/conf.py b/doc/conf.py
index 5217193..9a1c735 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -17,41 +17,45 @@
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.insert(0, os.path.abspath('.'))
+# sys.path.insert(0, os.path.abspath('.'))
 
-sys.path.insert(0, os.path.abspath('../lems'))
-sys.path.insert(0, os.path.abspath('..'))
+sys.path.insert(0, os.path.abspath("../lems"))
+sys.path.insert(0, os.path.abspath(".."))
 
 # -- General configuration -----------------------------------------------------
 
 # If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
+# needs_sphinx = '1.0'
 
 # Add any Sphinx extension module names here, as strings. They can be extensions
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo',
-              'sphinxcontrib.bibtex']
+extensions = [
+    "sphinx.ext.autodoc",
+    "sphinx.ext.doctest",
+    "sphinx.ext.todo",
+    "sphinxcontrib.bibtex",
+]
 
-bibtex_bibfiles = ['refs.bib']
+bibtex_bibfiles = ["refs.bib"]
 
 # Include TODOs in docs
 todo_include_todos = True
 
 # Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
+templates_path = ["_templates"]
 
 # The suffix of source filenames.
-source_suffix = '.rst'
+source_suffix = ".rst"
 
 # The encoding of source files.
-#source_encoding = 'utf-8-sig'
+# source_encoding = 'utf-8-sig'
 
 # The master toctree document.
-master_doc = 'index'
+master_doc = "index"
 
 # General information about the project.
-project = u'PyLEMS'
-copyright = u'2021, LEMS authors and contributors'
+project = u"PyLEMS"
+copyright = u"2021, LEMS authors and contributors"
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
@@ -59,127 +63,127 @@
 #
 # The short X.Y version.
 version = ""
-for aline in open('../lems/__init__.py'):
+for aline in open("../lems/__init__.py"):
     # space here is important since __version__ is used in generation of
     # version_info also
-    if '__version__ =' in aline:
-        version = aline.split("'")[1]
+    if "__version__ =" in aline:
+        version = aline.split('"')[1]
 # The full version, including alpha/beta/rc tags.
 release = version
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
-#language = None
+# language = None
 
 # There are two options for replacing |today|: either, you set today to some
 # non-false value, then it is used:
-#today = ''
+# today = ''
 # Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
+# today_fmt = '%B %d, %Y'
 
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
-exclude_patterns = ['_build']
+exclude_patterns = ["_build"]
 
 # The reST default role (used for this markup: `text`) to use for all documents.
-#default_role = None
+# default_role = None
 
 # If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
+# add_function_parentheses = True
 
 # If true, the current module name will be prepended to all description
 # unit titles (such as .. function::).
-#add_module_names = True
+# add_module_names = True
 
 # If true, sectionauthor and moduleauthor directives will be shown in the
 # output. They are ignored by default.
-#show_authors = False
+# show_authors = False
 
 # The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
+pygments_style = "sphinx"
 
 # A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
+# modindex_common_prefix = []
 
 
 # -- Options for HTML output ---------------------------------------------------
 
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # a list of builtin themes.
-html_theme = 'nature'
+html_theme = "nature"
 
 # Theme options are theme-specific and customize the look and feel of a theme
 # further.  For a list of options available for each theme, see the
 # documentation.
-#html_theme_options = {}
+# html_theme_options = {}
 
 # Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
+# html_theme_path = []
 
 # The name for this set of Sphinx documents.  If None, it defaults to
 # "<project> v<release> documentation".
-#html_title = None
+# html_title = None
 
 # A shorter title for the navigation bar.  Default is the same as html_title.
-#html_short_title = None
+# html_short_title = None
 
 # The name of an image file (relative to this directory) to place at the top
 # of the sidebar.
-html_logo = ''
+html_logo = ""
 
 # The name of an image file (within the static path) to use as favicon of the
 # docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
 # pixels large.
-#html_favicon = None
+# html_favicon = None
 
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
 # so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
+html_static_path = ["_static"]
 
 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
 # using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
+# html_last_updated_fmt = '%b %d, %Y'
 
 # If true, SmartyPants will be used to convert quotes and dashes to
 # typographically correct entities.
-#html_use_smartypants = True
+# html_use_smartypants = True
 
 # Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
+# html_sidebars = {}
 
 # Additional templates that should be rendered to pages, maps page names to
 # template names.
-#html_additional_pages = {}
+# html_additional_pages = {}
 
 # If false, no module index is generated.
-#html_domain_indices = True
+# html_domain_indices = True
 
 # If false, no index is generated.
-#html_use_index = True
+# html_use_index = True
 
 # If true, the index is split into individual pages for each letter.
-#html_split_index = False
+# html_split_index = False
 
 # If true, links to the reST sources are added to the pages.
-#html_show_sourcelink = True
+# html_show_sourcelink = True
 
 # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
+# html_show_sphinx = True
 
 # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
+# html_show_copyright = True
 
 # If true, an OpenSearch description file will be output, and all pages will
 # contain a <link> tag referring to it.  The value of this option must be the
 # base URL from which the finished HTML is served.
-#html_use_opensearch = ''
+# html_use_opensearch = ''
 
 # This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
+# html_file_suffix = None
 
 # Output file base name for HTML help builder.
-htmlhelp_basename = 'pylemsdoc'
+htmlhelp_basename = "pylemsdoc"
 
 
 # -- Options for LaTeX output --------------------------------------------------
@@ -197,29 +201,34 @@
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title, author, documentclass [howto/manual]).
 latex_documents = [
-    ('index', 'pylems.tex', 'PyLEMS Documentation',
-     'LEMS authors and contributors', 'manual'),
+    (
+        "index",
+        "pylems.tex",
+        "PyLEMS Documentation",
+        "LEMS authors and contributors",
+        "manual",
+    ),
 ]
 
 # The name of an image file (relative to this directory) to place at the top of
 # the title page.
-#latex_logo = None
+# latex_logo = None
 
 # For "manual" documents, if this is true, then toplevel headings are parts,
 # not chapters.
-#latex_use_parts = False
+# latex_use_parts = False
 
 # If true, show page references after internal links.
-#latex_show_pagerefs = False
+# latex_show_pagerefs = False
 
 # If true, show URL addresses after external links.
-#latex_show_urls = False
+# latex_show_urls = False
 
 # Documents to append as an appendix to all manuals.
-#latex_appendices = []
+# latex_appendices = []
 
 # If false, no module index is generated.
-#latex_domain_indices = True
+# latex_domain_indices = True
 
 
 # -- Options for manual page output --------------------------------------------
@@ -227,12 +236,11 @@
 # One entry per manual page. List of tuples
 # (source start file, name, description, authors, manual section).
 man_pages = [
-    ('index', 'PyLEMS', 'PyLEMS Documentation',
-     ['LEMS authors and contributors'], 1)
+    ("index", "PyLEMS", "PyLEMS Documentation", ["LEMS authors and contributors"], 1)
 ]
 
 # If true, show URL addresses after external links.
-#man_show_urls = False
+# man_show_urls = False
 
 
 # -- Options for Texinfo output ------------------------------------------------
@@ -241,16 +249,22 @@
 # (source start file, target name, title, author,
 #  dir menu entry, description, category)
 texinfo_documents = [
-    ('index', 'PyLEMS', 'PyLEMS Documentation',
-     'LEMS authors and contributors', 'PyLEMS', 'This package provides PyLEMS for working with LEMS.',
-     'Miscellaneous'),
+    (
+        "index",
+        "PyLEMS",
+        "PyLEMS Documentation",
+        "LEMS authors and contributors",
+        "PyLEMS",
+        "This package provides PyLEMS for working with LEMS.",
+        "Miscellaneous",
+    ),
 ]
 
 # Documents to append as an appendix to all manuals.
-#texinfo_appendices = []
+# texinfo_appendices = []
 
 # If false, no module index is generated.
-#texinfo_domain_indices = True
+# texinfo_domain_indices = True
 
 # How to display URL addresses: 'footnote', 'no', or 'inline'.
-#texinfo_show_urls = 'footnote'
+# texinfo_show_urls = 'footnote'
diff --git a/examples/bounce-conditional.xml b/examples/bounce-conditional.xml
new file mode 100644
index 0000000..9e56a1f
--- /dev/null
+++ b/examples/bounce-conditional.xml
@@ -0,0 +1,72 @@
+<Lems>
+
+    <Target component="sim"/> 
+  
+    <Dimension name="length" l="1" />
+    <Dimension name="time" t="1" />
+    <Dimension name="speed" l="1" t="-1"/>
+    <Dimension name="acceleration" l="1" t="-2"/>
+	
+    <Unit symbol="s" dimension="time"/>
+    <Unit symbol="m" dimension="length"/>
+    <Unit symbol="m_per_s" dimension="speed"/>
+    <Unit symbol="m_per_s2" dimension="acceleration"/>
+
+
+
+    <ComponentType name="ball">
+        <Parameter name="y0" dimension="length"/>
+        <Parameter name="fbounce" dimension="none"/>
+        <Parameter name="t1" dimension="time"/>
+        <Parameter name="t2" dimension="time"/>
+        <Exposure name="height" dimension="time"/>
+        
+        <Constant name="AccG" dimension="acceleration" value="9.8m_per_s2"/>
+    
+        <Dynamics>
+            <StateVariable name="height" exposure="height" dimension="length"/>
+            <StateVariable name="vel" dimension="speed"/>
+			
+            <OnStart>
+                <StateAssignment variable="height" value="y0"/>
+                <StateAssignment variable="vel" value="0"/>
+            </OnStart>
+	
+            <ConditionalDerivedVariable name="effacc" dimension="acceleration">
+                <Case condition="t .lt. t1" value="-1 * AccG"/>
+                <Case condition="t .lt. t2" value="-0.1 * AccG"/>
+                <Case condition="t .geq. t2" value="-1 * AccG"/>
+            </ConditionalDerivedVariable>
+
+
+            <TimeDerivative variable="vel" value="effacc"/>
+            <TimeDerivative variable="height" value="vel"/>
+
+            <OnCondition test="height .lt. 0">
+                <StateAssignment variable="vel" value="fbounce * -vel"/>
+                <StateAssignment variable="height" value="0"/>
+            </OnCondition>
+        </Dynamics>
+    </ComponentType>
+        
+ 
+
+ 
+    <ball id="ball" fbounce="0.9" y0="5m" t1="5s" t2="10s"/>
+	
+	
+    <Include file="SingleSimulation.xml" />
+ 
+
+
+    <Simulation id="sim" length="20s" step="0.01s" target="ball">
+        <Display id="disp1" title="Net1" xmin="0" xmax="30" ymin="-1" ymax="6" timeScale="1s">
+            <Line id="g0"  timeScale="1s" quantity="height" scale="1m" color="#0000f0"/>
+        
+        </Display> 
+ 	
+  
+ 
+    </Simulation>
+
+</Lems>
\ No newline at end of file
diff --git a/lems/__init__.py b/lems/__init__.py
index 3b6c720..ef41913 100644
--- a/lems/__init__.py
+++ b/lems/__init__.py
@@ -5,10 +5,14 @@
 
 import logging
 
-logger = logging.getLogger('LEMS')
+logger = logging.getLogger("LEMS")
 
-__version__ = '0.5.5'
+__version__ = "0.5.9"
 
-__schema_version__ = '0.7.6'
+__schema_version__ = "0.7.6"
 __schema_branch__ = "development"
-__schema_location__ = 'https://raw.githubusercontent.com/LEMS/LEMS/{0}/Schemas/LEMS/LEMS_v{1}.xsd'.format(__schema_branch__, __schema_version__)
+__schema_location__ = (
+    "https://raw.githubusercontent.com/LEMS/LEMS/{0}/Schemas/LEMS/LEMS_v{1}.xsd".format(
+        __schema_branch__, __schema_version__
+    )
+)
diff --git a/lems/base/base.py b/lems/base/base.py
index dd42a32..1b35f5e 100644
--- a/lems/base/base.py
+++ b/lems/base/base.py
@@ -7,6 +7,7 @@
 
 import copy
 
+
 class LEMSBase(object):
     """
     Base object for PyLEMS.
@@ -16,4 +17,4 @@ def copy(self):
         return copy.deepcopy(self)
 
     def toxml(self):
-        return ''
+        return ""
diff --git a/lems/base/errors.py b/lems/base/errors.py
index 19064db..50cc9f1 100644
--- a/lems/base/errors.py
+++ b/lems/base/errors.py
@@ -5,6 +5,7 @@
 :organization: LEMS (https://github.com/organizations/LEMS)
 """
 
+
 class LEMSError(Exception):
     """
     Base exception class.
@@ -23,7 +24,7 @@ def __init__(self, message, *params, **key_params):
         :param key_params: Named arguments for formatting.
         :type key_params: dict
         """
-        
+
         self.message = None
         """ Error message
         :type: string """
@@ -37,7 +38,7 @@ def __init__(self, message, *params, **key_params):
             if key_params:
                 self.message = message(**key_params)
             else:
-                self.message = message    
+                self.message = message
 
     def __str__(self):
         """
@@ -46,9 +47,10 @@ def __str__(self):
         :return: The error message
         :rtype: string
         """
-        
+
         return self.message
 
+
 class StackError(LEMSError):
     """
     Exception class to signal errors in the Stack class.
@@ -56,6 +58,7 @@ class StackError(LEMSError):
 
     pass
 
+
 class ParseError(LEMSError):
     """
     Exception class to signal errors found during parsing.
@@ -63,6 +66,7 @@ class ParseError(LEMSError):
 
     pass
 
+
 class ModelError(LEMSError):
     """
     Exception class to signal errors in creating the model.
@@ -70,6 +74,7 @@ class ModelError(LEMSError):
 
     pass
 
+
 class SimBuildError(LEMSError):
     """
     Exception class to signal errors in building the simulation.
@@ -77,6 +82,7 @@ class SimBuildError(LEMSError):
 
     pass
 
+
 class SimError(LEMSError):
     """
     Exception class to signal errors in simulation.
diff --git a/lems/base/map.py b/lems/base/map.py
index 3435438..7ca7e7c 100644
--- a/lems/base/map.py
+++ b/lems/base/map.py
@@ -7,23 +7,24 @@
 
 from lems.base.base import LEMSBase
 
+
 class Map(dict, LEMSBase):
     """
     Map class.
 
     Same as dict, but iterates over values.
     """
-    
+
     def __init__(self, *params, **key_params):
         """
         Constructor.
         """
-        
+
         dict.__init__(self, *params, **key_params)
 
     def __iter__(self):
         """
         Returns an iterator.
         """
-        
+
         return iter(self.values())
diff --git a/lems/base/stack.py b/lems/base/stack.py
index abfd09b..95eb600 100644
--- a/lems/base/stack.py
+++ b/lems/base/stack.py
@@ -8,6 +8,7 @@
 from lems.base.base import LEMSBase
 from lems.base.errors import StackError
 
+
 class Stack(LEMSBase):
     """
     Basic stack implementation.
@@ -47,7 +48,7 @@ def pop(self):
             self.stack = self.stack[1:]
             return val
         else:
-            raise StackError('Stack empty')
+            raise StackError("Stack empty")
 
     def top(self):
         """
@@ -62,7 +63,7 @@ def top(self):
         if self.stack:
             return self.stack[0]
         else:
-            raise StackError('Stack empty')
+            raise StackError("Stack empty")
 
     def is_empty(self):
         """
@@ -83,13 +84,13 @@ def __str__(self):
         """
 
         if len(self.stack) == 0:
-            s = '[]'
+            s = "[]"
         else:
-            s = '[' + str(self.stack[0])
+            s = "[" + str(self.stack[0])
             for i in range(1, len(self.stack)):
-                s += ', ' + str(self.stack[i])
-            s += ']'
+                s += ", " + str(self.stack[i])
+            s += "]"
         return s
 
     def __repr__(self):
-        return self.__str__()
\ No newline at end of file
+        return self.__str__()
diff --git a/lems/base/util.py b/lems/base/util.py
index 3425455..cbafa72 100644
--- a/lems/base/util.py
+++ b/lems/base/util.py
@@ -10,53 +10,56 @@
 
 id_counter = 0
 
+
 def make_id():
     global id_counter
     id_counter = id_counter + 1
-    return '__id_{0}__'.format(id_counter)
+    return "__id_{0}__".format(id_counter)
+
 
 def merge_maps(m, base):
     """
     Merge in undefined map entries from given map.
-    
+
     :param m: Map to be merged into.
     :type m: lems.util.Map
-    
+
     :param base: Map to be merged into.
     :type base: lems.util.Map
     """
-    
+
     for k in base.keys():
         if k not in m:
             m[k] = base[k]
 
+
 def merge_lists(l, base):
     """
     Merge in undefined list entries from given list.
-    
+
     :param l: List to be merged into.
     :type l: list
-    
+
     :param base: List to be merged into.
     :type base: list
     """
-    
+
     for i in base:
         if i not in l:
             l.append(i)
-            
-        
+
+
 def validate_lems(file_name):
 
     from lxml import etree
+
     try:
         from urllib2 import urlopen  # Python 2
     except:
-        from urllib.request import urlopen # Python 3
-        
+        from urllib.request import urlopen  # Python 3
+
     schema_file = urlopen(__schema_location__)
     xmlschema = etree.XMLSchema(etree.parse(schema_file))
     print("Validating {0} against {1}".format(file_name, schema_file.geturl()))
     xmlschema.assertValid(etree.parse(file_name))
     print("It's valid!")
-
diff --git a/lems/dlems/exportdlems.py b/lems/dlems/exportdlems.py
index 1298fc2..bae1a3a 100644
--- a/lems/dlems/exportdlems.py
+++ b/lems/dlems/exportdlems.py
@@ -16,223 +16,221 @@
 from lems.model.dynamics import OnCondition
 from lems.model.dynamics import StateAssignment
 
-SI_PREF = {'p': 1e-12, 'n': 1e-9, 'u': 1e-6, 'm': 1e-3, 'c': 1e-2}
+SI_PREF = {"p": 1e-12, "n": 1e-9, "u": 1e-6, "m": 1e-3, "c": 1e-2}
+
 
 def to_si(model, unit_str):
     return str(model.get_numeric_value(unit_str))
 
+
 def comp2sign(cond):
-    ret = '???'
-    if cond in ('gt', 'geq'):
-        ret = '+'
-    elif cond in ('lt', 'leq'):
-        ret = '-'
-    elif cond == 'eq':
-        ret = '0'
+    ret = "???"
+    if cond in ("gt", "geq"):
+        ret = "+"
+    elif cond in ("lt", "leq"):
+        ret = "-"
+    elif cond == "eq":
+        ret = "0"
     return ret
-    
+
+
 def has_display(disp, pop):
     pop = re.compile(pop)
-    #iterate over plots/dumps pertaining to current element
-    quants = [li.parameters['quantity'] for li in disp.children]
+    # iterate over plots/dumps pertaining to current element
+    quants = [li.parameters["quantity"] for li in disp.children]
     return any([pop.search(q) for q in quants])
 
-    
+
 def any_svs_plotted(disp, svs):
-    s = lambda x: x[x.rfind('/')+1:]
-    return any([s(li.parameters['quantity']) in svs for li in disp.children])
+    s = lambda x: x[x.rfind("/") + 1 :]
+    return any([s(li.parameters["quantity"]) in svs for li in disp.children])
 
 
 def inequality_to_condition(ineq):
 
     r = re.compile("(.+)(?:\.([glneqt]+)\.)(.+)")
     s = r.search(ineq)
-    expr =  ''.join([s.group(1).strip(), ' - (',  s.group(3).strip() + ')'])
+    expr = "".join([s.group(1).strip(), " - (", s.group(3).strip() + ")"])
     sign = comp2sign(s.group(2))
     return (expr, sign)
 
-def export_component(model, comp, sim_comp, parent_pop='', file_name=None):
-    
-        comp_type = model.component_types[comp.type]
 
-        dlems = OrderedDict()
-        dlems['name'] = comp.id
-        params = OrderedDict()
+def export_component(model, comp, sim_comp, parent_pop="", file_name=None):
 
-        for p in comp.parameters.keys():
-            params[p] = to_si(model, comp.parameters[p])
+    comp_type = model.component_types[comp.type]
 
-        for p in order_derived_parameters(comp_type):
-            params[p] = to_si(model, comp_type.derived_parameters[p])
+    dlems = OrderedDict()
+    dlems["name"] = comp.id
+    params = OrderedDict()
 
-        for c in comp_type.constants.keys():
-            params[c] = to_si(model, comp_type.constants[c].value)
-        dlems['parameters']=params
+    for p in comp.parameters.keys():
+        params[p] = to_si(model, comp.parameters[p])
 
-        dyn = comp_type.dynamics
-        dvs = OrderedDict()
-        for dv in order_derived_variables(dyn):
-            val = dyn.derived_variables[dv].value
-            if val is not None:
-                dvs[dv] = val
-            else:
-                dvs[dv] = "0"
+    for p in order_derived_parameters(comp_type):
+        params[p] = to_si(model, comp_type.derived_parameters[p])
 
-        dlems['state_functions']=dvs
+    for c in comp_type.constants.keys():
+        params[c] = to_si(model, comp_type.constants[c].value)
+    dlems["parameters"] = params
 
-        tds = OrderedDict()
+    dyn = comp_type.dynamics
+    dvs = OrderedDict()
+    for dv in order_derived_variables(dyn):
+        val = dyn.derived_variables[dv].value
+        if val is not None:
+            dvs[dv] = val
+        else:
+            dvs[dv] = "0"
 
-        for td in dyn.time_derivatives:
-            tds[td.variable] = td.value
+    dlems["state_functions"] = dvs
 
-        dlems['dynamics']=tds
+    tds = OrderedDict()
 
-        svs = OrderedDict()
-        for sv in dyn.state_variables:
-            for eh in dyn.event_handlers:
-                if isinstance(eh, OnStart):
-                    for action in eh.actions:
-                        if isinstance(action, StateAssignment):
-                            if action.variable == sv.name:
-                                svs[sv.name] = action.value
-            if not sv.name in svs: 
-                svs[sv.name] = '0'
+    for td in dyn.time_derivatives:
+        tds[td.variable] = td.value
 
-        dlems['state']=svs
+    dlems["dynamics"] = tds
 
-        evs = []
-        count_cond = 0
-        
+    svs = OrderedDict()
+    for sv in dyn.state_variables:
         for eh in dyn.event_handlers:
-            if isinstance(eh, OnCondition):
-                ev = OrderedDict()
-                ev['name'] = 'condition_%i'%count_cond
-                (cond, dir) = inequality_to_condition(eh.test)
-                ev['condition'] = cond
-                ev['direction'] = dir 
-                effect = OrderedDict()
-                state_effects = OrderedDict()
+            if isinstance(eh, OnStart):
                 for action in eh.actions:
                     if isinstance(action, StateAssignment):
-                        state_effects[action.variable] = action.value
-                effect['state'] = state_effects
-                ev['effect'] = effect
-                evs.append(ev)
-                count_cond+=1   
-
-        dlems['events']=evs
-
-        dlems['t_start'] = '0'
-        dlems['t_end'] = to_si(model, sim_comp.parameters['length'])
-        dlems['dt'] = to_si(model, sim_comp.parameters['step'])
-
-        disps = []
-
-        for d in sim_comp.children: 
-
-            if d.type == 'Display' and has_display(d, parent_pop) and any_svs_plotted(d, svs.keys()):
-                
-            
-                di = OrderedDict()
-                abax = OrderedDict()
-                abax['min'] = d.parameters['xmin']
-                abax['max'] = d.parameters['xmax']
-                
-                orax = OrderedDict()
-                orax['min'] = d.parameters['ymin']
-                orax['max'] = d.parameters['ymax']
-
-                
-                curves = []
-                for li in d.children:
-                    cur = OrderedDict() 
-                    s = li.parameters['quantity']
-                    x = s[s.rfind('/')+1:]
-                    cur['abscissa'] = 't'
-                    cur['ordinate'] = x
-                    cur['colour'] = li.parameters['color'] 
-                    px = re.search('([cmunp])s', li.parameters['timeScale'], re.IGNORECASE)
-                    py = re.search('([cmunp])+\w', li.parameters['scale'], re.IGNORECASE)
-                    try:
-                        scale_x = SI_PREF[px.group()[0]]
-                    except (KeyError, AttributeError) as e:
-                        scale_x = 1
-                    try:
-                        scale_y = SI_PREF[py.group()[0]]
-                    except (KeyError, AttributeError) as e:
-                        scale_y = 1
-                    #dlems is currently concerned with state var plots only
-                    if cur['ordinate'] in svs:
-                        curves.append(cur)
-                
-                abax = {k: str(scale_x*float(v)) for (k, v) in abax.items()} 
-                orax = {k: str(scale_y*float(v)) for (k, v) in orax.items()} 
-                di['abscissa_axis'] = abax
-                di['ordinate_axis'] = orax
-
-                di['curves'] = curves
-                disps.append(di)
-                
-                
-            elif d.type == 'OutputFile':
-                dlems['dump_to_file'] = d.parameters['fileName']
-                for dd in d.children:
-                    s = dd.parameters['quantity']
-                
-        dlems['display'] = disps
-
-        dlems_file_name = file_name
-        if dlems_file_name is None:
-            dlems_file_name = 'comp_%s.json'%comp.id
-            
-        dlems_file = open(dlems_file_name, 'w')
-
-        dlems_file.write(json.dumps(dlems, indent=4, separators=(',', ': ')))
-
-        dlems_file.close()
-
-        reopen = open(dlems_file_name,'r')
-        print(reopen.read())
-        reopen.close()
-
-        print("Written to %s"%dlems_file_name)
-    
-
-
-if __name__ == '__main__':
+                        if action.variable == sv.name:
+                            svs[sv.name] = action.value
+        if not sv.name in svs:
+            svs[sv.name] = "0"
+
+    dlems["state"] = svs
+
+    evs = []
+    count_cond = 0
+
+    for eh in dyn.event_handlers:
+        if isinstance(eh, OnCondition):
+            ev = OrderedDict()
+            ev["name"] = "condition_%i" % count_cond
+            (cond, dir) = inequality_to_condition(eh.test)
+            ev["condition"] = cond
+            ev["direction"] = dir
+            effect = OrderedDict()
+            state_effects = OrderedDict()
+            for action in eh.actions:
+                if isinstance(action, StateAssignment):
+                    state_effects[action.variable] = action.value
+            effect["state"] = state_effects
+            ev["effect"] = effect
+            evs.append(ev)
+            count_cond += 1
+
+    dlems["events"] = evs
+
+    dlems["t_start"] = "0"
+    dlems["t_end"] = to_si(model, sim_comp.parameters["length"])
+    dlems["dt"] = to_si(model, sim_comp.parameters["step"])
+
+    disps = []
+
+    for d in sim_comp.children:
+
+        if (
+            d.type == "Display"
+            and has_display(d, parent_pop)
+            and any_svs_plotted(d, svs.keys())
+        ):
+
+            di = OrderedDict()
+            abax = OrderedDict()
+            abax["min"] = d.parameters["xmin"]
+            abax["max"] = d.parameters["xmax"]
+
+            orax = OrderedDict()
+            orax["min"] = d.parameters["ymin"]
+            orax["max"] = d.parameters["ymax"]
+
+            curves = []
+            for li in d.children:
+                cur = OrderedDict()
+                s = li.parameters["quantity"]
+                x = s[s.rfind("/") + 1 :]
+                cur["abscissa"] = "t"
+                cur["ordinate"] = x
+                cur["colour"] = li.parameters["color"]
+                px = re.search("([cmunp])s", li.parameters["timeScale"], re.IGNORECASE)
+                py = re.search("([cmunp])+\w", li.parameters["scale"], re.IGNORECASE)
+                try:
+                    scale_x = SI_PREF[px.group()[0]]
+                except (KeyError, AttributeError) as e:
+                    scale_x = 1
+                try:
+                    scale_y = SI_PREF[py.group()[0]]
+                except (KeyError, AttributeError) as e:
+                    scale_y = 1
+                # dlems is currently concerned with state var plots only
+                if cur["ordinate"] in svs:
+                    curves.append(cur)
+
+            abax = {k: str(scale_x * float(v)) for (k, v) in abax.items()}
+            orax = {k: str(scale_y * float(v)) for (k, v) in orax.items()}
+            di["abscissa_axis"] = abax
+            di["ordinate_axis"] = orax
+
+            di["curves"] = curves
+            disps.append(di)
+
+        elif d.type == "OutputFile":
+            dlems["dump_to_file"] = d.parameters["fileName"]
+            for dd in d.children:
+                s = dd.parameters["quantity"]
+
+    dlems["display"] = disps
+
+    dlems_file_name = file_name
+    if dlems_file_name is None:
+        dlems_file_name = "comp_%s.json" % comp.id
+
+    dlems_file = open(dlems_file_name, "w")
+
+    dlems_file.write(json.dumps(dlems, indent=4, separators=(",", ": ")))
+
+    dlems_file.close()
+
+    reopen = open(dlems_file_name, "r")
+    print(reopen.read())
+    reopen.close()
+
+    print("Written to %s" % dlems_file_name)
+
+
+if __name__ == "__main__":
     model = Model()
 
     try:
-        lems_file = sys.argv[1] 
+        lems_file = sys.argv[1]
     except:
-        lems_file = '../NeuroML2/LEMSexamples/LEMS_NML2_Ex9_FN.xml'
-        model.add_include_directory('../NeuroML2/NeuroML2CoreTypes')
+        lems_file = "../NeuroML2/LEMSexamples/LEMS_NML2_Ex9_FN.xml"
+        model.add_include_directory("../NeuroML2/NeuroML2CoreTypes")
 
-    print('Importing LEMS file from: %s'%lems_file)
+    print("Importing LEMS file from: %s" % lems_file)
     model.import_from_file(lems_file)
 
     target = model.targets[0]
 
     sim_comp = model.components[target]
 
-    target_net = sim_comp.parameters['target']
+    target_net = sim_comp.parameters["target"]
 
     target_comp = model.components[target_net]
 
-
-    if target_comp.type == 'network':
+    if target_comp.type == "network":
 
         for child in target_comp.children:
 
-            if child.type == 'population':
+            if child.type == "population":
 
-                comp =  model.components[child.parameters['component']]
+                comp = model.components[child.parameters["component"]]
 
                 export_component(model, comp, sim_comp, child.id)
     else:
         export_component(model, target_comp, sim_comp)
-    
-
-
-
-
diff --git a/lems/model/component.py b/lems/model/component.py
index 18d59b4..1b5b34f 100644
--- a/lems/model/component.py
+++ b/lems/model/component.py
@@ -7,29 +7,31 @@
 
 from lems.base.base import LEMSBase
 from lems.base.map import Map
-from lems.base.errors import ModelError,ParseError
+from lems.base.errors import ModelError, ParseError
 
 from lems.model.dynamics import Dynamics
 from lems.model.structure import Structure
 from lems.model.simulation import Simulation
 from lems.parser.expr import ExprParser
+from xml.sax.saxutils import quoteattr
+
 
 class Parameter(LEMSBase):
     """
     Stores a parameter declaration.
     """
-    
-    def __init__(self, name, dimension, description = ''):
+
+    def __init__(self, name, dimension, description=""):
         """
         Constructor.
 
         See instance variable documentation for more details on parameters.
         """
-        
+
         self.name = name
         """ Name of the parameter.
         :type: str """
-         
+
         self.dimension = dimension
         """ Physical dimension of the parameter.
         :type: str """
@@ -37,7 +39,7 @@ def __init__(self, name, dimension, description = ''):
         self.fixed = False
         """ Whether the parameter has been fixed or not.
         :type: bool """
-        
+
         self.fixed_value = None
         """ Value if fixed.
         :type: str """
@@ -59,51 +61,64 @@ def toxml(self):
         Exports this object into a LEMS XML object
         """
 
-        return '<{0} name="{1}" dimension="{2}"'.format('Fixed' if self.fixed else 'Parameter', self.name, self.dimension) +\
-          (' description = "{0}"'.format(self.description) if self.description else '') +\
-          '/>'
-          
-          
+        return (
+            '<{0} name="{1}" dimension="{2}"'.format(
+                "Fixed" if self.fixed else "Parameter", self.name, self.dimension
+            )
+            + (
+                ' description = "{0}"'.format(self.description)
+                if self.description
+                else ""
+            )
+            + "/>"
+        )
+
     def __str__(self):
-        return '{0}: name="{1}" dimension="{2}"'.format('Fixed' if self.fixed else 'Parameter', self.name, self.dimension) +\
-          (' description = "{0}"'.format(self.description) if self.description else '')
-          
-          
+        return '{0}: name="{1}" dimension="{2}"'.format(
+            "Fixed" if self.fixed else "Parameter", self.name, self.dimension
+        ) + (
+            ' description = "{0}"'.format(self.description) if self.description else ""
+        )
+
     def __repr__(self):
         return self.__str__()
 
+
 class Fixed(Parameter):
     """
     Stores a fixed parameter specification.
     """
-    
-    def __init__(self, parameter, value, description = ''):
+
+    def __init__(self, parameter, value, description=""):
         """
         Constructor.
 
         See instance variable documentation for more details on parameters.
         """
 
-        Parameter.__init__(self, parameter, '__dimension_inherited__', description)
-        
+        Parameter.__init__(self, parameter, "__dimension_inherited__", description)
+
         self.fixed = True
         self.fixed_value = value
-        
+
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        return '<Fixed parameter="{0}"'.format(self.name) + ' value="{0}"'.format(self.fixed_value)+'/>'
-    
-    
-        
-class Property(LEMSBase): 
-    """ 
-    Store the specification of a property. 
-    """ 
- 
-    def __init__(self, name, dimension = None, default_value = None, description = ''): 
+        return (
+            '<Fixed parameter="{0}"'.format(self.name)
+            + ' value="{0}"'.format(self.fixed_value)
+            + "/>"
+        )
+
+
+class Property(LEMSBase):
+    """
+    Store the specification of a property.
+    """
+
+    def __init__(self, name, dimension=None, default_value=None, description=""):
         """
         Constructor.
         """
@@ -115,11 +130,11 @@ def __init__(self, name, dimension = None, default_value = None, description = '
         self.dimension = dimension
         """ Physical dimensions of the property.
         :type: str """
-        
+
         self.description = description
         """ Description of the property.
         :type: str """
-        
+
         self.default_value = default_value
         """ Default value of the property.
         :type: float """
@@ -129,18 +144,24 @@ def toxml(self):
         Exports this object into a LEMS XML object
         """
 
-        return '<Property name="{0}"'.format(self.name) +\
-          (' dimension="{0}"'.format(self.dimension) if self.dimension else 'none') +\
-          (' defaultValue = "{0}"'.format(self.default_value) if self.default_value else '') +\
-          '/>'
-          
+        return (
+            '<Property name="{0}"'.format(self.name)
+            + (' dimension="{0}"'.format(self.dimension) if self.dimension else "none")
+            + (
+                ' defaultValue = "{0}"'.format(self.default_value)
+                if self.default_value
+                else ""
+            )
+            + "/>"
+        )
+
 
 class IndexParameter(LEMSBase):
     """
     Stores a parameter which is an index (integer > 0).
     """
-    
-    def __init__(self, name, description = ''):
+
+    def __init__(self, name, description=""):
         """
         Constructor.
         """
@@ -148,28 +169,34 @@ def __init__(self, name, description = ''):
         self.name = name
         """ Name of the parameter.
         :type: str """
-        
+
         self.description = description
         """ Description of this parameter.
         :type: str """
-        
-        
+
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        return '<IndexParameter name="{0}"'.format(self.name) + '' + \
-            (' description = "{0}"'.format(self.description) if self.description else '') +\
-            '/>'
-        
-        
-class DerivedParameter(LEMSBase): 
-    """ 
-    Store the specification of a derived parameter. 
-    """ 
- 
-    def __init__(self, name, value, dimension = None, description = ''): 
+        return (
+            '<IndexParameter name="{0}"'.format(self.name)
+            + ""
+            + (
+                ' description = "{0}"'.format(self.description)
+                if self.description
+                else ""
+            )
+            + "/>"
+        )
+
+
+class DerivedParameter(LEMSBase):
+    """
+    Store the specification of a derived parameter.
+    """
+
+    def __init__(self, name, value, dimension=None, description=""):
         """
         Constructor.
 
@@ -183,53 +210,60 @@ def __init__(self, name, value, dimension = None, description = ''):
         self.dimension = dimension
         """ Physical dimensions of the derived parameter.
         :type: str """
-        
+
         self.value = value
         """ Value of the derived parameter.
         :type: str """
-        
+
         self.description = description
         """ Description of the derived parameter.
         :type: str """
-        
+
         try:
             ep = ExprParser(self.value)
             self.expression_tree = ep.parse()
         except:
-            raise ParseError("Parse error when parsing value expression "
-                                 "'{0}' for derived parameter {1}",
-                                 self.value, self.name)
-        
-                             
-
+            raise ParseError(
+                "Parse error when parsing value expression "
+                "'{0}' for derived parameter {1}",
+                self.value,
+                self.name,
+            )
 
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        return '<DerivedParameter name="{0}"'.format(self.name) +\
-          (' dimension="{0}"'.format(self.dimension) if self.dimension else '') +\
-          (' description="{0}"'.format(self.description) if self.description else '') +\
-          (' value="{0}"'.format(self.value) if self.value else '') +\
-          '/>'
+        return (
+            '<DerivedParameter name="{0}"'.format(self.name)
+            + (' dimension="{0}"'.format(self.dimension) if self.dimension else "")
+            + (
+                " description={0}".format(
+                    quoteattr(self.description) if self.description else '""'
+                )
+            )
+            + (' value="{0}"'.format(self.value) if self.value else "")
+            + "/>"
+        )
+
 
 class Constant(LEMSBase):
     """
     Stores a constant specification.
     """
-    
-    def __init__(self, name, value, dimension = None, symbol = None, description = ''):
+
+    def __init__(self, name, value, dimension=None, symbol=None, description=""):
         """
         Constructor.
 
         See instance variable documentation for more details on parameters.
         """
-        
+
         self.name = name
         """ Name of the constant.
         :type: str """
-        
+
         self.symbol = symbol
         """ Symbol of the constant.
         :type: str """
@@ -255,31 +289,37 @@ def toxml(self):
         Exports this object into a LEMS XML object
         """
 
-        return '<Constant' +\
-          (' name = "{0}"'.format(self.name) if self.name else '') +\
-          (' symbol = "{0}"'.format(self.symbol) if self.symbol else '') +\
-          (' value = "{0}"'.format(self.value) if self.value else '') +\
-          (' dimension = "{0}"'.format(self.dimension) if self.dimension else '') +\
-          (' description = "{0}"'.format(self.description) if self.description else '') +\
-          '/>'
-        
+        return (
+            "<Constant"
+            + (' name = "{0}"'.format(self.name) if self.name else "")
+            + (' symbol = "{0}"'.format(self.symbol) if self.symbol else "")
+            + (' value = "{0}"'.format(self.value) if self.value else "")
+            + (' dimension = "{0}"'.format(self.dimension) if self.dimension else "")
+            + (
+                ' description = "{0}"'.format(self.description)
+                if self.description
+                else ""
+            )
+            + "/>"
+        )
+
 
 class Exposure(LEMSBase):
     """
     Stores a exposure specification.
     """
 
-    def __init__(self, name, dimension, description = ''):
+    def __init__(self, name, dimension, description=""):
         """
         Constructor.
 
         See instance variable documentation for more details on parameters.
         """
-        
+
         self.name = name
         """ Name of the exposure.
         :type: str """
-         
+
         self.dimension = dimension
         """ Physical dimension of the exposure.
         :type: str """
@@ -293,30 +333,37 @@ def toxml(self):
         Exports this object into a LEMS XML object
         """
 
-        return '<Exposure name="{0}" dimension="{1}"'.format(self.name, self.dimension) +\
-          (' description = "{0}"'.format(self.description) if self.description else '') +\
-          '/>'
+        return (
+            '<Exposure name="{0}" dimension="{1}"'.format(self.name, self.dimension)
+            + (
+                ' description = "{0}"'.format(self.description)
+                if self.description
+                else ""
+            )
+            + "/>"
+        )
+
 
 class Requirement(LEMSBase):
     """
     Stores a requirement specification.
     """
 
-    def __init__(self, name, dimension, description = ''):
+    def __init__(self, name, dimension, description=""):
         """
         Constructor.
 
         See instance variable documentation for more details on parameters.
         """
-        
+
         self.name = name
         """ Name of the requirement.
         :type: str """
-         
+
         self.dimension = dimension
         """ Physical dimension of the requirement.
         :type: str """
-        
+
         self.description = description
         """ Description of this requirement.
         :type: str """
@@ -326,17 +373,23 @@ def toxml(self):
         Exports this object into a LEMS XML object
         """
 
-        return '<Requirement name="{0}" dimension="{1}"'.format(self.name, self.dimension) +\
-          (' description = "{0}"'.format(self.description) if self.description else '') +\
-          '/>'
-          
-          
+        return (
+            '<Requirement name="{0}" dimension="{1}"'.format(self.name, self.dimension)
+            + (
+                ' description = "{0}"'.format(self.description)
+                if self.description
+                else ""
+            )
+            + "/>"
+        )
+
+
 class ComponentRequirement(LEMSBase):
     """
     Specifies a component that is required
     """
-    
-    def __init__(self, name, description = ''):
+
+    def __init__(self, name, description=""):
         """
         Constructor.
         """
@@ -344,40 +397,46 @@ def __init__(self, name, description = ''):
         self.name = name
         """ Name of the Component required.
         :type: str """
-        
+
         self.description = description
         """ Description of this ComponentRequirement.
         :type: str """
-        
-        
+
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        return '<ComponentRequirement name="{0}"'.format(self.name) + '' + \
-            (' description = "{0}"'.format(self.description) if self.description else '') +\
-            '/>'
-        
-          
+        return (
+            '<ComponentRequirement name="{0}"'.format(self.name)
+            + ""
+            + (
+                ' description = "{0}"'.format(self.description)
+                if self.description
+                else ""
+            )
+            + "/>"
+        )
+
+
 class InstanceRequirement(LEMSBase):
     """
     Stores an instance requirement specification.
     """
 
-    def __init__(self, name, type, description = ''):
+    def __init__(self, name, type, description=""):
         """
         Constructor.
         """
-        
+
         self.name = name
         """ Name of the instance requirement.
         :type: str """
-         
+
         self.type = type
         """ Type of the instance required.
         :type: str """
-        
+
         self.description = description
         """ Description of this InstanceRequirement.
         :type: str """
@@ -387,26 +446,33 @@ def toxml(self):
         Exports this object into a LEMS XML object
         """
 
-        return '<InstanceRequirement name="{0}" type="{1}"'.format(self.name, self.type) +\
-          (' description = "{0}"'.format(self.description) if self.description else '') +\
-          '/>'
+        return (
+            '<InstanceRequirement name="{0}" type="{1}"'.format(self.name, self.type)
+            + (
+                ' description = "{0}"'.format(self.description)
+                if self.description
+                else ""
+            )
+            + "/>"
+        )
+
 
 class Children(LEMSBase):
     """
     Stores children specification.
     """
-    
-    def __init__(self, name, type_, description = "", multiple = False):
+
+    def __init__(self, name, type_, description="", multiple=False):
         """
         Constructor.
 
         See instance variable documentation for more details on parameters.
         """
-        
+
         self.name = name
         """ Name of the children.
         :type: str """
-         
+
         self.type = type_
         """ Component type of the children.
         :type: str """
@@ -424,24 +490,30 @@ def toxml(self):
         Exports this object into a LEMS XML object
         """
 
-        return '<{3} name="{0}" type="{1}" description="{2}"/>'.format(self.name, self.type, self.description, 'Children' if self.multiple else 'Child')
+        return '<{3} name="{0}" type="{1}" description={2}/>'.format(
+            self.name,
+            self.type,
+            quoteattr(self.description) if self.description else '""',
+            "Children" if self.multiple else "Child",
+        )
+
 
 class Text(LEMSBase):
     """
     Stores a text entry specification.
     """
 
-    def __init__(self, name, description = ''):
+    def __init__(self, name, description=""):
         """
         Constructor.
 
         See instance variable documentation for more details on parameters.
         """
-        
+
         self.name = name
         """ Name of the text entry.
         :type: str """
-         
+
         self.description = description
         """ Description of the text entry.
         :type: str """
@@ -455,32 +527,43 @@ def toxml(self):
         Exports this object into a LEMS XML object
         """
 
-        return '<Text name="{0}"'.format(self.name) +\
-          (' description = "{0}"'.format(self.description) if self.description else '') +\
-          '/>'
-          
-          
+        return (
+            '<Text name="{0}"'.format(self.name)
+            + (
+                ' description = "{0}"'.format(self.description)
+                if self.description
+                else ""
+            )
+            + "/>"
+        )
+
     def __str__(self):
-        return 'Text, name: {0}'.format(self.name)+\
-          (', description = "{0}"'.format(self.description) if self.description else '') +\
-          (', value = "{0}"'.format(self.value) if self.value else '')
-          
-          
+        return (
+            "Text, name: {0}".format(self.name)
+            + (
+                ', description = "{0}"'.format(self.description)
+                if self.description
+                else ""
+            )
+            + (', value = "{0}"'.format(self.value) if self.value else "")
+        )
+
     def __repr__(self):
         return self.__str__()
-        
+
+
 class Link(LEMSBase):
     """
     Stores a link specification.
     """
 
-    def __init__(self, name, type_, description = ''):
+    def __init__(self, name, type_, description=""):
         """
         Constructor.
 
         See instance variable documentation for more details on parameters.
         """
-        
+
         self.name = name
         """ Name of the link entry.
         :type: str """
@@ -488,7 +571,7 @@ def __init__(self, name, type_, description = ''):
         self.type = type_
         """ Type of the link.
         :type: str """
-         
+
         self.description = description
         """ Description of the link.
         :type: str """
@@ -502,27 +585,33 @@ def toxml(self):
         Exports this object into a LEMS XML object
         """
 
-        return '<Link name="{0}" type="{1}"'.format(self.name, self.type) +\
-          (' description = "{0}"'.format(self.description) if self.description else '') +\
-          '/>'
+        return (
+            '<Link name="{0}" type="{1}"'.format(self.name, self.type)
+            + (
+                ' description = "{0}"'.format(self.description)
+                if self.description
+                else ""
+            )
+            + "/>"
+        )
+
 
-        
 class Path(LEMSBase):
     """
     Stores a path entry specification.
     """
 
-    def __init__(self, name, description = ''):
+    def __init__(self, name, description=""):
         """
         Constructor.
 
         See instance variable documentation for more details on parameters.
         """
-        
+
         self.name = name
         """ Name of the path entry.
         :type: str """
-         
+
         self.description = description
         """ Description of the path entry.
         :type: str """
@@ -536,30 +625,39 @@ def toxml(self):
         Exports this object into a LEMS XML object
         """
 
-        return '<Path name="{0}"'.format(self.name) +\
-          (' description = "{0}"'.format(self.description) if self.description else '') +\
-          '/>'
-        
+        return (
+            '<Path name="{0}"'.format(self.name)
+            + (
+                ' description = "{0}"'.format(self.description)
+                if self.description
+                else ""
+            )
+            + "/>"
+        )
+
+
 class EventPort(LEMSBase):
     """
     Stores an event port specification.
     """
 
-    def __init__(self, name, direction, description = ''):
+    def __init__(self, name, direction, description=""):
         """
         Constructor.
 
         See instance variable documentation for more details on parameters.
         """
-        
+
         self.name = name
         """ Name of the event port.
         :type: str """
 
         d = direction.lower()
-        if d != 'in' and d != 'out':
-            raise ModelError("Invalid direction '{0}' in event port '{1}'".format(direction, name))
-         
+        if d != "in" and d != "out":
+            raise ModelError(
+                "Invalid direction '{0}' in event port '{1}'".format(direction, name)
+            )
+
         self.direction = direction
         """ Direction - IN/OUT .
         :type: str """
@@ -573,10 +671,17 @@ def toxml(self):
         Exports this object into a LEMS XML object
         """
 
-        return '<EventPort name="{0}" direction="{1}"'.format(self.name, self.direction) +\
-          (' description = "{0}"'.format(self.description) if self.description else '') +\
-          '/>'
-        
+        return (
+            '<EventPort name="{0}" direction="{1}"'.format(self.name, self.direction)
+            + (
+                ' description = "{0}"'.format(self.description)
+                if self.description
+                else ""
+            )
+            + "/>"
+        )
+
+
 class ComponentReference(LEMSBase):
     """
     Stores a component reference.
@@ -610,16 +715,19 @@ def toxml(self):
         Exports this object into a LEMS XML object
         """
 
-        return '<ComponentReference name="{0}" type="{1}"'.format(self.name, self.type) + \
-          (' local = "{0}"'.format(self.local) if self.local else '') + \
-            '/>'
-        
+        return (
+            '<ComponentReference name="{0}" type="{1}"'.format(self.name, self.type)
+            + (' local = "{0}"'.format(self.local) if self.local else "")
+            + "/>"
+        )
+
+
 class Attachments(LEMSBase):
     """
     Stores an attachment type specification.
     """
 
-    def __init__(self, name, type_, description = ''):
+    def __init__(self, name, type_, description=""):
         """
         Constructor.
 
@@ -643,9 +751,16 @@ def toxml(self):
         Exports this object into a LEMS XML object
         """
 
-        return '<Attachments name="{0}" type="{1}"'.format(self.name, self.type) +\
-          (' description = "{0}"'.format(self.description) if self.description else '') +\
-          '/>'
+        return (
+            '<Attachments name="{0}" type="{1}"'.format(self.name, self.type)
+            + (
+                ' description = "{0}"'.format(self.description)
+                if self.description
+                else ""
+            )
+            + "/>"
+        )
+
 
 class Fat(LEMSBase):
     """
@@ -658,19 +773,19 @@ def __init__(self):
 
         See instance variable documentation for more details on parameters.
         """
-        
+
         self.parameters = Map()
         """ Map of parameters in this component type.
         :type: Map(str -> lems.model.component.Parameter) """
-        
+
         self.properties = Map()
         """ Map of properties in this component type.
         :type: Map(str -> lems.model.component.Property) """
-        
+
         self.derived_parameters = Map()
         """ Map of derived_parameters in this component type.
         :type: Map(str -> lems.model.component.Parameter) """
-        
+
         self.index_parameters = Map()
         """ Map of index_parameters in this component type.
         :type: Map(str -> lems.model.component.IndexParameter) """
@@ -738,7 +853,7 @@ def __init__(self):
         self.types = set()
         """ Set of compatible component types.
         :type: set(str) """
-        
+
     def add_parameter(self, parameter):
         """
         Adds a paramter to this component type.
@@ -748,8 +863,7 @@ def add_parameter(self, parameter):
         """
 
         self.parameters[parameter.name] = parameter
-        
-        
+
     def add_property(self, property):
         """
         Adds a property to this component type.
@@ -759,7 +873,7 @@ def add_property(self, property):
         """
 
         self.properties[property.name] = property
-        
+
     def add_derived_parameter(self, derived_parameter):
         """
         Adds a derived_parameter to this component type.
@@ -769,8 +883,7 @@ def add_derived_parameter(self, derived_parameter):
         """
 
         self.derived_parameters[derived_parameter.name] = derived_parameter
-        
-        
+
     def add_index_parameter(self, index_parameter):
         """
         Adds an index_parameter to this component type.
@@ -781,7 +894,6 @@ def add_index_parameter(self, index_parameter):
 
         self.index_parameters[index_parameter.name] = index_parameter
 
-
     def add_constant(self, constant):
         """
         Adds a paramter to this component type.
@@ -792,7 +904,6 @@ def add_constant(self, constant):
 
         self.constants[constant.name] = constant
 
-
     def add_exposure(self, exposure):
         """
         Adds a exposure to this component type.
@@ -803,7 +914,6 @@ def add_exposure(self, exposure):
 
         self.exposures[exposure.name] = exposure
 
-
     def add_requirement(self, requirement):
         """
         Adds a requirement to this component type.
@@ -814,7 +924,6 @@ def add_requirement(self, requirement):
 
         self.requirements[requirement.name] = requirement
 
-
     def add_component_requirement(self, component_requirement):
         """
         Adds a component requirement to this component type.
@@ -825,7 +934,6 @@ def add_component_requirement(self, component_requirement):
 
         self.component_requirements[component_requirement.name] = component_requirement
 
-
     def add_instance_requirement(self, instance_requirement):
         """
         Adds an instance requirement to this component type.
@@ -836,7 +944,6 @@ def add_instance_requirement(self, instance_requirement):
 
         self.instance_requirements[instance_requirement.name] = instance_requirement
 
-
     def add_children(self, children):
         """
         Adds children to this component type.
@@ -947,14 +1054,15 @@ def add(self, child):
         elif isinstance(child, Attachments):
             self.add_attachments(child)
         else:
-            raise ModelError('Unsupported child element')
+            raise ModelError("Unsupported child element")
+
 
 class ComponentType(Fat):
     """
     Stores a component type declaration.
     """
 
-    def __init__(self, name, description = '', extends = None):
+    def __init__(self, name, description="", extends=None):
         """
         Constructor.
 
@@ -962,11 +1070,11 @@ def __init__(self, name, description = '', extends = None):
         """
 
         Fat.__init__(self)
-    
+
         self.name = name
         """ Name of the component type.
         :type: str """
-         
+
         self.extends = extends
         """ Base component type.
         :type: str """
@@ -978,87 +1086,94 @@ def __init__(self, name, description = '', extends = None):
         self.types.add(name)
 
     def __str__(self):
-        return 'ComponentType, name: {0}'.format(self.name)
-        
+        return "ComponentType, name: {0}".format(self.name)
+
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        xmlstr = '<ComponentType name="{0}"'.format(self.name) +\
-          (' extends="{0}"'.format(self.extends) if self.extends else '') +\
-          (' description="{0}"'.format(self.description) if self.description else '')
+        xmlstr = (
+            '<ComponentType name="{0}"'.format(self.name)
+            + (' extends="{0}"'.format(self.extends) if self.extends else "")
+            + (
+                " description={0}".format(
+                    quoteattr(self.description) if self.description else '""'
+                )
+            )
+        )
 
-        chxmlstr = ''
+        chxmlstr = ""
 
         for property in self.properties:
             chxmlstr += property.toxml()
 
         for parameter in self.parameters:
             chxmlstr += parameter.toxml()
-            
+
         for derived_parameter in self.derived_parameters:
             chxmlstr += derived_parameter.toxml()
-            
+
         for index_parameter in self.index_parameters:
             chxmlstr += index_parameter.toxml()
 
         for constant in self.constants:
             chxmlstr += constant.toxml()
-            
-        childxml = ''
-        childrenxml = ''
-        
+
+        childxml = ""
+        childrenxml = ""
+
         for children in self.children:
             if children.multiple:
                 childrenxml += children.toxml()
             else:
                 childxml += children.toxml()
-            
+
         chxmlstr += childxml
         chxmlstr += childrenxml
-            
+
         for link in self.links:
             chxmlstr += link.toxml()
-            
+
         for component_reference in self.component_references:
             chxmlstr += component_reference.toxml()
-            
+
         for attachment in self.attachments:
             chxmlstr += attachment.toxml()
-            
+
         for event_port in self.event_ports:
             chxmlstr += event_port.toxml()
-            
+
         for exposure in self.exposures:
             chxmlstr += exposure.toxml()
-            
+
         for requirement in self.requirements:
             chxmlstr += requirement.toxml()
-            
+
         for component_requirement in self.component_requirements:
             chxmlstr += component_requirement.toxml()
-            
+
         for instance_requirement in self.instance_requirements:
             chxmlstr += instance_requirement.toxml()
-            
+
         for path in self.paths:
             chxmlstr += path.toxml()
-            
+
         for text in self.texts:
             chxmlstr += text.toxml()
 
         chxmlstr += self.dynamics.toxml()
         chxmlstr += self.structure.toxml()
         chxmlstr += self.simulation.toxml()
-            
+
         if chxmlstr:
-            xmlstr += '>' + chxmlstr + '</ComponentType>'
+            xmlstr += ">" + chxmlstr + "</ComponentType>"
         else:
-            xmlstr += '/>'
+            xmlstr += "/>"
 
         return xmlstr
 
+
 class Component(LEMSBase):
     """
     Stores a component instantiation.
@@ -1088,15 +1203,16 @@ def __init__(self, id_, type_, **params):
         self.children = list()
         """ List of child components.
         :type: list(lems.model.component.Component) """
-        
+
         self.parent_id = None
         """ Optional id of parent
         :type: str """
-        
 
     def __str__(self):
-        return 'Component, id: {0}, type: {1},\n   parameters: {2}\n   parent: {3}\n'.format(self.id, self.type, self.parameters, self.parent_id)
-    
+        return "Component, id: {0}, type: {1},\n   parameters: {2}\n   parent: {3}\n".format(
+            self.id, self.type, self.parameters, self.parent_id
+        )
+
     def __repr__(self):
         return self.__str__()
 
@@ -1133,19 +1249,18 @@ def add(self, child):
         if isinstance(child, Component):
             self.add_child(child)
         else:
-            raise ModelError('Unsupported child element')
-        
+            raise ModelError("Unsupported child element")
+
     def set_parent_id(self, parent_id):
         """
         Sets the id of the parent Component
-        
+
         :param parent_id: id of the parent Component
         :type parent_id: str
         """
-        
+
         self.parent_id = parent_id
-        
-        
+
     def toxml(self):
         """
         Exports this object into a LEMS XML object
@@ -1157,15 +1272,15 @@ def toxml(self):
             xmlstr += ' {0}="{1}"'.format(k, v)
 
         if self.children:
-            xmlstr += '>'
+            xmlstr += ">"
             for child in self.children:
                 xmlstr += child.toxml()
-            xmlstr += '</Component>'
+            xmlstr += "</Component>"
         else:
-            xmlstr += '/>'
+            xmlstr += "/>"
 
         return xmlstr
-    
+
 
 class FatComponent(Fat):
     """
@@ -1192,16 +1307,19 @@ def __init__(self, id_, type_):
         self.child_components = list()
         """ List of child components.
         :type: lems.model.component.FatComponent """
-        
+
         self.parent_id = None
         """ Optional id of parent
         :type: str """
-        
 
     def __str__(self):
-        return 'FatComponent, id: {0}, type: {1}, parent:{2}'.format(self.id, self.type, self.parent_id)+\
-          (', num children: {0}'.format(len(self.child_components)) if len(self.child_components)>0 else '')
-        
+        return "FatComponent, id: {0}, type: {1}, parent:{2}".format(
+            self.id, self.type, self.parent_id
+        ) + (
+            ", num children: {0}".format(len(self.child_components))
+            if len(self.child_components) > 0
+            else ""
+        )
 
     def add_child_component(self, child_component):
         """
@@ -1224,13 +1342,13 @@ def add(self, child):
             self.add_child_component(child)
         else:
             Fat.add(self, child)
-            
+
     def set_parent_id(self, parent_id):
         """
         Sets the id of the parent Component
-        
+
         :param parent_id: id of the parent Component
         :type parent_id: str
         """
-        
+
         self.parent_id = parent_id
diff --git a/lems/model/dynamics.py b/lems/model/dynamics.py
index a4fa763..1ad1275 100644
--- a/lems/model/dynamics.py
+++ b/lems/model/dynamics.py
@@ -7,15 +7,16 @@
 
 from lems.base.base import LEMSBase
 from lems.base.map import Map
-from lems.base.errors import ModelError,ParseError
+from lems.base.errors import ModelError, ParseError
 from lems.parser.expr import ExprParser
 
+
 class StateVariable(LEMSBase):
     """
     Store the specification of a state variable.
     """
 
-    def __init__(self, name, dimension, exposure = None):
+    def __init__(self, name, dimension, exposure=None):
         """
         Constructor.
 
@@ -35,18 +36,23 @@ def __init__(self, name, dimension, exposure = None):
         :type: str """
 
     def __str__(self):
-        return 'StateVariable name="{0}" dimension="{1}"'.format(self.name, self.dimension) +\
-          (' exposure="{0}"'.format(self.exposure) if self.exposure else '') 
-
+        return 'StateVariable name="{0}" dimension="{1}"'.format(
+            self.name, self.dimension
+        ) + (' exposure="{0}"'.format(self.exposure) if self.exposure else "")
 
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        return '<StateVariable name="{0}" dimension="{1}"'.format(self.name, self.dimension) +\
-          (' exposure="{0}"'.format(self.exposure) if self.exposure else '') +\
-          '/>'
+        return (
+            '<StateVariable name="{0}" dimension="{1}"'.format(
+                self.name, self.dimension
+            )
+            + (' exposure="{0}"'.format(self.exposure) if self.exposure else "")
+            + "/>"
+        )
+
 
 class DerivedVariable(LEMSBase):
     """
@@ -64,27 +70,27 @@ def __init__(self, name, **params):
         """ Name of the derived variable.
         :type: str """
 
-        self.dimension = params['dimension'] if 'dimension' in params else None
+        self.dimension = params["dimension"] if "dimension" in params else None
         """ Dimension of the derived variable or None if computed.
         :type: str """
 
-        self.exposure = params['exposure'] if 'exposure' in params else None
+        self.exposure = params["exposure"] if "exposure" in params else None
         """ Exposure name for the derived variable.
         :type: str """
 
-        self.select = params['select'] if 'select' in params else None
+        self.select = params["select"] if "select" in params else None
         """ Selection path/expression for the derived variable.
         :type: str """
 
-        self.value = params['value'] if 'value' in params else None
+        self.value = params["value"] if "value" in params else None
         """ Value of the derived variable.
         :type: str """
 
-        self.reduce = params['reduce'] if 'reduce' in params else None
+        self.reduce = params["reduce"] if "reduce" in params else None
         """ Reduce method for the derived variable.
         :type: str """
 
-        self.required = params['required'] if 'required' in params else None
+        self.required = params["required"] if "required" in params else None
         """ Requried or not.
         :type: str """
 
@@ -96,25 +102,30 @@ def __init__(self, name, **params):
             try:
                 self.expression_tree = ExprParser(self.value).parse()
             except:
-                raise ParseError("Parse error when parsing value expression "
-                                 "'{0}' for derived variable {1}",
-                                 self.value, self.name)
+                raise ParseError(
+                    "Parse error when parsing value expression "
+                    "'{0}' for derived variable {1}",
+                    self.value,
+                    self.name,
+                )
 
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        return '<DerivedVariable name="{0}"'.format(self.name) +\
-          (' dimension="{0}"'.format(self.dimension) if self.dimension else '') +\
-          (' exposure="{0}"'.format(self.exposure) if self.exposure else '') +\
-          (' select="{0}"'.format(self.select) if self.select else '') +\
-          (' value="{0}"'.format(self.value) if self.value else '') +\
-          (' reduce="{0}"'.format(self.reduce) if self.reduce else '') +\
-          (' required="{0}"'.format(self.required) if self.required else '') +\
-          '/>'
-          
-          
+        return (
+            '<DerivedVariable name="{0}"'.format(self.name)
+            + (' dimension="{0}"'.format(self.dimension) if self.dimension else "")
+            + (' exposure="{0}"'.format(self.exposure) if self.exposure else "")
+            + (' select="{0}"'.format(self.select) if self.select else "")
+            + (' value="{0}"'.format(self.value) if self.value else "")
+            + (' reduce="{0}"'.format(self.reduce) if self.reduce else "")
+            + (' required="{0}"'.format(self.required) if self.required else "")
+            + "/>"
+        )
+
+
 class Case(LEMSBase):
     """
     Store the specification of a case for a Conditional Derived Variable.
@@ -136,36 +147,42 @@ def __init__(self, condition, value):
         self.condition_expression_tree = None
         """ Parse tree for the case condition expression.
         :type: lems.parser.expr.ExprNode """
-        
+
         self.value_expression_tree = None
         """ Parse tree for the case condition expression.
         :type: lems.parser.expr.ExprNode """
-        
+
         try:
             self.value_expression_tree = ExprParser(self.value).parse()
-            
+
             if not self.condition:
                 self.condition_expression_tree = None
             else:
                 self.condition_expression_tree = ExprParser(self.condition).parse()
         except:
-            raise ParseError("Parse error when parsing case with condition "
-                             "'{0}' and value {1}",
-                             self.condition, self.value)
-        
+            raise ParseError(
+                "Parse error when parsing case with condition " "'{0}' and value {1}",
+                self.condition,
+                self.value,
+            )
+
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        return '<Case condition="{0}" value="{1}"'.format(self.condition, self.value) + '/>'
-          
+        return (
+            '<Case condition="{0}" value="{1}"'.format(self.condition, self.value)
+            + "/>"
+        )
+
+
 class ConditionalDerivedVariable(LEMSBase):
     """
     Store the specification of a conditional derived variable.
     """
 
-    def __init__(self, name, dimension, exposure = None):
+    def __init__(self, name, dimension, exposure=None):
         """
         Constructor.
 
@@ -183,12 +200,11 @@ def __init__(self, name, dimension, exposure = None):
         self.exposure = exposure
         """ Exposure name for the state variable.
         :type: str """
-        
+
         self.cases = list()
         """ List of cases related to this conditional derived variable.
         :type: list(lems.model.dynamics.Case) """
-        
-        
+
     def add_case(self, case):
         """
         Adds a case to this conditional derived variable.
@@ -209,30 +225,32 @@ def add(self, child):
         if isinstance(child, Case):
             self.add_case(child)
         else:
-            raise ModelError('Unsupported child element')
-
+            raise ModelError("Unsupported child element")
 
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        xmlstr = '<ConditionalDerivedVariable name="{0}"'.format(self.name) +\
-          (' dimension="{0}"'.format(self.dimension) if self.dimension else '') +\
-          (' exposure="{0}"'.format(self.exposure) if self.exposure else '') 
-          
-        chxmlstr = ''
+        xmlstr = (
+            '<ConditionalDerivedVariable name="{0}"'.format(self.name)
+            + (' dimension="{0}"'.format(self.dimension) if self.dimension else "")
+            + (' exposure="{0}"'.format(self.exposure) if self.exposure else "")
+        )
+
+        chxmlstr = ""
 
         for case in self.cases:
             chxmlstr += case.toxml()
 
         if chxmlstr:
-            xmlstr += '>' + chxmlstr + '</ConditionalDerivedVariable>'
+            xmlstr += ">" + chxmlstr + "</ConditionalDerivedVariable>"
         else:
-            xmlstr += '/>'
-            
+            xmlstr += "/>"
+
         return xmlstr
 
+
 class TimeDerivative(LEMSBase):
     """
     Store the specification of a time derivative specifcation.
@@ -256,20 +274,26 @@ def __init__(self, variable, value):
         self.expression_tree = None
         """ Parse tree for the time derivative expression.
         :type: lems.parser.expr.ExprNode """
-        
+
         try:
             self.expression_tree = ExprParser(value).parse()
         except:
-            raise ParseError("Parse error when parsing value expression "
-                             "'{0}' for state variable {1}",
-                             self.value, self.variable)
-        
+            raise ParseError(
+                "Parse error when parsing value expression "
+                "'{0}' for state variable {1}",
+                self.value,
+                self.variable,
+            )
+
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        return '<TimeDerivative variable="{0}" value="{1}"/>'.format(self.variable, self.value)
+        return '<TimeDerivative variable="{0}" value="{1}"/>'.format(
+            self.variable, self.value
+        )
+
 
 class Action(LEMSBase):
     """
@@ -278,6 +302,7 @@ class Action(LEMSBase):
 
     pass
 
+
 class StateAssignment(Action):
     """
     State assignment specification.
@@ -307,17 +332,22 @@ def __init__(self, variable, value):
         try:
             self.expression_tree = ExprParser(value).parse()
         except:
-            raise ParseError("Parse error when parsing state assignment "
-                             "value expression "
-                             "'{0}' for state variable {1}",
-                             self.value, self.variable)
+            raise ParseError(
+                "Parse error when parsing state assignment "
+                "value expression "
+                "'{0}' for state variable {1}",
+                self.value,
+                self.variable,
+            )
 
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        return '<StateAssignment variable="{0}" value="{1}"/>'.format(self.variable, self.value)
+        return '<StateAssignment variable="{0}" value="{1}"/>'.format(
+            self.variable, self.value
+        )
 
 
 class EventOut(Action):
@@ -328,16 +358,16 @@ class EventOut(Action):
     def __init__(self, port):
         """
         Constructor.
-        
+
         See instance variable documentation for more details on parameters.
         """
-        
+
         Action.__init__(self)
 
         self.port = port
         """ Port on which the event comes in.
         :type: str """
-        
+
     def toxml(self):
         """
         Exports this object into a LEMS XML object
@@ -345,6 +375,7 @@ def toxml(self):
 
         return '<EventOut port="{0}"/>'.format(self.port)
 
+
 class Transition(Action):
     """
     Regime transition specification.
@@ -353,10 +384,10 @@ class Transition(Action):
     def __init__(self, regime):
         """
         Constructor.
-        
+
         See instance variable documentation for more details on parameters.
         """
-        
+
         Action.__init__(self)
 
         self.regime = regime
@@ -370,6 +401,7 @@ def toxml(self):
 
         return '<Transition regime="{0}"/>'.format(self.regime)
 
+
 class EventHandler(LEMSBase):
     """
     Base class for event handlers.
@@ -385,7 +417,7 @@ def __init__(self):
         :type: list(lems.model.dynamics.Action) """
 
     def __str__(self):
-        istr = 'EventHandler...'
+        istr = "EventHandler..."
         return istr
 
     def add_action(self, action):
@@ -408,8 +440,9 @@ def add(self, child):
         if isinstance(child, Action):
             self.add_action(child)
         else:
-            raise ModelError('Unsupported child element')
-        
+            raise ModelError("Unsupported child element")
+
+
 class OnStart(EventHandler):
     """
     Specification for event handler called upon initialization of the component.
@@ -419,14 +452,14 @@ def __init__(self):
         """
         Constructor.
         """
-        
+
         EventHandler.__init__(self)
 
     def __str__(self):
-        istr = 'OnStart: ['
+        istr = "OnStart: ["
         for action in self.actions:
             istr += str(action)
-        istr += ']'
+        istr += "]"
         return str(istr)
 
     def toxml(self):
@@ -434,20 +467,21 @@ def toxml(self):
         Exports this object into a LEMS XML object
         """
 
-        xmlstr = '<OnStart'
+        xmlstr = "<OnStart"
 
-        chxmlstr = ''
+        chxmlstr = ""
 
         for action in self.actions:
             chxmlstr += action.toxml()
 
         if chxmlstr:
-            xmlstr += '>' + chxmlstr + '</OnStart>'
+            xmlstr += ">" + chxmlstr + "</OnStart>"
         else:
-            xmlstr += '/>'
+            xmlstr += "/>"
 
         return xmlstr
 
+
 class OnCondition(EventHandler):
     """
     Specification for event handler called upon satisfying a given condition.
@@ -456,10 +490,10 @@ class OnCondition(EventHandler):
     def __init__(self, test):
         """
         Constructor.
-        
+
         See instance variable documentation for more details on parameters.
         """
-        
+
         EventHandler.__init__(self)
 
         self.test = test
@@ -470,9 +504,9 @@ def __init__(self, test):
             self.expression_tree = ExprParser(test).parse()
         except:
             raise ParseError("Parse error when parsing OnCondition test '{0}'", test)
-        
+
     def __str__(self):
-        istr = 'OnCondition...'
+        istr = "OnCondition..."
         return istr
 
     def toxml(self):
@@ -482,18 +516,19 @@ def toxml(self):
 
         xmlstr = '<OnCondition test="{0}"'.format(self.test)
 
-        chxmlstr = ''
+        chxmlstr = ""
 
         for action in self.actions:
             chxmlstr += action.toxml()
 
         if chxmlstr:
-            xmlstr += '>' + chxmlstr + '</OnCondition>'
+            xmlstr += ">" + chxmlstr + "</OnCondition>"
         else:
-            xmlstr += '/>'
+            xmlstr += "/>"
 
         return xmlstr
 
+
 class OnEvent(EventHandler):
     """
     Specification for event handler called upon receiving en event sent by another component.
@@ -502,10 +537,10 @@ class OnEvent(EventHandler):
     def __init__(self, port):
         """
         Constructor.
-        
+
         See instance variable documentation for more details on parameters.
         """
-        
+
         EventHandler.__init__(self)
 
         self.port = port
@@ -513,7 +548,7 @@ def __init__(self, port):
         :type: str """
 
     def __str__(self):
-        istr = 'OnEvent, port: %s'%self.port
+        istr = "OnEvent, port: %s" % self.port
         return istr
 
     def toxml(self):
@@ -523,18 +558,19 @@ def toxml(self):
 
         xmlstr = '<OnEvent port="{0}"'.format(self.port)
 
-        chxmlstr = ''
+        chxmlstr = ""
 
         for action in self.actions:
             chxmlstr += action.toxml()
 
         if chxmlstr:
-            xmlstr += '>' + chxmlstr + '</OnEvent>'
+            xmlstr += ">" + chxmlstr + "</OnEvent>"
         else:
-            xmlstr += '/>'
+            xmlstr += "/>"
 
         return xmlstr
 
+
 class OnEntry(EventHandler):
     """
     Specification for event handler called upon entry into a new behavior regime.
@@ -544,7 +580,7 @@ def __init__(self):
         """
         Constructor.
         """
-        
+
         EventHandler.__init__(self)
 
     def toxml(self):
@@ -552,31 +588,40 @@ def toxml(self):
         Exports this object into a LEMS XML object
         """
 
-        xmlstr = '<OnEntry'
+        xmlstr = "<OnEntry"
 
-        chxmlstr = ''
+        chxmlstr = ""
 
         for action in self.actions:
             chxmlstr += action.toxml()
 
         if chxmlstr:
-            xmlstr += '>' + chxmlstr + '</OnEntry>'
+            xmlstr += ">" + chxmlstr + "</OnEntry>"
         else:
-            xmlstr += '/>'
+            xmlstr += "/>"
 
         return xmlstr
 
+
 class KineticScheme(LEMSBase):
     """
     Kinetic scheme specifications.
     """
 
-    def __init__(self, name, nodes, state_variable, 
-                 edges, edge_source, edge_target,
-                 forward_rate, reverse_rate):
+    def __init__(
+        self,
+        name,
+        nodes,
+        state_variable,
+        edges,
+        edge_source,
+        edge_target,
+        forward_rate,
+        reverse_rate,
+    ):
         """
         Constructor.
-        
+
         See instance variable documentation for more details on parameters.
         """
 
@@ -617,22 +662,27 @@ def toxml(self):
         Exports this object into a LEMS XML object
         """
 
-        return ('<KineticScheme '
-                'name="{0}" '
-                'nodes="{1}" '
-                'edges="{2}" '
-                'stateVariable="{3}" '
-                'edgeSource="{4}" '
-                'edgeTarget="{5}" '
-                'forwardRate="{6}" '
-                'reverseRate="{7}"/>').format(self.name,
-                                              self.nodes,
-                                              self.edges,
-                                              self.state_variable,
-                                              self.edge_source,
-                                              self.edge_target,
-                                              self.forward_rate,
-                                              self.reverse_rate)
+        return (
+            "<KineticScheme "
+            'name="{0}" '
+            'nodes="{1}" '
+            'edges="{2}" '
+            'stateVariable="{3}" '
+            'edgeSource="{4}" '
+            'edgeTarget="{5}" '
+            'forwardRate="{6}" '
+            'reverseRate="{7}"/>'
+        ).format(
+            self.name,
+            self.nodes,
+            self.edges,
+            self.state_variable,
+            self.edge_source,
+            self.edge_target,
+            self.forward_rate,
+            self.reverse_rate,
+        )
+
 
 class Behavioral(LEMSBase):
     """
@@ -642,7 +692,7 @@ class Behavioral(LEMSBase):
     def __init__(self):
         """
         Constructor.
-        
+
         See instance variable documentation for more details on parameters.
         """
 
@@ -673,24 +723,25 @@ def __init__(self):
         self.kinetic_schemes = Map()
         """ Map of kinetic schemes in this behavior regime.
         :type: dict(str -> lems.model.dynamics.KineticScheme) """
-        
-        
+
     def has_content(self):
-        if len(self.state_variables)==0 and \
-           len(self.derived_variables)==0 and \
-           len(self.conditional_derived_variables)==0 and \
-           len(self.time_derivatives)==0 and \
-           len(self.event_handlers)==0 and \
-           len(self.kinetic_schemes)==0:
-               return False
+        if (
+            len(self.state_variables) == 0
+            and len(self.derived_variables) == 0
+            and len(self.conditional_derived_variables) == 0
+            and len(self.time_derivatives) == 0
+            and len(self.event_handlers) == 0
+            and len(self.kinetic_schemes) == 0
+        ):
+            return False
         else:
             return True
-        
+
     def clear(self):
         """
         Clear behavioral entities.
         """
-        
+
         self.time_derivatives = Map()
 
     def add_state_variable(self, sv):
@@ -702,7 +753,7 @@ def add_state_variable(self, sv):
         """
 
         self.state_variables[sv.name] = sv
-        
+
     def add_derived_variable(self, dv):
         """
         Adds a derived variable to this behavior regime.
@@ -712,7 +763,7 @@ def add_derived_variable(self, dv):
         """
 
         self.derived_variables[dv.name] = dv
-        
+
     def add_conditional_derived_variable(self, cdv):
         """
         Adds a conditional derived variable to this behavior regime.
@@ -722,7 +773,7 @@ def add_conditional_derived_variable(self, cdv):
         """
 
         self.conditional_derived_variables[cdv.name] = cdv
-        
+
     def add_time_derivative(self, td):
         """
         Adds a time derivative to this behavior regime.
@@ -740,7 +791,7 @@ def add_event_handler(self, eh):
         :param eh: Event handler.
         :type eh: lems.model.dynamics.EventHandler
         """
-        
+
         self.event_handlers.append(eh)
 
     def add_kinetic_scheme(self, ks):
@@ -773,21 +824,21 @@ def add(self, child):
         elif isinstance(child, KineticScheme):
             self.add_kinetic_scheme(child)
         else:
-            raise ModelError('Unsupported child element')
-        
+            raise ModelError("Unsupported child element")
+
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        chxmlstr = ''
+        chxmlstr = ""
 
         for state_variable in self.state_variables:
             chxmlstr += state_variable.toxml()
 
         for derived_variable in self.derived_variables:
             chxmlstr += derived_variable.toxml()
-            
+
         for conditional_derived_variable in self.conditional_derived_variables:
             chxmlstr += conditional_derived_variable.toxml()
 
@@ -805,36 +856,38 @@ def toxml(self):
                 chxmlstr += regime.toxml()
 
         if isinstance(self, Dynamics):
-            xmlprefix = 'Dynamics'
-            xmlsuffix = 'Dynamics'
-            xmlempty = ''
+            xmlprefix = "Dynamics"
+            xmlsuffix = "Dynamics"
+            xmlempty = ""
         else:
-            xmlprefix = 'Regime name="{0}"'.format(self.name) +\
-              (' initial="true"' if self.initial else '')
-            xmlsuffix = 'Regime'
-            xmlempty = '<{0}/>',format(xmlprefix)
+            xmlprefix = 'Regime name="{0}"'.format(self.name) + (
+                ' initial="true"' if self.initial else ""
+            )
+            xmlsuffix = "Regime"
+            xmlempty = "<{0}/>", format(xmlprefix)
 
         if chxmlstr:
-            xmlstr = '<{0}>'.format(xmlprefix) + chxmlstr + '</{0}>'.format(xmlsuffix)
+            xmlstr = "<{0}>".format(xmlprefix) + chxmlstr + "</{0}>".format(xmlsuffix)
         else:
             xmlstr = xmlempty
 
         return xmlstr
-                
+
+
 class Regime(Behavioral):
     """
     Stores a single behavioral regime for a component type.
     """
 
-    def __init__(self, name, parent_behavioral, initial = False):
+    def __init__(self, name, parent_behavioral, initial=False):
         """
         Constructor.
-        
+
         See instance variable documentation for more details on parameters.
         """
 
         Behavioral.__init__(self)
-        
+
         self.name = name
         """ Name of this behavior regime.
         :type: str """
@@ -846,7 +899,8 @@ def __init__(self, name, parent_behavioral, initial = False):
         self.initial = initial
         """ Initial behavior regime.
         :type: bool """
-        
+
+
 class Dynamics(Behavioral):
     """
     Stores behavioral dynamics specification for a component type.
@@ -856,7 +910,7 @@ def __init__(self):
         """
         Constructor.
         """
-        
+
         Behavioral.__init__(self)
 
         self.regimes = Map()
@@ -868,7 +922,7 @@ def add_regime(self, regime):
         Adds a behavior regime to this dynamics object.
 
         :param regime: Behavior regime to be added.
-        :type regime: lems.model.dynamics.Regime """
+        :type regime: lems.model.dynamics.Regime"""
 
         self.regimes[regime.name] = regime
 
@@ -883,10 +937,9 @@ def add(self, child):
             self.add_regime(child)
         else:
             Behavioral.add(self, child)
-            
+
     def has_content(self):
-        if len(self.regimes)>0: 
+        if len(self.regimes) > 0:
             return True
         else:
             return Behavioral.has_content(self)
-        
diff --git a/lems/model/fundamental.py b/lems/model/fundamental.py
index 640822d..c36362d 100644
--- a/lems/model/fundamental.py
+++ b/lems/model/fundamental.py
@@ -7,11 +7,12 @@
 
 from lems.base.base import LEMSBase
 
+
 class Include(LEMSBase):
     """
     Include another LEMS file.
     """
-    
+
     def __init__(self, filename):
         """
         Constructor.
@@ -20,120 +21,124 @@ def __init__(self, filename):
         :type name: str
 
         """
-        
+
         self.file = filename
         """ Name of the file.
         :type: str """
-        
 
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        return '<Include file="%s"/>'%self.file
+        return '<Include file="%s"/>' % self.file
+
 
 class Dimension(LEMSBase):
     """
     Stores a dimension in terms of the seven fundamental SI units.
     """
-    
-    def __init__(self, name, description = '', **params):
+
+    def __init__(self, name, description="", **params):
         """
         Constructor.
 
         :param name: Name of the dimension.
         :type name: str
 
-        :param params: Key arguments specifying powers for each of the 
+        :param params: Key arguments specifying powers for each of the
         seven fundamental SI dimensions.
         :type params: dict()
         """
-        
+
         self.name = name
         """ Name of the dimension.
         :type: str """
 
-        self.m = params['m'] if 'm' in params else 0
+        self.m = params["m"] if "m" in params else 0
         """ Power for the mass dimension.
         :type: int """
-        
-        self.l = params['l'] if 'l' in params else 0
+
+        self.l = params["l"] if "l" in params else 0
         """ Power for the length dimension.
         :type: int """
-        
-        self.t = params['t'] if 't' in params else 0
+
+        self.t = params["t"] if "t" in params else 0
         """ Power for the time dimension.
         :type: int """
-        
-        self.i = params['i'] if 'i' in params else 0
+
+        self.i = params["i"] if "i" in params else 0
         """ Power for the electic current dimension.
         :type: int """
-        
-        self.k = params['k'] if 'k' in params else 0
+
+        self.k = params["k"] if "k" in params else 0
         """ Power for the temperature dimension.
         :type: int """
-        
-        self.n = params['n'] if 'n' in params else 0
+
+        self.n = params["n"] if "n" in params else 0
         """ Power for the quantity dimension.
         :type: int """
-        
-        self.j = params['j'] if 'j' in params else 0
+
+        self.j = params["j"] if "j" in params else 0
         """ Power for the luminous intensity dimension.
         :type: int """
 
         self.description = description
         """ Description of this dimension.
         :type: str """
-        
 
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        return '<Dimension name="{0}"'.format(self.name) +\
-          (' m = "{0}"'.format(self.m) if self.m != 0 else '') +\
-          (' l = "{0}"'.format(self.l) if self.l != 0 else '') +\
-          (' t = "{0}"'.format(self.t) if self.t != 0 else '') +\
-          (' i = "{0}"'.format(self.i) if self.i != 0 else '') +\
-          (' k = "{0}"'.format(self.k) if self.k != 0 else '') +\
-          (' n = "{0}"'.format(self.n) if self.n != 0 else '') +\
-          (' j = "{0}"'.format(self.j) if self.j != 0 else '') +\
-          '/>'
-          
+        return (
+            '<Dimension name="{0}"'.format(self.name)
+            + (' m = "{0}"'.format(self.m) if self.m != 0 else "")
+            + (' l = "{0}"'.format(self.l) if self.l != 0 else "")
+            + (' t = "{0}"'.format(self.t) if self.t != 0 else "")
+            + (' i = "{0}"'.format(self.i) if self.i != 0 else "")
+            + (' k = "{0}"'.format(self.k) if self.k != 0 else "")
+            + (' n = "{0}"'.format(self.n) if self.n != 0 else "")
+            + (' j = "{0}"'.format(self.j) if self.j != 0 else "")
+            + "/>"
+        )
+
+
 class Unit(LEMSBase):
     """
     Stores a unit definition.
     """
-    
-    def __init__(self, name, symbol, dimension, power = 0, scale = 1.0, offset = 0.0, description = ''):
+
+    def __init__(
+        self, name, symbol, dimension, power=0, scale=1.0, offset=0.0, description=""
+    ):
         """
         Constructor.
 
         See instance variable documentation for more details on parameters.
         """
-        
+
         self.name = name
         """ Name of the unit.
         :type: str """
-        
+
         self.symbol = symbol
         """ Symbol for the unit.
         :type: str """
-        
+
         self.dimension = dimension
         """ Dimension for the unit.
         :type: str """
-        
+
         self.power = power
         """ Scaling by power of 10.
         :type: int """
-        
+
         self.scale = scale
         """ Scaling.
         :type: float """
-        
+
         self.offset = offset
         """ Offset for non-zero units.
         :type: float """
@@ -141,7 +146,7 @@ def __init__(self, name, symbol, dimension, power = 0, scale = 1.0, offset = 0.0
         self.description = description
         """ Description of this unit.
         :type: str """
-        
+
     def toxml(self):
         """
         Exports this object into a LEMS XML object
@@ -151,11 +156,17 @@ def toxml(self):
         # https://github.com/LEMS/LEMS/issues/4
         #  '''(' name = "{0}"'.format(self.name) if self.name else '') +\'''
 
-        return '<Unit' +\
-          (' symbol = "{0}"'.format(self.symbol) if self.symbol else '') +\
-          (' dimension = "{0}"'.format(self.dimension) if self.dimension else '') +\
-          (' power = "{0}"'.format(self.power) if self.power else '') +\
-          (' scale = "{0}"'.format(self.scale) if self.scale else '') +\
-          (' offset = "{0}"'.format(self.offset) if self.offset else '') +\
-          (' description = "{0}"'.format(self.description) if self.description else '') +\
-          '/>'
+        return (
+            "<Unit"
+            + (' symbol = "{0}"'.format(self.symbol) if self.symbol else "")
+            + (' dimension = "{0}"'.format(self.dimension) if self.dimension else "")
+            + (' power = "{0}"'.format(self.power) if self.power else "")
+            + (' scale = "{0}"'.format(self.scale) if self.scale else "")
+            + (' offset = "{0}"'.format(self.offset) if self.offset else "")
+            + (
+                ' description = "{0}"'.format(self.description)
+                if self.description
+                else ""
+            )
+            + "/>"
+        )
diff --git a/lems/model/model.py b/lems/model/model.py
index 18b6652..eb5f6ee 100644
--- a/lems/model/model.py
+++ b/lems/model/model.py
@@ -7,11 +7,13 @@
 
 import os
 from os.path import dirname
+
 # For python versions where typing isn't available at all
 try:
-    from typing import List, Dict
+    from typing import List, Dict, Union, Tuple
 except ImportError:
     pass
+import copy
 
 from lems import __schema_location__, __schema_version__
 from lems.base.base import LEMSBase
@@ -21,12 +23,28 @@
 from lems.base.errors import ModelError
 from lems.base.errors import SimBuildError
 
-from lems.model.fundamental import Dimension,Unit,Include
-from lems.model.component import Constant,ComponentType,Component,FatComponent,Exposure
-from lems.model.simulation import Run,Record,EventRecord,DataDisplay,DataWriter,EventWriter
-from lems.model.structure import With,EventConnection,ChildInstance,MultiInstantiate
+from lems.model.fundamental import Dimension, Unit, Include
+from lems.model.component import (
+    Constant,
+    ComponentType,
+    Component,
+    FatComponent,
+    Exposure,
+)
+from lems.model.simulation import (
+    Run,
+    Record,
+    EventRecord,
+    DataDisplay,
+    DataWriter,
+    EventWriter,
+)
+from lems.model.structure import With, EventConnection, ChildInstance, MultiInstantiate
 
 import xml.dom.minidom as minidom
+from xml.parsers.expat import ExpatError, errors
+from xml.sax.saxutils import quoteattr
+
 
 import logging
 
@@ -40,7 +58,7 @@ class Model(LEMSBase):
 
     target_lems_version = __schema_version__
     schema_location = __schema_location__
-    #schema_location = '/home/padraig/LEMS/Schemas/LEMS/LEMS_v%s.xsd'%target_lems_version
+    # schema_location = '/home/padraig/LEMS/Schemas/LEMS/LEMS_v%s.xsd'%target_lems_version
 
     debug = False
 
@@ -101,6 +119,17 @@ def __init__(self, include_includes=True, fail_on_missing_includes=True):
         """ Whether to raise an Exception when a file in an <Include> element is not found
         :type: boolean """
 
+        self.resolved_model = None
+        """ A resolved version of the model, generated by self.resolve()
+        :type: None or Model"""
+
+        self.comp_ref_map = None
+        """ A map of the component references in the model, generated by
+        self.get_comp_reference_map
+
+        :type: None or Map
+        """
+
     def add_target(self, target):
         """
         Adds a simulation target to the model.
@@ -151,8 +180,8 @@ def add_component_type(self, component_type):
         name = component_type.name
 
         # To handle colons in names in LEMS
-        if ':' in name:
-            name = name.replace(':', '_')
+        if ":" in name:
+            name = name.replace(":", "_")
             component_type.name = name
 
         self.component_types[name] = component_type
@@ -209,7 +238,7 @@ def add(self, child):
         elif isinstance(child, Constant):
             self.add_constant(child)
         else:
-            raise ModelError('Unsupported child element')
+            raise ModelError("Unsupported child element")
 
     def add_include_directory(self, path):
         """
@@ -221,7 +250,7 @@ def add_include_directory(self, path):
 
         self.include_directories.append(path)
 
-    def include_file(self, path, include_dirs = []):
+    def include_file(self, path, include_dirs=[]):
         """
         Includes a file into the current model.
 
@@ -232,7 +261,10 @@ def include_file(self, path, include_dirs = []):
         :type include_dirs: list(str)
         """
         if self.include_includes:
-            if self.debug: print("------------------                   Including a file: %s"%path)
+            if self.debug:
+                print(
+                    "------------------                   Including a file: %s" % path
+                )
             inc_dirs = include_dirs if include_dirs else self.include_dirs
 
             parser = LEMSFileParser(self, inc_dirs, self.include_includes)
@@ -242,20 +274,22 @@ def include_file(self, path, include_dirs = []):
                     self.included_files.append(path)
                     return
                 else:
-                    if self.debug: print("Already included: %s"%path)
+                    if self.debug:
+                        print("Already included: %s" % path)
                     return
             else:
                 for inc_dir in inc_dirs:
-                    new_path = (inc_dir + '/' + path)
+                    new_path = inc_dir + "/" + path
                     if os.access(new_path, os.F_OK):
                         if not new_path in self.included_files:
                             parser.parse(open(new_path).read())
                             self.included_files.append(new_path)
                             return
                         else:
-                            if self.debug: print("Already included: %s"%path)
+                            if self.debug:
+                                print("Already included: %s" % path)
                             return
-            msg = 'Unable to open ' + path
+            msg = "Unable to open " + path
             if self.fail_on_missing_includes:
                 raise Exception(msg)
             elif self.debug:
@@ -280,13 +314,19 @@ def export_to_dom(self):
         """
         Exports this model to a DOM.
         """
-        namespaces = 'xmlns="http://www.neuroml.org/lems/%s" ' + \
-                     'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' + \
-                     'xsi:schemaLocation="http://www.neuroml.org/lems/%s %s"'
+        namespaces = (
+            'xmlns="http://www.neuroml.org/lems/%s" '
+            + 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" '
+            + 'xsi:schemaLocation="http://www.neuroml.org/lems/%s %s"'
+        )
 
-        namespaces = namespaces%(self.target_lems_version,self.target_lems_version,self.schema_location)
+        namespaces = namespaces % (
+            self.target_lems_version,
+            self.target_lems_version,
+            self.schema_location,
+        )
 
-        xmlstr = '<Lems %s>'%namespaces
+        xmlstr = "<Lems %s>" % namespaces
 
         for include in self.includes:
             xmlstr += include.toxml()
@@ -309,12 +349,17 @@ def export_to_dom(self):
         for component in self.components:
             xmlstr += component.toxml()
 
-        xmlstr += '</Lems>'
+        xmlstr += "</Lems>"
 
-        xmldom = minidom.parseString(xmlstr)
+        try:
+            xmldom = minidom.parseString(xmlstr)
+        except ExpatError as er:
+            print("Parsing error:", errors.messages[er.code])
+            print("at: " + xmlstr[er.offset : er.offset + 20])
+            raise
         return xmldom
 
-    def export_to_file(self, filepath, level_prefix = '  '):
+    def export_to_file(self, filepath, level_prefix="  "):
         """
         Exports this model to a file.
 
@@ -322,18 +367,26 @@ def export_to_file(self, filepath, level_prefix = '  '):
         :type filepath: str
         """
         xmldom = self.export_to_dom()
-        xmlstr = xmldom.toprettyxml(level_prefix, '\n',)
+        xmlstr = xmldom.toprettyxml(
+            level_prefix,
+            "\n",
+        )
 
-
-        f = open(filepath, 'w')
+        f = open(filepath, "w")
         f.write(xmlstr)
         f.close()
 
     def resolve(self):
+        # type: () -> Model
         """
-        Resolves references in this model.
+        Resolves references in this model and returns resolved model.
+
+        :returns: resolved Model
         """
 
+        if self.resolved_model:
+            return self.resolved_model
+
         model = self.copy()
 
         for ct in model.component_types:
@@ -348,7 +401,8 @@ def resolve(self):
             c2.numeric_value = model.get_numeric_value(c2.value, c2.dimension)
             model.add(c2)
 
-        return model
+        self.resolved_model = model
+        return self.resolved_model
 
     def resolve_component_type(self, component_type):
         """
@@ -363,8 +417,11 @@ def resolve_component_type(self, component_type):
             try:
                 base_ct = self.component_types[component_type.extends]
             except:
-                raise ModelError("Component type '{0}' trying to extend unknown component type '{1}'",
-                                 component_type.name, component_type.extends)
+                raise ModelError(
+                    "Component type '{0}' trying to extend unknown component type '{1}'",
+                    component_type.name,
+                    component_type.extends,
+                )
 
             self.resolve_component_type(base_ct)
             self.merge_component_types(component_type, base_ct)
@@ -383,7 +440,7 @@ def merge_component_types(self, ct, base_ct):
         :type base_ct: lems.model.component.ComponentType
         """
 
-        #merge_maps(ct.parameters, base_ct.parameters)
+        # merge_maps(ct.parameters, base_ct.parameters)
         for parameter in base_ct.parameters:
             if parameter.name in ct.parameters:
                 p = ct.parameters[parameter.name]
@@ -413,16 +470,21 @@ def merge_component_types(self, ct, base_ct):
 
         merge_maps(ct.dynamics.state_variables, base_ct.dynamics.state_variables)
         merge_maps(ct.dynamics.derived_variables, base_ct.dynamics.derived_variables)
-        merge_maps(ct.dynamics.conditional_derived_variables, base_ct.dynamics.conditional_derived_variables)
+        merge_maps(
+            ct.dynamics.conditional_derived_variables,
+            base_ct.dynamics.conditional_derived_variables,
+        )
         merge_maps(ct.dynamics.time_derivatives, base_ct.dynamics.time_derivatives)
 
-        #merge_lists(ct.dynamics.event_handlers, base_ct.dynamics.event_handlers)
+        # merge_lists(ct.dynamics.event_handlers, base_ct.dynamics.event_handlers)
 
         merge_maps(ct.dynamics.kinetic_schemes, base_ct.dynamics.kinetic_schemes)
 
         merge_lists(ct.structure.event_connections, base_ct.structure.event_connections)
         merge_lists(ct.structure.child_instances, base_ct.structure.child_instances)
-        merge_lists(ct.structure.multi_instantiates, base_ct.structure.multi_instantiates)
+        merge_lists(
+            ct.structure.multi_instantiates, base_ct.structure.multi_instantiates
+        )
 
         merge_maps(ct.simulation.runs, base_ct.simulation.runs)
         merge_maps(ct.simulation.records, base_ct.simulation.records)
@@ -441,19 +503,26 @@ def fatten_component(self, c):
         :return: Fattened component.
         :rtype: lems.model.component.FatComponent
         """
-        if self.debug: print("Fattening %s"%c.id)
+        if self.debug:
+            print("Fattening %s" % c.id)
         try:
             ct = self.component_types[c.type]
         except:
-            raise ModelError("Unable to resolve type '{0}' for component '{1}'; existing: {2}",
-                             c.type, c.id, self.component_types.keys())
+            raise ModelError(
+                "Unable to resolve type '{0}' for component '{1}'; existing: {2}",
+                c.type,
+                c.id,
+                self.component_types.keys(),
+            )
 
         fc = FatComponent(c.id, c.type)
-        if c.parent_id: fc.set_parent_id(c.parent_id)
+        if c.parent_id:
+            fc.set_parent_id(c.parent_id)
 
         ### Resolve parameters
         for parameter in ct.parameters:
-            if self.debug: print("Checking: %s"%parameter)
+            if self.debug:
+                print("Checking: %s" % parameter)
             if parameter.name in c.parameters:
                 p = parameter.copy()
                 p.value = c.parameters[parameter.name]
@@ -464,8 +533,11 @@ def fatten_component(self, c):
                 p.numeric_value = self.get_numeric_value(p.value, p.dimension)
                 fc.add_parameter(p)
             else:
-                raise ModelError("Parameter '{0}' not initialized for component '{1}'",
-                                 parameter.name, c.id)
+                raise ModelError(
+                    "Parameter '{0}' not initialized for component '{1}'",
+                    parameter.name,
+                    c.id,
+                )
 
         ### Resolve properties
         for property in ct.properties:
@@ -486,13 +558,15 @@ def fatten_component(self, c):
         ### Resolve constants
         for constant in ct.constants:
             constant2 = constant.copy()
-            constant2.numeric_value = self.get_numeric_value(constant2.value, constant2.dimension)
+            constant2.numeric_value = self.get_numeric_value(
+                constant2.value, constant2.dimension
+            )
             fc.add(constant2)
 
         ### Resolve texts
         for text in ct.texts:
             t = text.copy()
-            t.value = c.parameters[text.name] if text.name in c.parameters else ''
+            t.value = c.parameters[text.name] if text.name in c.parameters else ""
             fc.add(t)
 
         ### Resolve texts
@@ -502,8 +576,11 @@ def fatten_component(self, c):
                 l.value = c.parameters[link.name]
                 fc.add(l)
             else:
-                raise ModelError("Link parameter '{0}' not initialized for component '{1}'",
-                                 link.name, c.id)
+                raise ModelError(
+                    "Link parameter '{0}' not initialized for component '{1}'",
+                    link.name,
+                    c.id,
+                )
 
         ### Resolve paths
         for path in ct.paths:
@@ -512,18 +589,23 @@ def fatten_component(self, c):
                 p.value = c.parameters[path.name]
                 fc.add(p)
             else:
-                raise ModelError("Path parameter '{0}' not initialized for component '{1}'",
-                                 path.name, c.id)
+                raise ModelError(
+                    "Path parameter '{0}' not initialized for component '{1}'",
+                    path.name,
+                    c.id,
+                )
 
-        if len(ct.component_requirements)>0:
+        if len(ct.component_requirements) > 0:
             raise ModelError("ComponentRequirement not yet implemented in PyLEMS!")
-        if len(ct.instance_requirements)>0:
+        if len(ct.instance_requirements) > 0:
             raise ModelError("InstanceRequirement not yet implemented in PyLEMS!")
 
         ### Resolve component references.
         for cref in ct.component_references:
             if cref.local:
-                raise ModelError("Attribute local on ComponentReference not yet implemented in PyLEMS!")
+                raise ModelError(
+                    "Attribute local on ComponentReference not yet implemented in PyLEMS!"
+                )
             if cref.name in c.parameters:
                 cref2 = cref.copy()
                 cid = c.parameters[cref.name]
@@ -534,8 +616,11 @@ def fatten_component(self, c):
                 cref2.referenced_component = self.fat_components[cid]
                 fc.add(cref2)
             else:
-                raise ModelError("Component reference '{0}' not initialized for component '{1}'",
-                                 cref.name, c.id)
+                raise ModelError(
+                    "Component reference '{0}' not initialized for component '{1}'",
+                    cref.name,
+                    c.id,
+                )
 
         merge_maps(fc.exposures, ct.exposures)
         merge_maps(fc.requirements, ct.requirements)
@@ -567,46 +652,61 @@ def get_parent_component(self, fc):
         """
         TODO: Replace with more efficient way to do this...
         """
-        if self.debug: print("Looking for parent of %s (%s)"%(fc.id, fc.parent_id))
+        if self.debug:
+            print("Looking for parent of %s (%s)" % (fc.id, fc.parent_id))
         parent_comp = None
         for comp in self.components.values():
-            if self.debug: print(" - Checking "+comp.id)
+            if self.debug:
+                print(" - Checking " + comp.id)
             for child in comp.children:
                 if parent_comp == None:
                     if child.id == fc.id and comp.id == fc.parent_id:
-                        if self.debug: print("1) It is "+comp.id)
+                        if self.debug:
+                            print("1) It is " + comp.id)
                         parent_comp = comp
                     else:
                         for child2 in child.children:
-                            if self.debug: print("    - Checking child: %s, %s"%(child.id,child2.id))
-                            if parent_comp == None and child2.id == fc.id and child.id == fc.parent_id:
-                                if self.debug: print("2) It is "+child.id)
+                            if self.debug:
+                                print(
+                                    "    - Checking child: %s, %s"
+                                    % (child.id, child2.id)
+                                )
+                            if (
+                                parent_comp == None
+                                and child2.id == fc.id
+                                and child.id == fc.parent_id
+                            ):
+                                if self.debug:
+                                    print("2) It is " + child.id)
                                 parent_comp = child
                                 break
                             else:
-                                if self.debug: print("No..."   )
+                                if self.debug:
+                                    print("No...")
         return parent_comp
 
     def resolve_structure(self, fc, ct):
         """
         Resolve structure specifications.
         """
-        if self.debug: print("++++++++ Resolving structure of (%s) with %s"%(fc, ct))
+        if self.debug:
+            print("++++++++ Resolving structure of (%s) with %s" % (fc, ct))
         for w in ct.structure.withs:
             try:
-                if w.instance == 'parent' or w.instance == 'this':
+                if w.instance == "parent" or w.instance == "this":
                     w2 = With(w.instance, w.as_)
                 else:
-                    w2 = With(fc.paths[w.instance].value,
-                              w.as_)
+                    w2 = With(fc.paths[w.instance].value, w.as_)
             except:
-                raise ModelError("Unable to resolve With parameters for "
-                                 "'{0}' in component '{1}'",
-                                 w.as_, fc.id)
+                raise ModelError(
+                    "Unable to resolve With parameters for " "'{0}' in component '{1}'",
+                    w.as_,
+                    fc.id,
+                )
             fc.structure.add(w2)
 
         if len(ct.structure.tunnels) > 0:
-            raise ModelError("Tunnel is not yet supported in PyLEMS!");
+            raise ModelError("Tunnel is not yet supported in PyLEMS!")
 
         for fe in ct.structure.for_eachs:
             fc.structure.add_for_each(fe)
@@ -617,54 +717,99 @@ def resolve_structure(self, fc, ct):
                 from_inst = fc.structure.withs[ev.from_].instance
                 to_inst = fc.structure.withs[ev.to].instance
 
-                if self.debug: print("EC..: "+from_inst+" to "+to_inst+ " in "+str(fc.paths))
+                if self.debug:
+                    print(
+                        "EC..: " + from_inst + " to " + to_inst + " in " + str(fc.paths)
+                    )
 
                 if len(fc.texts) > 0 or len(fc.paths) > 0:
 
-                    source_port = fc.texts[ev.source_port].value if ev.source_port and len(ev.source_port)>0 and ev.source_port in fc.texts else None
-                    target_port = fc.texts[ev.target_port].value if ev.target_port and len(ev.target_port)>0 and ev.target_port in fc.texts else None
+                    source_port = (
+                        fc.texts[ev.source_port].value
+                        if ev.source_port
+                        and len(ev.source_port) > 0
+                        and ev.source_port in fc.texts
+                        else None
+                    )
+                    target_port = (
+                        fc.texts[ev.target_port].value
+                        if ev.target_port
+                        and len(ev.target_port) > 0
+                        and ev.target_port in fc.texts
+                        else None
+                    )
 
-                    if self.debug: print("sp: %s"%source_port)
-                    if self.debug: print("tp: %s"%target_port)
+                    if self.debug:
+                        print("sp: %s" % source_port)
+                    if self.debug:
+                        print("tp: %s" % target_port)
 
                     receiver = None
 
                     # TODO: Get more efficient way to find parent comp
-                    if '../' in ev.receiver:
+                    if "../" in ev.receiver:
                         receiver_id = None
                         parent_attr = ev.receiver[3:]
-                        if self.debug: print("Finding %s in the parent of: %s (%i)"%(parent_attr, fc, id(fc)))
+                        if self.debug:
+                            print(
+                                "Finding %s in the parent of: %s (%i)"
+                                % (parent_attr, fc, id(fc))
+                            )
 
                         for comp in self.components.values():
-                            if self.debug: print(" - Checking %s (%i)" %(comp.id,id(comp)))
+                            if self.debug:
+                                print(" - Checking %s (%i)" % (comp.id, id(comp)))
                             for child in comp.children:
-                                if self.debug: print("    - Checking %s (%i)" %(child.id,id(child)))
+                                if self.debug:
+                                    print(
+                                        "    - Checking %s (%i)" % (child.id, id(child))
+                                    )
                                 for child2 in child.children:
-                                    if child2.id == fc.id and child2.type == fc.type and child.id == fc.parent_id:
-                                        if self.debug: print("    - Got it?: %s (%i), child: %s"%(child.id, id(child), child2))
+                                    if (
+                                        child2.id == fc.id
+                                        and child2.type == fc.type
+                                        and child.id == fc.parent_id
+                                    ):
+                                        if self.debug:
+                                            print(
+                                                "    - Got it?: %s (%i), child: %s"
+                                                % (child.id, id(child), child2)
+                                            )
                                         receiver_id = child.parameters[parent_attr]
-                                        if self.debug: print("Got it: "+receiver_id)
+                                        if self.debug:
+                                            print("Got it: " + receiver_id)
                                         break
 
                         if receiver_id is not None:
                             for comp in self.fat_components:
                                 if comp.id == receiver_id:
-                                        receiver = comp
-                                        if self.debug: print("receiver is: %s"%receiver)
+                                    receiver = comp
+                                    if self.debug:
+                                        print("receiver is: %s" % receiver)
 
-                    if self.debug: print("rec1: %s"%receiver)
+                    if self.debug:
+                        print("rec1: %s" % receiver)
                     if not receiver:
-                        receiver = fc.component_references[ev.receiver].referenced_component if ev.receiver else None
-                    receiver_container = fc.texts[ev.receiver_container].value if (fc.texts and ev.receiver_container) else ''
+                        receiver = (
+                            fc.component_references[ev.receiver].referenced_component
+                            if ev.receiver
+                            else None
+                        )
+                    receiver_container = (
+                        fc.texts[ev.receiver_container].value
+                        if (fc.texts and ev.receiver_container)
+                        else ""
+                    )
 
-                    if self.debug: print("rec2: %s"%receiver)
-                    if len(receiver_container)==0:
+                    if self.debug:
+                        print("rec2: %s" % receiver)
+                    if len(receiver_container) == 0:
                         # TODO: remove this hard coded check!
-                        receiver_container = 'synapses'
+                        receiver_container = "synapses"
 
                 else:
-                    #if from_inst == 'parent':
-                        #par = fc.component_references[ev.receiver]
+                    # if from_inst == 'parent':
+                    # par = fc.component_references[ev.receiver]
 
                     if self.debug:
                         print("+++++++++++++++++++")
@@ -676,54 +821,79 @@ def resolve_structure(self, fc, ct):
                     receiver = None
                     receiver_container = None
 
-                ev2 = EventConnection(from_inst,
-                                      to_inst,
-                                      source_port,
-                                      target_port,
-                                      receiver,
-                                      receiver_container)
+                ev2 = EventConnection(
+                    from_inst,
+                    to_inst,
+                    source_port,
+                    target_port,
+                    receiver,
+                    receiver_container,
+                )
                 if self.debug:
-                    print("Created EC: "+ev2.toxml())
+                    print("Created EC: " + ev2.toxml())
                     print(receiver)
                     print(receiver_container)
             except:
                 logging.exception("Something awful happened!")
-                raise ModelError("Unable to resolve event connection parameters in component '{0}'",fc)
+                raise ModelError(
+                    "Unable to resolve event connection parameters in component '{0}'",
+                    fc,
+                )
             fc.structure.add(ev2)
 
         for ch in ct.structure.child_instances:
             try:
-                if self.debug: print(ch.toxml())
-                if '../' in ch.component:
+                if self.debug:
+                    print(ch.toxml())
+                if "../" in ch.component:
                     parent = self.get_parent_component(fc)
-                    if self.debug: print("Parent: %s"%parent)
+                    if self.debug:
+                        print("Parent: %s" % parent)
                     comp_ref = ch.component[3:]
-                    if self.debug: print("comp_ref: %s"%comp_ref)
+                    if self.debug:
+                        print("comp_ref: %s" % comp_ref)
                     comp_id = parent.parameters[comp_ref]
                     comp = self.fat_components[comp_id]
                     ch2 = ChildInstance(ch.component, comp)
                 else:
-                    ref_comp = fc.component_references[ch.component].referenced_component
+                    ref_comp = fc.component_references[
+                        ch.component
+                    ].referenced_component
                     ch2 = ChildInstance(ch.component, ref_comp)
             except Exception as e:
-                if self.debug: print(e)
-                raise ModelError("Unable to resolve child instance parameters for "
-                                 "'{0}' in component '{1}'",
-                                 ch.component, fc.id)
+                if self.debug:
+                    print(e)
+                raise ModelError(
+                    "Unable to resolve child instance parameters for "
+                    "'{0}' in component '{1}'",
+                    ch.component,
+                    fc.id,
+                )
             fc.structure.add(ch2)
 
         for mi in ct.structure.multi_instantiates:
             try:
                 if mi.component:
-                    mi2 = MultiInstantiate(component=fc.component_references[mi.component].referenced_component,
-                                           number=int(fc.parameters[mi.number].numeric_value))
+                    mi2 = MultiInstantiate(
+                        component=fc.component_references[
+                            mi.component
+                        ].referenced_component,
+                        number=int(fc.parameters[mi.number].numeric_value),
+                    )
                 else:
-                    mi2 = MultiInstantiate(component_type=fc.component_references[mi.component_type].referenced_component,
-                                           number=int(fc.parameters[mi.number].numeric_value))
+                    mi2 = MultiInstantiate(
+                        component_type=fc.component_references[
+                            mi.component_type
+                        ].referenced_component,
+                        number=int(fc.parameters[mi.number].numeric_value),
+                    )
             except:
-                raise ModelError("Unable to resolve multi-instantiate parameters for "
-                                 "'{0}' in component '{1}'",
-                                 mi.component, fc)
+                raise ModelError(
+                    "Unable to resolve multi-instantiate parameters for "
+                    "'{0}' in component '{1}'",
+                    mi.component,
+                    fc,
+                )
             fc.structure.add(mi2)
 
     def resolve_simulation(self, fc, ct):
@@ -733,73 +903,89 @@ def resolve_simulation(self, fc, ct):
 
         for run in ct.simulation.runs:
             try:
-                run2 = Run(fc.component_references[run.component].referenced_component,
-                           run.variable,
-                           fc.parameters[run.increment].numeric_value,
-                           fc.parameters[run.total].numeric_value)
+                run2 = Run(
+                    fc.component_references[run.component].referenced_component,
+                    run.variable,
+                    fc.parameters[run.increment].numeric_value,
+                    fc.parameters[run.total].numeric_value,
+                )
             except:
-                raise ModelError("Unable to resolve simulation run parameters in component '{0}'",
-                                 fc.id)
+                raise ModelError(
+                    "Unable to resolve simulation run parameters in component '{0}'",
+                    fc.id,
+                )
             fc.simulation.add(run2)
 
         for record in ct.simulation.records:
             try:
-                record2 = Record(fc.paths[record.quantity].value,
-                                 fc.parameters[record.scale].numeric_value if record.scale else 1,
-                                 fc.texts[record.color].value if record.color else '#000000')
+                record2 = Record(
+                    fc.paths[record.quantity].value,
+                    fc.parameters[record.scale].numeric_value if record.scale else 1,
+                    fc.texts[record.color].value if record.color else "#000000",
+                )
             except:
-                raise ModelError("Unable to resolve simulation record parameters in component '{0}'",
-                                 fc.id)
+                raise ModelError(
+                    "Unable to resolve simulation record parameters in component '{0}'",
+                    fc.id,
+                )
             fc.simulation.add(record2)
 
         for event_record in ct.simulation.event_records:
             try:
-                event_record2 = EventRecord(fc.paths[event_record.quantity].value,
-                                 fc.texts[event_record.eventPort].value)
+                event_record2 = EventRecord(
+                    fc.paths[event_record.quantity].value,
+                    fc.texts[event_record.eventPort].value,
+                )
             except:
-                raise ModelError("Unable to resolve simulation event_record parameters in component '{0}'",
-                                 fc.id)
+                raise ModelError(
+                    "Unable to resolve simulation event_record parameters in component '{0}'",
+                    fc.id,
+                )
             fc.simulation.add(event_record2)
 
         for dd in ct.simulation.data_displays:
             try:
-                dd2 = DataDisplay(fc.texts[dd.title].value,
-                                  '')
-                if 'timeScale' in fc.parameters:
-                    dd2.timeScale = fc.parameters['timeScale'].numeric_value
+                dd2 = DataDisplay(fc.texts[dd.title].value, "")
+                if "timeScale" in fc.parameters:
+                    dd2.timeScale = fc.parameters["timeScale"].numeric_value
             except:
-                raise ModelError("Unable to resolve simulation display parameters in component '{0}'",
-                                 fc.id)
+                raise ModelError(
+                    "Unable to resolve simulation display parameters in component '{0}'",
+                    fc.id,
+                )
             fc.simulation.add(dd2)
 
         for dw in ct.simulation.data_writers:
             try:
-                path = '.'
+                path = "."
                 if fc.texts[dw.path] and fc.texts[dw.path].value:
                     path = fc.texts[dw.path].value
 
-                dw2 = DataWriter(path,
-                                 fc.texts[dw.file_name].value)
+                dw2 = DataWriter(path, fc.texts[dw.file_name].value)
             except:
-                raise ModelError("Unable to resolve simulation writer parameters in component '{0}'",
-                                 fc.id)
+                raise ModelError(
+                    "Unable to resolve simulation writer parameters in component '{0}'",
+                    fc.id,
+                )
             fc.simulation.add(dw2)
 
         for ew in ct.simulation.event_writers:
             try:
-                path = '.'
+                path = "."
                 if fc.texts[ew.path] and fc.texts[ew.path].value:
                     path = fc.texts[ew.path].value
 
-                ew2 = EventWriter(path,
-                                 fc.texts[ew.file_name].value,
-                                 fc.texts[ew.format].value)
+                ew2 = EventWriter(
+                    path, fc.texts[ew.file_name].value, fc.texts[ew.format].value
+                )
             except:
-                raise ModelError("Unable to resolve simulation writer parameters in component '{0}'",
-                                 fc.id)
+                raise ModelError(
+                    "Unable to resolve simulation writer parameters in component '{0}'",
+                    fc.id,
+                )
             fc.simulation.add(ew2)
 
-    def get_numeric_value(self, value_str, dimension = None):
+    def get_numeric_value(self, value_str, dimension=None):
         """
         Get the numeric value for a parameter value specification.
 
@@ -819,37 +1005,114 @@ def get_numeric_value(self, value_str, dimension = None):
                 n = nn
                 s = value_str[i:]
             except ValueError:
-                i = i-1
+                i = i - 1
 
         number = n
         sym = s
 
         numeric_value = None
 
-        if sym == '':
+        if sym == "":
             numeric_value = number
         else:
             if sym in self.units:
                 unit = self.units[sym]
                 if dimension:
-                    if dimension != unit.dimension and dimension != '*':
-                        raise SimBuildError("Unit symbol '{0}' cannot "
-                                            "be used for dimension '{1}'",
-                                            sym, dimension)
+                    if dimension != unit.dimension and dimension != "*":
+                        raise SimBuildError(
+                            "Unit symbol '{0}' cannot " "be used for dimension '{1}'",
+                            sym,
+                            dimension,
+                        )
                 else:
                     dimension = unit.dimension
 
                 numeric_value = (number * (10 ** unit.power) * unit.scale) + unit.offset
             else:
-                raise SimBuildError("Unknown unit symbol '{0}'. Known: {1}",
-                                    sym, self.units)
+                raise SimBuildError(
+                    "Unknown unit symbol '{0}'. Known: {1}", sym, self.units
+                )
 
-        #print("Have converted %s to value: %s, dimension %s"%(value_str, numeric_value, dimension))
+        # print("Have converted %s to value: %s, dimension %s"%(value_str, numeric_value, dimension))
         return numeric_value
 
-    def list_exposures(self, substring=None):
-        # type: (str) -> Dict[Component, List[Exposure]]
-        """Get exposures from model.
+    def get_component_list(self, substring=""):
+        # type: (str) -> Dict[str, Component]
+        """Get all components whose id matches the given substring.
+
+        Note that in PyLEMS, if a component does not have an id attribute,
+        PyLEMS uses the name of the component as its ID.
+        See the parser methods in LEMSFileParser.
+
+        This function is required because the component and fat_component
+        attribute of the model class only holds lists of the top level
+        components and not its child/children elements. So we need to manually
+        fetch them.
+
+        :param substring: substring to match components against
+        :type substring: str
+        :returns: Dict of components matching the substring of the form {'id' : Component }
+
+        """
+        comp_list = {}
+        ret_list = {}
+        # For each top level component, recursively get to all children
+        # There is no advantage of resolving the model and using fat_components
+        # here. They do store a component's "children" but as `Children`
+        # objects and one cannot easily recursively descend the tree using
+        # them. So it is easier to use (non-fat) components here, which hold
+        # children as `Component` objects.
+        for comp in self.components:
+            comp_list.update(self.get_nested_components(comp))
+
+        for c in comp_list.values():
+            if substring in c.id:
+                ret_list.update({c.id: c})
+
+        return ret_list
+
+    def get_fattened_component_list(self, substring=""):
+        # type: (str) -> Map
+        """Get a list of fattened components whose ids include the substring.
+
+        A "fattened component" is one where all elements of the components have
+        been resolved. See lems.model.component.FatComponent.
+
+        :param substring: substring to match components against
+        :type substring: str
+        :returns: Map of fattened components matching the substring
+
+        """
+        resolved_model = self.resolve()
+        fattened_comp_list = Map()
+
+        comp_list = resolved_model.get_component_list(substring).values()
+        for comp in comp_list:
+            fattened_comp_list[comp.id] = resolved_model.fatten_component(comp)
+
+        return fattened_comp_list
+
+    def get_nested_components(self, comp):
+        # type: (Component) -> Dict[str, Component]
+        """Get all nested (child/children) components in the comp component
+
+        :param comp: component to get all nested (child/children) components for
+        :type comp: Component
+        :returns: list of components
+
+        """
+        comp_list = {}
+        comp_list.update({comp.id: comp})
+
+        for c in comp.children:
+            comp_list.update(self.get_nested_components(c))
+
+        return comp_list
+
+    def list_exposures(self, substring=""):
+        # type: (str) -> Dict[FatComponent, Map]
+        """Get exposures from model belonging to components which contain the
+        given substring.
 
         :param substring: substring to match for in component names
         :type substring: str
@@ -862,50 +1125,266 @@ def list_exposures(self, substring=None):
 
         """
         exposures = {}
-        comp_list = []
-        if substring:
-            for comp in self.components:
-                if substring in comp.id:
-                    comp_list.append(comp)
-        else:
-            comp_list = self.components
+        comp_list = self.get_fattened_component_list(substring)
 
-        for comp in comp_list:
+        for comp in comp_list.values():
+            cur_type = self.component_types[comp.type]
+            allexps = Map()
+            # Add exposures of the component type itself
             try:
-                exposures[comp] = self.component_types[comp.type].exposures
+                allexps.update(self.component_types[comp.type].exposures)
             except KeyError:
-                pass  # found a component without any exposures
+                if self.debug:
+                    print("No exposures found for {}".format(comp.type))
+
+            # Also get exposures inherited from parents
+            while cur_type.extends:
+                parent = cur_type.extends
+                try:
+                    allexps.update(self.component_types[parent].exposures)
+                except KeyError:
+                    if self.debug:
+                        print("No exposures found for {}".format(parent.type))
+                cur_type = self.component_types[parent]
+            exposures[comp] = allexps
+
         return exposures
 
-    def get_recording_path(self, comp, exposures):
-        # type: (Component, List[Exposure]) -> List[str]
-        """Create recording path from a component and its list of exposures.
+    def get_full_comp_paths_with_comp_refs(self, comp, comptext=None):
+        # type: (FatComponent, Union[None, str]) -> None
+        """Get list of component paths with all component references also
+        resolved for the given component `comp`.
 
-        :param comp: component
+        This does not return a value, but fills in self.temp_vec with all the
+        possible paths as individual lists. These can then be passed to the
+        construct_path method to construct string paths.
+
+        Additionally, note that this generates paths from the model
+        declaration, not from a built simulation instance of the model.
+        Therefore, it does not find paths that are constructed during build
+        time.
+
+        XXX: should this be converted to a private method?
+
+        :param comp: Component to get all paths for
         :type comp: Component
-        :param exposures: list of exposures
-        :type exposures: [Exposure]
-        :returns: list of strings, one for each recording path
+        :param comptext: text to use for component (used for generation of path strings)
+        :type comptext: str
 
         """
-        retlist = []
-        for exposure in exposures:
-            retlist.append(comp.id + "/" + exposure.name)
-        return retlist
-
-    def list_recording_paths(self, substring=None):
-        # type: (str) -> List[str]
-        """Get the recording path strings for exposures of matching component
-        ids.
+        debug = False
+        # ref_map = self.get_comp_ref_map()
+        fat_components = self.get_fattened_component_list()
+        if debug:
+            print("Processing {}".format(comp.id))
+        self.temp_vec.append(comp.id)
+        if comptext:
+            if debug:
+                print("for {}, text given: {}".format(comp.id, comptext))
+            self.path_vec.append(comptext)
+        else:
+            self.path_vec.append(comp.id)
+
+        # proceed further in the tree
+        nextchildren = []
+        # check if any children components are used in the model for this comp
+        for ch in comp.children:
+            if ch.name in fat_components:
+                nextchildren.append(fat_components[ch.name])
+                if debug:
+                    print(
+                        "children {} for {} added".format(
+                            fat_components[ch.name], comp.id
+                        )
+                    )
+        # check if any child components are used in the model for this comp
+        nextchild = []
+        for cc in comp.child_components:
+            if cc.id in fat_components:
+                nextchild.append(cc)
+                if debug:
+                    print("child {} for {} added".format(cc, comp.id))
+
+        nextattachment = []
+        # attachments
+        # TODO: not sure what function these serve before build time
+        for at in comp.attachments:
+            if at.name in fat_components:
+                nextattachment.append(fat_components[at.name])
+                if debug:
+                    print("attachment {} for {} added".format(cc, comp.id))
+
+        # structure
+        # multi instantiates
+        nextmi = []
+        for mi in comp.structure.multi_instantiates:
+            # replace comp with comp[*] for each multi instantiated comp
+            self.path_vec[-1] = "SKIP"
+            for mi_n in range(mi.number):
+                nextmi.append(mi.component)
+            if debug:
+                print("MI {} for {} added".format(mi.component.id, comp.id))
+        # child instances
+        nextci = []
+        for ci in comp.structure.child_instances:
+            nextci.append(ci.referenced_component)
+            if debug:
+                print("CI {} for {} added".format(ci.referenced_component.id, comp.id))
+        # nothing to be done for Withs
+        # event connections: note: when the simulation is built, the event
+        # connections are processes and the sources attached to the necessary
+        # target instances. Since we are not building the simulation here, we
+        # cannot list the exposures from event connection inputs at the target
+        # instances.
+        nextec = []
+        for ec in comp.structure.event_connections:
+            nextec.append(fat_components[ec.receiver.id])
+            if debug:
+                print("EC {} appended for {}".format(ec.receiver.id, comp.id))
+
+        # a leaf node
+        if (
+            not len(nextchildren)
+            and not len(nextchild)
+            and not len(nextattachment)
+            and not len(nextmi)
+            and not len(nextci)
+            and not len(nextec)
+        ):
+            if debug:
+                print("{} is leaf".format(comp.id))
+                print("Append {} to recording_paths".format(self.temp_vec))
+                print("Append {} to recording_paths_text".format(self.path_vec))
+            # append a copy since the path_vec is emptied out each time
+            self.recording_paths.append(copy.deepcopy(self.temp_vec))
+            self.recording_paths_text.append(copy.deepcopy(self.path_vec))
+            self.temp_vec.pop()
+            self.path_vec.pop()
+            return
+
+        # process all next level nodes
+        for nextnode in nextchildren + nextchild:
+            self.get_full_comp_paths_with_comp_refs(nextnode)
+        for nextnode in nextattachment:
+            self.get_full_comp_paths_with_comp_refs(nextnode, "SKIP")
+        i = 0
+        for nextnode in nextmi:
+            self.get_full_comp_paths_with_comp_refs(
+                nextnode, "{}[{}]".format(comp.id, i)
+            )
+            i += 1
+        for nextnode in nextci:
+            self.get_full_comp_paths_with_comp_refs(nextnode, "SKIP")
+        for nextnode in nextec:
+            self.get_full_comp_paths_with_comp_refs(nextnode)
+
+        self.temp_vec.pop()
+        self.path_vec.pop()
+
+    def construct_path(self, pathlist, skip=None):
+        # type: (List[str], str) -> str
+        """Construct path from a list.
+
+        :param vec: list of text strings to generate path from
+        :type vec: list(str)
+        :param skip: text strings to skip
+        :type skip: str
+        :returns: generated path string
 
-        :param substring: substring to match component ids against
+        """
+        # remove "", which are components we don't want to include in the path
+        if skip:
+            while skip in pathlist:
+                pathlist.remove(skip)
+        return "/".join(pathlist)
+
+    def list_recording_paths_for_exposures(self, substring="", target=""):
+        # (str, str) -> List[str]
+        """List recording paths for exposures in the model for components
+        matching the given substring, and for the given simulation target.
+
+        This is a helper method that will generate *all* recording paths for
+        exposures in the provided LEMS model. Since a detailed model may
+        include many paths, it is suggested to use the `substring` parameter to
+        limit the list to necessary components only.
+
+        Please note that this uses only the declared model, and not a built
+        instance of the model. Therefore, it returns a subset of all possible
+        paths.
+
+        :param substring: substring to match component IDs against
         :type substring: str
-        :returns: list of recording paths
-
+        :param target: simulation target whose components are to be analysed
+        :type target: str
+        :return: list of generated path strings
         """
-        recording_paths = []
+        if not len(target):
+            print("Please provide a target element.")
+            return []
+
         exposures = self.list_exposures(substring)
+        resolved_comps = self.get_fattened_component_list()
+        target_comp = self.get_fattened_component_list(target)
+        if len(target_comp) != 1:
+            print("Multiple targets found. Please use a unique target name")
+            return []
+
+        if self.debug:
+            print(resolved_comps)
+        # temporary for the depth first search
+        self.temp_vec = []
+        self.path_vec = []
+        # store our recording paths
+        # this stores the comp.ids
+        self.recording_paths = []
+        self.recording_paths_text = []
+        target_comp = resolved_comps[target]
+        self.get_full_comp_paths_with_comp_refs(target_comp)
+
+        exp_paths = []
+        for r in range(len(self.recording_paths)):
+            p = self.recording_paths[r]
+            t = self.recording_paths_text[r]
+            # go over each element, appending exposures where needed
+            for i in range(len(p)):
+                compid = p[i]
+                comppath = t[0 : i + 1]
+                for acomp, exps in exposures.items():
+                    if acomp.id == compid:
+                        for exp in exps:
+                            if self.debug:
+                                print(
+                                    "full comppath is {}".format(comppath + [exp.name])
+                                )
+                            newpath = self.construct_path(comppath + [exp.name], "SKIP")
+                            if newpath not in exp_paths:
+                                exp_paths.append(newpath)
+                else:
+                    if self.debug:
+                        print("No exposures for {}".format(p[i]))
+                    pass
 
-        for comp, exps in exposures.items():
-            recording_paths.extend(self.get_recording_path(comp, exps))
-        return recording_paths
+        exp_paths.sort()
+        if self.debug:
+            print("\n".join(exp_paths))
+        return exp_paths
+
+    def get_comp_ref_map(self):
+        # type () -> Map[str, List[FatComponent]]
+        """Get a Map of ComponentReferences in the model.
+
+        :returns: Map with target -> [source] entries
+        """
+        if self.comp_ref_map:
+            return self.comp_ref_map
+
+        fat_components = self.get_fattened_component_list()
+
+        self.comp_ref_map = Map()
+        for fc in fat_components.values():
+            for cr in fc.component_references.values():
+                try:
+                    self.comp_ref_map[cr.referenced_component.id].append(fc)
+                except KeyError:
+                    self.comp_ref_map[cr.referenced_component.id] = [fc]
+        return self.comp_ref_map
diff --git a/lems/model/simulation.py b/lems/model/simulation.py
index 500d83e..eece19f 100644
--- a/lems/model/simulation.py
+++ b/lems/model/simulation.py
@@ -9,6 +9,7 @@
 from lems.base.errors import ModelError
 from lems.base.map import Map
 
+
 class Run(LEMSBase):
     """
     Stores the description of an object to be run according to an independent
@@ -45,27 +46,29 @@ def toxml(self):
         Exports this object into a LEMS XML object
         """
 
-        return '<Run component="{0}" variable="{1}" increment="{2}" total="{3}"/>'.format(self.component,
-                                                                                          self.variable,
-                                                                                          self.increment,
-                                                                                          self.total)
+        return (
+            '<Run component="{0}" variable="{1}" increment="{2}" total="{3}"/>'.format(
+                self.component, self.variable, self.increment, self.total
+            )
+        )
+
 
 class Record(LEMSBase):
     """
     Stores the parameters of a <Record> statement.
     """
 
-    def __init__(self, quantity, scale = None, color = None, id = None):
+    def __init__(self, quantity, scale=None, color=None, id=None):
         """
         Constructor.
 
         See instance variable documentation for information on parameters.
         """
 
-        self.id = ''
+        self.id = ""
         """ Id of the quantity
         :type: str """
-        
+
         self.quantity = quantity
         """ Path to the quantity to be recorded.
         :type: str """
@@ -87,10 +90,11 @@ def toxml(self):
         Exports this object into a LEMS XML object
         """
 
-        return '<Record quantity="{0}" scale="{1}" color="{2}" id="{3}"/>'.format(self.quantity,
-                                                                         self.scale,
-                                                                         self.color,
-                                                                         self.id)
+        return '<Record quantity="{0}" scale="{1}" color="{2}" id="{3}"/>'.format(
+            self.quantity, self.scale, self.color, self.id
+        )
+
+
 class EventRecord(LEMSBase):
     """
     Stores the parameters of an <EventRecord> statement.
@@ -103,10 +107,10 @@ def __init__(self, quantity, eventPort):
         See instance variable documentation for information on parameters.
         """
 
-        self.id = ''
+        self.id = ""
         """ Id of the quantity
         :type: str """
-        
+
         self.quantity = quantity
         """ Path to the quantity to be recorded.
         :type: str """
@@ -120,8 +124,10 @@ def toxml(self):
         Exports this object into a LEMS XML object
         """
 
-        return '<EventRecord quantity="{0}" eventPort="{1}"/>'.format(self.quantity,
-                                                                         self.eventPort)
+        return '<EventRecord quantity="{0}" eventPort="{1}"/>'.format(
+            self.quantity, self.eventPort
+        )
+
 
 class DataOutput(LEMSBase):
     """
@@ -135,6 +141,7 @@ def __init__(self):
 
         pass
 
+
 class DataDisplay(DataOutput):
     """
     Stores specification for a data display.
@@ -160,14 +167,16 @@ def __init__(self, title, data_region):
         self.time_scale = 1
         """ Time scale
         :type: Number """
-        
+
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        return '<DataDisplay title="{0}" dataRegion="{1}"/>'.format(self.title,
-                                                                    self.data_region)
+        return '<DataDisplay title="{0}" dataRegion="{1}"/>'.format(
+            self.title, self.data_region
+        )
+
 
 class DataWriter(DataOutput):
     """
@@ -182,7 +191,7 @@ def __init__(self, path, file_name):
         """
 
         DataOutput.__init__(self)
-        
+
         self.path = path
         """ Path to the quantity to be saved to file.
         :type: string """
@@ -191,19 +200,19 @@ def __init__(self, path, file_name):
         """ Text parameter to be used for the file name
         :type: string """
 
-
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        return '<DataWriter path="{0}" fileName="{1}"/>'.format(self.path,
-                                                                self.file_name)
-                                                                
+        return '<DataWriter path="{0}" fileName="{1}"/>'.format(
+            self.path, self.file_name
+        )
+
     def __str__(self):
-        return 'DataWriter, path: {0}, fileName: {1}'.format(self.path, self.file_name)
-    
-    
+        return "DataWriter, path: {0}, fileName: {1}".format(self.path, self.file_name)
+
+
 class EventWriter(DataOutput):
     """
     Stores specification for an event writer.
@@ -217,7 +226,7 @@ def __init__(self, path, file_name, format):
         """
 
         DataOutput.__init__(self)
-        
+
         self.path = path
         """ Path to the quantity to be saved to file.
         :type: string """
@@ -230,18 +239,19 @@ def __init__(self, path, file_name, format):
         """ Text parameter to be used for the format
         :type: string """
 
-
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        return '<EventWriter path="{0}" fileName="{1}" format="{2}"/>'.format(self.path,
-                                                                self.file_name, self.format)
-                                                                
-    def __str__(self):
-        return 'EventWriter, path: {0}, fileName: {1}, format: {2}'.format(self.path, self.file_name, self.format)
+        return '<EventWriter path="{0}" fileName="{1}" format="{2}"/>'.format(
+            self.path, self.file_name, self.format
+        )
 
+    def __str__(self):
+        return "EventWriter, path: {0}, fileName: {1}, format: {2}".format(
+            self.path, self.file_name, self.format
+        )
 
 
 class Simulation(LEMSBase):
@@ -361,14 +371,14 @@ def add(self, child):
         elif isinstance(child, EventWriter):
             self.add_event_writer(child)
         else:
-            raise ModelError('Unsupported child element')
-        
+            raise ModelError("Unsupported child element")
+
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        chxmlstr = ''
+        chxmlstr = ""
 
         for run in self.runs:
             chxmlstr += run.toxml()
@@ -389,8 +399,8 @@ def toxml(self):
             chxmlstr += event_writer.toxml()
 
         if chxmlstr:
-            xmlstr = '<Simulation>' + chxmlstr + '</Simulation>'
+            xmlstr = "<Simulation>" + chxmlstr + "</Simulation>"
         else:
-            xmlstr = ''
+            xmlstr = ""
 
         return xmlstr
diff --git a/lems/model/structure.py b/lems/model/structure.py
index 31fa2ee..de75a35 100644
--- a/lems/model/structure.py
+++ b/lems/model/structure.py
@@ -9,6 +9,7 @@
 from lems.base.map import Map
 from lems.base.errors import ModelError
 
+
 class With(LEMSBase):
     """
     Stores a with-as statement.
@@ -17,7 +18,7 @@ class With(LEMSBase):
     def __init__(self, instance, as_, list=None, index=None):
         """
         Constructor referencing single identified instance, or list/index.
-        
+
         """
 
         self.instance = instance
@@ -35,20 +36,21 @@ def __init__(self, instance, as_, list=None, index=None):
         self.index = index
         """ index in list to be referenced.
         :type: str """
-        
 
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        return '<With ' + \
-          (' instance="{0}"'.format(self.instance) if self.instance else '') +\
-          (' list="{0}"'.format(self.list) if self.list else '') + \
-          (' index="{0}"'.format(self.index) if self.index else '') + \
-          ' as="{1}"/>'.format(self.instance, self.as_)
-          
-          
+        return (
+            "<With "
+            + (' instance="{0}"'.format(self.instance) if self.instance else "")
+            + (' list="{0}"'.format(self.list) if self.list else "")
+            + (' index="{0}"'.format(self.index) if self.index else "")
+            + ' as="{1}"/>'.format(self.instance, self.as_)
+        )
+
+
 class Tunnel(LEMSBase):
     """
     Stores a Tunnel.
@@ -57,7 +59,7 @@ class Tunnel(LEMSBase):
     def __init__(self, name, end_a, end_b, component_a, component_b):
         """
         Constructor.
-        
+
         """
 
         self.name = name
@@ -75,35 +77,37 @@ def __init__(self, name, end_a, end_b, component_a, component_b):
         self.component_a = component_a
         """ Component to create at A.
         :type: str """
-        
+
         self.component_b = component_b
         """ Component to create at B.
         :type: str """
 
-        
-
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        return '<Tunnel name="{0}"'.format(self.name) + \
-               ' endA="{0}"'.format(self.end_a) + \
-               ' endB="{0}"'.format(self.end_b) + \
-               ' componentA="{0}"'.format(self.component_a) + \
-               ' componentB="{0}"'.format(self.component_b) + '/>'
+        return (
+            '<Tunnel name="{0}"'.format(self.name)
+            + ' endA="{0}"'.format(self.end_a)
+            + ' endB="{0}"'.format(self.end_b)
+            + ' componentA="{0}"'.format(self.component_a)
+            + ' componentB="{0}"'.format(self.component_b)
+            + "/>"
+        )
+
 
 class EventConnection(LEMSBase):
     """
     Stores an event connection specification.
     """
 
-    def __init__(self, from_, to, 
-                 source_port, target_port,
-                 receiver, receiver_container):
+    def __init__(
+        self, from_, to, source_port, target_port, receiver, receiver_container
+    ):
         """
         Constructor.
-        
+
         See instance variable documentation for more details on parameters.
         """
 
@@ -124,41 +128,51 @@ def __init__(self, from_, to,
         :type: str """
 
         self.receiver = receiver
-        """ Name of the proxy receiver component attached to the target component that actually receiving the event.
-        :type: str """
+        """ Proxy receiver component attached to the target component that actually receiving the event.
+        :type: Component """
 
         self.receiver_container = receiver_container
         """ Name of the child component grouping to add the receiver to.
         :type: str """
 
     def __eq__(self, o):
-        return (self.from_ == o.from_ and self.to == o.to and
-                self.source_port == o.source_port and self.target_port == o.target_port)
-
+        return (
+            self.from_ == o.from_
+            and self.to == o.to
+            and self.source_port == o.source_port
+            and self.target_port == o.target_port
+        )
 
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        return '<EventConnection' +\
-          (' from="{0}"'.format(self.from_) if self.from_ else '') +\
-          (' to="{0}"'.format(self.to) if self.to else '') +\
-          (' sourcePort="{0}"'.format(self.source_port) if self.source_port else '') +\
-          (' targetPort="{0}"'.format(self.target_port) if self.target_port else '') +\
-          (' receiver="{0}"'.format(self.receiver) if self.receiver else '') +\
-          (' receiverContainer="{0}"'.format(self.receiver_container) if self.receiver_container else '') +\
-          '/>'
+        return (
+            "<EventConnection"
+            + (' from="{0}"'.format(self.from_) if self.from_ else "")
+            + (' to="{0}"'.format(self.to) if self.to else "")
+            + (' sourcePort="{0}"'.format(self.source_port) if self.source_port else "")
+            + (' targetPort="{0}"'.format(self.target_port) if self.target_port else "")
+            + (' receiver="{0}"'.format(self.receiver) if self.receiver else "")
+            + (
+                ' receiverContainer="{0}"'.format(self.receiver_container)
+                if self.receiver_container
+                else ""
+            )
+            + "/>"
+        )
+
 
 class ChildInstance(LEMSBase):
     """
     Stores a child instantiation specification.
     """
 
-    def __init__(self, component, referenced_component = None):
+    def __init__(self, component, referenced_component=None):
         """
         Constructor.
-        
+
         See instance variable documentation for more details on parameters.
         """
 
@@ -169,7 +183,7 @@ def __init__(self, component, referenced_component = None):
         self.referenced_component = referenced_component
         """ Target component being referenced after resolution.
         :type: lems.model.component.FatComponent """
-        
+
     def __eq__(self, o):
         return self.component == o.component
 
@@ -180,6 +194,7 @@ def toxml(self):
 
         return '<ChildInstance component="{0}"/>'.format(self.component)
 
+
 class Assign(LEMSBase):
     """
     Stores a child assign specification.
@@ -188,7 +203,7 @@ class Assign(LEMSBase):
     def __init__(self, property, value):
         """
         Constructor.
-        
+
         See instance variable documentation for more details on parameters.
         """
 
@@ -218,13 +233,15 @@ class MultiInstantiate(LEMSBase):
     def __init__(self, component=None, number=None, component_type=None):
         """
         Constructor.
-        
+
         See instance variable documentation for more details on parameters.
         """
         if component and component_type:
-            raise AttributeError("MultiInstantiate should contain either"
-                                 " an attribute component or an attribute"
-                                 " component_type, not both.")
+            raise AttributeError(
+                "MultiInstantiate should contain either"
+                " an attribute component or an attribute"
+                " component_type, not both."
+            )
 
         self.component = component
         """ Name of the component reference to be used for instantiation.
@@ -242,7 +259,7 @@ def __init__(self, component=None, number=None, component_type=None):
         self.assignments = []
         """ List of assignments included in MultiInstantiate.
         :type: list(Assign) """
-        
+
     def __eq__(self, o):
         if self.component:
             flag = self.component == o.component and self.number == o.number
@@ -269,13 +286,13 @@ def add(self, child):
         if isinstance(child, Assign):
             self.add_assign(child)
         else:
-            raise ModelError('Unsupported child element')
+            raise ModelError("Unsupported child element")
 
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
-        argstr = ''
+        argstr = ""
         if self.component:
             argstr += 'component="{0}" '.format(self.component)
         if self.component_type:
@@ -283,32 +300,35 @@ def toxml(self):
         if self.number:
             argstr += 'number="{0}" '.format(self.number)
         if self.assignments:
-            chxmlstr = ''
+            chxmlstr = ""
             for assign in self.assignments:
                 chxmlstr += assign.toxml()
-            return '<MultiInstantiate {0}>{1}</MultiInstantiate>'.format(argstr, chxmlstr)
+            return "<MultiInstantiate {0}>{1}</MultiInstantiate>".format(
+                argstr, chxmlstr
+            )
         else:
-            return '<MultiInstantiate {0}/>'.format(argstr)
+            return "<MultiInstantiate {0}/>".format(argstr)
+
 
 class ForEach(LEMSBase):
     """
     ForEach specification.
     """
+
     def __init__(self, instances, as_):
 
         self.instances = instances
-        
+
         self.as_ = as_
-        
+
         self.event_connections = list()
         """ List of event connections.
         :type: list(lems.model.structure.EventConnection) """
-        
+
         self.for_eachs = list()
         """ List of for each specs.
         :type: list(lems.model.structure.ForEach) """
-        
-        
+
     def add_for_each(self, fe):
         """
         Adds a for-each specification.
@@ -318,8 +338,7 @@ def add_for_each(self, fe):
         """
 
         self.for_eachs.append(fe)
-        
-        
+
     def add_event_connection(self, ec):
         """
         Adds an event conenction to the structure.
@@ -329,12 +348,12 @@ def add_event_connection(self, ec):
         """
 
         self.event_connections.append(ec)
-        
+
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
-        chxmlstr = ''
+        chxmlstr = ""
 
         for event_connection in self.event_connections:
             chxmlstr += event_connection.toxml()
@@ -342,10 +361,11 @@ def toxml(self):
         for for_each in self.for_eachs:
             chxmlstr += for_each.toxml()
 
+        return '<ForEach instances="{0}" as="{1}">{2}</ForEach>'.format(
+            self.instances, self.as_, chxmlstr
+        )
+
 
-        return '<ForEach instances="{0}" as="{1}">{2}</ForEach>'.format(self.instances, self.as_, chxmlstr)
-        
-        
 class Structure(LEMSBase):
     """
     Stores structural properties of a component type.
@@ -359,7 +379,7 @@ def __init__(self):
         self.withs = Map()
         """ Map of With statements.
         :type: Map(str -> lems.model.structure.With) """
-        
+
         self.tunnels = Map()
         """ Map of tunnel statements.
         :type: Map(str -> lems.model.structure.Tunnel) """
@@ -379,14 +399,16 @@ def __init__(self):
         self.for_eachs = list()
         """ List of for each specs.
         :type: list(lems.model.structure.ForEach) """
-        
+
     def has_content(self):
-        if len(self.withs)==0 and \
-           len(self.event_connections)==0 and \
-           len(self.child_instances)==0 and \
-           len(self.multi_instantiates)==0 and \
-           len(self.for_eachs)==0:
-               return False
+        if (
+            len(self.withs) == 0
+            and len(self.event_connections) == 0
+            and len(self.child_instances) == 0
+            and len(self.multi_instantiates) == 0
+            and len(self.for_eachs) == 0
+        ):
+            return False
         else:
             return True
 
@@ -409,7 +431,7 @@ def add_tunnel(self, tunnel):
         """
 
         self.tunnels[tunnel.name] = tunnel
-        
+
     def add_event_connection(self, ec):
         """
         Adds an event conenction to the structure.
@@ -468,13 +490,13 @@ def add(self, child):
         elif isinstance(child, ForEach):
             self.add_for_each(child)
         else:
-            raise ModelError('Unsupported child element')
+            raise ModelError("Unsupported child element")
 
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
-        chxmlstr = ''
+        chxmlstr = ""
 
         for with_ in self.withs:
             chxmlstr += with_.toxml()
@@ -492,8 +514,8 @@ def toxml(self):
             chxmlstr += for_each.toxml()
 
         if chxmlstr:
-            xmlstr = '<Structure>' + chxmlstr + '</Structure>'
+            xmlstr = "<Structure>" + chxmlstr + "</Structure>"
         else:
-            xmlstr = ''
+            xmlstr = ""
 
         return xmlstr
diff --git a/lems/parser/LEMS.py b/lems/parser/LEMS.py
index de33c4f..a48eee9 100644
--- a/lems/parser/LEMS.py
+++ b/lems/parser/LEMS.py
@@ -21,21 +21,22 @@
 
 def get_nons_tag_from_node(node):
     tag = node.tag
-    bits = tag.split('}')
+    bits = tag.split("}")
     if len(bits) == 1:
         return tag
-    elif '/lems/' in bits[0]:
+    elif "/lems/" in bits[0]:
         return bits[1]
-    elif 'neuroml2' in bits[0]:
+    elif "neuroml2" in bits[0]:
         return bits[1]
-    elif 'rdf' in bits[0]:
-        return "rdf_"+bits[1]
-    elif 'model-qualifiers' in bits[0]:
-        return "bqmodel_"+bits[1]
-    elif 'biology-qualifiers' in bits[0]:
-        return "bqbiol_"+bits[1]
+    elif "rdf" in bits[0]:
+        return "rdf_" + bits[1]
+    elif "model-qualifiers" in bits[0]:
+        return "bqmodel_" + bits[1]
+    elif "biology-qualifiers" in bits[0]:
+        return "bqbiol_" + bits[1]
     else:
-        return "%s:%s"%(bits[0],bits[1])
+        return "%s:%s" % (bits[0], bits[1])
+
 
 class LEMSXMLNode:
     def __init__(self, pyxmlnode):
@@ -54,14 +55,15 @@ def __init__(self, pyxmlnode):
             self.children.append(LEMSXMLNode(pyxmlchild))
 
     def __str__(self):
-        return 'LEMSXMLNode <{0} {1}>'.format(self.tag, self.attrib)
+        return "LEMSXMLNode <{0} {1}>".format(self.tag, self.attrib)
+
 
 class LEMSFileParser(LEMSBase):
     """
     LEMS XML file format parser class.
     """
 
-    def __init__(self, model, include_dirs = [], include_includes=True):
+    def __init__(self, model, include_dirs=[], include_includes=True):
         """
         Constructor.
 
@@ -99,115 +101,150 @@ def init_parser(self):
         Initializes the parser
         """
 
-        #self.token_list = None
-        #self.prev_token_lists = None
+        # self.token_list = None
+        # self.prev_token_lists = None
 
         self.valid_children = dict()
-        self.valid_children['lems'] = ['component', 'componenttype',
-                                       'target', 'include',
-                                       'dimension', 'unit', 'assertion']
-
-        #TODO: make this generic for any domain specific language based on LEMS
-        self.valid_children['neuroml'] = ['include', 'componenttype']
-
-        self.valid_children['componenttype'] = ['dynamics',
-                                                'child', 'children',
-                                                'componentreference',
-                                                'exposure', 'eventport',
-                                                'fixed', 'link', 'parameter',
-                                                'property',
-                                                'indexparameter',
-                                                'path', 'requirement',
-                                                'componentrequirement',
-                                                'instancerequirement',
-                                                'simulation', 'structure',
-                                                'text', 'attachments',
-                                                'constant', 'derivedparameter']
-
-        self.valid_children['dynamics'] = ['derivedvariable',
-                                           'conditionalderivedvariable',
-                                           'oncondition',
-                                           'onevent', 'onstart',
-                                           'statevariable', 'timederivative',
-                                           'kineticscheme', 'regime']
-
-        self.valid_children['component'] = ['component']
-
-        self.valid_children['conditionalderivedvariable'] = ['case']
-
-        self.valid_children['regime'] = ['oncondition', 'onentry', 'timederivative']
-        self.valid_children['oncondition'] = ['eventout', 'stateassignment', 'transition']
-        self.valid_children['onentry'] = ['eventout', 'stateassignment', 'transition']
-        self.valid_children['onevent'] = ['eventout', 'stateassignment', 'transition']
-        self.valid_children['onstart'] = ['eventout', 'stateassignment', 'transition']
-        self.valid_children['structure'] = ['childinstance',
-                                            'eventconnection',
-                                            'foreach',
-                                            'multiinstantiate',
-                                            'with',
-                                            'tunnel']
-
-        self.valid_children['foreach'] = ['foreach', 'eventconnection']
-
-        self.valid_children['simulation'] = ['record', 'eventrecord', 'run',
-                                             'datadisplay', 'datawriter', 'eventwriter']
+        self.valid_children["lems"] = [
+            "component",
+            "componenttype",
+            "target",
+            "include",
+            "dimension",
+            "unit",
+            "assertion",
+        ]
+
+        # TODO: make this generic for any domain specific language based on LEMS
+        self.valid_children["neuroml"] = ["include", "componenttype"]
+
+        self.valid_children["componenttype"] = [
+            "dynamics",
+            "child",
+            "children",
+            "componentreference",
+            "exposure",
+            "eventport",
+            "fixed",
+            "link",
+            "parameter",
+            "property",
+            "indexparameter",
+            "path",
+            "requirement",
+            "componentrequirement",
+            "instancerequirement",
+            "simulation",
+            "structure",
+            "text",
+            "attachments",
+            "constant",
+            "derivedparameter",
+        ]
+
+        self.valid_children["dynamics"] = [
+            "derivedvariable",
+            "conditionalderivedvariable",
+            "oncondition",
+            "onevent",
+            "onstart",
+            "statevariable",
+            "timederivative",
+            "kineticscheme",
+            "regime",
+        ]
+
+        self.valid_children["component"] = ["component"]
+
+        self.valid_children["conditionalderivedvariable"] = ["case"]
+
+        self.valid_children["regime"] = ["oncondition", "onentry", "timederivative"]
+        self.valid_children["oncondition"] = [
+            "eventout",
+            "stateassignment",
+            "transition",
+        ]
+        self.valid_children["onentry"] = ["eventout", "stateassignment", "transition"]
+        self.valid_children["onevent"] = ["eventout", "stateassignment", "transition"]
+        self.valid_children["onstart"] = ["eventout", "stateassignment", "transition"]
+        self.valid_children["structure"] = [
+            "childinstance",
+            "eventconnection",
+            "foreach",
+            "multiinstantiate",
+            "with",
+            "tunnel",
+        ]
+
+        self.valid_children["foreach"] = ["foreach", "eventconnection"]
+
+        self.valid_children["simulation"] = [
+            "record",
+            "eventrecord",
+            "run",
+            "datadisplay",
+            "datawriter",
+            "eventwriter",
+        ]
 
         self.tag_parse_table = dict()
-        #self.tag_parse_table['assertion'] = self.parse_assertion
-        self.tag_parse_table['attachments'] = self.parse_attachments
-        self.tag_parse_table['child'] = self.parse_child
-        self.tag_parse_table['childinstance'] = self.parse_child_instance
-        self.tag_parse_table['children'] = self.parse_children
-        self.tag_parse_table['component'] = self.parse_component
-        self.tag_parse_table['componentreference'] = self.parse_component_reference
-        self.tag_parse_table['componentrequirement'] = self.parse_component_requirement
-        self.tag_parse_table['componenttype'] = self.parse_component_type
-        self.tag_parse_table['constant'] = self.parse_constant
-        self.tag_parse_table['datadisplay'] = self.parse_data_display
-        self.tag_parse_table['datawriter'] = self.parse_data_writer
-        self.tag_parse_table['eventwriter'] = self.parse_event_writer
-        self.tag_parse_table['derivedparameter'] = self.parse_derived_parameter
-        self.tag_parse_table['derivedvariable'] = self.parse_derived_variable
-        self.tag_parse_table['conditionalderivedvariable'] = self.parse_conditional_derived_variable
-        self.tag_parse_table['case'] = self.parse_case
-        self.tag_parse_table['dimension'] = self.parse_dimension
-        self.tag_parse_table['dynamics'] = self.parse_dynamics
-        self.tag_parse_table['eventconnection'] = self.parse_event_connection
-        self.tag_parse_table['eventout'] = self.parse_event_out
-        self.tag_parse_table['eventport'] = self.parse_event_port
-        self.tag_parse_table['exposure'] = self.parse_exposure
-        self.tag_parse_table['fixed'] = self.parse_fixed
-        self.tag_parse_table['foreach'] = self.parse_for_each
-        self.tag_parse_table['include'] = self.parse_include
-        self.tag_parse_table['indexparameter'] = self.parse_index_parameter
-        self.tag_parse_table['kineticscheme'] = self.parse_kinetic_scheme
-        self.tag_parse_table['link'] = self.parse_link
-        self.tag_parse_table['multiinstantiate'] = self.parse_multi_instantiate
-        self.tag_parse_table['oncondition'] = self.parse_on_condition
-        self.tag_parse_table['onentry'] = self.parse_on_entry
-        self.tag_parse_table['onevent'] = self.parse_on_event
-        self.tag_parse_table['onstart'] = self.parse_on_start
-        self.tag_parse_table['parameter'] = self.parse_parameter
-        self.tag_parse_table['property'] = self.parse_property
-        self.tag_parse_table['path'] = self.parse_path
-        self.tag_parse_table['record'] = self.parse_record
-        self.tag_parse_table['eventrecord'] = self.parse_event_record
-        self.tag_parse_table['regime'] = self.parse_regime
-        self.tag_parse_table['requirement'] = self.parse_requirement
-        self.tag_parse_table['instancerequirement'] = self.parse_instance_requirement
-        self.tag_parse_table['run'] = self.parse_run
-        #self.tag_parse_table['show'] = self.parse_show
-        self.tag_parse_table['simulation'] = self.parse_simulation
-        self.tag_parse_table['stateassignment'] = self.parse_state_assignment
-        self.tag_parse_table['statevariable'] = self.parse_state_variable
-        self.tag_parse_table['structure'] = self.parse_structure
-        self.tag_parse_table['target'] = self.parse_target
-        self.tag_parse_table['text'] = self.parse_text
-        self.tag_parse_table['timederivative'] = self.parse_time_derivative
-        self.tag_parse_table['transition'] = self.parse_transition
-        self.tag_parse_table['tunnel'] = self.parse_tunnel
-        self.tag_parse_table['unit'] = self.parse_unit
-        self.tag_parse_table['with'] = self.parse_with
+        # self.tag_parse_table['assertion'] = self.parse_assertion
+        self.tag_parse_table["attachments"] = self.parse_attachments
+        self.tag_parse_table["child"] = self.parse_child
+        self.tag_parse_table["childinstance"] = self.parse_child_instance
+        self.tag_parse_table["children"] = self.parse_children
+        self.tag_parse_table["component"] = self.parse_component
+        self.tag_parse_table["componentreference"] = self.parse_component_reference
+        self.tag_parse_table["componentrequirement"] = self.parse_component_requirement
+        self.tag_parse_table["componenttype"] = self.parse_component_type
+        self.tag_parse_table["constant"] = self.parse_constant
+        self.tag_parse_table["datadisplay"] = self.parse_data_display
+        self.tag_parse_table["datawriter"] = self.parse_data_writer
+        self.tag_parse_table["eventwriter"] = self.parse_event_writer
+        self.tag_parse_table["derivedparameter"] = self.parse_derived_parameter
+        self.tag_parse_table["derivedvariable"] = self.parse_derived_variable
+        self.tag_parse_table[
+            "conditionalderivedvariable"
+        ] = self.parse_conditional_derived_variable
+        self.tag_parse_table["case"] = self.parse_case
+        self.tag_parse_table["dimension"] = self.parse_dimension
+        self.tag_parse_table["dynamics"] = self.parse_dynamics
+        self.tag_parse_table["eventconnection"] = self.parse_event_connection
+        self.tag_parse_table["eventout"] = self.parse_event_out
+        self.tag_parse_table["eventport"] = self.parse_event_port
+        self.tag_parse_table["exposure"] = self.parse_exposure
+        self.tag_parse_table["fixed"] = self.parse_fixed
+        self.tag_parse_table["foreach"] = self.parse_for_each
+        self.tag_parse_table["include"] = self.parse_include
+        self.tag_parse_table["indexparameter"] = self.parse_index_parameter
+        self.tag_parse_table["kineticscheme"] = self.parse_kinetic_scheme
+        self.tag_parse_table["link"] = self.parse_link
+        self.tag_parse_table["multiinstantiate"] = self.parse_multi_instantiate
+        self.tag_parse_table["oncondition"] = self.parse_on_condition
+        self.tag_parse_table["onentry"] = self.parse_on_entry
+        self.tag_parse_table["onevent"] = self.parse_on_event
+        self.tag_parse_table["onstart"] = self.parse_on_start
+        self.tag_parse_table["parameter"] = self.parse_parameter
+        self.tag_parse_table["property"] = self.parse_property
+        self.tag_parse_table["path"] = self.parse_path
+        self.tag_parse_table["record"] = self.parse_record
+        self.tag_parse_table["eventrecord"] = self.parse_event_record
+        self.tag_parse_table["regime"] = self.parse_regime
+        self.tag_parse_table["requirement"] = self.parse_requirement
+        self.tag_parse_table["instancerequirement"] = self.parse_instance_requirement
+        self.tag_parse_table["run"] = self.parse_run
+        # self.tag_parse_table['show'] = self.parse_show
+        self.tag_parse_table["simulation"] = self.parse_simulation
+        self.tag_parse_table["stateassignment"] = self.parse_state_assignment
+        self.tag_parse_table["statevariable"] = self.parse_state_variable
+        self.tag_parse_table["structure"] = self.parse_structure
+        self.tag_parse_table["target"] = self.parse_target
+        self.tag_parse_table["text"] = self.parse_text
+        self.tag_parse_table["timederivative"] = self.parse_time_derivative
+        self.tag_parse_table["transition"] = self.parse_transition
+        self.tag_parse_table["tunnel"] = self.parse_tunnel
+        self.tag_parse_table["unit"] = self.parse_unit
+        self.tag_parse_table["with"] = self.parse_with
 
         self.xml_node_stack = []
 
@@ -227,8 +264,7 @@ def counter():
 
         self.id_counter = counter()
 
-
-    def process_nested_tags(self, node, tag = ''):
+    def process_nested_tags(self, node, tag=""):
         """
         Process child tags.
 
@@ -239,7 +275,7 @@ def process_nested_tags(self, node, tag = ''):
         """
         ##print("---------Processing: %s, %s"%(node.tag,tag))
 
-        if tag == '':
+        if tag == "":
             t = node.ltag
         else:
             t = tag.lower()
@@ -250,10 +286,10 @@ def process_nested_tags(self, node, tag = ''):
             ctagl = child.ltag
 
             if ctagl in self.tag_parse_table and ctagl in self.valid_children[t]:
-                #print("Processing known type: %s"%ctagl)
+                # print("Processing known type: %s"%ctagl)
                 self.tag_parse_table[ctagl](child)
             else:
-                #print("Processing unknown type: %s"%ctagl)
+                # print("Processing unknown type: %s"%ctagl)
                 self.parse_component_by_typename(child, child.tag)
 
             self.xml_node_stack = self.xml_node_stack[1:]
@@ -268,90 +304,88 @@ def parse(self, xmltext):
 
         xml = LEMSXMLNode(xe.XML(xmltext))
 
-        if xml.ltag != 'lems' and xml.ltag != 'neuroml':
-            raise ParseError('<Lems> expected as root element (or even <neuroml>), found: {0}'.format(xml.ltag))
+        if xml.ltag != "lems" and xml.ltag != "neuroml":
+            raise ParseError(
+                "<Lems> expected as root element (or even <neuroml>), found: {0}".format(
+                    xml.ltag
+                )
+            )
 
-        if xml.ltag == 'lems':
-            if 'description' in xml.lattrib:
-                self.model.description = xml.lattrib['description']
+        if xml.ltag == "lems":
+            if "description" in xml.lattrib:
+                self.model.description = xml.lattrib["description"]
 
         self.process_nested_tags(xml)
 
-
     def raise_error(self, message, *params, **key_params):
         """
         Raise a parse error.
         """
 
-        s = 'Parser error in '
+        s = "Parser error in "
 
         self.xml_node_stack.reverse()
         if len(self.xml_node_stack) > 1:
             node = self.xml_node_stack[0]
-            s += '<{0}'.format(node.tag)
-            if 'name' in node.lattrib:
-                s += ' name=\"{0}\"'.format(node.lattrib['name'])
-            if 'id' in node.lattrib:
-                s += ' id=\"{0}\"'.format(node.lattrib['id'])
-            s += '>'
+            s += "<{0}".format(node.tag)
+            if "name" in node.lattrib:
+                s += ' name="{0}"'.format(node.lattrib["name"])
+            if "id" in node.lattrib:
+                s += ' id="{0}"'.format(node.lattrib["id"])
+            s += ">"
 
         for node in self.xml_node_stack[1:]:
-            s += '.<{0}'.format(node.tag)
-            if 'name' in node.lattrib:
-                s += ' name=\"{0}\"'.format(node.lattrib['name'])
-            if 'id' in node.lattrib:
-                s += ' id=\"{0}\"'.format(node.lattrib['id'])
-            s += '>'
+            s += ".<{0}".format(node.tag)
+            if "name" in node.lattrib:
+                s += ' name="{0}"'.format(node.lattrib["name"])
+            if "id" in node.lattrib:
+                s += ' id="{0}"'.format(node.lattrib["id"])
+            s += ">"
 
-        s += ':\n  ' + message
+        s += ":\n  " + message
 
         raise ParseError(s, *params, **key_params)
 
         self.xml_node_stack.reverse()
 
-
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-#####################################################################################
-
-
-
-
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
+    #####################################################################################
 
     def parse_assertion(self, node):
         """
@@ -361,8 +395,7 @@ def parse_assertion(self, node):
         :type node: xml.etree.Element
         """
 
-        print('TODO - <Assertion>')
-
+        print("TODO - <Assertion>")
 
     def parse_attachments(self, node):
         """
@@ -372,19 +405,20 @@ def parse_attachments(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'name' in node.lattrib:
-            name = node.lattrib['name']
+        if "name" in node.lattrib:
+            name = node.lattrib["name"]
         else:
-            self.raise_error('<Attachments> must specify a name.')
+            self.raise_error("<Attachments> must specify a name.")
 
-        if 'type' in node.lattrib:
-            type_ = node.lattrib['type']
+        if "type" in node.lattrib:
+            type_ = node.lattrib["type"]
         else:
-            self.raise_error("Attachment '{0}' must specify a type.",
-                             name)
+            self.raise_error("Attachment '{0}' must specify a type.", name)
 
-        description = node.lattrib.get('description', '')
-        self.current_component_type.add_attachments(Attachments(name, type_, description))
+        description = node.lattrib.get("description", "")
+        self.current_component_type.add_attachments(
+            Attachments(name, type_, description)
+        )
 
     def parse_child(self, node):
         """
@@ -394,18 +428,20 @@ def parse_child(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'name' in node.lattrib:
-            name = node.lattrib['name']
+        if "name" in node.lattrib:
+            name = node.lattrib["name"]
         else:
-            self.raise_error('<Child> must specify a name.')
+            self.raise_error("<Child> must specify a name.")
 
-        if 'type' in node.lattrib:
-            type_ = node.lattrib['type']
+        if "type" in node.lattrib:
+            type_ = node.lattrib["type"]
         else:
             self.raise_error("Child '{0}' must specify a type.", name)
 
-        description = node.lattrib.get('description', '')
-        self.current_component_type.add_children(Children(name, type_, description, multiple=False))
+        description = node.lattrib.get("description", "")
+        self.current_component_type.add_children(
+            Children(name, type_, description, multiple=False)
+        )
 
     def parse_child_instance(self, node):
         """
@@ -415,10 +451,10 @@ def parse_child_instance(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'component' in node.lattrib:
-            component = node.lattrib['component']
+        if "component" in node.lattrib:
+            component = node.lattrib["component"]
         else:
-            self.raise_error('<ChildInstance> must specify a component reference')
+            self.raise_error("<ChildInstance> must specify a component reference")
 
         self.current_structure.add_child_instance(ChildInstance(component))
 
@@ -430,18 +466,20 @@ def parse_children(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'name' in node.lattrib:
-            name = node.lattrib['name']
+        if "name" in node.lattrib:
+            name = node.lattrib["name"]
         else:
-            self.raise_error('<Children> must specify a name.')
+            self.raise_error("<Children> must specify a name.")
 
-        if 'type' in node.lattrib:
-            type_ = node.lattrib['type']
+        if "type" in node.lattrib:
+            type_ = node.lattrib["type"]
         else:
             self.raise_error("Children '{0}' must specify a type.", name)
 
-        description = node.lattrib.get('description', '')
-        self.current_component_type.add_children(Children(name, type_, description, multiple=True))
+        description = node.lattrib.get("description", "")
+        self.current_component_type.add_children(
+            Children(name, type_, description, multiple=True)
+        )
 
     def parse_component_by_typename(self, node, type_):
         """
@@ -455,15 +493,15 @@ def parse_component_by_typename(self, node, type_):
 
         :raises ParseError: Raised when the component does not have an id.
         """
-        #print('Parsing component {0} by typename {1}'.format(node, type_))
-        if 'id' in node.lattrib:
-            id_ = node.lattrib['id']
+        # print('Parsing component {0} by typename {1}'.format(node, type_))
+        if "id" in node.lattrib:
+            id_ = node.lattrib["id"]
         else:
-            #self.raise_error('Component must have an id')
-            id_ = node.tag #make_id()
+            # self.raise_error('Component must have an id')
+            id_ = node.tag  # make_id()
 
-        if 'type' in node.lattrib:
-            type_ = node.lattrib['type']
+        if "type" in node.lattrib:
+            type_ = node.lattrib["type"]
         else:
             type_ = node.tag
 
@@ -477,12 +515,12 @@ def parse_component_by_typename(self, node, type_):
             self.model.add_component(component)
 
         for key in node.attrib:
-            if key.lower() not in ['id', 'type']:
+            if key.lower() not in ["id", "type"]:
                 component.set_parameter(key, node.attrib[key])
 
         old_component = self.current_component
         self.current_component = component
-        self.process_nested_tags(node, 'component')
+        self.process_nested_tags(node, "component")
         self.current_component = old_component
 
     def parse_component(self, node):
@@ -493,17 +531,16 @@ def parse_component(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'id' in node.lattrib:
-            id_ = node.lattrib['id']
+        if "id" in node.lattrib:
+            id_ = node.lattrib["id"]
         else:
-            #self.raise_error('Component must have an id')
+            # self.raise_error('Component must have an id')
             id_ = make_id()
 
-        if 'type' in node.lattrib:
-            type_ = node.lattrib['type']
+        if "type" in node.lattrib:
+            type_ = node.lattrib["type"]
         else:
-                self.raise_error("Component {0} must have a type.",
-                                 id_)
+            self.raise_error("Component {0} must have a type.", id_)
 
         component = Component(id_, type_)
 
@@ -514,7 +551,7 @@ def parse_component(self, node):
             self.model.add_component(component)
 
         for key in node.attrib:
-            if key.lower() not in ['id', 'type']:
+            if key.lower() not in ["id", "type"]:
                 component.set_parameter(key, node.attrib[key])
 
         old_component = self.current_component
@@ -530,24 +567,28 @@ def parse_component_reference(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'name' in node.lattrib:
-            name = node.lattrib['name']
+        if "name" in node.lattrib:
+            name = node.lattrib["name"]
         else:
-            self.raise_error('<ComponentReference> must specify a name for the ' +
-                             'reference.')
+            self.raise_error(
+                "<ComponentReference> must specify a name for the " + "reference."
+            )
 
-        if 'type' in node.lattrib:
-            type_ = node.lattrib['type']
+        if "type" in node.lattrib:
+            type_ = node.lattrib["type"]
         else:
-            self.raise_error('<ComponentReference> must specify a type for the ' +
-                             'reference.')
+            self.raise_error(
+                "<ComponentReference> must specify a type for the " + "reference."
+            )
 
-        if 'local' in node.lattrib:
-            local = node.lattrib['local']
+        if "local" in node.lattrib:
+            local = node.lattrib["local"]
         else:
             local = None
 
-        self.current_component_type.add_component_reference(ComponentReference(name, type_, local))
+        self.current_component_type.add_component_reference(
+            ComponentReference(name, type_, local)
+        )
 
     def parse_component_type(self, node):
         """
@@ -560,19 +601,19 @@ def parse_component_type(self, node):
         """
 
         try:
-            name = node.lattrib['name']
+            name = node.lattrib["name"]
         except:
-            self.raise_error('<ComponentType> must specify a name')
+            self.raise_error("<ComponentType> must specify a name")
 
-        if 'extends' in node.lattrib:
-            extends = node.lattrib['extends']
+        if "extends" in node.lattrib:
+            extends = node.lattrib["extends"]
         else:
             extends = None
 
-        if 'description' in node.lattrib:
-            description = node.lattrib['description']
+        if "description" in node.lattrib:
+            description = node.lattrib["description"]
         else:
-            description = ''
+            description = ""
 
         component_type = ComponentType(name, description, extends)
         self.model.add_component_type(component_type)
@@ -590,19 +631,19 @@ def parse_constant(self, node):
         """
 
         try:
-            name = node.lattrib['name']
+            name = node.lattrib["name"]
         except:
-            self.raise_error('<Constant> must specify a name.')
+            self.raise_error("<Constant> must specify a name.")
 
-        dimension = node.lattrib.get('dimension', None)
+        dimension = node.lattrib.get("dimension", None)
 
         try:
-            value = node.lattrib['value']
+            value = node.lattrib["value"]
         except:
             self.raise_error("Constant '{0}' must have a value.", name)
 
-        if 'description' in node.lattrib:
-            description = node.lattrib['description']
+        if "description" in node.lattrib:
+            description = node.lattrib["description"]
         else:
             description = None
 
@@ -621,13 +662,13 @@ def parse_data_display(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'title' in node.lattrib:
-            title = node.lattrib['title']
+        if "title" in node.lattrib:
+            title = node.lattrib["title"]
         else:
-            self.raise_error('<DataDisplay> must have a title.')
+            self.raise_error("<DataDisplay> must have a title.")
 
-        if 'dataregion' in node.lattrib:
-            data_region = node.lattrib['dataregion']
+        if "dataregion" in node.lattrib:
+            data_region = node.lattrib["dataregion"]
         else:
             data_region = None
 
@@ -641,16 +682,15 @@ def parse_data_writer(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'path' in node.lattrib:
-            path = node.lattrib['path']
+        if "path" in node.lattrib:
+            path = node.lattrib["path"]
         else:
-            self.raise_error('<DataWriter> must specify a path.')
+            self.raise_error("<DataWriter> must specify a path.")
 
-        if 'filename' in node.lattrib:
-            file_path = node.lattrib['filename']
+        if "filename" in node.lattrib:
+            file_path = node.lattrib["filename"]
         else:
-            self.raise_error("Data writer for '{0}' must specify a filename.",
-                             path)
+            self.raise_error("Data writer for '{0}' must specify a filename.", path)
 
         self.current_simulation.add_data_writer(DataWriter(path, file_path))
 
@@ -662,22 +702,20 @@ def parse_event_writer(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'path' in node.lattrib:
-            path = node.lattrib['path']
+        if "path" in node.lattrib:
+            path = node.lattrib["path"]
         else:
-            self.raise_error('<EventWriter> must specify a path.')
+            self.raise_error("<EventWriter> must specify a path.")
 
-        if 'filename' in node.lattrib:
-            file_path = node.lattrib['filename']
+        if "filename" in node.lattrib:
+            file_path = node.lattrib["filename"]
         else:
-            self.raise_error("Event writer for '{0}' must specify a filename.",
-                             path)
+            self.raise_error("Event writer for '{0}' must specify a filename.", path)
 
-        if 'format' in node.lattrib:
-            format = node.lattrib['format']
+        if "format" in node.lattrib:
+            format = node.lattrib["format"]
         else:
-            self.raise_error("Event writer for '{0}' must specify a format.",
-                             path)
+            self.raise_error("Event writer for '{0}' must specify a format.", path)
 
         self.current_simulation.add_event_writer(EventWriter(path, file_path, format))
 
@@ -689,37 +727,39 @@ def parse_derived_parameter(self, node):
         :type node: xml.etree.Element
         """
 
-        #if self.current_context.context_type != Context.COMPONENT_TYPE:
+        # if self.current_context.context_type != Context.COMPONENT_TYPE:
         #    self.raise_error('Dynamics must be defined inside a ' +
         #                     'component type')
 
-        if 'name' in node.lattrib:
-            name = node.lattrib['name']
+        if "name" in node.lattrib:
+            name = node.lattrib["name"]
         else:
-            self.raise_error('A derived parameter must have a name')
+            self.raise_error("A derived parameter must have a name")
 
-        if 'dimension' in node.lattrib:
-            dimension = node.lattrib['dimension']
+        if "dimension" in node.lattrib:
+            dimension = node.lattrib["dimension"]
         else:
             dimension = None
 
-        if 'value' in node.lattrib:
-            value = node.lattrib['value']
+        if "value" in node.lattrib:
+            value = node.lattrib["value"]
         else:
             value = None
 
         # TODO: this is not used in the DerivedParameter constructor
-        if 'select' in node.lattrib:
-            select = node.lattrib['select']
+        if "select" in node.lattrib:
+            select = node.lattrib["select"]
         else:
             select = None
 
-        if 'description' in node.lattrib:
-            description = node.lattrib['description']
+        if "description" in node.lattrib:
+            description = node.lattrib["description"]
         else:
             description = None
 
-        self.current_component_type.add_derived_parameter(DerivedParameter(name, value, dimension, description))
+        self.current_component_type.add_derived_parameter(
+            DerivedParameter(name, value, dimension, description)
+        )
 
     def parse_derived_variable(self, node):
         """
@@ -731,21 +771,27 @@ def parse_derived_variable(self, node):
         :raises ParseError: Raised when no name of specified for the derived variable.
         """
 
-        if 'name' in node.lattrib:
-            name = node.lattrib['name']
-        elif 'exposure' in node.lattrib:
-            name = node.lattrib['exposure']
+        if "name" in node.lattrib:
+            name = node.lattrib["name"]
+        elif "exposure" in node.lattrib:
+            name = node.lattrib["exposure"]
         else:
-            self.raise_error('<DerivedVariable> must specify a name')
+            self.raise_error("<DerivedVariable> must specify a name")
 
         params = dict()
-        for attr_name in ['dimension', 'exposure', 'select', 'value', 'reduce', 'required']:
+        for attr_name in [
+            "dimension",
+            "exposure",
+            "select",
+            "value",
+            "reduce",
+            "required",
+        ]:
             if attr_name in node.lattrib:
                 params[attr_name] = node.lattrib[attr_name]
 
         self.current_regime.add_derived_variable(DerivedVariable(name, **params))
 
-
     def parse_conditional_derived_variable(self, node):
         """
         Parses <ConditionalDerivedVariable>
@@ -756,32 +802,35 @@ def parse_conditional_derived_variable(self, node):
         :raises ParseError: Raised when no name or value is specified for the conditional derived variable.
         """
 
-        if 'name' in node.lattrib:
-            name = node.lattrib['name']
-        elif 'exposure' in node.lattrib:
-            name = node.lattrib['exposure']
+        if "name" in node.lattrib:
+            name = node.lattrib["name"]
+        elif "exposure" in node.lattrib:
+            name = node.lattrib["exposure"]
         else:
-            self.raise_error('<ConditionalDerivedVariable> must specify a name')
+            self.raise_error("<ConditionalDerivedVariable> must specify a name")
 
-        if 'exposure' in node.lattrib:
-            exposure = node.lattrib['exposure']
+        if "exposure" in node.lattrib:
+            exposure = node.lattrib["exposure"]
         else:
             exposure = None
 
-        if 'dimension' in node.lattrib:
-            dimension = node.lattrib['dimension']
+        if "dimension" in node.lattrib:
+            dimension = node.lattrib["dimension"]
         else:
             dimension = None
 
-        conditional_derived_variable = ConditionalDerivedVariable(name, dimension, exposure)
+        conditional_derived_variable = ConditionalDerivedVariable(
+            name, dimension, exposure
+        )
 
-        self.current_regime.add_conditional_derived_variable(conditional_derived_variable)
+        self.current_regime.add_conditional_derived_variable(
+            conditional_derived_variable
+        )
 
         self.current_conditional_derived_variable = conditional_derived_variable
 
         self.process_nested_tags(node)
 
-
     def parse_case(self, node):
         """
         Parses <Case>
@@ -793,14 +842,14 @@ def parse_case(self, node):
         """
 
         try:
-            condition = node.lattrib['condition']
+            condition = node.lattrib["condition"]
         except:
             condition = None
 
         try:
-            value = node.lattrib['value']
+            value = node.lattrib["value"]
         except:
-            self.raise_error('<Case> must specify a value')
+            self.raise_error("<Case> must specify a value")
 
         self.current_conditional_derived_variable.add_case(Case(condition, value))
 
@@ -815,14 +864,14 @@ def parse_dimension(self, node):
         """
 
         try:
-            name = node.lattrib['name']
+            name = node.lattrib["name"]
         except:
-            self.raise_error('<Dimension> must specify a name')
+            self.raise_error("<Dimension> must specify a name")
 
-        description = node.lattrib.get('description', '')
+        description = node.lattrib.get("description", "")
 
         dim = dict()
-        for d in ['l', 'm', 't', 'i', 'k', 'c', 'n']:
+        for d in ["l", "m", "t", "i", "k", "c", "n"]:
             dim[d] = int(node.lattrib.get(d, 0))
 
         self.model.add_dimension(Dimension(name, description, **dim))
@@ -849,22 +898,28 @@ def parse_event_connection(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'from' in node.lattrib:
-            from_ = node.lattrib['from']
+        if "from" in node.lattrib:
+            from_ = node.lattrib["from"]
         else:
-            self.raise_error('<EventConnection> must provide a source (from) component reference.')
+            self.raise_error(
+                "<EventConnection> must provide a source (from) component reference."
+            )
 
-        if 'to' in node.lattrib:
-            to = node.lattrib['to']
+        if "to" in node.lattrib:
+            to = node.lattrib["to"]
         else:
-            self.raise_error('<EventConnection> must provide a target (to) component reference.')
+            self.raise_error(
+                "<EventConnection> must provide a target (to) component reference."
+            )
 
-        source_port = node.lattrib.get('sourceport', '')
-        target_port = node.lattrib.get('targetport', '')
-        receiver = node.lattrib.get('receiver', '')
-        receiver_container = node.lattrib.get('receivercontainer', '')
+        source_port = node.lattrib.get("sourceport", "")
+        target_port = node.lattrib.get("targetport", "")
+        receiver = node.lattrib.get("receiver", "")
+        receiver_container = node.lattrib.get("receivercontainer", "")
 
-        ec = EventConnection(from_, to, source_port, target_port, receiver, receiver_container)
+        ec = EventConnection(
+            from_, to, source_port, target_port, receiver, receiver_container
+        )
         self.current_structure.add_event_connection(ec)
 
     def parse_event_out(self, node):
@@ -876,9 +931,9 @@ def parse_event_out(self, node):
         """
 
         try:
-            port = node.lattrib['port']
+            port = node.lattrib["port"]
         except:
-            self.raise_error('<EventOut> must be specify a port.')
+            self.raise_error("<EventOut> must be specify a port.")
 
         action = EventOut(port)
 
@@ -892,24 +947,25 @@ def parse_event_port(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'name' in node.lattrib:
-            name = node.lattrib['name']
+        if "name" in node.lattrib:
+            name = node.lattrib["name"]
         else:
-            self.raise_error(('<EventPort> must specify a name.'))
+            self.raise_error(("<EventPort> must specify a name."))
 
-        if 'direction' in node.lattrib:
-            direction = node.lattrib['direction']
+        if "direction" in node.lattrib:
+            direction = node.lattrib["direction"]
         else:
             self.raise_error("Event port '{0}' must specify a direction.")
 
         direction = direction.lower()
-        if direction != 'in' and direction != 'out':
-            self.raise_error(('Event port direction must be \'in\' '
-                              'or \'out\''))
+        if direction != "in" and direction != "out":
+            self.raise_error(("Event port direction must be 'in' " "or 'out'"))
 
-        description = node.lattrib.get('description', '')
+        description = node.lattrib.get("description", "")
 
-        self.current_component_type.add_event_port(EventPort(name, direction, description))
+        self.current_component_type.add_event_port(
+            EventPort(name, direction, description)
+        )
 
     def parse_exposure(self, node):
         """
@@ -922,20 +978,19 @@ def parse_exposure(self, node):
         """
 
         if self.current_component_type == None:
-            self.raise_error('Exposures must be defined in a component type')
+            self.raise_error("Exposures must be defined in a component type")
 
         try:
-            name = node.lattrib['name']
+            name = node.lattrib["name"]
         except:
-            self.raise_error('<Exposure> must specify a name')
+            self.raise_error("<Exposure> must specify a name")
 
         try:
-            dimension = node.lattrib['dimension']
+            dimension = node.lattrib["dimension"]
         except:
-            self.raise_error("Exposure '{0}' must specify a dimension",
-                             name)
+            self.raise_error("Exposure '{0}' must specify a dimension", name)
 
-        description = node.lattrib.get('description', '')
+        description = node.lattrib.get("description", "")
 
         self.current_component_type.add_exposure(Exposure(name, dimension, description))
 
@@ -948,16 +1003,16 @@ def parse_fixed(self, node):
         """
 
         try:
-            parameter = node.lattrib['parameter']
+            parameter = node.lattrib["parameter"]
         except:
-            self.raise_error('<Fixed> must specify a parameter to be fixed.')
+            self.raise_error("<Fixed> must specify a parameter to be fixed.")
 
         try:
-            value = node.lattrib['value']
+            value = node.lattrib["value"]
         except:
             self.raise_error("Fixed parameter '{0}'must specify a value.", parameter)
 
-        description = node.lattrib.get('description', '')
+        description = node.lattrib.get("description", "")
 
         self.current_component_type.add_parameter(Fixed(parameter, value, description))
 
@@ -970,20 +1025,21 @@ def parse_for_each(self, node):
         """
 
         if self.current_structure == None:
-            self.raise_error('<ForEach> can only be made within ' +
-                             'a structure definition')
+            self.raise_error(
+                "<ForEach> can only be made within " + "a structure definition"
+            )
 
-        if 'instances' in node.lattrib:
-            instances = node.lattrib['instances']
+        if "instances" in node.lattrib:
+            instances = node.lattrib["instances"]
         else:
-            self.raise_error('<ForEach> must specify a reference to target'
-                             'instances')
+            self.raise_error("<ForEach> must specify a reference to target" "instances")
 
-        if 'as' in node.lattrib:
-            as_ = node.lattrib['as']
+        if "as" in node.lattrib:
+            as_ = node.lattrib["as"]
         else:
-            self.raise_error('<ForEach> must specify a name for the '
-                             'enumerated target instances')
+            self.raise_error(
+                "<ForEach> must specify a name for the " "enumerated target instances"
+            )
 
         old_structure = self.current_structure
         fe = ForEach(instances, as_)
@@ -1004,18 +1060,19 @@ def parse_include(self, node):
         :raises ParseError: Raised when the file to be included is not specified.
         """
         if not self.include_includes:
-            if self.model.debug: print("Ignoring included LEMS file: %s"%node.lattrib['file'])
+            if self.model.debug:
+                print("Ignoring included LEMS file: %s" % node.lattrib["file"])
         else:
 
-            #TODO: remove this hard coding for reading NeuroML includes...
-            if 'file' not in node.lattrib:
-                if 'href' in node.lattrib:
-                    self.model.include_file(node.lattrib['href'], self.include_dirs)
+            # TODO: remove this hard coding for reading NeuroML includes...
+            if "file" not in node.lattrib:
+                if "href" in node.lattrib:
+                    self.model.include_file(node.lattrib["href"], self.include_dirs)
                     return
                 else:
-                    self.raise_error('<Include> must specify the file to be included.')
+                    self.raise_error("<Include> must specify the file to be included.")
 
-            self.model.include_file(node.lattrib['file'], self.include_dirs)
+            self.model.include_file(node.lattrib["file"], self.include_dirs)
 
     def parse_kinetic_scheme(self, node):
         """
@@ -1025,49 +1082,68 @@ def parse_kinetic_scheme(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'name' in node.lattrib:
-            name = node.lattrib['name']
+        if "name" in node.lattrib:
+            name = node.lattrib["name"]
         else:
-            self.raise_error('<KineticScheme> must specify a name.')
+            self.raise_error("<KineticScheme> must specify a name.")
 
-        if 'nodes' in node.lattrib:
-            nodes = node.lattrib['nodes']
+        if "nodes" in node.lattrib:
+            nodes = node.lattrib["nodes"]
         else:
             self.raise_error("Kinetic scheme '{0}' must specify nodes.", name)
 
-        if 'statevariable' in node.lattrib:
-            state_variable = node.lattrib['statevariable']
+        if "statevariable" in node.lattrib:
+            state_variable = node.lattrib["statevariable"]
         else:
-            self.raise_error("Kinetic scheme '{0}' must specify a state variable.", name)
+            self.raise_error(
+                "Kinetic scheme '{0}' must specify a state variable.", name
+            )
 
-        if 'edges' in node.lattrib:
-            edges = node.lattrib['edges']
+        if "edges" in node.lattrib:
+            edges = node.lattrib["edges"]
         else:
             self.raise_error("Kinetic scheme '{0}' must specify edges.", name)
 
-        if 'edgesource' in node.lattrib:
-            edge_source = node.lattrib['edgesource']
+        if "edgesource" in node.lattrib:
+            edge_source = node.lattrib["edgesource"]
         else:
-            self.raise_error("Kinetic scheme '{0}' must specify the edge source attribute.", name)
+            self.raise_error(
+                "Kinetic scheme '{0}' must specify the edge source attribute.", name
+            )
 
-        if 'edgetarget' in node.lattrib:
-            edge_target = node.lattrib['edgetarget']
+        if "edgetarget" in node.lattrib:
+            edge_target = node.lattrib["edgetarget"]
         else:
-            self.raise_error("Kinetic scheme '{0}' must specify the edge target attribute.", name)
+            self.raise_error(
+                "Kinetic scheme '{0}' must specify the edge target attribute.", name
+            )
 
-        if 'forwardrate' in node.lattrib:
-            forward_rate = node.lattrib['forwardrate']
+        if "forwardrate" in node.lattrib:
+            forward_rate = node.lattrib["forwardrate"]
         else:
-            self.raise_error("Kinetic scheme '{0}' must specify the forward rate attribute.", name)
+            self.raise_error(
+                "Kinetic scheme '{0}' must specify the forward rate attribute.", name
+            )
 
-        if 'reverserate' in node.lattrib:
-            reverse_rate = node.lattrib['reverserate']
+        if "reverserate" in node.lattrib:
+            reverse_rate = node.lattrib["reverserate"]
         else:
-            self.raise_error("Kinetic scheme '{0}' must specify the reverse rate attribute", name)
+            self.raise_error(
+                "Kinetic scheme '{0}' must specify the reverse rate attribute", name
+            )
 
-        self.current_regime.add_kinetic_scheme(KineticScheme(name, nodes, state_variable,
-                                                             edges, edge_source, edge_target,
-                                                             forward_rate, reverse_rate))
+        self.current_regime.add_kinetic_scheme(
+            KineticScheme(
+                name,
+                nodes,
+                state_variable,
+                edges,
+                edge_source,
+                edge_target,
+                forward_rate,
+                reverse_rate,
+            )
+        )
 
     def parse_link(self, node):
         """
@@ -1077,17 +1153,17 @@ def parse_link(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'name' in node.lattrib:
-            name = node.lattrib['name']
+        if "name" in node.lattrib:
+            name = node.lattrib["name"]
         else:
-            self.raise_error('<Link> must specify a name')
+            self.raise_error("<Link> must specify a name")
 
-        if 'type' in node.lattrib:
-            type_ = node.lattrib['type']
+        if "type" in node.lattrib:
+            type_ = node.lattrib["type"]
         else:
             self.raise_error("Link '{0}' must specify a type", name)
 
-        description = node.lattrib.get('description', '')
+        description = node.lattrib.get("description", "")
 
         self.current_component_type.add_link(Link(name, type_, description))
 
@@ -1099,18 +1175,22 @@ def parse_multi_instantiate(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'component' in node.lattrib:
-            component = node.lattrib['component']
+        if "component" in node.lattrib:
+            component = node.lattrib["component"]
         else:
-            self.raise_error('<MultiInstantiate> must specify a component reference.')
+            self.raise_error("<MultiInstantiate> must specify a component reference.")
 
-        if 'number' in node.lattrib:
-            number = node.lattrib['number']
+        if "number" in node.lattrib:
+            number = node.lattrib["number"]
         else:
-            self.raise_error("Multi instantiation of '{0}' must specify a parameter specifying the number.",
-                             component)
+            self.raise_error(
+                "Multi instantiation of '{0}' must specify a parameter specifying the number.",
+                component,
+            )
 
-        self.current_structure.add_multi_instantiate(MultiInstantiate(component, number))
+        self.current_structure.add_multi_instantiate(
+            MultiInstantiate(component, number)
+        )
 
     def parse_on_condition(self, node):
         """
@@ -1121,9 +1201,9 @@ def parse_on_condition(self, node):
         """
 
         try:
-            test = node.lattrib['test']
+            test = node.lattrib["test"]
         except:
-            self.raise_error('<OnCondition> must specify a test.')
+            self.raise_error("<OnCondition> must specify a test.")
 
         event_handler = OnCondition(test)
 
@@ -1159,9 +1239,9 @@ def parse_on_event(self, node):
         """
 
         try:
-            port = node.lattrib['port']
+            port = node.lattrib["port"]
         except:
-            self.raise_error('<OnEvent> must specify a port.')
+            self.raise_error("<OnEvent> must specify a port.")
 
         event_handler = OnEvent(port)
 
@@ -1199,21 +1279,19 @@ def parse_parameter(self, node):
         """
 
         if self.current_component_type == None:
-            self.raise_error('Parameters can only be defined in ' +
-                             'a component type')
+            self.raise_error("Parameters can only be defined in " + "a component type")
 
         try:
-            name = node.lattrib['name']
+            name = node.lattrib["name"]
         except:
-            self.raise_error('<Parameter> must specify a name')
+            self.raise_error("<Parameter> must specify a name")
 
         try:
-            dimension = node.lattrib['dimension']
+            dimension = node.lattrib["dimension"]
         except:
-            self.raise_error("Parameter '{0}' has no dimension",
-                             name)
+            self.raise_error("Parameter '{0}' has no dimension", name)
 
-        description = node.lattrib.get('description', '')
+        description = node.lattrib.get("description", "")
         parameter = Parameter(name, dimension, description)
 
         self.current_component_type.add_parameter(parameter)
@@ -1230,27 +1308,24 @@ def parse_property(self, node):
         """
 
         if self.current_component_type == None:
-            self.raise_error('Property can only be defined in ' +
-                             'a component type')
+            self.raise_error("Property can only be defined in " + "a component type")
 
         try:
-            name = node.lattrib['name']
+            name = node.lattrib["name"]
         except:
-            self.raise_error('<Property> must specify a name')
+            self.raise_error("<Property> must specify a name")
 
         try:
-            dimension = node.lattrib['dimension']
+            dimension = node.lattrib["dimension"]
         except:
-            self.raise_error("Property '{0}' has no dimension",
-                             name)
+            self.raise_error("Property '{0}' has no dimension", name)
 
-        default_value = node.lattrib.get('defaultvalue', None)
+        default_value = node.lattrib.get("defaultvalue", None)
 
         property = Property(name, dimension, default_value=default_value)
 
         self.current_component_type.add_property(property)
 
-
     def parse_index_parameter(self, node):
         """
         Parses <IndexParameter>
@@ -1262,20 +1337,19 @@ def parse_index_parameter(self, node):
         """
 
         if self.current_component_type == None:
-            self.raise_error('IndexParameters can only be defined in ' +
-                             'a component type')
+            self.raise_error(
+                "IndexParameters can only be defined in " + "a component type"
+            )
 
         try:
-            name = node.lattrib['name']
+            name = node.lattrib["name"]
         except:
-            self.raise_error('<IndexParameter> must specify a name')
-
+            self.raise_error("<IndexParameter> must specify a name")
 
         index_parameter = IndexParameter(name)
 
         self.current_component_type.add_index_parameter(index_parameter)
 
-
     def parse_tunnel(self, node):
         """
         Parses <Tunnel>
@@ -1287,32 +1361,30 @@ def parse_tunnel(self, node):
         """
 
         try:
-            name = node.lattrib['name']
+            name = node.lattrib["name"]
         except:
-            self.raise_error('<Tunnel> must specify a name')
+            self.raise_error("<Tunnel> must specify a name")
         try:
-            end_a = node.lattrib['enda']
+            end_a = node.lattrib["enda"]
         except:
-            self.raise_error('<Tunnel> must specify: endA')
+            self.raise_error("<Tunnel> must specify: endA")
         try:
-            end_b = node.lattrib['enda']
+            end_b = node.lattrib["enda"]
         except:
-            self.raise_error('<Tunnel> must specify: endB')
+            self.raise_error("<Tunnel> must specify: endB")
         try:
-            component_a = node.lattrib['componenta']
+            component_a = node.lattrib["componenta"]
         except:
-            self.raise_error('<Tunnel> must specify: componentA')
+            self.raise_error("<Tunnel> must specify: componentA")
         try:
-            component_b = node.lattrib['componentb']
+            component_b = node.lattrib["componentb"]
         except:
-            self.raise_error('<Tunnel> must specify: componentB')
-
+            self.raise_error("<Tunnel> must specify: componentB")
 
         tunnel = Tunnel(name, end_a, end_b, component_a, component_b)
 
         self.current_structure.add_tunnel(tunnel)
 
-
     def parse_path(self, node):
         """
         Parses <Path>
@@ -1321,12 +1393,12 @@ def parse_path(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'name' in node.lattrib:
-            name = node.lattrib['name']
+        if "name" in node.lattrib:
+            name = node.lattrib["name"]
         else:
-            self.raise_error('<Path> must specify a name.')
+            self.raise_error("<Path> must specify a name.")
 
-        description = node.lattrib.get('description', '')
+        description = node.lattrib.get("description", "")
 
         self.current_component_type.add_path(Path(name, description))
 
@@ -1339,17 +1411,18 @@ def parse_record(self, node):
         """
 
         if self.current_simulation == None:
-            self.raise_error('<Record> must be only be used inside a ' +
-                             'simulation specification')
+            self.raise_error(
+                "<Record> must be only be used inside a " + "simulation specification"
+            )
 
-        if 'quantity' in node.lattrib:
-            quantity = node.lattrib['quantity']
+        if "quantity" in node.lattrib:
+            quantity = node.lattrib["quantity"]
         else:
-            self.raise_error('<Record> must specify a quantity.')
+            self.raise_error("<Record> must specify a quantity.")
 
-        scale = node.lattrib.get('scale', None)
-        color  = node.lattrib.get('color', None)
-        id  = node.lattrib.get('id', None)
+        scale = node.lattrib.get("scale", None)
+        color = node.lattrib.get("color", None)
+        id = node.lattrib.get("id", None)
 
         self.current_simulation.add_record(Record(quantity, scale, color, id))
 
@@ -1362,19 +1435,20 @@ def parse_event_record(self, node):
         """
 
         if self.current_simulation == None:
-            self.raise_error('<EventRecord> must be only be used inside a ' +
-                             'simulation specification')
+            self.raise_error(
+                "<EventRecord> must be only be used inside a "
+                + "simulation specification"
+            )
 
-        if 'quantity' in node.lattrib:
-            quantity = node.lattrib['quantity']
+        if "quantity" in node.lattrib:
+            quantity = node.lattrib["quantity"]
         else:
-            self.raise_error('<EventRecord> must specify a quantity.')
+            self.raise_error("<EventRecord> must specify a quantity.")
 
-        if 'eventport' in node.lattrib:
-            eventPort = node.lattrib['eventport']
+        if "eventport" in node.lattrib:
+            eventPort = node.lattrib["eventport"]
         else:
-            self.raise_error('<EventRecord> must specify an eventPort.')
-
+            self.raise_error("<EventRecord> must specify an eventPort.")
 
         self.current_simulation.add_event_record(EventRecord(quantity, eventPort))
 
@@ -1386,13 +1460,13 @@ def parse_regime(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'name' in node.lattrib:
-            name = node.lattrib['name']
+        if "name" in node.lattrib:
+            name = node.lattrib["name"]
         else:
-            name = ''
+            name = ""
 
-        if 'initial' in node.lattrib:
-            initial = (node.lattrib['initial'].strip().lower() == 'true')
+        if "initial" in node.lattrib:
+            initial = node.lattrib["initial"].strip().lower() == "true"
         else:
             initial = False
 
@@ -1413,18 +1487,20 @@ def parse_requirement(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'name' in node.lattrib:
-            name = node.lattrib['name']
+        if "name" in node.lattrib:
+            name = node.lattrib["name"]
         else:
-            self.raise_error('<Requirement> must specify a name')
+            self.raise_error("<Requirement> must specify a name")
 
-        if 'dimension' in node.lattrib:
-            dimension = node.lattrib['dimension']
+        if "dimension" in node.lattrib:
+            dimension = node.lattrib["dimension"]
         else:
-            self.raise_error("Requirement \{0}' must specify a dimension.", name)
+            self.raise_error("Requirement %s must specify a dimension." % name)
 
-        description = node.lattrib.get('description', '')
-        self.current_component_type.add_requirement(Requirement(name, dimension, description))
+        description = node.lattrib.get("description", "")
+        self.current_component_type.add_requirement(
+            Requirement(name, dimension, description)
+        )
 
     def parse_component_requirement(self, node):
         """
@@ -1434,12 +1510,14 @@ def parse_component_requirement(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'name' in node.lattrib:
-            name = node.lattrib['name']
+        if "name" in node.lattrib:
+            name = node.lattrib["name"]
         else:
-            self.raise_error('<ComponentRequirement> must specify a name')
+            self.raise_error("<ComponentRequirement> must specify a name")
 
-        self.current_component_type.add_component_requirement(ComponentRequirement(name))
+        self.current_component_type.add_component_requirement(
+            ComponentRequirement(name)
+        )
 
     def parse_instance_requirement(self, node):
         """
@@ -1449,17 +1527,19 @@ def parse_instance_requirement(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'name' in node.lattrib:
-            name = node.lattrib['name']
+        if "name" in node.lattrib:
+            name = node.lattrib["name"]
         else:
-            self.raise_error('<InstanceRequirement> must specify a name')
+            self.raise_error("<InstanceRequirement> must specify a name")
 
-        if 'type' in node.lattrib:
-            type = node.lattrib['type']
+        if "type" in node.lattrib:
+            type = node.lattrib["type"]
         else:
-            self.raise_error("InstanceRequirement \{0}' must specify a type.", name)
+            self.raise_error("InstanceRequirement %s must specify a type." % name)
 
-        self.current_component_type.add_instance_requirement(InstanceRequirement(name, type))
+        self.current_component_type.add_instance_requirement(
+            InstanceRequirement(name, type)
+        )
 
     def parse_run(self, node):
         """
@@ -1469,27 +1549,29 @@ def parse_run(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'component' in node.lattrib:
-            component = node.lattrib['component']
+        if "component" in node.lattrib:
+            component = node.lattrib["component"]
         else:
-            self.raise_error('<Run> must specify a target component')
+            self.raise_error("<Run> must specify a target component")
 
-        if 'variable' in node.lattrib:
-            variable = node.lattrib['variable']
+        if "variable" in node.lattrib:
+            variable = node.lattrib["variable"]
         else:
-            self.raise_error('<Run> must specify a state variable')
+            self.raise_error("<Run> must specify a state variable")
 
-        if 'increment' in node.lattrib:
-            increment = node.lattrib['increment']
+        if "increment" in node.lattrib:
+            increment = node.lattrib["increment"]
         else:
-            self.raise_error('<Run> must specify an increment for the ' +
-                             'state variable')
+            self.raise_error(
+                "<Run> must specify an increment for the " + "state variable"
+            )
 
-        if 'total' in node.lattrib:
-            total = node.lattrib['total']
+        if "total" in node.lattrib:
+            total = node.lattrib["total"]
         else:
-            self.raise_error('<Run> must specify a final value for the ' +
-                             'state variable')
+            self.raise_error(
+                "<Run> must specify a final value for the " + "state variable"
+            )
 
         self.current_simulation.add_run(Run(component, variable, increment, total))
 
@@ -1525,22 +1607,22 @@ def parse_state_assignment(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'variable' in node.lattrib:
-            variable = node.lattrib['variable']
+        if "variable" in node.lattrib:
+            variable = node.lattrib["variable"]
         else:
-            self.raise_error('<StateAssignment> must specify a variable name')
+            self.raise_error("<StateAssignment> must specify a variable name")
 
-        if 'value' in node.lattrib:
-            value = node.lattrib['value']
+        if "value" in node.lattrib:
+            value = node.lattrib["value"]
         else:
-            self.raise_error("State assignment for '{0}' must specify a value.",
-                             variable)
+            self.raise_error(
+                "State assignment for '{0}' must specify a value.", variable
+            )
 
         action = StateAssignment(variable, value)
 
         self.current_event_handler.add_action(action)
 
-
     def parse_state_variable(self, node):
         """
         Parses <StateVariable>
@@ -1551,18 +1633,18 @@ def parse_state_variable(self, node):
         :raises ParseError: Raised when the state variable is not being defined in the context of a component type.
         """
 
-        if 'name' in node.lattrib:
-            name = node.lattrib['name']
+        if "name" in node.lattrib:
+            name = node.lattrib["name"]
         else:
-            self.raise_error('<StateVariable> must specify a name')
+            self.raise_error("<StateVariable> must specify a name")
 
-        if 'dimension' in node.lattrib:
-            dimension = node.lattrib['dimension']
+        if "dimension" in node.lattrib:
+            dimension = node.lattrib["dimension"]
         else:
             self.raise_error("State variable '{0}' must specify a dimension", name)
 
-        if 'exposure' in node.lattrib:
-            exposure = node.lattrib['exposure']
+        if "exposure" in node.lattrib:
+            exposure = node.lattrib["exposure"]
         else:
             exposure = None
 
@@ -1588,7 +1670,7 @@ def parse_target(self, node):
         :type node: xml.etree.Element
         """
 
-        self.model.add_target(node.lattrib['component'])
+        self.model.add_target(node.lattrib["component"])
 
     def parse_text(self, node):
         """
@@ -1598,12 +1680,12 @@ def parse_text(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'name' in node.lattrib:
-            name = node.lattrib['name']
+        if "name" in node.lattrib:
+            name = node.lattrib["name"]
         else:
-            self.raise_error('<Text> must specify a name.')
+            self.raise_error("<Text> must specify a name.")
 
-        description = node.lattrib.get('description', '')
+        description = node.lattrib.get("description", "")
 
         self.current_component_type.add_text(Text(name, description))
 
@@ -1617,16 +1699,17 @@ def parse_time_derivative(self, node):
         :raises ParseError: Raised when the time derivative does not hava a variable name of a value.
         """
 
-        if 'variable' in node.lattrib:
-            variable = node.lattrib['variable']
+        if "variable" in node.lattrib:
+            variable = node.lattrib["variable"]
         else:
-            self.raise_error('<TimeDerivative> must specify a variable.')
+            self.raise_error("<TimeDerivative> must specify a variable.")
 
-        if 'value' in node.lattrib:
-            value = node.lattrib['value']
+        if "value" in node.lattrib:
+            value = node.lattrib["value"]
         else:
-            self.raise_error("Time derivative for '{0}' must specify an expression.",
-                             variable)
+            self.raise_error(
+                "Time derivative for '{0}' must specify an expression.", variable
+            )
 
         self.current_regime.add_time_derivative(TimeDerivative(variable, value))
 
@@ -1638,10 +1721,10 @@ def parse_transition(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'regime' in node.lattrib:
-            regime = node.lattrib['regime']
+        if "regime" in node.lattrib:
+            regime = node.lattrib["regime"]
         else:
-            self.raise_error('<Transition> mut specify a regime.')
+            self.raise_error("<Transition> mut specify a regime.")
 
         action = Transition(regime)
 
@@ -1659,28 +1742,28 @@ def parse_unit(self, node):
         """
 
         try:
-            symbol = node.lattrib['symbol']
-            dimension = node.lattrib['dimension']
+            symbol = node.lattrib["symbol"]
+            dimension = node.lattrib["dimension"]
         except:
-            self.raise_error('Unit must have a symbol and dimension.')
+            self.raise_error("Unit must have a symbol and dimension.")
 
-        if 'power' in node.lattrib:
-            power = int(node.lattrib['power'])
+        if "power" in node.lattrib:
+            power = int(node.lattrib["power"])
         else:
             power = 0
 
-        if 'name' in node.lattrib:
-            name = node.lattrib['name']
+        if "name" in node.lattrib:
+            name = node.lattrib["name"]
         else:
-            name = ''
+            name = ""
 
-        if 'scale' in node.lattrib:
-            scale = float(node.lattrib['scale'])
+        if "scale" in node.lattrib:
+            scale = float(node.lattrib["scale"])
         else:
             scale = 1.0
 
-        if 'offset' in node.lattrib:
-            offset = float(node.lattrib['offset'])
+        if "offset" in node.lattrib:
+            offset = float(node.lattrib["offset"])
         else:
             offset = 0.0
 
@@ -1694,21 +1777,20 @@ def parse_with(self, node):
         :type node: xml.etree.Element
         """
 
-        if 'instance' in node.lattrib:
-            instance = node.lattrib['instance']
+        if "instance" in node.lattrib:
+            instance = node.lattrib["instance"]
             list = None
             index = None
-        elif 'list' in node.lattrib and 'index' in node.lattrib:
+        elif "list" in node.lattrib and "index" in node.lattrib:
             instance = None
-            list = node.lattrib['list']
-            index = node.lattrib['index']
+            list = node.lattrib["list"]
+            index = node.lattrib["index"]
         else:
-            self.raise_error('<With> must specify EITHER instance OR list & index')
+            self.raise_error("<With> must specify EITHER instance OR list & index")
 
-        if 'as' in node.lattrib:
-            as_ = node.lattrib['as']
+        if "as" in node.lattrib:
+            as_ = node.lattrib["as"]
         else:
-            self.raise_error('<With> must specify a name for the '
-                             'target instance')
+            self.raise_error("<With> must specify a name for the " "target instance")
 
         self.current_structure.add_with(With(instance, as_, list, index))
diff --git a/lems/parser/expr.py b/lems/parser/expr.py
index 46af8d5..ee9cebf 100644
--- a/lems/parser/expr.py
+++ b/lems/parser/expr.py
@@ -8,7 +8,23 @@
 from lems.base.base import LEMSBase
 from lems.base.stack import Stack
 
-known_functions = ['exp', 'log', 'sqrt', 'sin', 'cos', 'tan', 'sinh', 'cosh', 'tanh', 'abs', 'ceil', 'factorial', 'random', 'H']
+known_functions = [
+    "exp",
+    "log",
+    "sqrt",
+    "sin",
+    "cos",
+    "tan",
+    "sinh",
+    "cosh",
+    "tanh",
+    "abs",
+    "ceil",
+    "factorial",
+    "random",
+    "H",
+]
+
 
 class ExprNode(LEMSBase):
     """
@@ -31,6 +47,7 @@ def __init__(self, type):
         """ Node type.
         :type: enum(ExprNode.OP, ExprNode.VALUE) """
 
+
 class ValueNode(ExprNode):
     """
     Value node in an expression parse tree. This will always be a leaf node.
@@ -48,29 +65,29 @@ def __init__(self, value):
         self.value = value
         """ Value to be stored in this node.
         :type: string """
-        
+
     def clean_up(self):
         """
         To make sure an integer is returned as a float. No division by integers!!
         """
         try:
-            return str(float(self.value)) 
+            return str(float(self.value))
         except ValueError:
             return self.value
-                
 
     def __str__(self):
         """
         Generates a string representation of this node.
         """
         return "{" + self.clean_up() + "}"
-    
+
     def __repr__(self):
         return self.__str__()
-    
+
     def to_python_expr(self):
         return self.clean_up()
 
+
 class OpNode(ExprNode):
     """
     Operation node in an expression parse tree. This will always be a
@@ -110,17 +127,16 @@ def __str__(self):
         Generates a string representation of this node.
         """
 
-        return '({0} {1} {2})'.format(self.op,
-                                      str(self.left),
-                                      str(self.right))
-                                      
+        return "({0} {1} {2})".format(self.op, str(self.left), str(self.right))
+
     def __repr__(self):
         return self.__str__()
-    
+
     def to_python_expr(self):
-        return '({0} {1} {2})'.format(self.left.to_python_expr(),
-                                      self.op,
-                                      self.right.to_python_expr())
+        return "({0} {1} {2})".format(
+            self.left.to_python_expr(), self.op, self.right.to_python_expr()
+        )
+
 
 class Func1Node(ExprNode):
     """
@@ -154,42 +170,43 @@ def __str__(self):
         Generates a string representation of this node.
         """
 
-        return '({0} {1})'.format(self.func, str(self.param))
-    
+        return "({0} {1})".format(self.func, str(self.param))
+
     def __repr__(self):
         return self.__str__()
-    
+
     def to_python_expr(self):
-        return '({0}({1}))'.format(self.func, self.param.to_python_expr())
+        return "({0}({1}))".format(self.func, self.param.to_python_expr())
 
 
 class ExprParser(LEMSBase):
     """
     Parser class for parsing an expression and generating a parse tree.
     """
-    
+
     debug = False
 
     op_priority = {
-        '$':-5,
-        'func':8,
-        '+':5,
-        '-':5,
-        '*':6,
-        '/':6,
-        '^':7,
-        '~':8,
-        'exp':8,
-        '.and.':1,
-        '.or.':1,
-        '.gt.':2,
-        '.ge.':2,
-        '.geq.':2,
-        '.lt.':2,
-        '.le.':2,
-        '.eq.':2,
-        '.neq.':2,
-        '.ne.':2}  # .neq. is preferred!
+        "$": -5,
+        "func": 8,
+        "+": 5,
+        "-": 5,
+        "*": 6,
+        "/": 6,
+        "^": 7,
+        "~": 8,
+        "exp": 8,
+        ".and.": 1,
+        ".or.": 1,
+        ".gt.": 2,
+        ".ge.": 2,
+        ".geq.": 2,
+        ".lt.": 2,
+        ".le.": 2,
+        ".eq.": 2,
+        ".neq.": 2,
+        ".ne.": 2,
+    }  # .neq. is preferred!
 
     depth = 0
 
@@ -249,15 +266,15 @@ def is_sym(self, str):
         :rtype: Boolean
         """
 
-        return str in ['+', '-', '~', '*', '/', '^', '(', ')']
+        return str in ["+", "-", "~", "*", "/", "^", "(", ")"]
 
     def priority(self, op):
         if self.is_op(op):
             return self.op_priority[op]
         elif self.is_func(op):
-            return self.op_priority['func']
+            return self.op_priority["func"]
         else:
-            return self.op_priority['$']
+            return self.op_priority["$"]
 
     def tokenize(self):
         """
@@ -275,52 +292,55 @@ def tokenize(self):
             i += 1
 
         while i < len(ps):
-            token = ''
+            token = ""
 
             if ps[i].isalpha():
-                while i < len(ps) and (ps[i].isalnum() or ps[i] == '_'):
+                while i < len(ps) and (ps[i].isalnum() or ps[i] == "_"):
                     token += ps[i]
                     i += 1
             elif ps[i].isdigit():
-                while i < len(ps) and (ps[i].isdigit() or
-                                       ps[i] == '.' or
-                                       ps[i] == 'e' or
-                                       ps[i] == 'E' or
-                                       (ps[i] == '+' and (ps[i-1] == 'e' or ps[i-1] == 'E')) or
-                                       (ps[i] == '-' and (ps[i-1] == 'e' or ps[i-1] == 'E'))):
+                while i < len(ps) and (
+                    ps[i].isdigit()
+                    or ps[i] == "."
+                    or ps[i] == "e"
+                    or ps[i] == "E"
+                    or (ps[i] == "+" and (ps[i - 1] == "e" or ps[i - 1] == "E"))
+                    or (ps[i] == "-" and (ps[i - 1] == "e" or ps[i - 1] == "E"))
+                ):
                     token += ps[i]
                     i += 1
-            elif ps[i] == '.':
-                if ps[i+1].isdigit():
-                    while i < len(ps) and (ps[i].isdigit() or ps[i] == '.'):
+            elif ps[i] == ".":
+                if ps[i + 1].isdigit():
+                    while i < len(ps) and (ps[i].isdigit() or ps[i] == "."):
                         token += ps[i]
                         i += 1
                 else:
-                    while i < len(ps) and (ps[i].isalpha() or ps[i] == '.'):
+                    while i < len(ps) and (ps[i].isalpha() or ps[i] == "."):
                         token += ps[i]
                         i += 1
             else:
                 token += ps[i]
                 i += 1
 
-            if token == '-' and \
-               (last_token == None or last_token == '(' or self.is_op(last_token)):
-                token = '~'
+            if token == "-" and (
+                last_token == None or last_token == "(" or self.is_op(last_token)
+            ):
+                token = "~"
 
             self.token_list += [token]
             last_token = token
 
             while i < len(ps) and ps[i].isspace():
                 i += 1
-                
+
     def make_op_node(self, op, right):
         if self.is_func(op):
             return Func1Node(op, right)
-        elif op == '~':
-            return OpNode('-', ValueNode('0'), right)
+        elif op == "~":
+            return OpNode("-", ValueNode("0"), right)
         else:
             left = self.val_stack.pop()
-            if left == '$':
+            if left == "$":
                 left = self.node_stack.pop()
             else:
                 left = ValueNode(left)
@@ -329,22 +349,32 @@ def make_op_node(self, op, right):
 
     def cleanup_stacks(self):
         right = self.val_stack.pop()
-        if right == '$':
+        if right == "$":
             right = self.node_stack.pop()
         else:
             right = ValueNode(right)
-            
-        if self.debug: print('- Cleanup > right: %s'% right)
-        
-        while self.op_stack.top() != '$':
-            if self.debug: print('5> op stack: %s, val stack: %s, node stack: %s'% ( self.op_stack, self.val_stack, self.node_stack))
+
+        if self.debug:
+            print("- Cleanup > right: %s" % right)
+
+        while self.op_stack.top() != "$":
+            if self.debug:
+                print(
+                    "5> op stack: %s, val stack: %s, node stack: %s"
+                    % (self.op_stack, self.val_stack, self.node_stack)
+                )
             op = self.op_stack.pop()
 
             right = self.make_op_node(op, right)
 
-            if self.debug: print('6> op stack: %s, val stack: %s, node stack: %s'% ( self.op_stack, self.val_stack, self.node_stack))
-            if self.debug: print('7> %s'% right)
-            #if self.debug: print(''
+            if self.debug:
+                print(
+                    "6> op stack: %s, val stack: %s, node stack: %s"
+                    % (self.op_stack, self.val_stack, self.node_stack)
+                )
+            if self.debug:
+                print("7> %s" % right)
+            # if self.debug: print(''
 
         return right
 
@@ -363,7 +393,8 @@ def parse_token_list_rec(self, min_precedence):
         exit_loop = False
 
         ExprParser.depth = ExprParser.depth + 1
-        if self.debug: print('>>>>> Depth: %i'% ExprParser.depth)
+        if self.debug:
+            print(">>>>> Depth: %i" % ExprParser.depth)
 
         precedence = min_precedence
 
@@ -371,107 +402,161 @@ def parse_token_list_rec(self, min_precedence):
             token = self.token_list[0]
             la = self.token_list[1] if len(self.token_list) > 1 else None
 
-            if self.debug: print('0> %s'% self.token_list)
-            if self.debug: print('1> Token: %s, next: %s, op stack: %s, val stack: %s, node stack: %s'% (token, la, self.op_stack, self.val_stack, self.node_stack))
+            if self.debug:
+                print("0> %s" % self.token_list)
+            if self.debug:
+                print(
+                    "1> Token: %s, next: %s, op stack: %s, val stack: %s, node stack: %s"
+                    % (token, la, self.op_stack, self.val_stack, self.node_stack)
+                )
 
             self.token_list = self.token_list[1:]
-            
+
             close_bracket = False
-            
-            if token == '(':
-                np = ExprParser('')
+
+            if token == "(":
+                np = ExprParser("")
                 np.token_list = self.token_list
 
                 nexp = np.parse2()
 
                 self.node_stack.push(nexp)
-                self.val_stack.push('$')
+                self.val_stack.push("$")
 
                 self.token_list = np.token_list
-                if self.debug: print('>>> Tokens left: %s'%self.token_list)
+                if self.debug:
+                    print(">>> Tokens left: %s" % self.token_list)
                 close_bracket = True
-            elif token == ')':
+            elif token == ")":
                 break
             elif self.is_func(token):
                 self.op_stack.push(token)
             elif self.is_op(token):
                 stack_top = self.op_stack.top()
-                if self.debug: print('OP Token: %s (prior: %i), top: %s (prior: %i)'% (token, self.priority(token), stack_top, self.priority(stack_top)))
+                if self.debug:
+                    print(
+                        "OP Token: %s (prior: %i), top: %s (prior: %i)"
+                        % (
+                            token,
+                            self.priority(token),
+                            stack_top,
+                            self.priority(stack_top),
+                        )
+                    )
                 if self.priority(token) < self.priority(stack_top):
-                    if self.debug: print('  Priority of %s is less than %s'%(token, stack_top))
+                    if self.debug:
+                        print("  Priority of %s is less than %s" % (token, stack_top))
                     self.node_stack.push(self.cleanup_stacks())
-                    self.val_stack.push('$')
+                    self.val_stack.push("$")
                 else:
-                    if self.debug: print('  Priority of %s is greater than %s'%(token, stack_top))
-                
+                    if self.debug:
+                        print(
+                            "  Priority of %s is greater than %s" % (token, stack_top)
+                        )
 
                 self.op_stack.push(token)
             else:
-                if self.debug: print('Not a bracket func or op...')
-                if la == '(':
-                    raise Exception("Error parsing expression: %s\nToken: %s is placed like a function but is not recognised!\nKnown functions: %s"%(self.parse_string, token, known_functions))
+                if self.debug:
+                    print("Not a bracket func or op...")
+                if la == "(":
+                    raise Exception(
+                        "Error parsing expression: %s\nToken: %s is placed like a function but is not recognised!\nKnown functions: %s"
+                        % (self.parse_string, token, known_functions)
+                    )
                 stack_top = self.op_stack.top()
-                if stack_top == '$':
-                    if self.debug: print("option a")
+                if stack_top == "$":
+                    if self.debug:
+                        print("option a")
                     self.node_stack.push(ValueNode(token))
-                    self.val_stack.push('$')
+                    self.val_stack.push("$")
                 else:
-                    if (self.is_op(la) and
-                        self.priority(stack_top) < self.priority(la)):
-                        if self.debug: print("option b")
+                    if self.is_op(la) and self.priority(stack_top) < self.priority(la):
+                        if self.debug:
+                            print("option b")
 
                         self.node_stack.push(ValueNode(token))
-                        self.val_stack.push('$')
+                        self.val_stack.push("$")
                     else:
-                        if self.debug: print("option c, nodes: %s"% self.node_stack)
+                        if self.debug:
+                            print("option c, nodes: %s" % self.node_stack)
                         op = self.op_stack.pop()
 
                         right = ValueNode(token)
-                        op_node = self.make_op_node(op,right)
+                        op_node = self.make_op_node(op, right)
 
                         self.node_stack.push(op_node)
-                        self.val_stack.push('$')
-                        
+                        self.val_stack.push("$")
+
             if close_bracket:
                 stack_top = self.op_stack.top()
-                if self.debug: print("+ Closing bracket, op stack: %s, node stack: %s la: %s"%(self.op_stack, self.node_stack, la))
-                if self.debug: print('>>> Tokens left: %s'%self.token_list)
-                
-                if stack_top == '$':
-                    if self.debug: print("+ option a")
-                    '''
+                if self.debug:
+                    print(
+                        "+ Closing bracket, op stack: %s, node stack: %s la: %s"
+                        % (self.op_stack, self.node_stack, la)
+                    )
+                if self.debug:
+                    print(">>> Tokens left: %s" % self.token_list)
+
+                if stack_top == "$":
+                    if self.debug:
+                        print("+ option a")
+                    """
                     self.node_stack.push(ValueNode(token))
-                    self.val_stack.push('$')'''
+                    self.val_stack.push('$')"""
                 else:
                     la = self.token_list[0] if len(self.token_list) > 1 else None
-                    if (self.is_op(la) and self.priority(stack_top) < self.priority(la)):
-                        if self.debug: print("+ option b")
-                        #self.node_stack.push(ValueNode(token))
-                        #self.val_stack.push('$')
+                    if self.is_op(la) and self.priority(stack_top) < self.priority(la):
+                        if self.debug:
+                            print("+ option b")
+                        # self.node_stack.push(ValueNode(token))
+                        # self.val_stack.push('$')
                     else:
-                        if self.debug: print("+ option c, nodes: %s"% self.node_stack)
-                        if self.debug: print('35> op stack: %s, val stack: %s, node stack: %s'% ( self.op_stack, self.val_stack, self.node_stack))
+                        if self.debug:
+                            print("+ option c, nodes: %s" % self.node_stack)
+                        if self.debug:
+                            print(
+                                "35> op stack: %s, val stack: %s, node stack: %s"
+                                % (self.op_stack, self.val_stack, self.node_stack)
+                            )
                         right = self.node_stack.pop()
                         op = self.op_stack.pop()
-                        op_node = self.make_op_node(stack_top,right)
-                        if self.debug: print("Made op node: %s, right: %s"%(op_node, right))
+                        op_node = self.make_op_node(stack_top, right)
+                        if self.debug:
+                            print("Made op node: %s, right: %s" % (op_node, right))
 
                         self.node_stack.push(op_node)
-                        self.val_stack.push('$')
-                        if self.debug: print('36> op stack: %s, val stack: %s, node stack: %s'% ( self.op_stack, self.val_stack, self.node_stack))
-                        
-            
-
-            if self.debug: print('2> Token: %s, next: %s, op stack: %s, val stack: %s, node stack: %s'% (token, la, self.op_stack, self.val_stack, self.node_stack))
-            if self.debug: print('')
-
-        if self.debug: print('3> op stack: %s, val stack: %s, node stack: %s'% ( self.op_stack, self.val_stack, self.node_stack))
+                        self.val_stack.push("$")
+                        if self.debug:
+                            print(
+                                "36> op stack: %s, val stack: %s, node stack: %s"
+                                % (self.op_stack, self.val_stack, self.node_stack)
+                            )
+
+            if self.debug:
+                print(
+                    "2> Token: %s, next: %s, op stack: %s, val stack: %s, node stack: %s"
+                    % (token, la, self.op_stack, self.val_stack, self.node_stack)
+                )
+            if self.debug:
+                print("")
+
+        if self.debug:
+            print(
+                "3> op stack: %s, val stack: %s, node stack: %s"
+                % (self.op_stack, self.val_stack, self.node_stack)
+            )
         ret = self.cleanup_stacks()
 
-        if self.debug: print('4> op stack: %s, val stack: %s, node stack: %s'% ( self.op_stack, self.val_stack, self.node_stack))
-        if self.debug: print('<<<<< Depth: %s, returning: %s'% (ExprParser.depth, ret))
+        if self.debug:
+            print(
+                "4> op stack: %s, val stack: %s, node stack: %s"
+                % (self.op_stack, self.val_stack, self.node_stack)
+            )
+        if self.debug:
+            print("<<<<< Depth: %s, returning: %s" % (ExprParser.depth, ret))
         ExprParser.depth = ExprParser.depth - 1
-        if self.debug: print('')
+        if self.debug:
+            print("")
         return ret
 
     def parse(self):
@@ -481,14 +566,15 @@ def parse(self):
         :return: Returns a token string.
         :rtype: lems.parser.expr.ExprNode
         """
-        #print("Parsing: %s"%self.parse_string)
+        # print("Parsing: %s"%self.parse_string)
         self.tokenize()
-        if self.debug: print("Tokens found: %s"%self.token_list)
-        
+        if self.debug:
+            print("Tokens found: %s" % self.token_list)
+
         try:
             parse_tree = self.parse2()
         except Exception as e:
-                raise e
+            raise e
         return parse_tree
 
     def parse2(self):
@@ -496,13 +582,13 @@ def parse2(self):
         self.val_stack = Stack()
         self.node_stack = Stack()
 
-        self.op_stack.push('$')
-        self.val_stack.push('$')
+        self.op_stack.push("$")
+        self.val_stack.push("$")
         try:
-            ret = self.parse_token_list_rec(self.op_priority['$'])
+            ret = self.parse_token_list_rec(self.op_priority["$"])
         except Exception as e:
             raise e
-    
+
         return ret
 
     def __str__(self):
diff --git a/lems/run.py b/lems/run.py
index 84a4097..c899aa3 100644
--- a/lems/run.py
+++ b/lems/run.py
@@ -9,42 +9,51 @@
 
 from lems.model.model import Model
 from lems.sim.build import SimulationBuilder
-from lems.model.simulation import DataDisplay,DataWriter
+from lems.model.simulation import DataDisplay, DataWriter
 
 
 dlems_info = "dLEMS (distilled LEMS in JSON format, see https://github.com/borismarin/som-codegen)"
-    
+
 
 def process_args():
-    """ 
+    """
     Parse command-line arguments.
     """
     parser = argparse.ArgumentParser()
 
-    parser.add_argument('-I', type=str,
-                        metavar='<Include directory>',
-                        action='append',
-                        help='Directory to be searched for included files')
-                        
-                        
-    parser.add_argument('lems_file', type=str, metavar='<LEMS file>', 
-                        help='LEMS file to be simulated')
-                        
-    parser.add_argument('-nogui',
-                        action='store_true',
-                        help="If this is specified, just parse & simulate the model, but don't show any plots")
-                        
-    parser.add_argument('-dlems',
-                        action='store_true',
-                        help="If this is specified, export the LEMS file as "+dlems_info)
-    
+    parser.add_argument(
+        "-I",
+        type=str,
+        metavar="<Include directory>",
+        action="append",
+        help="Directory to be searched for included files",
+    )
+
+    parser.add_argument(
+        "lems_file", type=str, metavar="<LEMS file>", help="LEMS file to be simulated"
+    )
+
+    parser.add_argument(
+        "-nogui",
+        action="store_true",
+        help="If this is specified, just parse & simulate the model, but don't show any plots",
+    )
+
+    parser.add_argument(
+        "-dlems",
+        action="store_true",
+        help="If this is specified, export the LEMS file as " + dlems_info,
+    )
+
     return parser.parse_args()
 
-def run(file_path,include_dirs=[],dlems=False,nogui=False):
+
+def run(file_path, include_dirs=[], dlems=False, nogui=False):
     """
     Function for running from a script or shell.
     """
     import argparse
+
     args = argparse.Namespace()
     args.lems_file = file_path
     args.I = include_dirs
@@ -52,89 +61,96 @@ def run(file_path,include_dirs=[],dlems=False,nogui=False):
     args.nogui = nogui
     main(args=args)
 
+
 def main(args=None):
     """
     Program entry point.
     """
-    
+
     if args is None:
         args = process_args()
-    
-    print('Parsing and resolving model: '+args.lems_file)
+
+    print("Parsing and resolving model: " + args.lems_file)
     model = Model()
     if args.I is not None:
         for dir in args.I:
             model.add_include_directory(dir)
     model.import_from_file(args.lems_file)
-    
+
     resolved_model = model.resolve()
-    
-    print('Building simulation')
+
+    print("Building simulation")
     sim = SimulationBuilder(resolved_model).build()
-    #sim.dump("Afterbuild:")
+    # sim.dump("Afterbuild:")
 
     if args.dlems:
-        print('Exporting as: '+dlems_info)
-        
+        print("Exporting as: " + dlems_info)
+
         from lems.dlems.exportdlems import export_component
-        
+
         target = model.targets[0]
 
         sim_comp = model.components[target]
 
-        target_net = sim_comp.parameters['target']
+        target_net = sim_comp.parameters["target"]
 
         target_comp = model.components[target_net]
-        
-        dlems_file_name = args.lems_file.replace('.xml', '.json')
+
+        dlems_file_name = args.lems_file.replace(".xml", ".json")
         if dlems_file_name == args.lems_file:
-            dlems_file_name = args.lems_file + '.json'
+            dlems_file_name = args.lems_file + ".json"
 
-        if target_comp.type == 'network':
+        if target_comp.type == "network":
 
             for child in target_comp.children:
 
-                if child.type == 'population':
+                if child.type == "population":
 
-                    comp =  model.components[child.parameters['component']]
+                    comp = model.components[child.parameters["component"]]
 
-                    export_component(model, comp, sim_comp, child.id, file_name=dlems_file_name)
+                    export_component(
+                        model, comp, sim_comp, child.id, file_name=dlems_file_name
+                    )
         else:
             export_component(model, sim_comp, target_comp)
-    
+
     else:
-        print('Running simulation')
+        print("Running simulation")
         sim.run()
         process_simulation_output(sim, model, args)
-    
+
+
 fig_count = 0
 
+
 def process_simulation_output(sim, model, options):
     global fig_count
 
-    print('Processing results')
+    print("Processing results")
     rq = []
     for rn in sim.runnables:
         rq.append(sim.runnables[rn])
 
     file_times = {}
     file_outs = {}
-    
+
     display_order = {}
     file_column_order = {}
-    
+
     simulation = model.components[model.targets[0]]
     for c in simulation.children:
-        if c.type == 'Display':
-            display_order[c.parameters['title']] = []
+        if c.type == "Display":
+            display_order[c.parameters["title"]] = []
             for l in c.children:
-                display_order[c.parameters['title']].append(l.parameters['quantity'])
-                
-        if c.type == 'OutputFile':
-            file_column_order[c.parameters['fileName']] = []
+                display_order[c.parameters["title"]].append(l.parameters["quantity"])
+
+        if c.type == "OutputFile":
+            file_column_order[c.parameters["fileName"]] = []
             for f in c.children:
-                file_column_order[c.parameters['fileName']].append(f.parameters['quantity'])
-                
+                file_column_order[c.parameters["fileName"]].append(
+                    f.parameters["quantity"]
+                )
+
     recordings = {}
 
     while rq != []:
@@ -152,42 +168,46 @@ def process_simulation_output(sim, model, options):
                     if not options.nogui:
                         if data_output.title not in recordings:
                             recordings[data_output.title] = {}
-                            
+
                         recordings[data_output.title][recording.full_path] = recording
                 elif isinstance(recording.data_output, DataWriter):
                     data_output = recording.data_output
                     times = []
                     vals = []
-                    for (x,y) in recording.values:
+                    for (x, y) in recording.values:
                         times.append(x)
                         vals.append(y)
                     file_times[data_output.file_name] = times
                     if data_output.file_name not in file_outs:
                         file_outs[data_output.file_name] = {}
-                
+
                     file_outs[data_output.file_name][recording.full_path] = vals
                 else:
-                    raise Exception("Invalid output type - " + str(type(recording.data_output)))
+                    raise Exception(
+                        "Invalid output type - " + str(type(recording.data_output))
+                    )
 
-    
-    
     for file_out_name in file_column_order.keys():
         times = file_times[file_out_name]
         vals = file_outs[file_out_name]
-        print('Going to save {0}x{1} data points to file {2}'.format(len(times),len(vals.keys()),file_out_name))
-        file_out = open(file_out_name, 'w')
-        i=0
-        
+        print(
+            "Going to save {0}x{1} data points to file {2}".format(
+                len(times), len(vals.keys()), file_out_name
+            )
+        )
+        file_out = open(file_out_name, "w")
+        i = 0
+
         for time in times:
-            file_out.write('{0}   '.format(time))
+            file_out.write("{0}   ".format(time))
             columns = file_column_order[file_out_name]
             for column in columns:
                 val = vals[column]
-                file_out.write('{0}   '.format(val[i]))
-                
-            file_out.write('\n')
+                file_out.write("{0}   ".format(val[i]))
+
+            file_out.write("\n")
             i += 1
-            
+
         file_out.close()
 
     if not options.nogui:
@@ -199,6 +219,7 @@ def process_simulation_output(sim, model, options):
 
     if fig_count > 0:
         import matplotlib.pyplot as pylab
+
         pylab.show()
 
 
@@ -208,13 +229,15 @@ def __init__(self, fig):
         self.plots = list()
         self.legend = list()
 
+
 displays = {}
 
+
 def plot_recording(recording):
-    
+
     import matplotlib.pyplot as pylab
     import numpy
-    
+
     global fig_count
 
     data_output = recording.data_output
@@ -238,17 +261,10 @@ def plot_recording(recording):
         f = pylab.figure(fig)
         pylab.title(data_output.title)
 
-
     pylab.figure(fig)
     p = pylab.subplot(111)
-    p.patch.set_facecolor('#7f7f7f')
-    plot, = pylab.plot(x, y,
-                      color=recorder.color,
-                      label=recorder.quantity)
+    p.patch.set_facecolor("#7f7f7f")
+    (plot,) = pylab.plot(x, y, color=recorder.color, label=recorder.quantity)
     displays[data_output.title].plots.append(plot)
     displays[data_output.title].legend.append(recorder.id)
     pylab.legend(displays[data_output.title].plots, displays[data_output.title].legend)
-
-
-
-
diff --git a/lems/sim/build.py b/lems/sim/build.py
index 44e9a95..09f3e1a 100644
--- a/lems/sim/build.py
+++ b/lems/sim/build.py
@@ -20,6 +20,7 @@ class SimulationBuilder(LEMSBase):
     """
     Simulation builder class.
     """
+
     debug = False
 
     def __init__(self, model):
@@ -42,7 +43,6 @@ def __init__(self, model):
 
         self.current_data_output = None
 
-
     def build(self):
         """
         Build the simulation components from the model.
@@ -55,16 +55,17 @@ def build(self):
 
         for component_id in self.model.targets:
             if component_id not in self.model.components:
-                raise SimBuildError("Unable to find target component '{0}'",
-                                    component_id)
+                raise SimBuildError(
+                    "Unable to find target component '{0}'", component_id
+                )
             component = self.model.fat_components[component_id]
 
             runnable = self.build_runnable(component)
             self.sim.add_runnable(runnable)
 
-        return self.sim 
+        return self.sim
 
-    def build_runnable(self, component, parent = None, id_ = None):
+    def build_runnable(self, component, parent=None, id_=None):
         """
         Build a runnable component from a component specification and add
         it to the simulation.
@@ -79,7 +80,11 @@ def build_runnable(self, component, parent = None, id_ = None):
 
         :raises SimBuildError: Raised when a component reference cannot be resolved.
         """
-        if self.debug: print("++++++++ Calling build_runnable of %s with parent %s"%(component, parent))
+        if self.debug:
+            print(
+                "++++++++ Calling build_runnable of %s with parent %s"
+                % (component, parent)
+            )
 
         if id_ == None:
             runnable = Runnable(component.id, component, parent)
@@ -103,60 +108,61 @@ def build_runnable(self, component, parent = None, id_ = None):
 
         for parameter in component.parameters:
             runnable.add_instance_variable(parameter.name, parameter.numeric_value)
-            
-        
+
         for property in component.properties:
-            print("\n\n*****************************************************************\n\n"+
-                  "   Property element is not stable in PyLEMS yet, see https://github.com/LEMS/pylems/issues/16\n\n"+
-                  "   Used in: %s\n\n"%property.toxml()+
-                  "*****************************************************************\n\n\n")
+            print(
+                "\n\n*****************************************************************\n\n"
+                + "   Property element is not stable in PyLEMS yet, see https://github.com/LEMS/pylems/issues/16\n\n"
+                + "   Used in: %s\n\n" % property.toxml()
+                + "*****************************************************************\n\n\n"
+            )
             runnable.add_instance_variable(property.name, property.default_value)
 
         derived_parameter_code = []
-        
+
         derived_parameter_ordering = order_derived_parameters(component)
-        
+
         for dpn in derived_parameter_ordering:
             derived_parameter = component.derived_parameters[dpn]
             runnable.add_derived_variable(derived_parameter.name)
-            
-            expression = self.build_expression_from_tree(runnable,
-                                                        None,
-                                                        derived_parameter.expression_tree)
-            
-            derived_parameter_code += ['self.{0} = ({1})'.format(
-                        derived_parameter.name,
-                        expression)]
-            derived_parameter_code += ['self.{0}_shadow = ({1})'.format(
-                        derived_parameter.name,
-                        expression)]
-       
-        suffix = ''
-        runnable.add_method('update_derived_parameters' + suffix, ['self'],
-                            derived_parameter_code)
-            
+
+            expression = self.build_expression_from_tree(
+                runnable, None, derived_parameter.expression_tree
+            )
+
+            derived_parameter_code += [
+                "self.{0} = ({1})".format(derived_parameter.name, expression)
+            ]
+            derived_parameter_code += [
+                "self.{0}_shadow = ({1})".format(derived_parameter.name, expression)
+            ]
+
+        suffix = ""
+        runnable.add_method(
+            "update_derived_parameters" + suffix, ["self"], derived_parameter_code
+        )
+
         for constant in component.constants:
             runnable.add_instance_variable(constant.name, constant.numeric_value)
 
         for text in component.texts:
             runnable.add_text_variable(text.name, text.value)
-            
+
         for link in component.links:
             runnable.add_text_variable(link.name, link.value)
 
         for ep in component.event_ports:
-            if ep.direction.lower() == 'in':
+            if ep.direction.lower() == "in":
                 runnable.add_event_in_port(ep.name)
             else:
                 runnable.add_event_out_port(ep.name)
 
-                
         dynamics = component.dynamics
         self.add_dynamics_1(component, runnable, dynamics, dynamics)
 
         for regime in dynamics.regimes:
             self.add_dynamics_1(component, runnable, regime, dynamics)
-            
+
             if regime.initial:
                 runnable.current_regime = regime.name
 
@@ -164,22 +170,32 @@ def build_runnable(self, component, parent = None, id_ = None):
             if rn not in runnable.regimes:
                 runnable.add_regime(RunnableRegime(rn))
             r = runnable.regimes[rn]
-            suffix = '_regime_' + rn
-
-            if 'update_state_variables' + suffix in runnable.__dict__: 
-                  r.update_state_variables = runnable.__dict__['update_state_variables' + suffix]
-                  
-            if 'update_derived_variables' + suffix in runnable.__dict__: 
-                r.update_derived_variables = runnable.__dict__['update_derived_variables' + suffix]
-            
-            if 'run_startup_event_handlers' + suffix in runnable.__dict__: 
-                r.run_startup_event_handlers = runnable.__dict__['run_startup_event_handlers' + suffix]
-            
-            if 'run_preprocessing_event_handlers' + suffix in runnable.__dict__: 
-                r.run_preprocessing_event_handlers = runnable.__dict__['run_preprocessing_event_handlers' + suffix]
-            
-            if 'run_postprocessing_event_handlers' + suffix in runnable.__dict__: 
-                r.run_postprocessing_event_handlers = runnable.__dict__['run_postprocessing_event_handlers' + suffix]
+            suffix = "_regime_" + rn
+
+            if "update_state_variables" + suffix in runnable.__dict__:
+                r.update_state_variables = runnable.__dict__[
+                    "update_state_variables" + suffix
+                ]
+
+            if "update_derived_variables" + suffix in runnable.__dict__:
+                r.update_derived_variables = runnable.__dict__[
+                    "update_derived_variables" + suffix
+                ]
+
+            if "run_startup_event_handlers" + suffix in runnable.__dict__:
+                r.run_startup_event_handlers = runnable.__dict__[
+                    "run_startup_event_handlers" + suffix
+                ]
+
+            if "run_preprocessing_event_handlers" + suffix in runnable.__dict__:
+                r.run_preprocessing_event_handlers = runnable.__dict__[
+                    "run_preprocessing_event_handlers" + suffix
+                ]
+
+            if "run_postprocessing_event_handlers" + suffix in runnable.__dict__:
+                r.run_postprocessing_event_handlers = runnable.__dict__[
+                    "run_postprocessing_event_handlers" + suffix
+                ]
 
         self.process_simulation_specs(component, runnable, component.simulation)
 
@@ -188,7 +204,7 @@ def build_runnable(self, component, parent = None, id_ = None):
             runnable.add_child(child.id, child_runnable)
 
             for children in component.children:
-                #GG - These conditions need more debugging.
+                # GG - These conditions need more debugging.
                 if children.type in child.types:
                     runnable.add_child_typeref(children.type, child_runnable)
                 if children.multiple:
@@ -204,18 +220,19 @@ def build_runnable(self, component, parent = None, id_ = None):
         self.build_structure(component, runnable, component.structure)
 
         dynamics = component.dynamics
-        self.add_dynamics_2(component, runnable,
-                            dynamics, dynamics)
+        self.add_dynamics_2(component, runnable, dynamics, dynamics)
         for regime in dynamics.regimes:
             self.add_dynamics_2(component, runnable, regime, dynamics)
 
             if regime.name not in runnable.regimes:
                 runnable.add_regime(RunnableRegime(regime.name))
             r = runnable.regimes[regime.name]
-            suffix = '_regime_' + regime.name
+            suffix = "_regime_" + regime.name
 
-            if 'update_kinetic_scheme' + suffix in runnable.__dict__: 
-                r.update_kinetic_scheme = runnable.__dict__['update_kinetic_scheme' + suffix]
+            if "update_kinetic_scheme" + suffix in runnable.__dict__:
+                r.update_kinetic_scheme = runnable.__dict__[
+                    "update_kinetic_scheme" + suffix
+                ]
 
         self.add_recording_behavior(component, runnable)
 
@@ -223,8 +240,7 @@ def build_runnable(self, component, parent = None, id_ = None):
         self.current_record_target = record_target_backup
 
         return runnable
-    
-    
+
     def build_event_connections(self, component, runnable, structure):
         """
         Adds event connections to a runnable component based on the structure
@@ -239,20 +255,23 @@ def build_event_connections(self, component, runnable, structure):
         :param structure: The structure object to be used to add structure code in the runnable component.
         :type structure: lems.model.structure.Structure
         """
-        if self.debug: print("\n++++++++ Calling build_event_connections of %s with runnable %s, parent %s"%(component.id, runnable.id, runnable.parent))
+        if self.debug:
+            print(
+                "\n++++++++ Calling build_event_connections of %s with runnable %s, parent %s"
+                % (component.id, runnable.id, runnable.parent)
+            )
         # Process event connections
         for ec in structure.event_connections:
-            if self.debug: print(ec.toxml())
+            if self.debug:
+                print(ec.toxml())
             source = runnable.parent.resolve_path(ec.from_)
             target = runnable.parent.resolve_path(ec.to)
             if ec.receiver:
-                receiver_template = self.build_runnable(ec.receiver,
-                                                            target)
-                                                            
-                #receiver = copy.deepcopy(receiver_template)
+                receiver_template = self.build_runnable(ec.receiver, target)
+
+                # receiver = copy.deepcopy(receiver_template)
                 receiver = receiver_template.copy()
-                receiver.id = "{0}__{1}__".format(component.id,
-                                                  receiver_template.id)
+                receiver.id = "{0}__{1}__".format(component.id, receiver_template.id)
 
                 if ec.receiver_container:
                     target.add_attachment(receiver, ec.receiver_container)
@@ -269,22 +288,31 @@ def build_event_connections(self, component, runnable, structure):
                 if len(source.event_out_ports) == 1:
                     source_port = source.event_out_ports[0]
                 else:
-                    raise SimBuildError(("No source event port "
-                                         "uniquely identifiable"
-                                         " in '{0}'").format(source.id))
+                    raise SimBuildError(
+                        (
+                            "No source event port " "uniquely identifiable" " in '{0}'"
+                        ).format(source.id)
+                    )
             if not target_port:
                 if len(target.event_in_ports) == 1:
                     target_port = target.event_in_ports[0]
                 else:
-                    raise SimBuildError(("No destination event port "
-                                         "uniquely identifiable "
-                                         "in '{0}'").format(target))
-             
-            if self.debug: print("register_event_out_callback\n   Source: %s, %s (port: %s) \n   -> %s, %s (port: %s)"%(source, id(source), source_port, target, id(target), target_port))
-            source.register_event_out_callback(\
-                source_port, lambda: target.inc_event_in(target_port))
-                
-            
+                    raise SimBuildError(
+                        (
+                            "No destination event port "
+                            "uniquely identifiable "
+                            "in '{0}'"
+                        ).format(target)
+                    )
+
+            if self.debug:
+                print(
+                    "register_event_out_callback\n   Source: %s, %s (port: %s) \n   -> %s, %s (port: %s)"
+                    % (source, id(source), source_port, target, id(target), target_port)
+                )
+            source.register_event_out_callback(
+                source_port, lambda: target.inc_event_in(target_port)
+            )
 
     def build_structure(self, component, runnable, structure):
         """
@@ -300,37 +328,36 @@ def build_structure(self, component, runnable, structure):
         :param structure: The structure object to be used to add structure code in the runnable component.
         :type structure: lems.model.structure.Structure
         """
-        if self.debug: print("\n++++++++ Calling build_structure of %s with runnable %s, parent %s"%(component.id, runnable.id, runnable.parent))
-        
+        if self.debug:
+            print(
+                "\n++++++++ Calling build_structure of %s with runnable %s, parent %s"
+                % (component.id, runnable.id, runnable.parent)
+            )
+
         # Process single-child instantiations
         for ch in structure.child_instances:
             child_runnable = self.build_runnable(ch.referenced_component, runnable)
             runnable.add_child(child_runnable.id, child_runnable)
 
             runnable.add_child_typeref(ch.component, child_runnable)
-            
+
         # Process multi-child instatiantions
         for mi in structure.multi_instantiates:
-            template = self.build_runnable(mi.component,
-                                           runnable)
+            template = self.build_runnable(mi.component, runnable)
 
             for i in range(mi.number):
-                #instance = copy.deepcopy(template)
+                # instance = copy.deepcopy(template)
                 instance = template.copy()
-                instance.id = "{0}__{1}__{2}".format(component.id,
-                                                     template.id,
-                                                     i)
+                instance.id = "{0}__{1}__{2}".format(component.id, template.id, i)
                 runnable.array.append(instance)
 
         # Process foreach statements
         for fe in structure.for_eachs:
             self.build_foreach(component, runnable, fe)
-        
-        self.build_event_connections(component, runnable, structure)
-
 
+        self.build_event_connections(component, runnable, structure)
 
-    def build_foreach(self, component, runnable, foreach, name_mappings = {}):
+    def build_foreach(self, component, runnable, foreach, name_mappings={}):
         """
         Iterate over ForEach constructs and process nested elements.
 
@@ -343,17 +370,25 @@ def build_foreach(self, component, runnable, foreach, name_mappings = {}):
         :param foreach: The ForEach structure object to be used to add structure code in the runnable component.
         :type foreach: lems.model.structure.ForEach
         """
-        if self.debug: print("\n++++++++ Calling build_foreach of %s with runnable %s, parent %s, name_mappings: %s"%(component.id, runnable.id, runnable.parent, name_mappings))
+        if self.debug:
+            print(
+                "\n++++++++ Calling build_foreach of %s with runnable %s, parent %s, name_mappings: %s"
+                % (component.id, runnable.id, runnable.parent, name_mappings)
+            )
 
         target_array = runnable.resolve_path(foreach.instances)
-        
+
         for target_runnable in target_array:
-            if self.debug: print("Applying contents of for_each to %s, as %s"%(target_runnable.id, foreach.as_))
+            if self.debug:
+                print(
+                    "Applying contents of for_each to %s, as %s"
+                    % (target_runnable.id, foreach.as_)
+                )
             name_mappings[foreach.as_] = target_runnable
 
             # Process foreach statements
             for fe2 in foreach.for_eachs:
-                #print fe2.toxml()
+                # print fe2.toxml()
                 target_array2 = runnable.resolve_path(fe2.instances)
 
                 for target_runnable2 in target_array2:
@@ -372,21 +407,40 @@ def build_foreach(self, component, runnable, foreach, name_mappings = {}):
                     if len(source.event_out_ports) == 1:
                         source_port = source.event_out_ports[0]
                     else:
-                        raise SimBuildError(("No source event port "
-                                             "uniquely identifiable"
-                                             " in '{0}'").format(source.id))
+                        raise SimBuildError(
+                            (
+                                "No source event port "
+                                "uniquely identifiable"
+                                " in '{0}'"
+                            ).format(source.id)
+                        )
                 if not target_port:
                     if len(target.event_in_ports) == 1:
                         target_port = target.event_in_ports[0]
                     else:
-                        raise SimBuildError(("No destination event port "
-                                             "uniquely identifiable "
-                                             "in '{0}'").format(target))
-
-                if self.debug: print("register_event_out_callback\n   Source: %s, %s (port: %s) \n   -> %s, %s (port: %s)"%(source, id(source), source_port, target, id(target), target_port))
-                source.register_event_out_callback(\
-                    source_port, lambda: target.inc_event_in(target_port))
-                
+                        raise SimBuildError(
+                            (
+                                "No destination event port "
+                                "uniquely identifiable "
+                                "in '{0}'"
+                            ).format(target)
+                        )
+
+                if self.debug:
+                    print(
+                        "register_event_out_callback\n   Source: %s, %s (port: %s) \n   -> %s, %s (port: %s)"
+                        % (
+                            source,
+                            id(source),
+                            source_port,
+                            target,
+                            id(target),
+                            target_port,
+                        )
+                    )
+                source.register_event_out_callback(
+                    source_port, lambda: target.inc_event_in(target_port)
+                )
 
     def add_dynamics_1(self, component, runnable, regime, dynamics):
         """
@@ -414,10 +468,10 @@ def add_dynamics_1(self, component, runnable, regime, dynamics):
         :raises SimBuildError: Raised when the component reference for <Run> cannot be resolved.
         """
 
-        if isinstance(regime, Dynamics) or regime.name == '':
-            suffix = ''
+        if isinstance(regime, Dynamics) or regime.name == "":
+            suffix = ""
         else:
-            suffix = '_regime_' + regime.name
+            suffix = "_regime_" + regime.name
 
         if isinstance(regime, Regime) and regime.initial:
             runnable.new_regime = regime.name
@@ -429,54 +483,67 @@ def add_dynamics_1(self, component, runnable, regime, dynamics):
         # Process time derivatives
         time_step_code = []
         for td in regime.time_derivatives:
-            if td.variable not in regime.state_variables and td.variable not in dynamics.state_variables:
-                raise SimBuildError(('Time derivative for undefined state '
-                                     'variable {0} in component {1}').format(td.variable, component.id))
-
-            exp = self.build_expression_from_tree(runnable,
-                                                  regime,
-                                                  td.expression_tree)
-            time_step_code += ['self.{0} += dt * ({1})'.format(td.variable,
-                                                               exp)]
-        runnable.add_method('update_state_variables' + suffix, ['self', 'dt'],
-                            time_step_code)
+            if (
+                td.variable not in regime.state_variables
+                and td.variable not in dynamics.state_variables
+            ):
+                raise SimBuildError(
+                    (
+                        "Time derivative for undefined state "
+                        "variable {0} in component {1}"
+                    ).format(td.variable, component.id)
+                )
+
+            exp = self.build_expression_from_tree(runnable, regime, td.expression_tree)
+            time_step_code += ["self.{0} += dt * ({1})".format(td.variable, exp)]
+        runnable.add_method(
+            "update_state_variables" + suffix, ["self", "dt"], time_step_code
+        )
 
         # Process derived variables
         derived_variable_code = []
         derived_variables_ordering = order_derived_variables(regime)
-        for dvn in derived_variables_ordering: #regime.derived_variables:
+        for dvn in derived_variables_ordering:  # regime.derived_variables:
             if dvn in dynamics.derived_variables:
                 dv = dynamics.derived_variables[dvn]
                 runnable.add_derived_variable(dv.name)
                 if dv.value:
-                    derived_variable_code += ['self.{0} = ({1})'.format(
-                        dv.name,
-                        self.build_expression_from_tree(runnable,
-                                                        regime,
-                                                        dv.expression_tree))]
+                    derived_variable_code += [
+                        "self.{0} = ({1})".format(
+                            dv.name,
+                            self.build_expression_from_tree(
+                                runnable, regime, dv.expression_tree
+                            ),
+                        )
+                    ]
                 elif dv.select:
                     if dv.reduce:
-                        derived_variable_code += self.build_reduce_code(dv.name,
-                                                                        dv.select,
-                                                                        dv.reduce)
+                        derived_variable_code += self.build_reduce_code(
+                            dv.name, dv.select, dv.reduce
+                        )
                     else:
-                        derived_variable_code += ['self.{0} = (self.{1})'.format(
-                            dv.name,
-                            dv.select.replace('/', '.'))]
+                        derived_variable_code += [
+                            "self.{0} = (self.{1})".format(
+                                dv.name, dv.select.replace("/", ".")
+                            )
+                        ]
                 else:
-                    raise SimBuildError(('Inconsistent derived variable settings'
-                                         'for {0}').format(dvn))
+                    raise SimBuildError(
+                        ("Inconsistent derived variable settings" "for {0}").format(dvn)
+                    )
             elif dvn in dynamics.conditional_derived_variables:
                 dv = dynamics.conditional_derived_variables[dvn]
                 runnable.add_derived_variable(dv.name)
-                derived_variable_code += self.build_conditional_derived_var_code(runnable,
-                                                                                 regime,
-                                                                                 dv)
+                derived_variable_code += self.build_conditional_derived_var_code(
+                    runnable, regime, dv
+                )
             else:
-                raise SimBuildError("Unknown derived variable '{0}' in '{1}'",
-                                     dvn, runnable.id)
-        runnable.add_method('update_derived_variables' + suffix, ['self'],
-                            derived_variable_code)
+                raise SimBuildError(
+                    "Unknown derived variable '{0}' in '{1}'", dvn, runnable.id
+                )
+        runnable.add_method(
+            "update_derived_variables" + suffix, ["self"], derived_variable_code
+        )
 
         # Process event handlers
         pre_event_handler_code = []
@@ -485,28 +552,35 @@ def add_dynamics_1(self, component, runnable, regime, dynamics):
         on_entry_added = False
         for eh in regime.event_handlers:
             if isinstance(eh, OnStart):
-                startup_event_handler_code += self.build_event_handler(runnable,
-                                                                       regime,
-                                                                       eh)
+                startup_event_handler_code += self.build_event_handler(
+                    runnable, regime, eh
+                )
             elif isinstance(eh, OnCondition):
-                post_event_handler_code += self.build_event_handler(runnable,
-                                                                    regime,
-                                                                    eh)
+                post_event_handler_code += self.build_event_handler(
+                    runnable, regime, eh
+                )
             else:
                 if isinstance(eh, OnEntry):
                     on_entry_added = True
-                pre_event_handler_code += self.build_event_handler(runnable,
-                                                                   regime,
-                                                                   eh)
+                pre_event_handler_code += self.build_event_handler(runnable, regime, eh)
         if isinstance(regime, Regime) and not on_entry_added:
-            pre_event_handler_code += self.build_event_handler(runnable, regime, OnEntry())
-            
-        runnable.add_method('run_startup_event_handlers' + suffix, ['self'],
-                            startup_event_handler_code)
-        runnable.add_method('run_preprocessing_event_handlers' + suffix, ['self'],
-                            pre_event_handler_code)
-        runnable.add_method('run_postprocessing_event_handlers' + suffix, ['self'],
-                            post_event_handler_code)
+            pre_event_handler_code += self.build_event_handler(
+                runnable, regime, OnEntry()
+            )
+
+        runnable.add_method(
+            "run_startup_event_handlers" + suffix, ["self"], startup_event_handler_code
+        )
+        runnable.add_method(
+            "run_preprocessing_event_handlers" + suffix,
+            ["self"],
+            pre_event_handler_code,
+        )
+        runnable.add_method(
+            "run_postprocessing_event_handlers" + suffix,
+            ["self"],
+            post_event_handler_code,
+        )
 
     def add_dynamics_2(self, component, runnable, regime, dynamics):
         """
@@ -534,17 +608,19 @@ def add_dynamics_2(self, component, runnable, regime, dynamics):
         :raises SimBuildError: Raised when the component reference for <Run> cannot be resolved.
         """
 
-        if isinstance(regime, Dynamics) or regime.name == '':
-            suffix = ''
+        if isinstance(regime, Dynamics) or regime.name == "":
+            suffix = ""
         else:
-            suffix = '_regime_' + regime.name
+            suffix = "_regime_" + regime.name
 
         # Process kinetic schemes
         ks_code = []
         for ks in regime.kinetic_schemes:
-            
-            raise NotImplementedError("KineticScheme element is not stable in PyLEMS yet, see https://github.com/LEMS/pylems/issues/15")
-        
+
+            raise NotImplementedError(
+                "KineticScheme element is not stable in PyLEMS yet, see https://github.com/LEMS/pylems/issues/15"
+            )
+
             try:
                 ###nodes = {node.id:node for node in runnable.__dict__[ks.nodes]}
                 nodes = {}
@@ -556,38 +632,61 @@ def add_dynamics_2(self, component, runnable, regime, dynamics):
                     from_ = edge.__dict__[ks.edge_source]
                     to = edge.__dict__[ks.edge_target]
 
-                    ks_code += [('self.{0}.{2} += dt * (-self.{3}.{4} * self.{0}.{2}_shadow'
-                                 ' + self.{3}.{5} * self.{1}.{2}_shadow)').format(
-                        from_, to, ks.state_variable, edge.id,
-                        ks.forward_rate, ks.reverse_rate)]
-
-                    ks_code += [('self.{1}.{2} += dt * (self.{3}.{4} * self.{0}.{2}_shadow'
-                                 ' - self.{3}.{5} * self.{1}.{2}_shadow)').format(
-                        from_, to, ks.state_variable, edge.id,
-                        ks.forward_rate, ks.reverse_rate)]
-
-                ks_code += ['sum = 0']
+                    ks_code += [
+                        (
+                            "self.{0}.{2} += dt * (-self.{3}.{4} * self.{0}.{2}_shadow"
+                            " + self.{3}.{5} * self.{1}.{2}_shadow)"
+                        ).format(
+                            from_,
+                            to,
+                            ks.state_variable,
+                            edge.id,
+                            ks.forward_rate,
+                            ks.reverse_rate,
+                        )
+                    ]
+
+                    ks_code += [
+                        (
+                            "self.{1}.{2} += dt * (self.{3}.{4} * self.{0}.{2}_shadow"
+                            " - self.{3}.{5} * self.{1}.{2}_shadow)"
+                        ).format(
+                            from_,
+                            to,
+                            ks.state_variable,
+                            edge.id,
+                            ks.forward_rate,
+                            ks.reverse_rate,
+                        )
+                    ]
+
+                ks_code += ["sum = 0"]
                 for node in nodes:
                     nodes[node].__dict__[ks.state_variable] = 1.0 / len(nodes)
-                    nodes[node].__dict__[ks.state_variable + '_shadow'] = 1.0 / len(nodes)
-                    ks_code += ['sum += self.{0}.{1}'.format(node, ks.state_variable)]
+                    nodes[node].__dict__[ks.state_variable + "_shadow"] = 1.0 / len(
+                        nodes
+                    )
+                    ks_code += ["sum += self.{0}.{1}".format(node, ks.state_variable)]
 
                 for node in nodes:
-                    ks_code += ['self.{0}.{1} /= sum'.format(node, ks.state_variable)]
+                    ks_code += ["self.{0}.{1} /= sum".format(node, ks.state_variable)]
 
                 for node in nodes:
-                    ks_code += [('self.{0}.{1}_shadow = '
-                                 'self.{0}.{1}').format(node,
-                                                        ks.state_variable)]
+                    ks_code += [
+                        ("self.{0}.{1}_shadow = " "self.{0}.{1}").format(
+                            node, ks.state_variable
+                        )
+                    ]
 
             except Exception as e:
-                raise SimBuildError(("Unable to construct kinetic scheme '{0}' "
-                                     "for component '{1}' - {2}").format(ks.name,
-                                                                         component.id,
-                                                                         str(e)))
+                raise SimBuildError(
+                    (
+                        "Unable to construct kinetic scheme '{0}' "
+                        "for component '{1}' - {2}"
+                    ).format(ks.name, component.id, str(e))
+                )
 
-        runnable.add_method('update_kinetic_scheme' + suffix, ['self', 'dt'],
-                            ks_code)
+        runnable.add_method("update_kinetic_scheme" + suffix, ["self", "dt"], ks_code)
 
     def process_simulation_specs(self, component, runnable, simulation):
         """
@@ -612,15 +711,13 @@ def process_simulation_specs(self, component, runnable, simulation):
 
         # Process runs
         for run in simulation.runs:
-            cid = run.component.id + '_' + component.id
+            cid = run.component.id + "_" + component.id
 
             target = self.build_runnable(run.component, runnable, cid)
             self.sim.add_runnable(target)
             self.current_record_target = target
 
-            target.configure_time(run.increment,
-                                  run.total)
-
+            target.configure_time(run.increment, run.total)
 
     def convert_op(self, op):
         """
@@ -634,26 +731,26 @@ def convert_op(self, op):
         :rtype: string
         """
 
-        if op == '.gt.':
-            return '>'
-        elif op == '.ge.' or op == '.geq.':
-            return '>='
-        elif op == '.lt.':
-            return '<'
-        elif op == '.le.':
-            return '<='
-        elif op == '.eq.':
-            return '=='
-        elif op == '.neq.':   
-            return '!='
-        elif op == '.ne.':   # .neq. is preferred!
-            return '!='
-        elif op == '^':
-            return '**'
-        elif op == '.and.':
-            return 'and'
-        elif op == '.or.':
-            return 'or'
+        if op == ".gt.":
+            return ">"
+        elif op == ".ge." or op == ".geq.":
+            return ">="
+        elif op == ".lt.":
+            return "<"
+        elif op == ".le.":
+            return "<="
+        elif op == ".eq.":
+            return "=="
+        elif op == ".neq.":
+            return "!="
+        elif op == ".ne.":  # .neq. is preferred!
+            return "!="
+        elif op == "^":
+            return "**"
+        elif op == ".and.":
+            return "and"
+        elif op == ".or.":
+            return "or"
         else:
             return op
 
@@ -669,16 +766,21 @@ def convert_func(self, func):
         :rtype: string
         """
 
-        if func == 'ln':
-            return 'log'
-        elif func == 'random':
-            return 'random.uniform'
-        elif func == 'H':
+        if func == "ln":
+            return "log"
+        elif func == "random":
+            return "random.uniform"
+        elif func == "H":
+
             def heaviside_step(x):
-                if x < 0: return 0
-                elif x > 0: return 1
-                else: return 0.5 
-            return 'heaviside_step'
+                if x < 0:
+                    return 0
+                elif x > 0:
+                    return 1
+                else:
+                    return 0.5
+
+            return "heaviside_step"
         else:
             return func
 
@@ -701,51 +803,50 @@ def build_expression_from_tree(self, runnable, regime, tree_node):
 
         component_type = self.model.component_types[runnable.component.type]
         dynamics = component_type.dynamics
-        
+
         if tree_node.type == ExprNode.VALUE:
             if tree_node.value[0].isalpha():
-                if tree_node.value == 't':
-                    return 'self.time_completed'
+                if tree_node.value == "t":
+                    return "self.time_completed"
                 elif tree_node.value in component_type.requirements:
-                    var_prefix = 'self'
+                    var_prefix = "self"
                     v = tree_node.value
 
                     r = runnable
 
-                    while (v not in r.instance_variables and
-                           v not in r.derived_variables):
-                        var_prefix = '{0}.{1}'.format(var_prefix, 'parent')
+                    while (
+                        v not in r.instance_variables and v not in r.derived_variables
+                    ):
+                        var_prefix = "{0}.{1}".format(var_prefix, "parent")
                         r = r.parent
                         if r == None:
-                            raise SimBuildError("Unable to resolve required "
-                                                "variable '{0}'".format(v))
-
-                    return '{0}.{1}'.format(var_prefix, v)
-                elif (tree_node.value in dynamics.derived_variables or (regime is not None and tree_node.value in regime.derived_variables)):
-                    return 'self.{0}'.format(tree_node.value)
+                            raise SimBuildError(
+                                "Unable to resolve required " "variable '{0}'".format(v)
+                            )
+
+                    return "{0}.{1}".format(var_prefix, v)
+                elif tree_node.value in dynamics.derived_variables or (
+                    regime is not None and tree_node.value in regime.derived_variables
+                ):
+                    return "self.{0}".format(tree_node.value)
                 else:
-                    return 'self.{0}_shadow'.format(tree_node.value)
+                    return "self.{0}_shadow".format(tree_node.value)
             else:
                 return tree_node.value
         elif tree_node.type == ExprNode.FUNC1:
-            pattern = '({0}({1}))'
+            pattern = "({0}({1}))"
             func = self.convert_func(tree_node.func)
-            if 'random.uniform' in func:
-                pattern = '({0}(0,{1}))'
-            return pattern.format(\
-                func,
-                self.build_expression_from_tree(runnable,
-                                                regime,
-                                                tree_node.param))
+            if "random.uniform" in func:
+                pattern = "({0}(0,{1}))"
+            return pattern.format(
+                func, self.build_expression_from_tree(runnable, regime, tree_node.param)
+            )
         else:
-            return '({0}) {1} ({2})'.format(\
-                self.build_expression_from_tree(runnable,
-                                                regime,
-                                                tree_node.left),
+            return "({0}) {1} ({2})".format(
+                self.build_expression_from_tree(runnable, regime, tree_node.left),
                 self.convert_op(tree_node.op),
-                self.build_expression_from_tree(runnable,
-                                                regime,
-                                                tree_node.right))
+                self.build_expression_from_tree(runnable, regime, tree_node.right),
+            )
 
     def build_event_handler(self, runnable, regime, event_handler):
         """
@@ -782,15 +883,18 @@ def build_on_condition(self, runnable, regime, on_condition):
 
         on_condition_code = []
 
-        on_condition_code += ['if {0}:'.format(\
-            self.build_expression_from_tree(runnable,
-                                            regime,
-                                            on_condition.expression_tree))]
+        on_condition_code += [
+            "if {0}:".format(
+                self.build_expression_from_tree(
+                    runnable, regime, on_condition.expression_tree
+                )
+            )
+        ]
 
         for action in on_condition.actions:
             code = self.build_action(runnable, regime, action)
             for line in code:
-                on_condition_code += ['    ' + line]
+                on_condition_code += ["    " + line]
 
         return on_condition_code
 
@@ -806,21 +910,27 @@ def build_on_event(self, runnable, regime, on_event):
         """
         on_event_code = []
 
-        if self.debug: on_event_code += ['print("Maybe handling something for %s ("+str(id(self))+")")'%(runnable.id),
-                          'print("EICs ("+str(id(self))+"): "+str(self.event_in_counters))']
-                          
-        on_event_code += ['count = self.event_in_counters[\'{0}\']'.\
-                          format(on_event.port),
-                          'while count > 0:',
-                          '    print("  Handling event")' if self.debug else '',
-                          '    count -= 1']
+        if self.debug:
+            on_event_code += [
+                'print("Maybe handling something for %s ("+str(id(self))+")")'
+                % (runnable.id),
+                'print("EICs ("+str(id(self))+"): "+str(self.event_in_counters))',
+            ]
+
+        on_event_code += [
+            "count = self.event_in_counters['{0}']".format(on_event.port),
+            "while count > 0:",
+            '    print("  Handling event")' if self.debug else "",
+            "    count -= 1",
+        ]
         for action in on_event.actions:
             code = self.build_action(runnable, regime, action)
             for line in code:
-                on_event_code += ['    ' + line]
+                on_event_code += ["    " + line]
 
-        on_event_code += ['self.event_in_counters[\'{0}\'] = 0'.\
-                          format(on_event.port),]
+        on_event_code += [
+            "self.event_in_counters['{0}'] = 0".format(on_event.port),
+        ]
 
         return on_event_code
 
@@ -857,13 +967,13 @@ def build_on_entry(self, runnable, regime, on_entry):
 
         on_entry_code = []
 
-        on_entry_code += ['if self.current_regime != self.last_regime:']
-        on_entry_code += ['    self.last_regime = self.current_regime']
+        on_entry_code += ["if self.current_regime != self.last_regime:"]
+        on_entry_code += ["    self.last_regime = self.current_regime"]
 
         for action in on_entry.actions:
             code = self.build_action(runnable, regime, action)
             for line in code:
-                on_entry_code += ['    ' + line]
+                on_entry_code += ["    " + line]
 
         return on_entry_code
 
@@ -885,7 +995,7 @@ def build_action(self, runnable, regime, action):
         if isinstance(action, Transition):
             return self.build_transition(action)
         else:
-            return ['pass']
+            return ["pass"]
 
     def build_state_assignment(self, runnable, regime, state_assignment):
         """
@@ -898,11 +1008,14 @@ def build_state_assignment(self, runnable, regime, state_assignment):
         :rtype: string
         """
 
-        return ['self.{0} = {1}'.format(\
-            state_assignment.variable,
-            self.build_expression_from_tree(runnable,
-                                            regime,
-                                            state_assignment.expression_tree))]
+        return [
+            "self.{0} = {1}".format(
+                state_assignment.variable,
+                self.build_expression_from_tree(
+                    runnable, regime, state_assignment.expression_tree
+                ),
+            )
+        ]
 
     def build_event_out(self, event_out):
         """
@@ -915,9 +1028,11 @@ def build_event_out(self, event_out):
         :rtype: string
         """
 
-        event_out_code = ['if "{0}" in self.event_out_callbacks:'.format(event_out.port),
-                          '    for c in self.event_out_callbacks[\'{0}\']:'.format(event_out.port),
-                          '        c()']
+        event_out_code = [
+            'if "{0}" in self.event_out_callbacks:'.format(event_out.port),
+            "    for c in self.event_out_callbacks['{0}']:".format(event_out.port),
+            "        c()",
+        ]
 
         return event_out_code
 
@@ -939,81 +1054,96 @@ def build_reduce_code(self, result, select, reduce):
         Builds a reduce operation on the selected target range.
         """
 
-        select = select.replace('/', '.')
-        select = select.replace(' ', '')
-        if reduce == 'add':
-            reduce_op = '+'
+        select = select.replace("/", ".")
+        select = select.replace(" ", "")
+        if reduce == "add":
+            reduce_op = "+"
             acc_start = 0
         else:
-            reduce_op = '*'
+            reduce_op = "*"
             acc_start = 1
 
-        #bits = select.split('[*]')
-        bits = re.split('\[.*\]', select)
-        seps = re.findall('\[.*\]', select)
+        # bits = select.split('[*]')
+        bits = re.split("\[.*\]", select)
+        seps = re.findall("\[.*\]", select)
 
-        code = ['self.{0} = {1}'.format(result, acc_start)]
-        code += ['self.{0}_shadow = {1}'.format(result, acc_start)]
+        code = ["self.{0} = {1}".format(result, acc_start)]
+        code += ["self.{0}_shadow = {1}".format(result, acc_start)]
 
-        code += ['try:']
+        code += ["try:"]
 
         if len(bits) == 1:
             target = select
-            code += ['    self.{0} = self.{1}'.format(result, target)]
-            code += ['    self.{0}_shadow = self.{1}'.format(result, target)]
+            code += ["    self.{0} = self.{1}".format(result, target)]
+            code += ["    self.{0}_shadow = self.{1}".format(result, target)]
         elif len(bits) == 2:
             sep = seps[0][1:-1]
 
-            if sep == '*':
+            if sep == "*":
                 array = bits[0]
                 ref = bits[1]
 
-                code += ['    acc = {0}'.format(acc_start)]
-                code += ['    for o in self.{0}:'.format(array)]
-                code += ['        acc = acc {0} o{1}'.format(reduce_op, ref)]
-                code += ['    self.{0} = acc'.format(result)]
-                code += ['    self.{0}_shadow = acc'.format(result)]
+                code += ["    acc = {0}".format(acc_start)]
+                code += ["    for o in self.{0}:".format(array)]
+                code += ["        acc = acc {0} o{1}".format(reduce_op, ref)]
+                code += ["    self.{0} = acc".format(result)]
+                code += ["    self.{0}_shadow = acc".format(result)]
             else:
-                bits2 = sep.split('=')
+                bits2 = sep.split("=")
                 if len(bits2) > 1:
                     array = bits[0]
                     ref = bits[1]
 
-                    code += ['    acc = {0}'.format(acc_start)]
-                    code += ['    for o in self.{0}:'.format(array)]
-                    code += ['        if o.{0} == {1}:'.format(bits2[0], bits2[1])]
-                    code += ['            acc = acc {0} o{1}'.format(reduce_op, ref)]
-                    code += ['    self.{0} = acc'.format(result)]
-                    code += ['    self.{0}_shadow = acc'.format(result)]
+                    code += ["    acc = {0}".format(acc_start)]
+                    code += ["    for o in self.{0}:".format(array)]
+                    code += ["        if o.{0} == {1}:".format(bits2[0], bits2[1])]
+                    code += ["            acc = acc {0} o{1}".format(reduce_op, ref)]
+                    code += ["    self.{0} = acc".format(result)]
+                    code += ["    self.{0}_shadow = acc".format(result)]
                 else:
                     raise SimbuildError("Invalid reduce target - '{0}'".format(select))
         else:
             raise SimbuildError("Invalid reduce target - '{0}'".format(select))
 
-        code += ['except:']
-        code += ['    pass']
+        code += ["except:"]
+        code += ["    pass"]
 
         return code
 
     def build_conditional_derived_var_code(self, runnable, regime, dv):
         code = []
-        el = ''
+        el = ""
         for case in dv.cases:
             if case.condition_expression_tree:
-                code += [el+'if {0}:'.format(self.build_expression_from_tree(runnable, 
-                                                                          regime, 
-                                                                          case.condition_expression_tree))]
-                el='el'
-                code += ['    self.{0} = {1}'.format(dv.name, self.build_expression_from_tree(runnable, 
-                                                                                              regime, 
-                                                                                              case.value_expression_tree))]
-                                                                                              
+                code += [
+                    el
+                    + "if {0}:".format(
+                        self.build_expression_from_tree(
+                            runnable, regime, case.condition_expression_tree
+                        )
+                    )
+                ]
+                el = "el"
+                code += [
+                    "    self.{0} = {1}".format(
+                        dv.name,
+                        self.build_expression_from_tree(
+                            runnable, regime, case.value_expression_tree
+                        ),
+                    )
+                ]
+
         for case in dv.cases:
             if case.condition_expression_tree is None:
-                code += ['else: ']
-                code += ['    self.{0} = {1}'.format(dv.name, self.build_expression_from_tree(runnable, 
-                                                                                              regime, 
-                                                                                              case.value_expression_tree))]
+                code += ["else: "]
+                code += [
+                    "    self.{0} = {1}".format(
+                        dv.name,
+                        self.build_expression_from_tree(
+                            runnable, regime, case.value_expression_tree
+                        ),
+                    )
+                ]
         return code
 
     def add_recording_behavior(self, component, runnable):
@@ -1032,10 +1162,14 @@ def add_recording_behavior(self, component, runnable):
 
         for rec in simulation.records:
             rec.id = runnable.id
-            self.current_record_target.add_variable_recorder(self.current_data_output, rec)
+            self.current_record_target.add_variable_recorder(
+                self.current_data_output, rec
+            )
+
 
 ############################################################
 
+
 def order_derived_parameters(component):
     """
     Finds ordering of derived_parameters.
@@ -1051,13 +1185,13 @@ def order_derived_parameters(component):
 
     if len(component.derived_parameters) == 0:
         return []
-    
+
     ordering = []
     dps = []
-    
+
     for dp in component.derived_parameters:
         dps.append(dp.name)
-            
+
     maxcount = 5
 
     count = maxcount
@@ -1066,7 +1200,7 @@ def order_derived_parameters(component):
         count = count - 1
 
         for dp1 in dps:
-            #exp_tree = regime.derived_variables[dv1].expression_tree
+            # exp_tree = regime.derived_variables[dv1].expression_tree
             value = component.derived_parameters[dp1].value
             found = False
             for dp2 in dps:
@@ -1079,10 +1213,13 @@ def order_derived_parameters(component):
                 break
 
     if count == 0:
-        raise SimBuildError(("Unable to find ordering for derived "
-                             "parameter in component '{0}'").format(component))
+        raise SimBuildError(
+            (
+                "Unable to find ordering for derived " "parameter in component '{0}'"
+            ).format(component)
+        )
 
-    #return ordering + dvsnoexp
+    # return ordering + dvsnoexp
     return ordering
 
 
@@ -1109,13 +1246,12 @@ def order_derived_variables(regime):
             dvsnoexp.append(dv.name)
         else:
             dvs.append(dv.name)
-            
+
     for dv in regime.conditional_derived_variables:
         if len(dv.cases) == 0:
             dvsnoexp.append(dv.name)
         else:
             dvs.append(dv.name)
-            
 
     count = maxcount
 
@@ -1127,7 +1263,7 @@ def order_derived_variables(regime):
                 dv = regime.derived_variables[dv1]
             else:
                 dv = regime.conditional_derived_variables[dv1]
-                
+
             found = False
             if isinstance(dv, DerivedVariable):
                 exp_tree = dv.expression_tree
@@ -1137,10 +1273,12 @@ def order_derived_variables(regime):
             else:
                 for case in dv.cases:
                     for dv2 in dvs:
-                        if dv1 != dv2 and (is_var_in_exp_tree(dv2, case.condition_expression_tree) or
-                                           is_var_in_exp_tree(dv2, case.value_expression_tree)):
+                        if dv1 != dv2 and (
+                            is_var_in_exp_tree(dv2, case.condition_expression_tree)
+                            or is_var_in_exp_tree(dv2, case.value_expression_tree)
+                        ):
                             found = True
-                            
+
             if not found:
                 ordering.append(dv1)
                 del dvs[dvs.index(dv1)]
@@ -1148,12 +1286,16 @@ def order_derived_variables(regime):
                 break
 
     if count == 0:
-        raise SimBuildError(("Unable to find ordering for derived "
-                             "variables in regime '{0}'").format(regime.name))
+        raise SimBuildError(
+            ("Unable to find ordering for derived " "variables in regime '{0}'").format(
+                regime.name
+            )
+        )
 
-    #return ordering + dvsnoexp
+    # return ordering + dvsnoexp
     return dvsnoexp + ordering
 
+
 def is_var_in_exp_tree(var, exp_tree):
     node = exp_tree
 
diff --git a/lems/sim/recording.py b/lems/sim/recording.py
index 1494d5b..749b790 100644
--- a/lems/sim/recording.py
+++ b/lems/sim/recording.py
@@ -7,6 +7,7 @@
 
 from lems.base.base import LEMSBase
 
+
 class Recording(LEMSBase):
     """
     Stores details of a variable recording across a single simulation run.
@@ -14,9 +15,9 @@ class Recording(LEMSBase):
 
     def __init__(self, variable, full_path, data_output, recorder):
         self.variable = variable
-        
+
         self.full_path = full_path
-        
+
         self.data_output = data_output
 
         self.recorder = recorder
@@ -24,7 +25,9 @@ def __init__(self, variable, full_path, data_output, recorder):
         self.values = []
 
     def __str__(self):
-        return 'Recording: {0} ({1}), {2}, size: {3}'.format(self.variable, self.full_path, self.recorder, len(self.values))
+        return "Recording: {0} ({1}), {2}, size: {3}".format(
+            self.variable, self.full_path, self.recorder, len(self.values)
+        )
 
     def __repr__(self):
         return self.__str__()
diff --git a/lems/sim/runnable.py b/lems/sim/runnable.py
index b1f770c..daafe82 100644
--- a/lems/sim/runnable.py
+++ b/lems/sim/runnable.py
@@ -15,84 +15,95 @@
 
 from math import *
 
-#import math
+# import math
 
-#class Ex1(Exception):
+# class Ex1(Exception):
 #    pass
 
-#def exp(x):
+# def exp(x):
 #    try:
 #        return math.exp(x)
 #    except Exception as e:
 #        print('ERROR performing exp({0})'.format(x))
 #        raise Ex1()
 
+
 class Reflective(LEMSBase):
-    
+
     debug = False
-    
+
     def __init__(self):
         self.instance_variables = []
         self.derived_variables = []
         self.array = []
         self.methods = {}
-        #self.total_code_string = '' 
+        # self.total_code_string = ''
 
-    #@classmethod
+    # @classmethod
     def add_method(self, method_name, parameter_list, statements):
         if statements == []:
-            return;
-        
-        code_string = 'def __generated_function__'
+            return
+
+        code_string = "def __generated_function__"
         if parameter_list == []:
-            code_string += '():\n'
+            code_string += "():\n"
         else:
-            code_string += '(' + parameter_list[0]
+            code_string += "(" + parameter_list[0]
             for parameter in parameter_list[1:]:
-                code_string += ', ' + parameter
-            code_string += '):\n'
-
+                code_string += ", " + parameter
+            code_string += "):\n"
 
         for statement in statements:
-            if 'random.uniform' in statement:
-                code_string += '    import random\n'
-                
+            if "random.uniform" in statement:
+                code_string += "    import random\n"
+
         if self.debug:
-            code_string += '    if "xxx" in "%s": print("Calling method: %s(), dv: %s, iv: %s")\n'%(method_name,method_name, str(self.derived_variables), str(self.instance_variables))
+            code_string += (
+                '    if "xxx" in "%s": print("Calling method: %s(), dv: %s, iv: %s")\n'
+                % (
+                    method_name,
+                    method_name,
+                    str(self.derived_variables),
+                    str(self.instance_variables),
+                )
+            )
         if statements == []:
-            code_string += '    pass'
+            code_string += "    pass"
         else:
             for statement in statements:
-                code_string += '    ' + statement + '\n'
+                code_string += "    " + statement + "\n"
 
         g = globals()
         l = locals()
-        
-        #print(code_string.replace('__generated_function__', 
+
+        # print(code_string.replace('__generated_function__',
         #                          '{0}.{1}'.format(self.component.type, method_name)))
 
         if self.debug and statements != []:
-            print("------------- %s, %s, %s ----------------"%(method_name, self.id, str(self.derived_variables)))
+            print(
+                "------------- %s, %s, %s ----------------"
+                % (method_name, self.id, str(self.derived_variables))
+            )
             print(code_string)
-        exec(compile(ast.parse(code_string), '<unknown>', 'exec'), g, l)
+        exec(compile(ast.parse(code_string), "<unknown>", "exec"), g, l)
 
-        #setattr(cls, method_name, __generated_function__)
-        self.__dict__[method_name] = l['__generated_function__']
-        del l['__generated_function__']
+        # setattr(cls, method_name, __generated_function__)
+        self.__dict__[method_name] = l["__generated_function__"]
+        del l["__generated_function__"]
 
     def add_instance_variable(self, variable, initial_value):
         self.instance_variables.append(variable)
 
-        code_string = 'self.{0} = {1}\nself.{0}_shadow = {1}'.format(\
-            variable, initial_value)
-        exec(compile(ast.parse(code_string), '<unknown>', 'exec'))
+        code_string = "self.{0} = {1}\nself.{0}_shadow = {1}".format(
+            variable, initial_value
+        )
+        exec(compile(ast.parse(code_string), "<unknown>", "exec"))
 
     def add_derived_variable(self, variable):
         self.derived_variables.append(variable)
 
-        code_string = 'self.{0} = {1}\nself.{0}_shadow = {1}'.format(\
-            variable, 0)
-        exec(compile(ast.parse(code_string), '<unknown>', 'exec'))
+        code_string = "self.{0} = {1}\nself.{0}_shadow = {1}".format(variable, 0)
+        exec(compile(ast.parse(code_string), "<unknown>", "exec"))
 
     def add_text_variable(self, variable, value):
         self.__dict__[variable] = value
@@ -103,6 +114,7 @@ def __getitem__(self, key):
     def __setitem__(self, key, val):
         self.array[key] = val
 
+
 class Regime:
     def __init__(self, name):
         self.name = name
@@ -113,10 +125,11 @@ def __init__(self, name):
         self.run_postprocessing_event_handlers = None
         self.update_kinetic_scheme = None
 
+
 class Runnable(Reflective):
     uid_count = 0
 
-    def __init__(self, id_, component, parent = None):
+    def __init__(self, id_, component, parent=None):
         Reflective.__init__(self)
 
         self.uid = Runnable.uid_count
@@ -148,22 +161,22 @@ def __init__(self, id_, component, parent = None):
 
         self.attachments = {}
 
-        self.new_regime = ''
-        self.current_regime = ''
-        self.last_regime = ''
+        self.new_regime = ""
+        self.current_regime = ""
+        self.last_regime = ""
         self.regimes = {}
-        
-        
+
     def __str__(self):
-        return 'Runnable, id: {0} ({1}, {2}), component: ({3})'.format(self.id, self.uid, id(self), self.component)
-    
+        return "Runnable, id: {0} ({1}, {2}), component: ({3})".format(
+            self.id, self.uid, id(self), self.component
+        )
+
     def __repr__(self):
         return self.__str__()
-            
 
     def add_child(self, id_, runnable):
         self.uchildren[runnable.uid] = runnable
-        
+
         self.children[id_] = runnable
         self.children[runnable.id] = runnable
 
@@ -178,14 +191,14 @@ def add_child_typeref(self, typename, runnable):
         self.__dict__[typename] = runnable
 
     def add_child_to_group(self, group_name, child):
-        #print("add_child_to_group in %s; grp: %s; child: %s "%(self.id, group_name, child))
+        # print("add_child_to_group in %s; grp: %s; child: %s "%(self.id, group_name, child))
         if group_name not in self.__dict__:
-            #print sorted(self.__dict__.keys())
+            # print sorted(self.__dict__.keys())
             self.__dict__[group_name] = []
             self.groups.append(group_name)
-        #print sorted(self.__dict__.keys())
-        #print ".........."
-        #print self.__dict__[group_name]
+        # print sorted(self.__dict__.keys())
+        # print ".........."
+        # print self.__dict__[group_name]
         # Force group_name attribute to be a list before we append to it.
         if type(self.__dict__[group_name]) is not list:
             self.__dict__[group_name] = [self.__dict__[group_name]]
@@ -196,17 +209,20 @@ def make_attachment(self, type_, name):
         self.attachments[type_] = name
         self.__dict__[name] = []
 
-    def add_attachment(self, runnable, container = None):
+    def add_attachment(self, runnable, container=None):
         for ctype in runnable.component.types:
             if ctype in self.attachments:
                 name = self.attachments[ctype]
                 if container is not None and container != name:
                     continue
-                
+
                 if name not in self.__dict__:
-                    raise SimBuildError('Cannot attach {0} to {1} in {2}'.format(
-                        runnable.id, name, self.id))
-                                                                                 
+                    raise SimBuildError(
+                        "Cannot attach {0} to {1} in {2}".format(
+                            runnable.id, name, self.id
+                        )
+                    )
+
                 runnable.id = runnable.id + str(len(self.__dict__[name]))
 
                 self.__dict__[name].append(runnable)
@@ -214,8 +230,9 @@ def add_attachment(self, runnable, container = None):
 
                 return
 
-        raise SimBuildError('Unable to find appropriate attachment for {0} in {1}',
-                            runnable.id, self.id)
+        raise SimBuildError(
+            "Unable to find appropriate attachment for {0} in {1}", runnable.id, self.id
+        )
 
     def add_event_in_port(self, port):
         self.event_in_ports.append(port)
@@ -224,9 +241,12 @@ def add_event_in_port(self, port):
 
     def inc_event_in(self, port):
         self.event_in_counters[port] += 1
-        if self.debug: 
-            print("\n--- Event in to %s (%s, %s) on port: %s"%(self.id, id(self), self.__class__, port))
-            print("EIC (%s): %s"%(id(self),self.event_in_counters))
+        if self.debug:
+            print(
+                "\n--- Event in to %s (%s, %s) on port: %s"
+                % (self.id, id(self), self.__class__, port)
+            )
+            print("EIC (%s): %s" % (id(self), self.event_in_counters))
 
     def add_event_out_port(self, port):
         self.event_out_ports.append(port)
@@ -237,42 +257,49 @@ def register_event_out_link(self, port, runnable, remote_port):
         self.event_out_callbacks[port].append((runnable, remote_port))
 
     def register_event_out_callback(self, port, callback):
-        if self.debug: print("register_event_out_callback on %s, port: %s, callback: %s"%(self.id, port, callback))
+        if self.debug:
+            print(
+                "register_event_out_callback on %s, port: %s, callback: %s"
+                % (self.id, port, callback)
+            )
         if port in self.event_out_callbacks:
             self.event_out_callbacks[port].append(callback)
         else:
-            raise SimBuildError('No event out port \'{0}\' in '
-                                'component \'{1}\''.format(port, self.id))
-        if self.debug: print("EOC: "+str(self.event_out_callbacks))
+            raise SimBuildError(
+                "No event out port '{0}' in " "component '{1}'".format(port, self.id)
+            )
+        if self.debug:
+            print("EOC: " + str(self.event_out_callbacks))
 
     def add_regime(self, regime):
         self.regimes[regime.name] = regime
 
     def resolve_path(self, path):
-        if self.debug: print("Resolving path: %s in %s"%(path, self))
-        if path == '':
+        if self.debug:
+            print("Resolving path: %s in %s" % (path, self))
+        if path == "":
             return self
-        if path == 'this':
+        if path == "this":
             return self
-        if path[0] == '/':
+        if path[0] == "/":
             return self.parent.resolve_path(path)
-        elif path.find('../') == 0:
+        elif path.find("../") == 0:
             return self.parent.resolve_path(path[3:])
-        elif path.find('..') == 0:
+        elif path.find("..") == 0:
             return self.parent
-        elif path == 'parent':
+        elif path == "parent":
             return self.parent
         else:
-            if path.find('/') >= 1:
-                (child, new_path) = path.split('/', 1)
+            if path.find("/") >= 1:
+                (child, new_path) = path.split("/", 1)
             else:
                 child = path
-                new_path = ''
+                new_path = ""
 
-            idxbegin = child.find('[')
-            idxend = child.find(']')
+            idxbegin = child.find("[")
+            idxend = child.find("]")
             if idxbegin != 0 and idxend > idxbegin:
-                idx = int(child[idxbegin+1:idxend])
+                idx = int(child[idxbegin + 1 : idxend])
                 child = child[:idxbegin]
             else:
                 idx = -1
@@ -284,54 +311,65 @@ def resolve_path(self, path):
             elif child in self.component.parameters:
                 ctx = self.component
                 p = ctx.parameters[child]
-                return self.resolve_path('../' + p.value)
+                return self.resolve_path("../" + p.value)
             elif child in self.__dict__.keys():
                 child_resolved = self.__dict__[child]
-                #print("Think it's a link from %s to %s"%(child, child_resolved))
-                return self.resolve_path('../' + child_resolved)
+                # print("Think it's a link from %s to %s"%(child, child_resolved))
+                return self.resolve_path("../" + child_resolved)
             else:
                 if self.debug:
                     keys = list(self.__dict__.keys())
                     keys.sort()
                     prefix = "--- "
-                    print('{0}    Keys for {1}'.format(prefix, self.id))
+                    print("{0}    Keys for {1}".format(prefix, self.id))
                     for k in keys:
                         key_str = str(self.__dict__[k])
-                        if len(key_str) > 0 and not key_str == "[]" and not key_str == "{}":
-                            print('{0}       {1} -> {2}'.format(prefix, k, key_str))
-                        
-                raise SimBuildError('Unable to find child \'{0}\' in '
-                                    '\'{1}\''.format(child, self.id))
-
-            if new_path == '':
+                        if (
+                            len(key_str) > 0
+                            and not key_str == "[]"
+                            and not key_str == "{}"
+                        ):
+                            print("{0}       {1} -> {2}".format(prefix, k, key_str))
+
+                raise SimBuildError(
+                    "Unable to find child '{0}' in " "'{1}'".format(child, self.id)
+                )
+
+            if new_path == "":
                 return childobj
             else:
                 return childobj.resolve_path(new_path)
 
     def add_variable_recorder(self, data_output, recorder):
-        self.add_variable_recorder2(data_output, recorder, recorder.quantity, recorder.quantity)
+        self.add_variable_recorder2(
+            data_output, recorder, recorder.quantity, recorder.quantity
+        )
 
     def add_variable_recorder2(self, data_output, recorder, path, full_path):
-        
-        if path[0] == '/':
+
+        if path[0] == "/":
             self.parent.add_variable_recorder2(data_output, recorder, path, full_path)
-        elif path.find('../') == 0:
-            self.parent.add_variable_recorder2(data_output, recorder, path[3:], full_path)
-        elif path.find('/') >= 1:
-            (child, new_path) = path.split('/', 1)
-            
-            if ':' in child:
+        elif path.find("../") == 0:
+            self.parent.add_variable_recorder2(
+                data_output, recorder, path[3:], full_path
+            )
+        elif path.find("/") >= 1:
+            (child, new_path) = path.split("/", 1)
+
+            if ":" in child:
                 syn_parts = child.split(":")
-                if syn_parts[0] == 'synapses' and syn_parts[2] == '0':
+                if syn_parts[0] == "synapses" and syn_parts[2] == "0":
                     child = syn_parts[1]
                 else:
-                    raise SimBuildError('Cannot determine what to do with (synapse?) path: %s (full path: %s)'
-                                        % (child, full_path))
-                
-            idxbegin = child.find('[')
-            idxend = child.find(']')
+                    raise SimBuildError(
+                        "Cannot determine what to do with (synapse?) path: %s (full path: %s)"
+                        % (child, full_path)
+                    )
+
+            idxbegin = child.find("[")
+            idxend = child.find("]")
             if idxbegin != 0 and idxend > idxbegin:
-                idx = int(child[idxbegin+1:idxend])
+                idx = int(child[idxbegin + 1 : idxend])
                 child = child[:idxbegin]
             else:
                 idx = -1
@@ -339,15 +377,13 @@ def add_variable_recorder2(self, data_output, recorder, path, full_path):
             if child in self.children:
                 childobj = self.children[child]
                 if idx == -1:
-                    childobj.add_variable_recorder2(data_output,
-                                                    recorder,
-                                                    new_path,
-                                                    full_path)
+                    childobj.add_variable_recorder2(
+                        data_output, recorder, new_path, full_path
+                    )
                 else:
-                    childobj.array[idx].add_variable_recorder2(data_output,
-                                                               recorder,
-                                                               new_path,
-                                                               full_path)
+                    childobj.array[idx].add_variable_recorder2(
+                        data_output, recorder, new_path, full_path
+                    )
             elif child in self.component.children:
                 cdef = self.component.children[child]
                 childobj = None
@@ -356,18 +392,20 @@ def add_variable_recorder2(self, data_output, recorder, path, full_path):
                     if cdef.type in c.component.types:
                         childobj = c
                 if childobj:
-                    childobj.add_variable_recorder2(data_output,
-                                                    recorder,
-                                                    new_path)
-                else:                    
-                    raise SimBuildError('Unable to find the child \'{0}\' in '
-                                        '\'{1}\''.format(child, self.id))
+                    childobj.add_variable_recorder2(data_output, recorder, new_path)
+                else:
+                    raise SimBuildError(
+                        "Unable to find the child '{0}' in "
+                        "'{1}'".format(child, self.id)
+                    )
             else:
-                raise SimBuildError('Unable to find a child \'{0}\' in '
-                                    '\'{1}\''.format(child, self.id))
+                raise SimBuildError(
+                    "Unable to find a child '{0}' in " "'{1}'".format(child, self.id)
+                )
         else:
-            self.recorded_variables.append(Recording(path, full_path, data_output, recorder))
-
+            self.recorded_variables.append(
+                Recording(path, full_path, data_output, recorder)
+            )
 
     def configure_time(self, time_step, time_total):
         self.time_step = time_step
@@ -384,7 +422,6 @@ def configure_time(self, time_step, time_total):
         ##     for component in components:
         ##         component.configure_time(self.time_step, self.time_total)
 
-
     def reset_time(self):
         self.time_completed = 0
 
@@ -400,12 +437,12 @@ def reset_time(self):
         ##         component.reset_time()
 
     def single_step(self, dt):
-        #return self.single_step2(dt)
+        # return self.single_step2(dt)
 
         # For debugging
         try:
             return self.single_step2(dt)
-        #except Ex1 as e:
+        # except Ex1 as e:
         #    print self.rate
         #    print self.midpoint
         #    print self.scale
@@ -419,31 +456,33 @@ def single_step(self, dt):
                 r = r.parent
                 name = "{0}.{1}".format(r.id, name)
 
-            print("Error in '{0} ({1})': {2}".format(name,
-                                                         self.component.type, 
-                                                         e))
+            print("Error in '{0} ({1})': {2}".format(name, self.component.type, e))
             print(e)
-            
+
             prefix = "- "
             if self.instance_variables:
-                print('Instance variables'.format(prefix))
+                print("Instance variables".format(prefix))
                 for vn in self.instance_variables:
-                    print('{0}      {1} = {2}'.format(prefix, vn, self.__dict__[vn]))
+                    print("{0}      {1} = {2}".format(prefix, vn, self.__dict__[vn]))
             if self.derived_variables:
-                print('{0}    Derived variables'.format(prefix))
+                print("{0}    Derived variables".format(prefix))
                 for vn in self.derived_variables:
-                    print('{0}      {1} = {2}'.format(prefix, vn, self.__dict__[vn]))
-            
+                    print("{0}      {1} = {2}".format(prefix, vn, self.__dict__[vn]))
+
             keys = list(self.__dict__.keys())
             keys.sort()
             for k in keys:
-                print('{0} -> {1}'.format(k, str(self.__dict__[k])))
-            print('')
-            print('')
+                print("{0} -> {1}".format(k, str(self.__dict__[k])))
+            print("")
+            print("")
 
             if isinstance(e, ArithmeticError):
-                print(('This is an arithmetic error. Consider reducing the '
-                       'integration time step.'))
+                print(
+                    (
+                        "This is an arithmetic error. Consider reducing the "
+                        "integration time step."
+                    )
+                )
 
             sys.exit(0)
 
@@ -453,66 +492,91 @@ def single_step2(self, dt):
 
         for child in self.array:
             child.single_step(dt)
-            
-        '''
+
+        """
         Regime transition now happens below...
         if self.new_regime != '':
             self.current_regime = self.new_regime
-            self.new_regime = '''''
-        
-        if getattr(self, "update_kinetic_scheme", None): self.update_kinetic_scheme(self, dt)
+            self.new_regime = """ ""
 
-        #if self.time_completed == 0:
+        if getattr(self, "update_kinetic_scheme", None):
+            self.update_kinetic_scheme(self, dt)
+
+        # if self.time_completed == 0:
         #    self.run_startup_event_handlers(self)
 
-        if getattr(self, "run_preprocessing_event_handlers", None): self.run_preprocessing_event_handlers(self)
-        if getattr(self, "update_shadow_variables", None): self.update_shadow_variables()
+        if getattr(self, "run_preprocessing_event_handlers", None):
+            self.run_preprocessing_event_handlers(self)
+        if getattr(self, "update_shadow_variables", None):
+            self.update_shadow_variables()
 
-        if getattr(self, "update_derived_variables", None): self.update_derived_variables(self)
-        if getattr(self, "update_shadow_variables", None): self.update_shadow_variables()
-                
-        if getattr(self, "update_state_variables", None): self.update_state_variables(self, dt)
-        if getattr(self, "update_shadow_variables", None): self.update_shadow_variables()
-        
-        #if self.time_completed == 0:
-        #    self.update_derived_parameters(self)
+        if getattr(self, "update_derived_variables", None):
+            self.update_derived_variables(self)
+        if getattr(self, "update_shadow_variables", None):
+            self.update_shadow_variables()
 
-        if getattr(self, "run_postprocessing_event_handlers", None): self.run_postprocessing_event_handlers(self)
-        if getattr(self, "update_shadow_variables", None): self.update_shadow_variables()
+        if getattr(self, "update_state_variables", None):
+            self.update_state_variables(self, dt)
+        if getattr(self, "update_shadow_variables", None):
+            self.update_shadow_variables()
 
-        if False:#self.id == 'hhpop__hhcell__0':
-            print('1', self.uid, self.v)
-        if False:#self.id == 'reverseRate':
-            print('2', self.parent.parent.parent.parent.uid, self.parent.parent.parent.parent.v)
+        # if self.time_completed == 0:
+        #    self.update_derived_parameters(self)
 
-        if self.current_regime != '':
-            if self.debug: print("In reg: "+self.current_regime)
+        if getattr(self, "run_postprocessing_event_handlers", None):
+            self.run_postprocessing_event_handlers(self)
+        if getattr(self, "update_shadow_variables", None):
+            self.update_shadow_variables()
+
+        if False:  # self.id == 'hhpop__hhcell__0':
+            print("1", self.uid, self.v)
+        if False:  # self.id == 'reverseRate':
+            print(
+                "2",
+                self.parent.parent.parent.parent.uid,
+                self.parent.parent.parent.parent.v,
+            )
+
+        if self.current_regime != "":
+            if self.debug:
+                print("In reg: " + self.current_regime)
             regime = self.regimes[self.current_regime]
 
-            #if getattr(self, "xxx", None): 
-            if getattr(regime, "update_kinetic_scheme", None): regime.update_kinetic_scheme(self, dt)
+            # if getattr(self, "xxx", None):
+            if getattr(regime, "update_kinetic_scheme", None):
+                regime.update_kinetic_scheme(self, dt)
+
+            if getattr(regime, "run_preprocessing_event_handlers", None):
+                regime.run_preprocessing_event_handlers(self)
+            if getattr(self, "update_shadow_variables", None):
+                self.update_shadow_variables()
 
-            if getattr(regime, "run_preprocessing_event_handlers", None): regime.run_preprocessing_event_handlers(self)
-            if getattr(self, "update_shadow_variables", None): self.update_shadow_variables()
+            if getattr(regime, "update_derived_variables", None):
+                regime.update_derived_variables(self)
+            if getattr(self, "update_shadow_variables", None):
+                self.update_shadow_variables()
 
-            if getattr(regime, "update_derived_variables", None): regime.update_derived_variables(self)
-            if getattr(self, "update_shadow_variables", None): self.update_shadow_variables()
+            if getattr(regime, "update_state_variables", None):
+                regime.update_state_variables(self, dt)
+            if getattr(self, "update_shadow_variables", None):
+                self.update_shadow_variables()
 
-            if getattr(regime, "update_state_variables", None): regime.update_state_variables(self, dt)
-            if getattr(self, "update_shadow_variables", None): self.update_shadow_variables()
+            if getattr(regime, "run_postprocessing_event_handlers", None):
+                regime.run_postprocessing_event_handlers(self)
+            if getattr(self, "update_shadow_variables", None):
+                self.update_shadow_variables()
 
-            if getattr(regime, "run_postprocessing_event_handlers", None): regime.run_postprocessing_event_handlers(self)
-            if getattr(self, "update_shadow_variables", None): self.update_shadow_variables()
-            
-            if self.new_regime != '':
+            if self.new_regime != "":
                 self.current_regime = self.new_regime
-                self.new_regime = ''
+                self.new_regime = ""
                 regime = self.regimes[self.current_regime]
-                if getattr(regime, "run_preprocessing_event_handlers", None): regime.run_preprocessing_event_handlers(self)
-                if getattr(self, "update_shadow_variables", None): self.update_shadow_variables()
-                
-            if self.debug: print("In reg: "+self.current_regime)
-                
+                if getattr(regime, "run_preprocessing_event_handlers", None):
+                    regime.run_preprocessing_event_handlers(self)
+                if getattr(self, "update_shadow_variables", None):
+                    self.update_shadow_variables()
+
+            if self.debug:
+                print("In reg: " + self.current_regime)
 
         self.record_variables()
 
@@ -523,45 +587,52 @@ def single_step2(self, dt):
             return dt
 
     def do_startup(self):
-        
+
         if self.debug and False:
-            print("  Doing startup: "+self.id)
-            for iv in self.instance_variables: print("%s = %s"%(iv,self.__dict__[iv]))
-            for dv in self.derived_variables: print("%s = %s"%(dv,self.__dict__[dv]))
-        
+            print("  Doing startup: " + self.id)
+            for iv in self.instance_variables:
+                print("%s = %s" % (iv, self.__dict__[iv]))
+            for dv in self.derived_variables:
+                print("%s = %s" % (dv, self.__dict__[dv]))
+
         for cid in self.uchildren:
             self.uchildren[cid].do_startup()
 
         for child in self.array:
             child.do_startup()
-        
-        #if getattr(self, "xxx", None): 
-        if getattr(self, "run_startup_event_handlers", None): self.run_startup_event_handlers(self)
-        if getattr(self, "update_derived_parameters", None): self.update_derived_parameters(self)
-        
+
+        # if getattr(self, "xxx", None):
+        if getattr(self, "update_derived_parameters", None):
+            self.update_derived_parameters(self)
+
         try:
-            if getattr(self, "update_derived_variables", None): self.update_derived_variables(self)
+            if getattr(self, "update_derived_variables", None):
+                self.update_derived_variables(self)
         except Exception as e:
-            print("Problem setting initial value of DerivedVariable in %s: %s"%(self.id,e))
+            print(
+                "Problem setting initial value of DerivedVariable in %s: %s"
+                % (self.id, e)
+            )
             print("Continuing...")
-      
+
+        # Run start up handlers after all the variables have been set up
+        if getattr(self, "run_startup_event_handlers", None):
+            self.run_startup_event_handlers(self)
+
         for cid in self.uchildren:
             self.uchildren[cid].do_startup()
 
         for child in self.array:
             child.do_startup()
-             
 
     def record_variables(self):
         for recording in self.recorded_variables:
-            recording.add_value(self.time_completed,
-                               self.__dict__[recording.variable])
+            recording.add_value(self.time_completed, self.__dict__[recording.variable])
 
     def push_state(self):
         vars = []
         for varname in self.instance_variables:
-            vars += [self.__dict__[varname],
-                     self.__dict__[varname + '_shadow']]
+            vars += [self.__dict__[varname], self.__dict__[varname + "_shadow"]]
         self.state_stack.push(vars)
 
         for cid in self.uchildren:
@@ -574,7 +645,7 @@ def pop_state(self):
         vars = self.state_stack.pop()
         for varname in self.instance_variables:
             self.__dict_[varname] = vars[0]
-            self.__dict_[varname + '_shadow'] = vars[1]
+            self.__dict_[varname + "_shadow"] = vars[1]
             vars = vars[2:]
 
         for cid in self.uchildren:
@@ -586,9 +657,9 @@ def pop_state(self):
     def update_shadow_variables(self):
         if self.plastic:
             for var in self.instance_variables:
-                self.__dict__[var + '_shadow'] = self.__dict__[var]
+                self.__dict__[var + "_shadow"] = self.__dict__[var]
             for var in self.derived_variables:
-                self.__dict__[var + '_shadow'] = self.__dict__[var]
+                self.__dict__[var + "_shadow"] = self.__dict__[var]
 
     def __lt__(self, other):
         return self.id < other.id
@@ -600,7 +671,8 @@ def copy(self):
         :return: Copy of this runnable.
         :rtype: lems.sim.runnable.Runnable
         """
-        if self.debug: print("Coping....."+self.id)
+        if self.debug:
+            print("Coping....." + self.id)
         r = Runnable(self.id, self.component, self.parent)
         copies = dict()
 
@@ -612,25 +684,25 @@ def copy(self):
         # Plasticity and state stack (?)
         r.plastic = self.plastic
         r.state_stack = Stack()
-        
+
         # Copy variables (GG - Faster using the add_* methods?)
         for v in self.instance_variables:
             r.instance_variables.append(v)
             r.__dict__[v] = self.__dict__[v]
-            r.__dict__[v + '_shadow'] = self.__dict__[v + '_shadow']
-        
+            r.__dict__[v + "_shadow"] = self.__dict__[v + "_shadow"]
+
         for v in self.derived_variables:
             r.derived_variables.append(v)
             r.__dict__[v] = self.__dict__[v]
-            r.__dict__[v + '_shadow'] = self.__dict__[v + '_shadow']
-        
+            r.__dict__[v + "_shadow"] = self.__dict__[v + "_shadow"]
+
         # Copy array elements
         for child in self.array:
             child_copy = child.copy()
             child_copy.parent = r
             r.array.append(child_copy)
             copies[child.uid] = child_copy
-            
+
         # Copy attachment def
         for att in self.attachments:
             atn = self.attachments[att]
@@ -643,7 +715,7 @@ def copy(self):
             child_copy = child.copy()
             child_copy.parent = r
             copies[child.uid] = child_copy
-            
+
             r.add_child(child_copy.id, child_copy)
 
             # For typerefs
@@ -662,7 +734,7 @@ def copy(self):
 
             except:
                 pass
-               
+
         # Copy event ports
         for port in self.event_in_ports:
             r.event_in_ports.append(port)
@@ -671,20 +743,20 @@ def copy(self):
         for port in self.event_out_ports:
             r.event_out_ports.append(port)
             r.event_out_callbacks[port] = self.event_out_callbacks[port]
-        
+
         for ec in r.component.structure.event_connections:
-            if self.debug: print("--- Fixing event_connection: %s in %s"%(ec.toxml(), id(r)))
-            
+            if self.debug:
+                print("--- Fixing event_connection: %s in %s" % (ec.toxml(), id(r)))
+
             source = r.parent.resolve_path(ec.from_)
             target = r.parent.resolve_path(ec.to)
-            
+
             if ec.receiver:
                 # Will throw error...
-                receiver_template = self.build_runnable(ec.receiver, target)                                
-                #receiver = copy.deepcopy(receiver_template)
+                receiver_template = self.build_runnable(ec.receiver, target)
+                # receiver = copy.deepcopy(receiver_template)
                 receiver = receiver_template.copy()
-                receiver.id = "{0}__{1}__".format(component.id,
-                                                  receiver_template.id)
+                receiver.id = "{0}__{1}__".format(component.id, receiver_template.id)
 
                 if ec.receiver_container:
                     target.add_attachment(receiver, ec.receiver_container)
@@ -701,34 +773,49 @@ def copy(self):
                 if len(source.event_out_ports) == 1:
                     source_port = source.event_out_ports[0]
                 else:
-                    raise SimBuildError(("No source event port "
-                                         "uniquely identifiable"
-                                         " in '{0}'").format(source.id))
+                    raise SimBuildError(
+                        (
+                            "No source event port " "uniquely identifiable" " in '{0}'"
+                        ).format(source.id)
+                    )
             if not target_port:
                 if len(target.event_in_ports) == 1:
                     target_port = target.event_in_ports[0]
                 else:
-                    raise SimBuildError(("No destination event port "
-                                         "uniquely identifiable "
-                                         "in '{0}'").format(target))
-             
-            if self.debug: print("register_event_out_callback\n   Source: %s, %s (port: %s) \n   -> %s, %s (port: %s)"%(source, id(source), source_port, target, id(target), target_port))
-            source.register_event_out_callback(\
-                source_port, lambda: target.inc_event_in(target_port))
-            
-        
-            
+                    raise SimBuildError(
+                        (
+                            "No destination event port "
+                            "uniquely identifiable "
+                            "in '{0}'"
+                        ).format(target)
+                    )
+
+            if self.debug:
+                print(
+                    "register_event_out_callback\n   Source: %s, %s (port: %s) \n   -> %s, %s (port: %s)"
+                    % (source, id(source), source_port, target, id(target), target_port)
+                )
+            source.register_event_out_callback(
+                source_port, lambda: target.inc_event_in(target_port)
+            )
 
         # Copy methods
-        if getattr(self, "update_kinetic_scheme", None): r.update_kinetic_scheme = self.update_kinetic_scheme
-        if getattr(self, "run_startup_event_handlers", None): r.run_startup_event_handlers = self.run_startup_event_handlers
-        if getattr(self, "run_preprocessing_event_handlers", None): r.run_preprocessing_event_handlers = self.run_preprocessing_event_handlers
-        if getattr(self, "run_postprocessing_event_handlers", None): r.run_postprocessing_event_handlers = self.run_postprocessing_event_handlers
-        
-        if getattr(self, "update_state_variables", None): r.update_state_variables = self.update_state_variables
-        if getattr(self, "update_derived_variables", None): r.update_derived_variables = self.update_derived_variables
-        #r.update_shadow_variables = self.update_shadow_variables
-        if getattr(self, "update_derived_parameters", None): r.update_derived_parameters = self.update_derived_parameters
+        if getattr(self, "update_kinetic_scheme", None):
+            r.update_kinetic_scheme = self.update_kinetic_scheme
+        if getattr(self, "run_startup_event_handlers", None):
+            r.run_startup_event_handlers = self.run_startup_event_handlers
+        if getattr(self, "run_preprocessing_event_handlers", None):
+            r.run_preprocessing_event_handlers = self.run_preprocessing_event_handlers
+        if getattr(self, "run_postprocessing_event_handlers", None):
+            r.run_postprocessing_event_handlers = self.run_postprocessing_event_handlers
+
+        if getattr(self, "update_state_variables", None):
+            r.update_state_variables = self.update_state_variables
+        if getattr(self, "update_derived_variables", None):
+            r.update_derived_variables = self.update_derived_variables
+        # r.update_shadow_variables = self.update_shadow_variables
+        if getattr(self, "update_derived_parameters", None):
+            r.update_derived_parameters = self.update_derived_parameters
 
         for rn in self.regimes:
             r.add_regime(self.regimes[rn])
@@ -745,11 +832,10 @@ def copy(self):
                     c2.parent = r
                     copies[c.uid] = c2
                     r.add_child_to_group(gn, c2)
-                    
 
         # Copy remaining runnable references.
         for k in self.__dict__:
-            if k == 'parent':
+            if k == "parent":
                 continue
             c = self.__dict__[k]
             if isinstance(c, Runnable):
@@ -760,33 +846,35 @@ def copy(self):
                     c2.parent = r
                     copies[c.uid] = c2
                     r.__dict__[k] = c2
-           
+
         # Copy text fields
-        for k in self.__dict__:          
+        for k in self.__dict__:
             if not k in r.__dict__:
                 c = self.__dict__[k]
-                if self.debug: print("Adding remaining field: %s = %s"%(k,c))
+                if self.debug:
+                    print("Adding remaining field: %s = %s" % (k, c))
                 r.__dict__[k] = c
-                
+
         if self.debug:
-            print('########################################')
+            print("########################################")
             keys = list(self.__dict__.keys())
             keys.sort()
             print(len(keys))
             for k in keys:
                 print(k, self.__dict__[k])
-            print('----------------------------------------')
+            print("----------------------------------------")
             keys = list(r.__dict__.keys())
             keys.sort()
             print(len(keys))
             for k in keys:
                 print(k, r.__dict__[k])
-            print('########################################')
-            print('')
-            print('')
-            print('')
-            print('')
-            
-        if self.debug: print("Finished coping..."+self.id)
-        
+            print("########################################")
+            print("")
+            print("")
+            print("")
+            print("")
+
+        if self.debug:
+            print("Finished coping..." + self.id)
+
         return r
diff --git a/lems/sim/sim.py b/lems/sim/sim.py
index 341c81b..ac50f23 100644
--- a/lems/sim/sim.py
+++ b/lems/sim/sim.py
@@ -10,10 +10,12 @@
 
 import heapq
 
+
 class Simulation(LEMSBase):
     """
     Simulation class.
     """
+
     debug = False
 
     def __init__(self):
@@ -43,7 +45,7 @@ def add_runnable(self, runnable):
         """
 
         if runnable.id in self.runnables:
-            raise SimError('Duplicate runnable component {0}'.format(runnable.id))
+            raise SimError("Duplicate runnable component {0}".format(runnable.id))
 
         self.runnables[runnable.id] = runnable
 
@@ -62,8 +64,7 @@ def step(self):
         (current_time, runnable) = heapq.heappop(self.run_queue)
         time = current_time
         while time == current_time:
-            next_time = current_time + runnable.single_step(\
-                runnable.time_step)
+            next_time = current_time + runnable.single_step(runnable.time_step)
 
             if next_time > current_time:
                 heapq.heappush(self.run_queue, (next_time, runnable))
@@ -88,11 +89,12 @@ def run(self):
         """
 
         self.init_run()
-        if self.debug: self.dump("AfterInit: ")
-        #print("++++++++++++++++ Time: %f"%self.current_time)
+        if self.debug:
+            self.dump("AfterInit: ")
+        # print("++++++++++++++++ Time: %f"%self.current_time)
         while self.step():
-            #self.dump("Time: %f"%self.current_time)
-            #print("++++++++++++++++ Time: %f"%self.current_time)
+            # self.dump("Time: %f"%self.current_time)
+            # print("++++++++++++++++ Time: %f"%self.current_time)
             pass
 
     def push_state(self):
@@ -111,43 +113,44 @@ def disable_plasticity(self):
         for id in self.runnables:
             self.runnables[id].plastic = False
 
-    def dump_runnable(self, runnable, prefix = '.'):
+    def dump_runnable(self, runnable, prefix="."):
         r = runnable
-        print('{0}...............  {1} ({2})'.format(prefix, r.id, r.component.type))
-        print(prefix+str(r))
+        print("{0}...............  {1} ({2})".format(prefix, r.id, r.component.type))
+        print(prefix + str(r))
         ignores = ["Display", "Line", "OutputColumn", "OutputFile", "Simulation"]
         verbose = r.component.type not in ignores
         if verbose:
             if r.instance_variables:
-                print('{0}    Instance variables'.format(prefix))
+                print("{0}    Instance variables".format(prefix))
                 for vn in r.instance_variables:
-                    print('{0}      {1} = {2}'.format(prefix, vn, r.__dict__[vn]))
+                    print("{0}      {1} = {2}".format(prefix, vn, r.__dict__[vn]))
             if r.derived_variables:
-                print('{0}    Derived variables'.format(prefix))
+                print("{0}    Derived variables".format(prefix))
                 for vn in r.derived_variables:
-                    print('{0}      {1} = {2}'.format(prefix, vn, r.__dict__[vn]))
-                
+                    print("{0}      {1} = {2}".format(prefix, vn, r.__dict__[vn]))
+
         if verbose:
             keys = list(r.__dict__.keys())
             keys.sort()
-            print('{0}    Keys for {1}'.format(prefix, r.id))
+            print("{0}    Keys for {1}".format(prefix, r.id))
             for k in keys:
                 key_str = str(r.__dict__[k])
                 if len(key_str) > 0 and not key_str == "[]" and not key_str == "{}":
-                    print('{0}       {1} -> {2}'.format(prefix, k, key_str))
-                    
+                    print("{0}       {1} -> {2}".format(prefix, k, key_str))
+
         if r.array:
             for c in r.array:
-                self.dump_runnable(c, prefix + '    .')
+                self.dump_runnable(c, prefix + "    .")
         if r.uchildren:
             for cn in r.uchildren:
-                self.dump_runnable(r.uchildren[cn], prefix + '    .')
+                self.dump_runnable(r.uchildren[cn], prefix + "    .")
 
-    def dump(self, prefix=''):
-        print('Runnables:')
+    def dump(self, prefix=""):
+        print("Runnables:")
         for id in self.runnables:
             self.dump_runnable(self.runnables[id], prefix)
 
+
 class Event:
     """
     Stores data associated with an event.
diff --git a/man/man1/README.md b/man/man1/README.md
new file mode 100644
index 0000000..7d27ec2
--- /dev/null
+++ b/man/man1/README.md
@@ -0,0 +1,11 @@
+# pylems.1
+
+
+Generated using `help2man <https://www.gnu.org/software/help2man/>`__ from `pylems -h` output:
+
+```
+$ help2man -n "LEMS interpreter implemented in Python" --version-string="0.5.8" -N pylems -S "https://lems.github.io" -o pylems.1
+```
+
+On Linux systems, this file would go into `/usr/share/man/man1`.
+The file can be locally viewed without installation using `man -l pylems.1`.
diff --git a/man/man1/pylems.1 b/man/man1/pylems.1
new file mode 100644
index 0000000..20702ad
--- /dev/null
+++ b/man/man1/pylems.1
@@ -0,0 +1,26 @@
+.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.48.5.
+.TH PYLEMS "1" "November 2021" "https://lems.github.io" "User Commands"
+.SH NAME
+pylems \- LEMS interpreter implemented in Python
+.SH DESCRIPTION
+usage: pylems [\-h] [\-I <Include directory>] [\-nogui] [\-dlems] <LEMS file>
+.SS "positional arguments:"
+.TP
+<LEMS file>
+LEMS file to be simulated
+.SS "options:"
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+show this help message and exit
+.TP
+\fB\-I\fR <Include directory>
+Directory to be searched for included files
+.TP
+\fB\-nogui\fR
+If this is specified, just parse & simulate the model,
+but don't show any plots
+.TP
+\fB\-dlems\fR
+If this is specified, export the LEMS file as dLEMS
+(distilled LEMS in JSON format, see
+https://github.com/borismarin/som\-codegen)
diff --git a/setup.py b/setup.py
index 578bf0e..0d5794e 100644
--- a/setup.py
+++ b/setup.py
@@ -5,30 +5,40 @@
 long_description = open("README.md").read()
 
 import lems
+
 version = lems.__version__
 
 setup(
-    name = "PyLEMS",
-    version = version,
-    packages = ['lems','lems.base','lems.model','lems.parser','lems.sim', 'lems.dlems'],
-    scripts=['pylems'],
-    author = "PyLEMS authors and contributors",
-    author_email = "gautham@lisphacker.org, p.gleeson@gmail.com",
-    description = "A Python library for working with the Low Entropy Model Specification language (LEMS)",
-    long_description = long_description,
+    name="PyLEMS",
+    version=version,
+    packages=[
+        "lems",
+        "lems.base",
+        "lems.model",
+        "lems.parser",
+        "lems.sim",
+        "lems.dlems",
+    ],
+    scripts=["pylems"],
+    data_files=[("man/man1", ['man/man1/pylems.1'])],
+    author="PyLEMS authors and contributors",
+    author_email="gautham@lisphacker.org, p.gleeson@gmail.com",
+    description="A Python library for working with the Low Entropy Model Specification language (LEMS)",
+    long_description=long_description,
     long_description_content_type="text/markdown",
-    install_requires=['lxml','typing'],
-    license = "LGPL",
+    install_requires=["lxml", 'typing; python_version<"3.5"'],
+    license="LGPL",
     url="https://github.com/LEMS/pylems",
-    classifiers = [
-        'Intended Audience :: Science/Research',
-        '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.6',
-        'Programming Language :: Python :: 3.7',
-        'Programming Language :: Python :: 3.8',
-        'Programming Language :: Python :: 3.9',
-        'Topic :: Scientific/Engineering']
+    classifiers=[
+        "Intended Audience :: Science/Research",
+        "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.6",
+        "Programming Language :: Python :: 3.7",
+        "Programming Language :: Python :: 3.8",
+        "Programming Language :: Python :: 3.9",
+        "Topic :: Scientific/Engineering",
+    ],
 )


Test patch:
diff --git a/examples/apitest.py b/examples/apitest.py
index 297bc88..57088b2 100755
--- a/examples/apitest.py
+++ b/examples/apitest.py
@@ -4,31 +4,31 @@
 
 model = lems.Model()
 
-model.add(lems.Dimension('voltage', m=1, l=3, t=-3, i=-1))
-model.add(lems.Dimension('time', t=1))
-model.add(lems.Dimension('capacitance', m=-1, l=-2, t=4, i=2))
+model.add(lems.Dimension("voltage", m=1, l=3, t=-3, i=-1))
+model.add(lems.Dimension("time", t=1))
+model.add(lems.Dimension("capacitance", m=-1, l=-2, t=4, i=2))
 
-model.add(lems.Unit('milliVolt', 'mV', 'voltage', -3))
-model.add(lems.Unit('milliSecond', 'ms', 'time', -3))
-model.add(lems.Unit('microFarad', 'uF', 'capacitance', -12))
+model.add(lems.Unit("milliVolt", "mV", "voltage", -3))
+model.add(lems.Unit("milliSecond", "ms", "time", -3))
+model.add(lems.Unit("microFarad", "uF", "capacitance", -12))
 
-iaf1 = lems.ComponentType('iaf1')
+iaf1 = lems.ComponentType("iaf1")
 model.add(iaf1)
 
-iaf1.add(lems.Parameter('threshold', 'voltage'))
-iaf1.add(lems.Parameter('refractoryPeriod', 'time'))
-iaf1.add(lems.Parameter('capacitance', 'capacitance'))
+iaf1.add(lems.Parameter("threshold", "voltage"))
+iaf1.add(lems.Parameter("refractoryPeriod", "time"))
+iaf1.add(lems.Parameter("capacitance", "capacitance"))
 
-model.add(lems.Component('celltype_a', 'iaf1'))
+model.add(lems.Component("celltype_a", "iaf1"))
 
-fn = '/tmp/model.xml'
+fn = "/tmp/model.xml"
 model.export_to_file(fn)
 
 print("----------------------------------------------")
-print(open(fn,'r').read())
+print(open(fn, "r").read())
 print("----------------------------------------------")
 
-print("Written generated LEMS to %s"%fn)
+print("Written generated LEMS to %s" % fn)
 
 from lems.base.util import validate_lems
 
diff --git a/examples/apitest2.py b/examples/apitest2.py
index fc839cf..fcc387d 100644
--- a/examples/apitest2.py
+++ b/examples/apitest2.py
@@ -4,44 +4,44 @@
 
 model = lems.Model()
 
-model.add(lems.Dimension('voltage', m=1, l=3, t=-3, i=-1))
-model.add(lems.Dimension('time', t=1))
-model.add(lems.Dimension('capacitance', m=-1, l=-2, t=4, i=2))
+model.add(lems.Dimension("voltage", m=1, l=3, t=-3, i=-1))
+model.add(lems.Dimension("time", t=1))
+model.add(lems.Dimension("capacitance", m=-1, l=-2, t=4, i=2))
 
-model.add(lems.Unit('milliVolt', 'mV', 'voltage', -3))
-model.add(lems.Unit('milliSecond', 'ms', 'time', -3))
-model.add(lems.Unit('microFarad', 'uF', 'capacitance', -12))
+model.add(lems.Unit("milliVolt", "mV", "voltage", -3))
+model.add(lems.Unit("milliSecond", "ms", "time", -3))
+model.add(lems.Unit("microFarad", "uF", "capacitance", -12))
 
-iaf1 = lems.ComponentType('iaf1')
+iaf1 = lems.ComponentType("iaf1")
 model.add(iaf1)
 
-iaf1.add(lems.Parameter('threshold', 'voltage'))
-iaf1.add(lems.Parameter('reset', 'voltage'))
-iaf1.add(lems.Parameter('refractoryPeriod', 'time'))
-iaf1.add(lems.Parameter('capacitance', 'capacitance'))
-iaf1.add(lems.Exposure('vexp', 'voltage'))
-dp = lems.DerivedParameter('range', 'threshold - reset', 'voltage')
+iaf1.add(lems.Parameter("threshold", "voltage"))
+iaf1.add(lems.Parameter("reset", "voltage"))
+iaf1.add(lems.Parameter("refractoryPeriod", "time"))
+iaf1.add(lems.Parameter("capacitance", "capacitance"))
+iaf1.add(lems.Exposure("vexp", "voltage"))
+dp = lems.DerivedParameter("range", "threshold - reset", "voltage")
 iaf1.add(dp)
 
-iaf1.dynamics.add(lems.StateVariable('v','voltage', 'vexp')) 
-iaf1.dynamics.add(lems.DerivedVariable('v2',dimension='voltage', value='v*2'))
-cdv = lems.ConditionalDerivedVariable('v_abs','voltage')
-cdv.add(lems.Case('v .geq. 0','v'))
-cdv.add(lems.Case('v .lt. 0','-1*v'))
+iaf1.dynamics.add(lems.StateVariable("v", "voltage", "vexp"))
+iaf1.dynamics.add(lems.DerivedVariable("v2", dimension="voltage", value="v*2"))
+cdv = lems.ConditionalDerivedVariable("v_abs", "voltage")
+cdv.add(lems.Case("v .geq. 0", "v"))
+cdv.add(lems.Case("v .lt. 0", "-1*v"))
 iaf1.dynamics.add(cdv)
 
 
-model.add(lems.Component('celltype_a', iaf1.name))
-model.add(lems.Component('celltype_b', iaf1.name, threshold="20mV"))
+model.add(lems.Component("celltype_a", iaf1.name))
+model.add(lems.Component("celltype_b", iaf1.name, threshold="20mV"))
 
-fn = '/tmp/model.xml'
+fn = "/tmp/model.xml"
 model.export_to_file(fn)
 
 print("----------------------------------------------")
-print(open(fn,'r').read())
+print(open(fn, "r").read())
 print("----------------------------------------------")
 
-print("Written generated LEMS to %s"%fn)
+print("Written generated LEMS to %s" % fn)
 
 from lems.base.util import validate_lems
 
diff --git a/examples/apitest3.py b/examples/apitest3.py
index d67930d..d11b4a9 100644
--- a/examples/apitest3.py
+++ b/examples/apitest3.py
@@ -6,44 +6,44 @@
 
 model.add(lems.Include("test.xml"))
 
-model.add(lems.Dimension('voltage', m=1, l=3, t=-3, i=-1))
-model.add(lems.Dimension('time', t=1))
-model.add(lems.Dimension('capacitance', m=-1, l=-2, t=4, i=2))
+model.add(lems.Dimension("voltage", m=1, l=3, t=-3, i=-1))
+model.add(lems.Dimension("time", t=1))
+model.add(lems.Dimension("capacitance", m=-1, l=-2, t=4, i=2))
 
-model.add(lems.Unit('milliVolt', 'mV', 'voltage', -3))
-model.add(lems.Unit('milliSecond', 'ms', 'time', -3))
-model.add(lems.Unit('microFarad', 'uF', 'capacitance', -12))
+model.add(lems.Unit("milliVolt", "mV", "voltage", -3))
+model.add(lems.Unit("milliSecond", "ms", "time", -3))
+model.add(lems.Unit("microFarad", "uF", "capacitance", -12))
 
-iaf1 = lems.ComponentType('iaf1')
+iaf1 = lems.ComponentType("iaf1")
 model.add(iaf1)
 
-iaf1.add(lems.Parameter('threshold', 'voltage'))
-iaf1.add(lems.Parameter('reset', 'voltage'))
-iaf1.add(lems.Parameter('refractoryPeriod', 'time'))
-iaf1.add(lems.Parameter('capacitance', 'capacitance'))
-iaf1.add(lems.Exposure('vexp', 'voltage'))
-dp = lems.DerivedParameter('range', 'threshold - reset', 'voltage')
+iaf1.add(lems.Parameter("threshold", "voltage"))
+iaf1.add(lems.Parameter("reset", "voltage"))
+iaf1.add(lems.Parameter("refractoryPeriod", "time"))
+iaf1.add(lems.Parameter("capacitance", "capacitance"))
+iaf1.add(lems.Exposure("vexp", "voltage"))
+dp = lems.DerivedParameter("range", "threshold - reset", "voltage")
 iaf1.add(dp)
 
-iaf1.dynamics.add(lems.StateVariable('v','voltage', 'vexp')) 
-iaf1.dynamics.add(lems.DerivedVariable('v2',dimension='voltage', value='v*2'))
-cdv = lems.ConditionalDerivedVariable('v_abs','voltage')
-cdv.add(lems.Case('v .geq. 0','v'))
-cdv.add(lems.Case('v .lt. 0','-1*v'))
+iaf1.dynamics.add(lems.StateVariable("v", "voltage", "vexp"))
+iaf1.dynamics.add(lems.DerivedVariable("v2", dimension="voltage", value="v*2"))
+cdv = lems.ConditionalDerivedVariable("v_abs", "voltage")
+cdv.add(lems.Case("v .geq. 0", "v"))
+cdv.add(lems.Case("v .lt. 0", "-1*v"))
 iaf1.dynamics.add(cdv)
 
 
-model.add(lems.Component('celltype_a', iaf1.name))
-model.add(lems.Component('celltype_b', iaf1.name, threshold="20mV"))
+model.add(lems.Component("celltype_a", iaf1.name))
+model.add(lems.Component("celltype_b", iaf1.name, threshold="20mV"))
 
-fn = '/tmp/model.xml'
+fn = "/tmp/model.xml"
 model.export_to_file(fn)
 
 print("----------------------------------------------")
-print(open(fn,'r').read())
+print(open(fn, "r").read())
 print("----------------------------------------------")
 
-print("Written generated LEMS to %s"%fn)
+print("Written generated LEMS to %s" % fn)
 
 from lems.base.util import validate_lems
 
diff --git a/examples/loadtest.py b/examples/loadtest.py
index 001ac44..24bf3ee 100755
--- a/examples/loadtest.py
+++ b/examples/loadtest.py
@@ -5,24 +5,24 @@
 
 model = Model()
 
-file_name = 'examples/hhcell.xml'
-#file_name = '../NeuroML2/NeuroML2CoreTypes/LEMS_NML2_Ex0_IaF.xml'
-#file_name = '../NeuroML2/NeuroML2CoreTypes/LEMS_NML2_Ex3_Net.xml'
-#file_name = '../org.neuroml.import/src/test/resources/BIOMD0000000185_LEMS.xml'
+file_name = "examples/hhcell.xml"
+# file_name = '../NeuroML2/NeuroML2CoreTypes/LEMS_NML2_Ex0_IaF.xml'
+# file_name = '../NeuroML2/NeuroML2CoreTypes/LEMS_NML2_Ex3_Net.xml'
+# file_name = '../org.neuroml.import/src/test/resources/BIOMD0000000185_LEMS.xml'
 
 if len(sys.argv) == 2:
-    file_name = sys.argv[1] 
+    file_name = sys.argv[1]
 
 model.import_from_file(file_name)
 
-fn = '/tmp/hhmodel.xml'
+fn = "/tmp/hhmodel.xml"
 model.export_to_file(fn)
 
 print("----------------------------------------------")
-print(open(fn,'r').read())
+print(open(fn, "r").read())
 print("----------------------------------------------")
 
-print("Written generated LEMS to %s"%fn)
+print("Written generated LEMS to %s" % fn)
 
 from lems.base.util import validate_lems
 
diff --git a/lems/test/NeuroML2CoreTypes/Cells.xml b/lems/test/NeuroML2CoreTypes/Cells.xml
new file mode 100644
index 0000000..b71ebdf
--- /dev/null
+++ b/lems/test/NeuroML2CoreTypes/Cells.xml
@@ -0,0 +1,1751 @@
+<Lems xmlns="http://www.neuroml.org/lems/0.7.5"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.neuroml.org/lems/0.7.5 ../../LEMS/Schemas/LEMS/LEMS_v0.7.5.xsd"
+      description="Defines both abstract cell models (e.g. _izhikevichCell_, adaptive exponential integrate and fire cell, _adExIaFCell_), point conductance based cell models (_pointCellCondBased_, _pointCellCondBasedCa_) and cells models (_cell_) which specify the _morphology_ (containing _segment_s) and _biophysicalProperties_ separately.">
+
+    <!-- A number of cell types for use in NeuroML 2 documents  -->
+
+    <Include file="NeuroMLCoreDimensions.xml"/>
+    <Include file="Channels.xml"/>
+    <Include file="Synapses.xml"/>
+    <Include file="Inputs.xml"/>
+
+
+    <ComponentType name="baseCell"
+        description="Base type of any cell (e.g. point neuron like _izhikevich2007Cell_, or a morphologically detailed _Cell_ with _segment_s) which can be used in a _population_"
+        extends="baseStandalone">
+
+    </ComponentType>
+
+
+    <ComponentType name="baseSpikingCell"
+        extends="baseCell"
+        description="Base type of any cell which can emit _spike events.">
+
+        <EventPort name="spike" direction="out" description="Spike event"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="baseCellMembPot"
+        extends="baseSpikingCell"
+        description="Any spiking cell which has a membrane potential _v with units of voltage (as opposed to a dimensionless membrane potential used in _baseCellMembPotDL_).">
+
+        <Exposure name="v" dimension="voltage" description="Membrane potential"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="baseCellMembPotDL"
+        extends="baseSpikingCell"
+        description="Any spiking cell which has a dimensioness membrane potential, _V (as opposed to a membrane potential units of voltage, _baseCellMembPot_).">
+
+        <Exposure name="V" dimension="none" description="Membrane potential"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="baseChannelPopulation"
+       extends="baseVoltageDepPointCurrent"
+       description="Base type for any current produced by a population of channels, all of which are of type _ionChannel">
+
+        <ComponentReference name="ionChannel" type="baseIonChannel"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="channelPopulation"
+        extends="baseChannelPopulation"
+        description="Population of a _number of ohmic ion channels. These each produce a conductance _channelg across a reversal potential _erev, giving a total current _i. Note that active membrane currents are more frequently specified as a density over an area of the _cell_ using _channelDensity_">
+
+        <Parameter name="number" dimension="none" description="The number of channels present. This will be multiplied by the time varying conductance of the individual ion channel (which extends _baseIonChannel_) to produce the total conductance"/>
+        <Parameter name="erev" dimension="voltage" description="The reversal potential of the current produced"/>
+
+        <Constant name="vShift" dimension="voltage" value="0mV" description="Set to a constant 0mV here to allow ion channels which use _vShift in their rate variable expressions to be used with _channelPopulation_, not just with _channelDensityVShift_ (where _vShift would be explicitly set)"/>
+
+        <Text name="ion" description="Which ion flows through the channel. Note: ideally this needs to be a property of ionChannel only, but it's here as it makes it easier to select channelPopulations transmitting specific ions."/>
+
+        <Dynamics>
+            <DerivedVariable name="channelg" dimension="conductance" select="ionChannel/g"/>
+            <DerivedVariable name="geff" dimension="conductance" value="channelg * number"/>
+            <DerivedVariable name="i" dimension="current" exposure="i" value="geff * (erev - v)"/>
+        </Dynamics>
+
+        <Structure>
+            <ChildInstance component="ionChannel"/>
+        </Structure>
+
+    </ComponentType>
+
+
+    <ComponentType name="channelPopulationNernst"
+        extends="baseChannelPopulation"
+        description="Population of a _number of channels with a time varying reversal potential _erev determined by Nernst equation. Note: hard coded for Ca only!">
+
+        <Parameter name="number" dimension="none" description="The number of channels present. This will be multiplied by the time varying conductance of the individual ion channel (which extends _baseIonChannel_) to produce the total conductance"/>
+
+        <Constant name="R" dimension="idealGasConstantDims" value="8.3144621 J_per_K_per_mol" description="TODO: Make this a global constant!"/>
+        <Constant name="zCa" dimension="none" value="2" description="TODO: Make this a global constant!"/>
+        <Constant name="F" dimension="charge_per_mole" value="96485.3 C_per_mol" description="TODO: Make this a global constant!"/>
+
+        <Constant name="vShift" dimension="voltage" value="0mV" description="Set to a constant 0mV here to allow ion channels which use _vShift in their rate variable expressions to be used with _channelPopulation_, not just with _channelDensityVShift_ (where _vShift would be explicitly set)"/>
+
+
+        <Exposure name="erev" dimension="voltage" description="The reversal potential of the current produced, calculated from _caConcExt and _caConc"/>
+
+        <Requirement name="temperature" dimension="temperature" description="The temperature to use in the calculation of _erev. Note this is generally exposed by a _networkWithTemperature_."/>
+        <Requirement name="caConc" dimension="concentration" description="The internal Ca2+ concentration, as calculated/exposed by the parent Component"/>
+        <Requirement name="caConcExt" dimension="concentration" description="The external Ca2+ concentration, as calculated/exposed by the parent Component"/>
+
+        <Text name="ion" description="Which ion flows through the channel. Note: ideally this needs to be a property of ionChannel only, but it's here as it makes it easier to select channelPopulations transmitting specific ions."/>
+
+        <Dynamics>
+
+            <DerivedVariable name="singleChannelConductance" dimension="conductance" select="ionChannel/g"/>
+            <DerivedVariable name="totalConductance" dimension="conductance" value="singleChannelConductance * number"/>
+
+            <DerivedVariable name="erev" dimension="voltage" exposure="erev" value="(R * temperature / (zCa * F)) * log(caConcExt / caConc)"/>
+
+            <!--TODO: see if the check on caconcext needed: DerivedVariable name="i" dimension="current" exposure="i" value="totalConductance * (erev - v)" valueCondition="caConcExt .gt. 0" valueIfFalse="0"/>  -->
+            <DerivedVariable name="i" dimension="current" exposure="i" value="totalConductance * (erev - v)"/>
+
+        </Dynamics>
+
+        <Structure>
+            <ChildInstance component="ionChannel"/>
+        </Structure>
+
+    </ComponentType>
+
+
+    <ComponentType name="baseChannelDensity"
+        description="Base type for a current of density _iDensity distributed on an area of a _cell_, flowing through the specified _ionChannel. Instances of this (normally _channelDensity_) are specified in the _membraneProperties_ of the _cell_.">
+
+        <ComponentReference name="ionChannel" type="baseIonChannel"/>
+
+        <Exposure name="iDensity" dimension="currentDensity"/>
+
+        <Requirement name="v" dimension="voltage"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="baseChannelDensityCond"
+        description="Base type for distributed conductances on an area of a cell producing a (not necessarily ohmic) current"
+        extends="baseChannelDensity">
+
+        <Parameter name="condDensity" dimension="conductanceDensity"/>
+
+        <Exposure name="gDensity" dimension="conductanceDensity"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="variableParameter"
+        description="Specifies a _parameter (e.g. condDensity) which can vary its value across a _segmentGroup. The value is calculated from _value attribute of the _inhomogeneousValue_ subelement. This element is normally a child of _channelDensityNonUniform_, _channelDensityNonUniformNernst_ or _channelDensityNonUniformGHK_ and is used to calculate the value of the conductance, etc. which will vary on different parts of the cell. The _segmentGroup specified here needs to define an _inhomogeneousParameter_ (referenced from _inhomogeneousParameter in the _inhomogeneousValue_), which calculates a _variable (e.g. p) varying across the cell (e.g. based on the path length from soma), which is then used in the _value attribute of the _inhomogeneousValue_ (so for example condDensity = f(p))">
+
+        <Child name="inhomogeneousValue" type="inhomogeneousValue"/>
+
+        <Text name="parameter"/>
+        <Text name="segmentGroup"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="inhomogeneousValue"
+        description="Specifies the _value of an _inhomogeneousParameter. For usage see _variableParameter_">
+
+        <Text name="inhomogeneousParameter"/>
+        <Text name="value"/>
+
+    </ComponentType>
+
+
+
+    <ComponentType name="channelDensityNonUniform"
+        extends="baseChannelDensity"
+        description="Specifies a time varying ohmic conductance density, which is distributed on a region of the _cell. The conductance density of the channel is not uniform, but is set using the _variableParameter_. Note, there is no dynamical description of this in LEMS yet, as this type only makes sense for multicompartmental cells. A ComponentType for this needs to be present to enable export of NeuroML 2 multicompartmental cells via LEMS/jNeuroML to NEURON">
+
+        <Parameter name="erev" dimension="voltage" description="The reversal potential of the current produced"/>
+
+        <Constant name="ZERO_CURR_DENS" dimension="currentDensity" value="0 A_per_m2"/>
+
+        <Child name="variableParameter" type="variableParameter"/>
+
+        <!-- TODO: Ensure Text elements are inherited from base type -->
+        <Text name="segmentGroup"/>
+        <Text name="ion" description="Which ion flows through the channel. Note: ideally this needs to be a property of ionChannel only, but it's here as it makes it easier to select channelPopulations transmitting specific ions."/>
+
+
+        <Dynamics>
+            <!--NOTE: channelDensityNonUniform is not used by jLEMS, only when jNeuroML maps NML2 cells with this element to
+                a multicompartmental format in another simulator, e.g. NEURON-->
+            <DerivedVariable name="iDensity"  dimension="currentDensity" exposure="iDensity" value="ZERO_CURR_DENS"/>
+        </Dynamics>
+
+        <Structure>
+            <ChildInstance component="ionChannel"/>
+        </Structure>
+
+    </ComponentType>
+
+
+    <ComponentType name="channelDensityNonUniformNernst"
+        extends="baseChannelDensity"
+        description="Specifies a time varying conductance density, which is distributed on a region of the _cell, and whose reversal potential is calculated from the Nernst equation. Hard coded for Ca only!. The conductance density of the channel is not uniform, but is set using the _variableParameter_. Note, there is no dynamical description of this in LEMS yet, as this type only makes sense for multicompartmental cells. A ComponentType for this needs to be present to enable export of NeuroML 2 multicompartmental cells via LEMS/jNeuroML to NEURON">
+
+        <Constant name="ZERO_CURR_DENS" dimension="currentDensity" value="0 A_per_m2"/>
+
+        <Child name="variableParameter" type="variableParameter"/>
+
+
+        <!-- TODO: Ensure Text elements are inherited from base type -->
+        <Text name="segmentGroup"/>
+        <Text name="ion" description="Which ion flows through the channel. Note: ideally this needs to be a property of ionChannel only, but it's here as it makes it easier to select channelPopulations transmitting specific ions."/>
+
+
+        <Dynamics>
+            <!--NOTE: channelDensityNonUniform is not used by jLEMS, only when jNeuroML maps NML2 cells with this element to
+                a multicompartmental format in another simulator, e.g. NEURON-->
+            <DerivedVariable name="iDensity"  dimension="currentDensity" exposure="iDensity" value="ZERO_CURR_DENS"/>
+        </Dynamics>
+
+        <Structure>
+            <ChildInstance component="ionChannel"/>
+        </Structure>
+
+    </ComponentType>
+
+
+    <ComponentType name="channelDensityNonUniformGHK"
+        extends="baseChannelDensity"
+        description="Specifies a time varying conductance density, which is distributed on a region of the _cell, and whose current is calculated from the Goldman-Hodgkin-Katz equation. Hard coded for Ca only!. The conductance density of the channel is not uniform, but is set using the _variableParameter_. Note, there is no dynamical description of this in LEMS yet, as this type only makes sense for multicompartmental cells. A ComponentType for this needs to be present to enable export of NeuroML 2 multicompartmental cells via LEMS/jNeuroML to NEURON">
+
+        <Constant name="ZERO_CURR_DENS" dimension="currentDensity" value="0 A_per_m2"/>
+
+        <Child name="variableParameter" type="variableParameter"/>
+
+
+        <!-- TODO: Ensure Text elements are inherited from base type -->
+        <Text name="segmentGroup"/>
+        <Text name="ion" description="Which ion flows through the channel. Note: ideally this needs to be a property of ionChannel only, but it's here as it makes it easier to select channelPopulations transmitting specific ions."/>
+
+
+        <Dynamics>
+            <!--NOTE: channelDensityNonUniform is not used by jLEMS, only when jNeuroML maps NML2 cells with this element to
+                a multicompartmental format in another simulator, e.g. NEURON-->
+            <DerivedVariable name="iDensity"  dimension="currentDensity" exposure="iDensity" value="ZERO_CURR_DENS"/>
+        </Dynamics>
+
+        <Structure>
+            <ChildInstance component="ionChannel"/>
+        </Structure>
+
+    </ComponentType>
+
+
+    <ComponentType name="channelDensity"
+        extends="baseChannelDensityCond"
+        description="Specifies a time varying ohmic conductance density, _gDensity, which is distributed on an area of the _cell (specified in _membraneProperties_) with fixed reversal potential _erev producing a current density _iDensity">
+
+        <Parameter name="erev" dimension="voltage" description="The reversal potential of the current produced"/>
+
+        <Constant name="vShift" dimension="voltage" value="0mV" description="Set to a constant 0mV here to allow ion channels which use _vShift in their rate variable expressions to be used with _channelDensity_, not just with _channelDensityVShift_ (where _vShift would be explicitly set)"/>
+
+        <!-- TODO: Ensure Text elements are inherited from base type -->
+        <Text name="segmentGroup" description="Which _segmentGroup_ the channelDensity is placed on. If this is missing, it implies it is placed on all _segment_s of the _cell_"/>
+        <Text name="ion" description="Which ion flows through the channel. Note: ideally this needs to be a property of ionChannel only, but it's here as it makes it easier to select channelPopulations transmitting specific ions."/>
+
+        <Dynamics>
+
+            <DerivedVariable name="channelf" dimension="none" select="ionChannel/fopen"/>
+
+            <DerivedVariable name="gDensity" dimension="conductanceDensity" exposure="gDensity" value="condDensity * channelf"/>
+
+            <DerivedVariable name="iDensity"  dimension="currentDensity" exposure="iDensity" value="gDensity * (erev - v)"/>
+
+        </Dynamics>
+
+        <Structure>
+            <ChildInstance component="ionChannel"/>
+        </Structure>
+
+    </ComponentType>
+
+    <ComponentType name="channelDensityVShift"
+        extends="channelDensity"
+        description="Same as _channelDensity_, but with a _vShift parameter to change voltage activation of gates. The exact usage of _vShift in expressions for rates is determined by the individual gates.">
+
+        <Parameter name="vShift" dimension="voltage"/>
+
+        <!-- TODO: Ensure Text elements are inherited from base type -->
+        <Text name="segmentGroup" description="Which _segmentGroup_ the channelDensity is placed on. If this is missing, it implies it is placed on all _segment_s of the _cell_"/>
+        <Text name="ion" description="Which ion flows through the channel. Note: ideally this needs to be a property of ionChannel only, but it's here as it makes it easier to select channelPopulations transmitting specific ions."/>
+
+
+        <Structure>
+            <ChildInstance component="ionChannel"/>
+        </Structure>
+
+    </ComponentType>
+
+
+    <ComponentType name="channelDensityNernst"
+        extends="baseChannelDensityCond"
+        description="Specifies a time varying conductance density, _gDensity, which is distributed on an area of the _cell, producing a current density _iDensity and whose reversal potential is calculated from the Nernst equation. Hard coded for Ca only! See https://github.com/OpenSourceBrain/ghk-nernst.">
+
+        <Constant name="R" dimension="idealGasConstantDims" value="8.3144621 J_per_K_per_mol" description="TODO: Make this a global constant!"/>
+        <Constant name="zCa" dimension="none" value="2" description="TODO: Make this a global constant!"/>
+        <Constant name="F" dimension="charge_per_mole" value="96485.3 C_per_mol" description="TODO: Make this a global constant!"/>
+
+        <Exposure name="erev" dimension="voltage" description="The reversal potential of the current produced, calculated from caConcExt and caConc"/>
+
+        <Requirement name="temperature" dimension="temperature"/>
+        <Requirement name="caConc" dimension="concentration"/>
+        <Requirement name="caConcExt" dimension="concentration"/>
+
+        <!-- TODO: Ensure Text elements are inherited from base type -->
+        <Text name="segmentGroup" description="Which _segmentGroup_ the channelDensityNernst is placed on. If this is missing, it implies it is placed on all _segment_s of the _cell_"/>
+        <Text name="ion" description="Which ion flows through the channel. Note: ideally this needs to be a property of ionChannel only, but it's here as it makes it easier to select channelPopulations transmitting specific ions."/>
+
+
+        <Dynamics>
+
+            <DerivedVariable name="channelf" dimension="none" select="ionChannel/fopen"/>
+
+            <ConditionalDerivedVariable name="gDensity" dimension="conductanceDensity" exposure="gDensity">
+            	<Case condition="caConcExt .gt. 0" value="condDensity * channelf"/>
+            	<Case condition="caConcExt .leq. 0" value="0"/>
+            </ConditionalDerivedVariable>
+
+            <ConditionalDerivedVariable name="erev" dimension="voltage" exposure="erev">
+            	<Case condition="caConcExt .gt. 0" value="(R * temperature / (zCa * F)) * log(caConcExt / caConc)"/>
+            	<Case condition="caConcExt .leq. 0" value="0"/>
+            </ConditionalDerivedVariable>
+
+            <!-- TODO check if needed <DerivedVariable name="iDensity"  dimension="currentDensity" exposure="iDensity"
+                                                       value="gDensity * (erev - v)" valueCondition="caConcExt .gt. 0" valueIfFalse="0"/>  -->
+            <ConditionalDerivedVariable name="iDensity" dimension="currentDensity" exposure="iDensity">
+            	<Case condition="caConcExt .gt. 0" value="gDensity * (erev - v)"/>
+            	<Case condition="caConcExt .leq. 0" value="0"/>
+            </ConditionalDerivedVariable>
+
+        </Dynamics>
+
+        <Structure>
+            <ChildInstance component="ionChannel"/>
+        </Structure>
+
+    </ComponentType>
+
+
+    <ComponentType name="channelDensityNernstCa2"
+                   extends="baseChannelDensityCond"
+                   description="This component is similar to the original component type _channelDensityNernst_ but it is changed in order to have a reversal potential that depends on a second independent Ca++ pool (ca2). See https://github.com/OpenSourceBrain/ghk-nernst.">
+
+        <Constant name="R" dimension="idealGasConstantDims" value="8.3144621 J_per_K_per_mol" description="TODO: Make this a global constant!"/>
+        <Constant name="zCa" dimension="none" value="2" description="TODO: Make this a global constant!"/>
+        <Constant name="F" dimension="charge_per_mole" value="96485.3 C_per_mol" description="TODO: Make this a global constant!"/>
+
+        <Exposure name="erev" dimension="voltage" description="The reversal potential of the current produced"/>
+
+        <Requirement name="temperature" dimension="temperature"/>
+        <Requirement name="caConc2" dimension="concentration"/>
+        <Requirement name="caConcExt2" dimension="concentration"/>
+
+        <Text name="segmentGroup" description="Which _segmentGroup_ the channelDensityNernstCa2 is placed on. If this is missing, it implies it is placed on all _segment_s of the _cell_"/>
+        <Text name="ion" description="Which ion flows through the channel. Note: ideally this needs to be a property of ionChannel only, but it's here as it makes it easier to select channelPopulations transmitting specific ions."/>
+
+
+        <Dynamics>
+
+            <DerivedVariable name="channelf" dimension="none" select="ionChannel/fopen"/>
+
+            <ConditionalDerivedVariable name="gDensity" dimension="conductanceDensity" exposure="gDensity">
+                <Case condition="caConcExt2 .gt. 0" value="condDensity * channelf"/>
+                <Case condition="caConcExt2 .leq. 0" value="0"/>
+            </ConditionalDerivedVariable>
+
+            <ConditionalDerivedVariable name="erev" dimension="voltage" exposure="erev">
+                <Case condition="caConcExt2 .gt. 0" value="(R * temperature / (zCa * F)) * log(caConcExt2 / caConc2)"/>
+                <Case condition="caConcExt2 .leq. 0" value="0"/>
+            </ConditionalDerivedVariable>
+
+            <ConditionalDerivedVariable name="iDensity" dimension="currentDensity" exposure="iDensity">
+                <Case condition="caConcExt2 .gt. 0" value="gDensity * (erev - v)"/>
+                <Case condition="caConcExt2 .leq. 0" value="0"/>
+            </ConditionalDerivedVariable>
+
+        </Dynamics>
+
+        <Structure>
+            <ChildInstance component="ionChannel"/>
+        </Structure>
+
+    </ComponentType>
+
+
+    <ComponentType name="channelDensityGHK"
+        extends="baseChannelDensity"
+        description="Specifies a time varying conductance density, _gDensity, which is distributed on an area of the cell, producing a current density _iDensity and whose reversal potential is calculated from the Goldman Hodgkin Katz equation. Hard coded for Ca only! See https://github.com/OpenSourceBrain/ghk-nernst.">
+
+        <Parameter name="permeability" dimension="permeability"/>
+
+        <Constant name="R" dimension="idealGasConstantDims" value="8.3144621 J_per_K_per_mol" description="TODO: Make this a global constant!"/>
+        <Constant name="zCa" dimension="none" value="2" description="TODO: Make this a global constant!"/>
+        <Constant name="F" dimension="charge_per_mole" value="96485.3 C_per_mol" description="TODO: Make this a global constant!"/>
+
+        <Requirement name="temperature" dimension="temperature"/>
+        <Requirement name="caConc" dimension="concentration"/>
+        <Requirement name="caConcExt" dimension="concentration"/>
+
+        <!-- TODO: Ensure Text elements are inherited from base type -->
+        <Text name="segmentGroup" description="Which _segmentGroup_ the channelDensityGHK is placed on. If this is missing, it implies it is placed on all _segment_s of the _cell_"/>
+        <Text name="ion" description="Which ion flows through the channel. Note: ideally this needs to be a property of ionChannel only, but it's here as it makes it easier to select channelPopulations transmitting specific ions."/>
+
+        <Dynamics>
+
+            <DerivedVariable name="K" dimension="per_voltage"  value="(zCa * F) / (R * temperature)"/>
+            <DerivedVariable name="expKv" dimension="none"  value="exp(-1 * K * v)"/>
+            <DerivedVariable name="channelf" dimension="none" select="ionChannel/fopen"/>
+
+	    <!--TODO: used conditional var, just as in nernst above, to circumvent problems with initialization.  -->
+            <ConditionalDerivedVariable name="iDensity"  dimension="currentDensity" exposure="iDensity">
+	            <Case condition="caConcExt .gt. 0" value="-1 * channelf * permeability * zCa * F * K * v * ( caConc - (caConcExt * expKv) ) / (1 - expKv)"/>
+	            <Case condition="caConcExt .leq. 0" value="0"/>
+	    </ConditionalDerivedVariable>
+
+        </Dynamics>
+        <Structure>
+            <ChildInstance component="ionChannel"/>
+        </Structure>
+    </ComponentType>
+
+
+    <ComponentType name="channelDensityGHK2"
+        extends="baseChannelDensityCond"
+        description="Time varying conductance density, _gDensity, which is distributed on an area of the cell, producing a current density _iDensity. Modified version of Jaffe et al. 1994 (used also in Lawrence et al. 2006). See https://github.com/OpenSourceBrain/ghk-nernst.">
+
+        <Constant name="VOLT_SCALE" dimension="voltage" value="1 mV"/>
+        <Constant name="CONC_SCALE" dimension="concentration" value="1 mM"/>
+        <Constant name="TEMP_SCALE" dimension="temperature" value="1 K"/>
+
+        <Requirement name="temperature" dimension="temperature"/>
+        <Requirement name="caConc" dimension="concentration"/>
+        <Requirement name="caConcExt" dimension="concentration"/>
+
+        <!-- TODO: Ensure Text elements are inherited from base type -->
+        <Text name="segmentGroup" description="Which _segmentGroup_ the channelDensityGHK2 is placed on. If this is missing, it implies it is placed on all _segment_s of the _cell_"/>
+        <Text name="ion" description="Which ion flows through the channel. Note: ideally this needs to be a property of ionChannel only, but it's here as it makes it easier to select channelPopulations transmitting specific ions."/>
+
+        <Dynamics>
+            <DerivedVariable name="V" dimension="none" value="v / VOLT_SCALE"/>
+            <DerivedVariable name="ca_conc_i" dimension="none" value="caConc / CONC_SCALE"/>
+            <DerivedVariable name="ca_conc_ext" dimension="none" value="caConcExt / CONC_SCALE"/>
+            <DerivedVariable name="T" dimension="none" value="temperature / TEMP_SCALE"/>
+
+            <DerivedVariable name="channelf" dimension="none" select="ionChannel/fopen"/>
+
+            <DerivedVariable name="gDensity" dimension="conductanceDensity" exposure="gDensity" value="condDensity * channelf"/>
+
+            <DerivedVariable name="tmp" dimension="none" value="(25 * T) / (293.15 * 2)"/>
+
+            <ConditionalDerivedVariable name="pOpen" dimension="voltage">
+                <Case condition="V/tmp .eq. 0." value="tmp * 1e-3 * (1 - ((ca_conc_i/ca_conc_ext) * exp(V/tmp))) * (1 - (V/tmp)/2)"/>
+                <Case condition="V/tmp .neq. 0." value="tmp * 1e-3 * (1 - ((ca_conc_i/ca_conc_ext) * exp(V/tmp))) * ((V/tmp) / (exp(V/tmp) - 1))"/>
+            </ConditionalDerivedVariable>
+
+            <ConditionalDerivedVariable name="iDensity" dimension="currentDensity" exposure="iDensity">
+	            <Case condition="ca_conc_ext .gt. 0" value="gDensity * pOpen"/>
+	            <Case condition="ca_conc_ext .leq. 0" value="0"/>
+	    </ConditionalDerivedVariable>
+
+        </Dynamics>
+
+        <Structure>
+            <ChildInstance component="ionChannel"/>
+        </Structure>
+
+    </ComponentType>
+
+
+    <ComponentType name="pointCellCondBased"
+        extends="baseCellMembPotCap"
+        description="Simple model of a conductance based cell, with no separate _morphology_ element, just an absolute capacitance _C, and a set of channel _populations. Note: use of _cell_ is generally preferable (and more widely supported), even for a single compartment cell.">
+
+        <Parameter name="v0" dimension="voltage" description="The initial membrane potential of the cell"/>  <!--TEMP: needs to be removed... -->
+        <Parameter name="thresh" dimension="voltage" description="The voltage threshold above which the cell is considered to be _spiking"/>
+
+        <Children name="populations" type="baseChannelPopulation"/>
+
+        <Attachments name="synapses" type="basePointCurrent"/>
+
+        <Dynamics>
+
+            <StateVariable name="v" exposure="v" dimension="voltage"/>
+            <StateVariable name="spiking" dimension="none"/>
+
+            <DerivedVariable name="iChannels" dimension="current" select="populations[*]/i" reduce="add"/>
+            <DerivedVariable name="iSyn" dimension="current" exposure="iSyn" select="synapses[*]/i" reduce="add" />
+            <DerivedVariable name="iMemb" dimension="current" exposure="iMemb" value="iChannels + iSyn"/>
+
+            <TimeDerivative variable="v" value="iMemb / C"/>
+
+            <OnStart>
+                <StateAssignment variable="v" value="v0"/>
+                <StateAssignment variable="spiking" value="0"/>
+            </OnStart>
+
+            <OnCondition test="v .gt. thresh .and. spiking .lt. 0.5">
+                <StateAssignment variable="spiking" value="1"/>
+                <EventOut port="spike"/>
+            </OnCondition>
+
+            <OnCondition test="v .lt. thresh">
+                <StateAssignment variable="spiking" value="0"/>
+            </OnCondition>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="pointCellCondBasedCa"
+        extends="baseCellMembPotCap"
+        description="TEMPORARY: Point cell with conductances and Ca concentration info. Not yet fully tested!!! TODO: Remove in favour of _cell_">
+
+        <Parameter name="v0" dimension="voltage" description="The initial membrane potential of the cell"/>  <!--TEMP: needs to be removed... -->
+        <Parameter name="thresh" dimension="voltage" description="The voltage threshold above which the cell is considered to be _spiking"/>
+
+        <Children name="populations" type="baseChannelPopulation"/>
+        <Children name="concentrationModels" type="concentrationModel"/>
+
+        <Attachments name="synapses" type="basePointCurrent"/>
+
+        <Exposure name="iCa" dimension="current"/>
+        <Exposure name="caConc" dimension="concentration"/>
+
+        <Dynamics>
+
+            <StateVariable name="v" exposure="v" dimension="voltage"/>
+            <StateVariable name="spiking" dimension="none"/>
+
+            <DerivedVariable name="iChannels" dimension="current" select="populations[*]/i" reduce="add"/>
+            <DerivedVariable name="iCa" dimension="current" exposure="iCa"  select="populations[ion='ca']/i" reduce="add"/>
+            <DerivedVariable name="caConc" dimension="concentration" exposure="caConc"  select="concentrationModels[species='ca']/concentration" reduce="add"/>
+
+            <DerivedVariable name="iSyn" dimension="current" exposure="iSyn" select="synapses[*]/i" reduce="add" />
+            <DerivedVariable name="iMemb" dimension="current" exposure="iMemb" value="iChannels + iSyn"/>
+
+            <TimeDerivative variable="v" value="iMemb / C"/>
+
+            <OnStart>
+                <StateAssignment variable="v" value="v0"/>
+                <StateAssignment variable="spiking" value="0"/>
+            </OnStart>
+
+            <OnCondition test="v .gt. thresh .and. spiking .lt. 0.5">
+                <StateAssignment variable="spiking" value="1"/>
+                <EventOut port="spike"/>
+            </OnCondition>
+
+            <OnCondition test="v .lt. thresh">
+                <StateAssignment variable="spiking" value="0"/>
+            </OnCondition>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="distal"
+        extends="point3DWithDiam"
+        description="Point on a _segment_ furthest from the soma. Should always be present in the description of a _segment_, unlike _proximal_">
+    </ComponentType>
+
+
+    <ComponentType name="proximal"
+        extends="point3DWithDiam"
+        description="Point on a _segment_ closest to the soma. Note, the proximal point can be omitted, and in this case is defined as being the point _fractionAlong between the proximal and _distal_ point of the _parent_, i.e. if _fractionAlong = 1 (as it is by default) it will be the _distal on the parent, or if _fractionAlong = 0, it will be the proximal point. If between 0 and 1, it is the linear interpolation between the two points.">
+
+    </ComponentType>
+
+
+    <ComponentType name="parent"
+        description="Specifies the _segment_ which is this segment's parent. The _fractionAlong specifies where it is connected, usually 1 (the default value), meaning the _distal_ point of the parent, or 0, meaning the _proximal_ point. If it is between these, a linear interpolation between the 2 points should be used.">
+        <Text name="segment" description="The id of the parent segment"/>
+        <Text name="fractionAlong" description="The fraction along the the parent segment at which this segment is attached. For usage see _proximal_"/>
+    </ComponentType>
+
+
+    <ComponentType name="segment"
+        description="A segment defines the smallest unit within a possibly branching structure (_morphology_), such as a dendrite or axon. Its _id should be a nonnegative integer (usually soma/root = 0). Its end points are given by the _proximal_ and _distal_ points. The _proximal_ point can be omitted, usually because it is the same as a point on the _parent_ segment, see _proximal_ for details. _parent_ specifies the parent segment. The first segment of a _cell_ (with no _parent_) usually represents the soma. The shape is normally a cylinder (radii of the _proximal_ and _distal_ equal, but positions different) or a conical frustum (radii and positions different). If the x,y,x positions of the _proximal_ and _distal_ are equal, the segment can be interpreted as a sphere, and in this case the radii of these points must be equal. NOTE: LEMS does not yet support multicompartmental modelling, so the Dynamics here is only appropriate for single compartment modelling. ">
+
+        <Constant name="LEN" dimension="length" value="1m"/>
+        <Child name="parent" type="parent"/>
+        <Child name="distal" type="distal"/>
+        <Child name="proximal" type="proximal"/>
+
+        <Exposure name="surfaceArea" dimension="area"/>
+        <Exposure name="radDist" dimension="length"/>
+        <Exposure name="length" dimension="length"/>
+
+        <Text name="name" description="An optional name for the segment. Convenient for providing a suitable variable name for generated code, e.g. soma, dend0"/>
+
+        <Dynamics>
+            <!-- TODO: make all of these derived params!! -->
+            <DerivedVariable name="radDist" dimension="length" exposure="radDist" select = "distal/radius"/>
+
+            <DerivedVariable name="dx" dimension="length" select = "distal/xLength"/>
+            <DerivedVariable name="dy" dimension="length" select = "distal/yLength"/>
+            <DerivedVariable name="dz" dimension="length" select = "distal/zLength"/>
+            <DerivedVariable name="px" dimension="length" select = "proximal/xLength"/>
+            <DerivedVariable name="py" dimension="length" select = "proximal/yLength"/>
+            <DerivedVariable name="pz" dimension="length" select = "proximal/zLength"/>
+
+            <DerivedVariable name="length" dimension="length" exposure="length" value = "sqrt(((dx - px) * (dx - px) + (dy - py) * (dy - py) + (dz - pz) * (dz - pz))/(LEN * LEN)) * LEN"/>
+
+            <!--<DerivedVariable name="surfaceArea" dimension="area" exposure="surfaceArea" value = "4 * radDist * radDist * 3.14159265" valueCondition="length .eq. 0" valueIfFalse = "2 * radDist * 3.14159265 * length"/>-->
+
+			<ConditionalDerivedVariable name="surfaceArea" dimension="area" exposure="surfaceArea">
+            			<Case condition="length .eq. 0 * LEN" value="4 * radDist * radDist * 3.14159265"/>
+				<Case condition="length .gt. 0 * LEN" value="2 * radDist * 3.14159265 * length"/>
+			</ConditionalDerivedVariable>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="segmentGroup" description="A method to describe a group of _segment_s in a _morphology_, e.g. soma_group, dendrite_group, axon_group. While a name is useful to describe the group, the _neuroLexId attribute can be used to explicitly specify the meaning of the group, e.g. sao1044911821 for 'Neuronal Cell Body', sao1211023249 for 'Dendrite'. The _segment_s in this group can be specified as: a list of individual _member_ segments; a _path_, all of the segments along which should be included; a _subTree_ of the _cell_ to include; other segmentGroups to _include_ (so all segments from those get included here). An _inhomogeneousParameter_ can be defined on the region of the cell specified by this group (see _variableParameter_ for usage).">
+
+        <Child name="notes" type="notes"/>
+        <Child name="annotation" type="annotation"/>
+        <Children name="property" type="property"/>
+        <Children name="members" type="member"/>
+        <Children name="paths" type="path"/>
+        <Children name="subTrees" type="subTree"/>
+        <Children name="includes" type="include"/> <!-- TODO deal with <include> used also for including ext NML files... -->
+        <Children name="inhomogeneousParameter" type="inhomogeneousParameter"/>
+
+        <Text name="neuroLexId" description="An id string for pointing to an entry in the NeuroLex ontology. Use of this attribute is a shorthand for a full
+        RDF based reference to the MIRIAM Resource urn:miriam:neurolex, with an bqbiol:is qualifier."/>
+
+    </ComponentType>
+
+
+    <ComponentType name="member" description="A single identified _segment which is part of the _segmentGroup_">
+        <Text name="segment"/>
+    </ComponentType>
+
+
+    <ComponentType name="from" description="In a _path_ or _subTree_, specifies which _segment (inclusive) from which to calculate the _segmentGroup_">
+        <Text name="segment"/>
+    </ComponentType>
+
+
+    <ComponentType name="to" description="In a _path_, specifies which _segment (inclusive) up to which to calculate the _segmentGroup_">
+        <Text name="segment"/>
+    </ComponentType>
+
+
+    <ComponentType name="include" description="Include all members of another _segmentGroup_ in this group">
+        <Text name="href" description="TODO: fix this!!! This is needed here, since include is used to include external nml files!!"/>
+        <Text name="segmentGroup"/>
+    </ComponentType>
+
+
+    <ComponentType name="path" description="Include all the _segment_s between those specified by _from_ and _to_, inclusive">
+        <Child name="from" type="from"/>
+        <Child name="to" type="to"/>
+    </ComponentType>
+
+
+    <ComponentType name="subTree" description="Include all the _segment_s distal to that specified by _from_ in the _segmentGroup_">
+        <Child name="from" type="from"/>
+    </ComponentType>
+
+
+    <ComponentType name="inhomogeneousParameter" description="An inhomogeneous parameter specified across the _segmentGroup_ (see _variableParameter_ for usage).">
+        <Child name="proximal" type="proximalProperties"/>
+        <Child name="distal" type="distalProperties"/>
+        <Text name="variable"/>
+        <Text name="metric"/>
+    </ComponentType>
+
+
+    <ComponentType name="proximalProperties" description="What to do at the proximal point when creating an inhomogeneous parameter">
+        <Text name="translationStart"/>
+    </ComponentType>
+
+
+    <ComponentType name="distalProperties" description="What to do at the distal point when creating an inhomogeneous parameter">
+        <Text name="normalizationEnd"/>
+    </ComponentType>
+
+
+    <ComponentType name="morphology" description="The collection of _segment_s which specify the 3D structure of the cell, along with a number of _segmentGroup_s">
+
+        <Children name="segments" type="segment"/>
+        <Children name="segmentGroups" type="segmentGroup"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="specificCapacitance"
+        description="Capacitance per unit area">
+        <Parameter name="value" dimension="specificCapacitance"/>
+        <Exposure name="specCap" dimension="specificCapacitance"/>
+        <Text name="segmentGroup"/>
+
+        <Dynamics>
+            <DerivedVariable name="specCap" dimension="specificCapacitance" exposure="specCap" value="value"/>
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="initMembPotential"
+       description="Explicitly set initial membrane potential for the cell">
+
+        <Parameter name="value" dimension="voltage"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="spikeThresh"
+        description="Membrane potential at which to emit a spiking event. Note, usually the spiking event will not be emitted again until the membrane potential has fallen below this value and rises again to cross it in a positive direction">
+
+        <Parameter name="value" dimension="voltage"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="membraneProperties"
+       description="Properties specific to the membrane, such as the _populations of channels, _channelDensities, _specificCapacitance, etc.">
+
+        <Child name="initMembPotential" type="initMembPotential"/>      <!--TEMP: needs to be removed... -->
+        <Child name="spikeThresh" type="spikeThresh"/>
+        <Children name="specificCapacitances" type="specificCapacitance"/>
+        <Children name="populations" type="baseChannelPopulation"/>
+        <Children name="channelDensities" type="baseChannelDensity"/>
+
+        <Exposure name="totChanCurrent" dimension="current"/>
+
+        <Exposure name="iCa" dimension="current"/>
+
+        <Exposure name="totSpecCap" dimension="specificCapacitance"/>
+
+        <Requirement name="surfaceArea" dimension="area"/>
+
+        <Dynamics>
+            <!-- Note this is not ideal, but for a single compartment cell (which is all this Dynamics should be used for) there should
+                 be only one specificCapacitance, referring to this compartment -->
+            <DerivedVariable name="totSpecCap" dimension="specificCapacitance" exposure="totSpecCap" select="specificCapacitances[*]/specCap" reduce="add"/>
+
+            <DerivedVariable name="totChanPopCurrent" dimension="current" select="populations[*]/i" reduce="add"/>
+            <DerivedVariable name="totChanDensCurrentDensity" dimension="currentDensity" select="channelDensities[*]/iDensity" reduce="add"/>
+
+            <DerivedVariable name="totChanCurrent" dimension="current" exposure="totChanCurrent" value="totChanPopCurrent + (totChanDensCurrentDensity * surfaceArea)"/>
+
+            <DerivedVariable name="totChanPopCurrentCa" dimension="current" select="populations[ion='ca']/i" reduce="add"/>
+            <DerivedVariable name="totChanDensCurrentDensityCa" dimension="currentDensity" select="channelDensities[ion='ca']/iDensity" reduce="add"/>
+
+            <DerivedVariable name="iCa" dimension="current" exposure="iCa" value="totChanPopCurrentCa + (totChanDensCurrentDensityCa * surfaceArea)"/>
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="membraneProperties2CaPools" extends="membraneProperties"
+        description="Variant of membraneProperties with 2 independent Ca pools">
+
+        <Child name="initMembPotential" type="initMembPotential"/>
+        <Child name="spikeThresh" type="spikeThresh"/>
+        <Children name="specificCapacitances" type="specificCapacitance"/>
+        <Children name="populations" type="baseChannelPopulation"/>
+        <Children name="channelDensities" type="baseChannelDensity"/>
+
+        <Exposure name="totChanCurrent" dimension="current"/>
+        <Exposure name="iCa" dimension="current"/>
+        <Exposure name="iCa2" dimension="current"/>
+        <Exposure name="totSpecCap" dimension="specificCapacitance"/>
+
+        <Requirement name="surfaceArea" dimension="area"/>
+
+        <Dynamics>
+
+            <DerivedVariable name="totSpecCap" dimension="specificCapacitance" exposure="totSpecCap" select="specificCapacitances[*]/specCap" reduce="add"/>
+
+            <DerivedVariable name="totChanPopCurrent" dimension="current" select="populations[*]/i" reduce="add"/>
+            <DerivedVariable name="totChanDensCurrentDensity" dimension="currentDensity" select="channelDensities[*]/iDensity" reduce="add"/>
+
+            <DerivedVariable name="totChanCurrent" dimension="current" exposure="totChanCurrent" value="totChanPopCurrent + (totChanDensCurrentDensity * surfaceArea)"/>
+
+            <DerivedVariable name="totChanPopCurrentCa" dimension="current" select="populations[ion='ca']/i" reduce="add"/>
+            <DerivedVariable name="totChanDensCurrentDensityCa" dimension="currentDensity" select="channelDensities[ion='ca']/iDensity" reduce="add"/>
+
+            <DerivedVariable name="iCa" dimension="current" exposure="iCa" value="totChanPopCurrentCa + (totChanDensCurrentDensityCa * surfaceArea)"/>
+
+            <DerivedVariable name="totChanPopCurrentCa2" dimension="current" select="populations[ion='ca2']/i" reduce="add"/>
+            <DerivedVariable name="totChanDensCurrentDensityCa2" dimension="currentDensity" select="channelDensities[ion='ca2']/iDensity" reduce="add"/>
+
+            <DerivedVariable name="iCa2" dimension="current" exposure="iCa2" value="totChanPopCurrentCa2 + (totChanDensCurrentDensityCa2 * surfaceArea)"/>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="biophysicalProperties"
+        description="The biophysical properties of the _cell_, including the _membraneProperties_ and the _intracellularProperties_">
+
+        <Child name="membraneProperties" type="membraneProperties"/>
+
+        <Child name="intracellularProperties" type="intracellularProperties"/>
+
+        <Exposure name="totSpecCap" dimension="specificCapacitance"/>
+
+        <Dynamics>
+            <DerivedVariable name="totSpecCap" dimension="specificCapacitance" exposure="totSpecCap" select="membraneProperties/totSpecCap"/>
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="biophysicalProperties2CaPools"
+                   description="The biophysical properties of the _cell_, including the _membraneProperties2CaPools_ and the _intracellularProperties2CaPools_ for a cell with two Ca pools">
+
+        <Child name="membraneProperties2CaPools" type="membraneProperties2CaPools"/>
+
+        <Child name="intracellularProperties2CaPools" type="intracellularProperties2CaPools"/>
+
+        <Exposure name="totSpecCap" dimension="specificCapacitance"/>
+
+        <Dynamics>
+            <DerivedVariable name="totSpecCap" dimension="specificCapacitance" exposure="totSpecCap" select="membraneProperties2CaPools/totSpecCap"/>
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="intracellularProperties"
+        description="Biophysical properties related to the intracellular space within the _cell_, such as the _resistivity_ and the list of ionic _species_ present. _caConc and _caConcExt are explicitly exposed here to facilitate accessing these values from other Components, even though _caConcExt is clearly not an intracellular property">
+
+        <Children name="resistivity" type="resistivity"/>
+        <Children name="speciesList" type="species"/>
+
+        <Exposure name="caConc" dimension="concentration"/>
+        <Exposure name="caConcExt" dimension="concentration"/>
+
+        <Dynamics>
+            <DerivedVariable name="caConc" dimension="concentration" exposure="caConc" select="speciesList[ion='ca']/concentration" reduce="add" required="false"/>
+            <DerivedVariable name="caConcExt" dimension="concentration" exposure="caConcExt" select="speciesList[ion='ca']/extConcentration" reduce="add" required="false"/>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="intracellularProperties2CaPools" extends="intracellularProperties"
+        description="Variant of intracellularProperties with 2 independent Ca pools">
+
+        <Children name="speciesList" type="species"/>
+        <Children name="resistivity" type="resistivity"/>
+
+        <Exposure name="caConc2" dimension="concentration"/>
+        <Exposure name="caConcExt2" dimension="concentration"/>
+        <Exposure name="caConc" dimension="concentration"/>
+        <Exposure name="caConcExt" dimension="concentration"/>
+
+        <Dynamics>
+
+            <DerivedVariable name="caConc2" dimension="concentration" exposure="caConc2" select="speciesList[ion='ca2']/concentration" reduce="add" required="false"/>
+            <DerivedVariable name="caConcExt2" dimension="concentration" exposure="caConcExt2" select="speciesList[ion='ca2']/extConcentration" reduce="add" required="false"/>
+
+            <DerivedVariable name="caConc" dimension="concentration" exposure="caConc" select="speciesList[ion='ca']/concentration" reduce="add" required="false"/>
+            <DerivedVariable name="caConcExt" dimension="concentration" exposure="caConcExt" select="speciesList[ion='ca']/extConcentration" reduce="add" required="false"/>
+
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="resistivity"
+       description="The resistivity, or specific axial resistance, of the cytoplasm">
+
+        <Parameter name="value" dimension="resistivity"/>
+        <Text name="segmentGroup"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="concentrationModel"
+        description="Base for any model of an _ion concentration which changes with time. Internal (_concentration) and external (_extConcentration) values for the concentration of the ion are given.">
+
+        <Exposure name="concentration" dimension="concentration"/>
+        <Exposure name="extConcentration" dimension="concentration"/>
+
+        <Requirement name="surfaceArea" dimension="area"/>
+
+        <Requirement name="initialConcentration" dimension="concentration"/>
+        <Requirement name="initialExtConcentration" dimension="concentration"/>
+
+        <Text name="ion"/>
+
+        <Dynamics>
+            <StateVariable name="concentration" exposure="concentration" dimension="concentration"/>
+            <StateVariable name="extConcentration" exposure="extConcentration" dimension="concentration"/>
+            <OnStart>
+                <StateAssignment variable="concentration" value="initialConcentration"/>
+                <StateAssignment variable="extConcentration" value="initialExtConcentration"/>
+            </OnStart>
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="decayingPoolConcentrationModel"
+        extends="concentrationModel"
+        description="Model of an intracellular buffering mechanism for _ion (currently hard Coded to be calcium, due to requirement for _iCa) which has a baseline level _restingConc and tends to this value with time course _decayConstant. The ion is assumed to occupy a shell inside the membrane of thickness _shellThickness.">
+
+        <Parameter name="restingConc" dimension="concentration"/>
+        <Parameter name="decayConstant" dimension="time"/>
+        <Parameter name="shellThickness" dimension="length"/>
+        <!--<Parameter name="radius" dimension="length"/>   needed to calc volume of pools, etc. -->
+        <!--<Exposure name="debugVal" dimension="none"/>-->
+
+        <Constant name="Faraday" dimension="charge_per_mole" value="96485.3C_per_mol"/>
+        <Constant name="AREA_SCALE" dimension="area" value="1m2"/>
+        <Constant name="LENGTH_SCALE" dimension="length" value="1m"/>
+
+        <Requirement name="iCa" dimension="current"/>
+
+        <Text name="ion"/> <!-- TODO: check why this isn't inherited from concentrationModel -->
+
+        <Dynamics>
+
+            <StateVariable name="concentration" exposure="concentration" dimension="concentration"/>
+            <StateVariable name="extConcentration" exposure="extConcentration" dimension="concentration"/>
+            <!--<StateVariable name="debugVal" exposure="debugVal" dimension="none"/>-->
+            <!--<DerivedVariable name="debug" dimension="none" value="shell_volume"/>-->
+
+            <DerivedVariable name="effectiveRadius" dimension="length" value="LENGTH_SCALE * sqrt(surfaceArea/(AREA_SCALE * (4 * 3.14159)))"/>  <!-- needed to calc volume of pools, etc. -->
+            <DerivedVariable name="innerRadius" dimension="length" value="effectiveRadius - shellThickness"/>
+
+            <DerivedVariable name="shellVolume" dimension="volume" value="(4 * (effectiveRadius * effectiveRadius * effectiveRadius) * 3.14159 / 3) - (4 * (innerRadius * innerRadius * innerRadius) * 3.14159 / 3)"/>
+
+            <TimeDerivative variable="concentration" value="iCa / (2 * Faraday * shellVolume) - ((concentration - restingConc) / decayConstant)"/>
+
+            <OnStart>
+                <StateAssignment variable="concentration" value="initialConcentration"/>
+                <StateAssignment variable="extConcentration" value="initialExtConcentration"/>
+            </OnStart>
+
+            <OnCondition test="concentration .lt. 0">
+                <StateAssignment variable="concentration" value="0"/>
+            </OnCondition>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="fixedFactorConcentrationModel"
+        extends="concentrationModel"
+        description="Model of buffering of concentration of an ion (currently hard coded to be calcium, due to requirement for _iCa) which has a baseline level _restingConc and tends to this value with time course _decayConstant. A fixed factor _rho is used to scale the incoming current *independently of the size of the compartment* to produce a concentration change.">
+
+        <Parameter name="restingConc" dimension="concentration"/>
+        <Parameter name="decayConstant" dimension="time"/>
+
+        <Parameter name="rho" dimension="rho_factor"/>
+
+        <Requirement name="iCa" dimension="current"/>
+        <Requirement name="surfaceArea" dimension="area"/>
+
+        <Text name="ion"/> <!-- TODO: check why this isn't inherited from concentrationModel -->
+
+        <Dynamics>
+
+            <StateVariable name="concentration" exposure="concentration" dimension="concentration"/>
+            <StateVariable name="extConcentration" exposure="extConcentration" dimension="concentration"/>
+
+            <TimeDerivative variable="concentration" value="(iCa/surfaceArea) * rho - ((concentration - restingConc) / decayConstant)"/>
+
+            <OnStart>
+                <StateAssignment variable="concentration" value="initialConcentration"/>
+                <StateAssignment variable="extConcentration" value="initialExtConcentration"/>
+            </OnStart>
+
+            <OnCondition test="concentration .lt. 0">
+                <StateAssignment variable="concentration" value="0"/>
+            </OnCondition>
+        </Dynamics>
+    </ComponentType>
+
+    <ComponentType name="fixedFactorConcentrationModelTraub"
+        extends="concentrationModel"
+        description="Model of buffering of concentration of an ion (currently hard coded to be calcium, due to requirement for _iCa) which has a baseline level _restingConc and tends to this value with time course 1 / _beta. A fixed factor _phi is used to scale the incoming current *independently of the size of the compartment* to produce a concentration change. Not recommended for use in models other than Traub et al. 2005!">
+
+        <Parameter name="restingConc" dimension="concentration"/>
+        <Parameter name="beta" dimension="per_time"/>
+
+        <Parameter name="phi" dimension="rho_factor"/>
+
+        <Requirement name="iCa" dimension="current"/>
+        <Requirement name="surfaceArea" dimension="area"/>
+
+        <Text name="species"/> <!-- TODO: check why this isn't inherited from concentrationModel -->
+
+        <Dynamics>
+
+            <StateVariable name="concentration" exposure="concentration" dimension="concentration"/>
+            <StateVariable name="extConcentration" exposure="extConcentration" dimension="concentration"/>
+
+            <TimeDerivative variable="concentration" value="(iCa/surfaceArea) * 1e-9 * phi - ((concentration - restingConc) * beta)"/>
+
+            <OnStart>
+                <StateAssignment variable="concentration" value="initialConcentration"/>
+                <StateAssignment variable="extConcentration" value="initialExtConcentration"/>
+            </OnStart>
+
+            <OnCondition test="concentration .lt. 0">
+                <StateAssignment variable="concentration" value="0"/>
+            </OnCondition>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="species"
+        description="Description of a chemical species identified by _ion, which has internal, _concentration, and external, _extConcentration values for its concentration">
+
+        <Parameter name="initialConcentration" dimension="concentration"/>
+        <Parameter name="initialExtConcentration" dimension="concentration"/>
+
+        <ComponentReference name="concentrationModel" type="concentrationModel"/>
+
+        <Exposure name="concentration" dimension="concentration"/>
+        <Exposure name="extConcentration" dimension="concentration"/>
+
+        <Text name="ion"/> <!-- TODO: this should be in id!!! -->
+        <Text name="segmentGroup"/>
+
+        <Dynamics>
+
+            <DerivedVariable name="concentration" exposure="concentration" dimension="concentration" select="concentrationModel/concentration"/>
+            <DerivedVariable name="extConcentration" exposure="extConcentration" dimension="concentration" select="concentrationModel/extConcentration"/>
+
+        </Dynamics>
+
+        <Structure>
+            <ChildInstance component="concentrationModel"/>
+        </Structure>
+
+    </ComponentType>
+
+
+    <ComponentType name="cell"
+        extends="baseCellMembPot"
+        description="Cell with _segment_s specified in a _morphology_ element along with details on its _biophysicalProperties_. NOTE: this can only be correctly simulated using jLEMS when there is a single segment in the cell, and _v of this cell represents the membrane potential in that isopotential segment.">
+
+        <Child name="morphology" type="morphology" description="Should only be used if morphology element is outside the cell. This points to the id of the morphology."/>
+
+        <Child name="biophysicalProperties" type="biophysicalProperties" description="Should only be used if biophysicalProperties element is outside the cell.  This points to the id of the biophysicalProperties"/>
+
+        <Attachments name="synapses" type="basePointCurrent"/>
+
+        <Exposure name="spiking" dimension="none"/>
+        <!--<Exposure name="debugVal" dimension="none"/>-->
+        <Exposure name="iChannels" dimension="current"/>
+        <Exposure name="iSyn" dimension="current"/>
+        <Exposure name="totSpecCap" dimension="specificCapacitance"/>
+
+        <Exposure name="surfaceArea" dimension="area"/>
+
+        <Exposure name="iCa" dimension="current"/>
+        <Exposure name="caConc" dimension="concentration"/>
+        <Exposure name="caConcExt" dimension="concentration"/>
+
+        <Text name="neuroLexId"/>
+
+        <Dynamics>
+            <StateVariable name="v" exposure="v" dimension="voltage"/>
+            <StateVariable name="spiking" exposure="spiking" dimension="none"/>
+            <!--<StateVariable name="debugVal" exposure="debugVal" dimension="none"/>-->
+
+            <DerivedVariable name="initMembPot" dimension="voltage" select="biophysicalProperties/membraneProperties/initMembPotential/value"/>
+            <DerivedVariable name="thresh" dimension="voltage" select="biophysicalProperties/membraneProperties/spikeThresh/value"/>
+
+            <!--<DerivedVariable name="debug" dimension="none" value="0"/>-->
+
+            <!--TODO replace this with just using first segment!!-->
+            <DerivedVariable name="surfaceArea" exposure="surfaceArea" dimension="area" select="morphology/segments[*]/surfaceArea" reduce="add"/>
+
+            <DerivedVariable name="totSpecCap" dimension="specificCapacitance" exposure="totSpecCap" select="biophysicalProperties/totSpecCap"/>
+            <DerivedVariable name="totCap" dimension="capacitance" value="totSpecCap * surfaceArea "/>
+
+            <DerivedVariable name="iChannels" dimension="current" exposure="iChannels" select="biophysicalProperties/membraneProperties/totChanCurrent"/>
+            <DerivedVariable name="iSyn" dimension="current" exposure="iSyn" select="synapses[*]/i" reduce="add" />
+
+            <DerivedVariable name="iCa" dimension="current" exposure="iCa" select="biophysicalProperties/membraneProperties/iCa"/>
+            <DerivedVariable name="caConc" dimension="concentration" exposure="caConc"  select="biophysicalProperties/intracellularProperties/caConc"/>
+            <DerivedVariable name="caConcExt" dimension="concentration" exposure="caConcExt"  select="biophysicalProperties/intracellularProperties/caConcExt"/>
+
+            <TimeDerivative variable="v" value="(iChannels + iSyn) / totCap"/>
+
+            <OnStart>
+                <StateAssignment variable="spiking" value="0"/>
+                <StateAssignment variable="v" value="initMembPot"/>
+            </OnStart>
+
+            <OnCondition test="v .gt. thresh .and. spiking .lt. 0.5">
+                <StateAssignment variable="spiking" value="1"/>
+                <EventOut port="spike"/>
+            </OnCondition>
+
+            <OnCondition test="v .lt. thresh">
+                <StateAssignment variable="spiking" value="0"/>
+            </OnCondition>
+
+            <!--<OnCondition test="t .geq. 0">
+                <StateAssignment variable="debugVal" value="debug"/>
+            </OnCondition>-->
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="cell2CaPools"
+                   extends="cell"
+                   description="Variant of cell with two independent Ca2+ pools. Cell with _segment_s specified in a _morphology_ element along with details on its _biophysicalProperties_. NOTE: this can only be correctly simulated using jLEMS when there is a single segment in the cell, and _v of this cell represents the membrane potential in that isopotential segment.">
+
+        <!--<Child name="notes" type="notes"/>
+        <Child name="annotation" type="annotation"/>
+
+        <Child name="morphology" type="morphology"/>-->
+
+        <Child name="biophysicalProperties2CaPools" type="biophysicalProperties2CaPools"/>
+
+        <Attachments name="synapses" type="basePointCurrent"/>
+
+        <!-- These are inherited from cell
+        <Exposure name="spiking" dimension="none"/>
+        <Exposure name="debugVal" dimension="none"/>
+        <Exposure name="iChannels" dimension="current"/>
+        <Exposure name="iSyn" dimension="current"/>
+        <Exposure name="totSpecCap" dimension="specificCapacitance"/>
+
+        <Exposure name="surfaceArea" dimension="area"/>
+
+        <Exposure name="iCa" dimension="current"/>
+        <Exposure name="caConc" dimension="concentration"/>
+        <Exposure name="caConcExt" dimension="concentration"/> -->
+
+        <Exposure name="iCa2" dimension="current"/>
+        <Exposure name="caConc2" dimension="concentration"/>
+        <Exposure name="caConcExt2" dimension="concentration"/>
+
+
+        <Text name="neuroLexId"/>
+
+        <Dynamics>
+            <StateVariable name="v" exposure="v" dimension="voltage"/>
+            <StateVariable name="spiking" exposure="spiking" dimension="none"/>
+            <!--<StateVariable name="debugVal" exposure="debugVal" dimension="none"/>-->
+
+            <DerivedVariable name="initMembPot" dimension="voltage" select="biophysicalProperties2CaPools/membraneProperties2CaPools/initMembPotential/value"/>
+            <DerivedVariable name="thresh" dimension="voltage" select="biophysicalProperties2CaPools/membraneProperties2CaPools/spikeThresh/value"/>
+
+            <!--<DerivedVariable name="debug" dimension="none" select="0"/>-->
+
+
+            <DerivedVariable name="surfaceArea" exposure="surfaceArea" dimension="area" select="morphology/segments[*]/surfaceArea" reduce="add"/>
+
+            <DerivedVariable name="totSpecCap" dimension="specificCapacitance" exposure="totSpecCap" select="biophysicalProperties2CaPools/totSpecCap"/>
+            <DerivedVariable name="totCap" dimension="capacitance" value="totSpecCap * surfaceArea "/>
+
+            <DerivedVariable name="iChannels" dimension="current" exposure="iChannels" select="biophysicalProperties2CaPools/membraneProperties2CaPools/totChanCurrent"/>
+            <DerivedVariable name="iSyn" dimension="current" exposure="iSyn" select="synapses[*]/i" reduce="add" />
+
+            <DerivedVariable name="iCa" dimension="current" exposure="iCa" select="biophysicalProperties2CaPools/membraneProperties2CaPools/iCa"/>
+
+            <DerivedVariable name="caConc" dimension="concentration" exposure="caConc"  select="biophysicalProperties2CaPools/intracellularProperties2CaPools/caConc"/>
+            <DerivedVariable name="caConcExt" dimension="concentration" exposure="caConcExt"  select="biophysicalProperties2CaPools/intracellularProperties2CaPools/caConcExt"/>
+
+            <DerivedVariable name="iCa2" dimension="current" exposure="iCa2" select="biophysicalProperties2CaPools/membraneProperties2CaPools/iCa2"/>
+
+            <DerivedVariable name="caConc2" dimension="concentration" exposure="caConc2" select="biophysicalProperties2CaPools/intracellularProperties2CaPools/caConc2"/>
+
+            <DerivedVariable name="caConcExt2" dimension="concentration" exposure="caConcExt2" select="biophysicalProperties2CaPools/intracellularProperties2CaPools/caConcExt2"/>
+
+
+            <TimeDerivative variable="v" value="(iChannels + iSyn) / totCap"/>
+
+            <OnStart>
+                <StateAssignment variable="spiking" value="0"/>
+                <StateAssignment variable="v" value="initMembPot"/>
+            </OnStart>
+
+            <OnCondition test="v .gt. thresh .and. spiking .lt. 0.5">
+                <StateAssignment variable="spiking" value="1"/>
+                <EventOut port="spike"/>
+            </OnCondition>
+
+            <OnCondition test="v .lt. thresh">
+                <StateAssignment variable="spiking" value="0"/>
+            </OnCondition>
+
+            <!--<OnCondition test="t .geq. 0">
+                <StateAssignment variable="debugVal" value="debug"/>
+            </OnCondition>-->
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+
+
+    <ComponentType name="baseCellMembPotCap"
+        extends="baseCellMembPot"
+        description="Any cell with a membrane potential _v with voltage units and a membrane capacitance _C. Also defines exposed value _iSyn for current due to external synapses and _iMemb for total transmembrane current (usually channel currents plus _iSyn)">
+        <Parameter name="C" dimension="capacitance" description="Total capacitance of the cell membrane"/>
+        <Exposure name="iSyn" dimension="current" description="Total current due to synaptic inputs"/>
+        <Exposure name="iMemb" dimension="current" description="Total current crossing the cell membrane"/>
+    </ComponentType>
+
+
+    <ComponentType name="baseIaf"
+       extends="baseCellMembPot"
+       description="Base ComponentType for an integrate and fire cell which emits a spiking event at membrane potential _thresh and and resets to _reset">
+        <Parameter name="thresh" dimension="voltage" description="The membrane potential at which to emit a spiking event and reset voltage"/>
+        <Parameter name="reset" dimension="voltage" description="The value the membrane potential is reset to on spiking"/>
+    </ComponentType>
+
+
+    <ComponentType name="iafTauCell"
+        extends="baseIaf"
+        description="Integrate and fire cell which returns to its leak reversal potential of _leakReversal with a time constant _tau">
+
+        <Parameter name="leakReversal" dimension="voltage"/>
+        <Parameter name="tau" dimension="time"/>
+
+        <Dynamics>
+            <StateVariable name="v" exposure="v" dimension="voltage"/>
+
+            <TimeDerivative variable="v" value="(leakReversal - v) / tau"/>
+
+            <OnStart>
+                <StateAssignment variable="v" value="leakReversal"/>
+            </OnStart>
+
+            <OnCondition test="v .gt. thresh">
+                <StateAssignment variable="v" value="reset"/>
+                <EventOut port="spike"/>
+            </OnCondition>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="iafTauRefCell"
+        extends="iafTauCell"
+        description="Integrate and fire cell which returns to its leak reversal potential of _leakReversal with a time course _tau. It has a refractory period of _refract after spiking">
+
+        <Parameter name="refract" dimension="time"/>
+
+        <Dynamics>
+            <StateVariable name="v" exposure="v" dimension="voltage"/>
+            <StateVariable name="lastSpikeTime" dimension="time"/>
+
+            <OnStart>
+                <StateAssignment variable="v" value="leakReversal"/>
+            </OnStart>
+
+            <Regime name="refractory">
+                <OnEntry>
+                    <StateAssignment variable="lastSpikeTime" value="t" />
+                    <StateAssignment variable="v" value="reset" />
+                </OnEntry>
+                <OnCondition test="t .gt. lastSpikeTime + refract">
+                    <Transition regime="integrating" />
+                </OnCondition>
+            </Regime>
+
+            <Regime name="integrating" initial="true">
+                <TimeDerivative variable="v" value="(leakReversal - v) / tau" />
+                <OnCondition test="v .gt. thresh">
+                    <EventOut port="spike"/>
+                    <Transition regime="refractory" />
+                </OnCondition>
+          <!--<OnEvent port="in">
+            <StateAssignment variable="v" value="v + deltaV"/>
+          </OnEvent>-->
+            </Regime>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="baseIafCapCell"
+        extends="baseCellMembPotCap"
+        description="Base Type for all Integrate and Fire cells with a capacitance _C, threshold _thresh and reset membrane potential _reset">
+        <Parameter name="thresh" dimension="voltage"/>  <!-- These are repeated from baseIaf since there can't yet be multiple inheritance -->
+        <Parameter name="reset" dimension="voltage"/>
+    </ComponentType>
+
+
+    <ComponentType name="iafCell"
+        extends="baseIafCapCell"
+        description="Integrate and fire cell with capacitance _C, _leakConductance and _leakReversal">
+
+        <Parameter name="leakConductance" dimension="conductance"/>
+        <Parameter name="leakReversal" dimension="voltage"/>
+
+        <Attachments name="synapses" type="basePointCurrent"/>
+
+        <Dynamics>
+
+            <StateVariable name="v" exposure="v" dimension="voltage"/>
+
+            <DerivedVariable name="iSyn" dimension="current" exposure="iSyn" select="synapses[*]/i" reduce="add" />
+            <DerivedVariable name="iMemb" dimension="current" exposure="iMemb" value="leakConductance * (leakReversal - v) + iSyn"/>
+
+            <TimeDerivative variable="v" value="iMemb / C"/>
+
+            <OnStart>
+                <StateAssignment variable="v" value="leakReversal"/>
+            </OnStart>
+
+            <OnCondition test="v .gt. thresh">
+                <StateAssignment variable="v" value="reset"/>
+                <EventOut port="spike"/>
+            </OnCondition>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="iafRefCell"
+                   extends="iafCell"
+                   description="Integrate and fire cell  with capacitance _C, _leakConductance, _leakReversal and refractory period _refract">
+
+        <Parameter name="refract" dimension="time"/>
+
+        <Attachments name="synapses" type="basePointCurrent"/>
+
+        <Dynamics>
+            <StateVariable name="v" exposure="v" dimension="voltage"/>
+            <StateVariable name="lastSpikeTime" dimension="time"/>
+
+            <!-- iSyn and iMemb value are meaningless in the refractory regime -->
+            <DerivedVariable name="iSyn" dimension="current" exposure="iSyn" select="synapses[*]/i" reduce="add" />
+            <DerivedVariable name="iMemb" dimension="current" exposure="iMemb" value="leakConductance * (leakReversal - v) + iSyn"/>
+
+            <OnStart>
+                <StateAssignment variable="v" value="leakReversal"/>
+            </OnStart>
+
+            <Regime name="refractory">
+                <OnEntry>
+                    <StateAssignment variable="lastSpikeTime" value="t" />
+                    <StateAssignment variable="v" value="reset" />
+                </OnEntry>
+                <OnCondition test="t .gt. lastSpikeTime + refract">
+                    <Transition regime="integrating" />
+                </OnCondition>
+            </Regime>
+
+            <Regime name="integrating" initial="true">
+                <TimeDerivative variable="v" value="iMemb / C"/>
+                <OnCondition test="v .gt. thresh">
+                    <EventOut port="spike"/>
+                    <Transition regime="refractory" />
+                </OnCondition>
+            </Regime>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="izhikevichCell"
+        extends="baseCellMembPot"
+        description="Cell based on the 2003 model of Izhikevich, see http://izhikevich.org/publications/spikes.htm">
+
+        <Parameter name="v0" dimension="voltage"/>  <!--TEMP: needs to be removed... -->
+        <Parameter name="a" dimension="none"/>
+        <Parameter name="b" dimension="none"/>
+        <Parameter name="c" dimension="none"/>
+        <Parameter name="d" dimension="none"/>
+        <Parameter name="thresh" dimension="voltage"/>
+
+    <!-- These are needed to ensure a, b, c, d, U & I remain dimensionless... -->
+        <Constant name="MSEC" dimension="time" value="1ms"/>
+        <Constant name="MVOLT" dimension="voltage" value="1mV"/>
+
+        <Attachments name="synapses" type="basePointCurrentDL"/>
+
+        <Exposure name="U" dimension="none"/>
+
+        <Dynamics>
+
+            <StateVariable name="v" dimension="voltage" exposure="v"/>
+            <StateVariable name="U" dimension="none" exposure="U"/>
+
+            <DerivedVariable name="ISyn" dimension="none" select="synapses[*]/I" reduce="add" />
+
+            <TimeDerivative variable="v" value="(0.04 * v^2 / MVOLT + 5 * v + (140.0 - U + ISyn) * MVOLT)/MSEC"/>
+            <TimeDerivative variable="U" value="a * (b * v / MVOLT - U) / MSEC"/>
+
+            <OnStart>
+                <StateAssignment variable="v" value="v0"/>
+                <StateAssignment variable="U" value="v0 * b / MVOLT"/>
+            </OnStart>
+
+            <OnCondition test="v .gt. thresh">
+                <StateAssignment variable="v" value="c * MVOLT"/>
+                <StateAssignment variable="U" value="U + d"/>
+                <EventOut port="spike"/>
+            </OnCondition>
+
+        </Dynamics>
+
+    </ComponentType>
+
+    <ComponentType name="izhikevich2007Cell"
+        extends="baseCellMembPotCap"
+        description="Cell based on the modified Izhikevich model in Izhikevich 2007, Dynamical systems in neuroscience, MIT Press">
+
+        <Parameter name="v0" dimension="voltage"/>
+
+        <!--
+        Defined in baseCellMembPotCap:
+        <Parameter name="C" dimension="capacitance"/>
+        -->
+        <Parameter name="k" dimension="conductance_per_voltage"/>
+
+        <Parameter name="vr" dimension="voltage"/>
+        <Parameter name="vt" dimension="voltage"/>
+        <Parameter name="vpeak" dimension="voltage"/>
+
+        <Parameter name="a" dimension="per_time"/>
+        <Parameter name="b" dimension="conductance"/>
+        <Parameter name="c" dimension="voltage"/>
+        <Parameter name="d" dimension="current"/>
+
+        <Attachments name="synapses" type="basePointCurrent"/>
+
+        <Exposure name="u" dimension="current"/>
+
+        <Dynamics>
+
+            <StateVariable name="v" dimension="voltage" exposure="v"/>
+            <StateVariable name="u" dimension="current" exposure="u"/>
+
+            <DerivedVariable name="iSyn"  dimension="current" exposure="iSyn" select="synapses[*]/i" reduce="add" />
+
+            <DerivedVariable name="iMemb" dimension="current" exposure="iMemb" value="k * (v-vr) * (v-vt) + iSyn - u"/>
+
+            <TimeDerivative variable="v" value="iMemb / C"/>
+            <TimeDerivative variable="u" value="a * (b * (v-vr) - u)"/>
+
+            <OnStart>
+                <StateAssignment variable="v" value="v0"/>
+                <StateAssignment variable="u" value="0"/>
+            </OnStart>
+
+            <OnCondition test="v .gt. vpeak">
+                <StateAssignment variable="v" value="c"/>
+                <StateAssignment variable="u" value="u + d"/>
+                <EventOut port="spike"/>
+            </OnCondition>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="adExIaFCell"
+        extends="baseCellMembPotCap"
+        description="Model based on Brette R and Gerstner W (2005) Adaptive Exponential Integrate-and-Fire Model as an Effective Description of Neuronal Activity. J Neurophysiol 94:3637-3642">
+
+        <Parameter name="gL" dimension="conductance"/>
+        <Parameter name="EL" dimension="voltage"/>
+        <Parameter name="VT" dimension="voltage"/>
+        <Parameter name="thresh" dimension="voltage"/>
+        <Parameter name="reset" dimension="voltage"/>
+        <Parameter name="delT" dimension="voltage"/>
+        <Parameter name="tauw" dimension="time"/>
+
+        <Parameter name="refract" dimension="time"/>
+
+        <Parameter name="a" dimension="conductance"/>
+        <Parameter name="b" dimension="current"/>
+
+        <Attachments name="synapses" type="basePointCurrent"/>
+
+        <Exposure name="w" dimension="current"/>
+
+        <Dynamics>
+
+            <StateVariable name="v" dimension="voltage" exposure="v"/>
+            <StateVariable name="w" dimension="current" exposure="w"/>
+
+            <StateVariable name="lastSpikeTime" dimension="time"/>
+
+            <DerivedVariable name="iSyn" dimension="current" exposure="iSyn" select="synapses[*]/i" reduce="add" />
+            <DerivedVariable name="iMemb" dimension="current" exposure="iMemb" value="-1 * gL * (v - EL) + gL * delT * exp((v - VT) / delT) - w + iSyn"/>
+
+            <OnStart>
+                <StateAssignment variable="v" value="EL"/>
+                <StateAssignment variable="w" value="0"/>
+            </OnStart>
+
+            <Regime name="refractory">
+                <!-- Note: this is important to change also during the refractory period!! -->
+                <TimeDerivative variable="w" value="(a * (v - EL) - w) / tauw"/>
+                <OnEntry>
+                    <StateAssignment variable="lastSpikeTime" value="t" />
+                    <StateAssignment variable="v" value="reset" />
+                    <StateAssignment variable="w" value="w + b"/>
+                </OnEntry>
+                <OnCondition test="t .gt. lastSpikeTime + refract">
+                    <Transition regime="integrating" />
+                </OnCondition>
+            </Regime>
+
+            <Regime name="integrating" initial="true">
+                <TimeDerivative variable="v" value="iMemb / C"/>
+                <TimeDerivative variable="w" value="(a * (v - EL) - w) / tauw"/>
+
+                <OnCondition test="v .gt. thresh">
+                    <EventOut port="spike"/>
+                    <Transition regime="refractory" />
+                </OnCondition>
+
+            </Regime>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType  name="fitzHughNagumo1969Cell"
+                   extends="baseCellMembPotDL"
+                   description="The Fitzhugh Nagumo model is a two-dimensional simplification of the Hodgkin-Huxley model of spike generation in squid giant axons.  This system was suggested by FitzHugh (FitzHugh R. [1961]: Impulses and physiological states in theoretical models of nerve membrane.  Biophysical J.  1:445-466), who called it &quot;Bonhoeffer-van der Pol model&quot;, and the equivalent circuit by Nagumo et al.  (Nagumo J., Arimoto S., and Yoshizawa S. [1962] An active pulse transmission line simulating nerve axon. Proc IRE. 50:2061-2070.1962). This version corresponds to the one described in FitzHugh R.[1969]: Mathematical models of excitation and propagation in nerve.  Chapter 1 (pp. 1-85 in H.P. Schwan, ed. Biological Engineering, McGraw-Hill Book Co., N.Y.)">
+
+       <Parameter name="a" dimension="none"/>
+       <Parameter name="b" dimension="none"/>
+       <Parameter name="I" dimension="none" description="plays the role of an external injected current"/>
+       <Parameter name="phi" dimension="none"/>
+
+       <!-- Initial Conditions -->
+       <Parameter name="V0" dimension="none"/>
+       <Parameter name="W0" dimension="none"/>
+
+       <Constant name="TS" dimension="time" value="1ms"/>
+
+       <!-- <Exposure name="V" dimension="none"/> --> <!-- Already exposed from baseCellMembPotDL -->
+       <Exposure name="W" dimension="none"/>
+       <Exposure name="F" dimension="none"/>
+
+       <Dynamics>
+
+           <StateVariable name="V" dimension="none" exposure="V"
+               description="V plays the role of the membrane potential"/>
+           <StateVariable name="W" dimension="none" exposure="W"
+               description="W plays the role of a recovery variable"/>
+
+           <!-- F must be a cubic polynomial in V -->
+           <DerivedVariable name="F" dimension="none" exposure="F" value="V - V^3 / 3"/>
+
+           <TimeDerivative variable="V" value="(F - W + I) / TS"/>
+           <TimeDerivative variable="W" value="phi * (V + a - b * W) / TS"/>
+
+           <OnStart>
+               <StateAssignment variable="V" value="V0"/>
+               <StateAssignment variable="W" value="W0"/>
+           </OnStart>
+
+       </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="fitzHughNagumoCell"
+                   extends="baseCellMembPotDL"
+                   description="Simple dimensionless model of spiking cell from FitzHugh and Nagumo. Superseded by _fitzHughNagumo1969Cell (See https://github.com/NeuroML/NeuroML2/issues/42)">
+
+        <Parameter name="I" dimension="none"/>
+
+        <!-- Needed to ensure V, W & I remain dimensionless... -->
+        <Constant name="SEC" dimension="time" value="1s"/>
+
+        <Exposure name="W" dimension="none"/>
+
+        <Dynamics>
+
+            <StateVariable name="V" dimension="none" exposure="V"/>
+            <StateVariable name="W" dimension="none" exposure="W"/>
+
+            <TimeDerivative variable="V" value="( (V - ((V^3) / 3)) - W + I) / SEC"/>
+            <TimeDerivative variable="W" value="(0.08 * (V + 0.7 - 0.8 * W)) / SEC"/>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="pinskyRinzelCA3Cell"
+               extends="baseCellMembPot"
+               description="Reduced CA3 cell model from Pinsky and Rinzel 1994. See https://github.com/OpenSourceBrain/PinskyRinzelModel">
+
+        <Parameter name="iSoma" dimension="currentDensity"/>
+        <Parameter name="iDend" dimension="currentDensity"/>
+
+        <Parameter name="gLs" dimension="conductanceDensity"/>
+        <Parameter name="gLd" dimension="conductanceDensity"/>
+        <Parameter name="gNa" dimension="conductanceDensity"/>
+        <Parameter name="gKdr" dimension="conductanceDensity"/>
+        <Parameter name="gCa" dimension="conductanceDensity"/>
+        <Parameter name="gKahp" dimension="conductanceDensity"/>
+        <Parameter name="gKC" dimension="conductanceDensity"/>
+        <Parameter name="gc" dimension="conductanceDensity"/>
+
+        <Parameter name="eNa" dimension="voltage"/>
+        <Parameter name="eCa" dimension="voltage"/>
+        <Parameter name="eK" dimension="voltage"/>
+        <Parameter name="eL" dimension="voltage"/>
+
+        <Parameter name="pp" dimension="none"/>
+        <Parameter name="cm" dimension="specificCapacitance"/>
+        <Parameter name="alphac" dimension="none"/>
+        <Parameter name="betac" dimension="none"/>
+
+        <Parameter name="gNmda" dimension="conductanceDensity"/>
+        <Parameter name="gAmpa" dimension="conductanceDensity"/>
+        <Parameter name="qd0" dimension="none"/>
+
+        <!-- Normalizing Constants -->
+        <Constant name="MSEC" dimension="time" value="1 ms"/>
+        <Constant name="MVOLT" dimension="voltage" value="1 mV"/>
+        <Constant name="UAMP_PER_CM2" dimension="currentDensity" value="1 uA_per_cm2"/>
+
+        <!-- Model Constants -->
+        <Constant name="Smax" dimension="none" value="125.0"/>
+        <Constant name="Vsyn" dimension="voltage" value="60.0 mV"/>
+        <Constant name="betaqd" dimension="none" value="0.001"/>
+
+        <Exposure name="Vs" dimension="voltage"/>
+        <Exposure name="Vd" dimension="voltage"/>
+        <Exposure name="ICad" dimension="currentDensity"/>
+        <Exposure name="Cad" dimension="none"/>
+        <Exposure name="hs" dimension="none"/>
+        <Exposure name="ns" dimension="none"/>
+        <Exposure name="sd" dimension="none"/>
+        <Exposure name="cd" dimension="none"/>
+        <Exposure name="qd" dimension="none"/>
+        <Exposure name="Si" dimension="none"/>
+        <Exposure name="Wi" dimension="none"/>
+
+
+        <Dynamics>
+
+            <StateVariable name="Vs" dimension="voltage" exposure="Vs"/>
+            <StateVariable name="Vd" dimension="voltage" exposure="Vd"/>
+            <StateVariable name="Cad" dimension="none" exposure="Cad"/>
+            <StateVariable name="hs" dimension="none" exposure="hs"/>
+            <StateVariable name="ns" dimension="none" exposure="ns"/>
+            <StateVariable name="sd" dimension="none" exposure="sd"/>
+            <StateVariable name="cd" dimension="none" exposure="cd"/>
+            <StateVariable name="qd" dimension="none" exposure="qd"/>
+
+
+            <!-- Synaptic Dynamics -->
+            <StateVariable name="Si" dimension="none" exposure="Si"/>
+            <StateVariable name="Wi" dimension="none" exposure="Wi"/>
+
+            <!-- Note Sisat is StateVariable & ConditionalDerivedVariable, see https://github.com/OpenSourceBrain/PinskyRinzelModel/issues/7 -->
+            <StateVariable name="Sisat" dimension="none"/>
+
+            <!-- baseCellMembPot compatibility -->
+            <DerivedVariable name="v" dimension="voltage" value="Vs" exposure="v"/>
+            <DerivedVariable name="ICad" dimension="currentDensity" exposure="ICad" value="gCa*sd*sd*(Vd-eCa)"/>
+
+
+
+            <DerivedVariable name="alphams_Vs" dimension="none" value="0.32*(-46.9-Vs/MVOLT)/(exp((-46.9-Vs/MVOLT)/4.0)-1.0)"/>
+            <DerivedVariable name="betams_Vs" dimension="none" value="0.28*(Vs/MVOLT+19.9)/(exp((Vs/MVOLT+19.9)/5.0)-1.0)"/>
+            <DerivedVariable name="Minfs_Vs" dimension="none" value="alphams_Vs/(alphams_Vs+betams_Vs)"/>
+
+            <DerivedVariable name="alphans_Vs" dimension="none" value="0.016*(-24.9-Vs/MVOLT)/(exp((-24.9-Vs/MVOLT)/5.0)-1.0)"/>
+            <DerivedVariable name="betans_Vs" dimension="none" value="0.25*exp(-1.0-0.025*Vs/MVOLT)"/>
+
+            <DerivedVariable name="alphahs_Vs" dimension="none" value="0.128*exp((-43.0-Vs/MVOLT)/18.0)"/>
+            <DerivedVariable name="betahs_Vs" dimension="none" value="4.0/(1.0+exp((-20.0-Vs/MVOLT)/5.0))"/>
+
+            <DerivedVariable name="alphasd_Vd" dimension="none" value="1.6/(1.0+exp(-0.072*(Vd/MVOLT-5.0)))"/>
+            <DerivedVariable name="betasd_Vd" dimension="none" value="0.02*(Vd/MVOLT+8.9)/(exp((Vd/MVOLT+8.9)/5.0)-1.0)"/>
+
+
+            <DerivedVariable name="Iampa" dimension="currentDensity" value="gAmpa*Wi*(Vd-Vsyn)"/>
+            <DerivedVariable name="Inmda" dimension="currentDensity" value="gNmda*Sisat*(Vd-Vsyn)/(1.0+0.28*exp(-0.062*(Vd/MVOLT-60.0)))"/>
+            <DerivedVariable name="Isyn" dimension="currentDensity" value="Iampa+Inmda"/>
+
+
+            <ConditionalDerivedVariable name="alphaqd" dimension="none">
+                <Case condition="0.00002*Cad .gt. 0.01" value="0.01"/>
+                <Case value="0.00002*Cad"/>
+            </ConditionalDerivedVariable>
+
+            <ConditionalDerivedVariable name="chid" dimension="none">
+                <Case condition="Cad/250 .gt. 1" value="1"/>
+                <Case value="Cad/250"/>
+            </ConditionalDerivedVariable>
+
+            <ConditionalDerivedVariable name="alphacd_Vd" dimension="none">
+                <Case condition="Vd .lt. -10*MVOLT" value="exp((Vd/MVOLT+50.0)/11-(Vd/MVOLT+53.5)/27)/18.975"/>
+                <Case value="2.0*exp((-53.5-Vd/MVOLT)/27.0)"/>
+            </ConditionalDerivedVariable>
+
+            <ConditionalDerivedVariable name="betacd_Vd" dimension="none">
+                <Case condition="Vd .lt. -10*MVOLT" value="(2.0*exp((-53.5-Vd/MVOLT)/27.0)-alphacd_Vd)"/>
+                <Case value="0"/>
+            </ConditionalDerivedVariable>
+
+            <!-- Note Sisat is StateVariable & ConditionalDerivedVariable, see https://github.com/OpenSourceBrain/PinskyRinzelModel/issues/7 -->
+            <ConditionalDerivedVariable name="Sisat" dimension="none">
+                <Case condition="Si .gt. Smax" value="Smax"/>
+                <Case value="Si"/>
+            </ConditionalDerivedVariable>
+
+
+            <TimeDerivative variable="Vs" value="(-gLs*(Vs-eL)-gNa*(Minfs_Vs^2)*hs*(Vs-eNa)-gKdr*ns*(Vs-eK)+(gc/pp)*(Vd-Vs)+iSoma/pp) / cm"/>
+            <TimeDerivative variable="Vd" value="(iDend/(1.0-pp)-Isyn/(1.0-pp)-gLd*(Vd-eL)-ICad-gKahp*qd*(Vd-eK)-gKC*cd*chid*(Vd-eK)+(gc*(Vs-Vd))/(1.0-pp)) / cm"/>
+            <TimeDerivative variable="Cad" value="(-0.13*ICad/UAMP_PER_CM2-0.075*Cad) / MSEC"/>
+            <TimeDerivative variable="hs" value="(alphahs_Vs-(alphahs_Vs+betahs_Vs)*hs) / MSEC"/>
+            <TimeDerivative variable="ns" value="(alphans_Vs-(alphans_Vs+betans_Vs)*ns) / MSEC"/>
+            <TimeDerivative variable="sd" value="(alphasd_Vd-(alphasd_Vd+betasd_Vd)*sd) / MSEC"/>
+            <TimeDerivative variable="cd" value="(alphacd_Vd-(alphacd_Vd+betacd_Vd)*cd) / MSEC"/>
+            <TimeDerivative variable="qd" value="(alphaqd-(alphaqd+betaqd)*qd) / MSEC"/>
+
+            <!-- Synaptic Dynamics -->
+            <TimeDerivative variable="Si" value="-Si/150.0" />
+            <TimeDerivative variable="Wi" value="-Wi/2.0" />
+
+
+            <OnStart>
+                <StateAssignment variable="Vs" value="eL"/>
+                <StateAssignment variable="Vd" value="eL"/>
+                <StateAssignment variable="qd" value="qd0" />
+            </OnStart>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+
+</Lems>
diff --git a/lems/test/NeuroML2CoreTypes/Channels.xml b/lems/test/NeuroML2CoreTypes/Channels.xml
new file mode 100644
index 0000000..a3d0ef5
--- /dev/null
+++ b/lems/test/NeuroML2CoreTypes/Channels.xml
@@ -0,0 +1,718 @@
+<Lems xmlns="http://www.neuroml.org/lems/0.7.5"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.neuroml.org/lems/0.7.5 ../../LEMS/Schemas/LEMS/LEMS_v0.7.5.xsd"
+      description="Defines voltage (and concentration) gated ion channel models. Ion channels will generally extend _baseIonChannel_. The most commonly used voltage dependent gate will extend _baseGate_.">
+
+    <!-- A number of channel types for use in NeuroML 2 documents  -->
+
+    <!-- Including standard unit comp types & units for NeuroML v2.0 -->
+    <Include file="NeuroMLCoreCompTypes.xml"/>
+
+
+    <ComponentType name="baseVoltageDepRate"
+                   description="Base ComponentType for voltage dependent rate. Produces a time varying rate _r which depends on _v.">
+        <Exposure name="r" dimension="per_time"/>
+        <Requirement name="v" dimension="voltage"/>
+    </ComponentType>
+
+
+    <ComponentType name="baseVoltageConcDepRate"
+                   description="Base ComponentType for voltage and concentration dependent rate. Produces a time varying rate _r which depends on _v and _caConc."
+                   extends="baseVoltageDepRate">
+        <Requirement name="caConc" dimension="concentration"/>
+    </ComponentType>
+
+
+    <ComponentType name="baseHHRate"
+                   description="Base ComponentType for rate which follow one of the typical forms for rate equations in the standard HH formalism, using the parameters _rate, _midpoint and _scale"
+                   extends="baseVoltageDepRate">
+        <Parameter name="rate" dimension="per_time"/>
+        <Parameter name="midpoint" dimension="voltage"/>
+        <Parameter name="scale" dimension="voltage"/>
+    </ComponentType>
+
+
+    <ComponentType name="HHExpRate"
+                   extends="baseHHRate"
+                   description="Exponential form for rate equation (Q: Should these be renamed hhExpRate, etc?)">
+        <Dynamics>
+            <DerivedVariable name="r" exposure="r" value="rate * exp((v - midpoint)/scale)" dimension="per_time"/>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="HHSigmoidRate"
+                   extends="baseHHRate"
+                   description="Sigmoidal form for rate equation">
+        <Dynamics>
+            <DerivedVariable name="r" exposure="r" value="rate / (1 + exp(0 - (v - midpoint)/scale))" dimension="per_time"/>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="HHExpLinearRate"
+                   extends="baseHHRate"
+                   description="Exponential linear form for rate equation. Linear for large positive _v, exponentially decays for large negative _v.">
+        <Dynamics>
+            <DerivedVariable name="x" value="(v - midpoint) / scale" dimension="none"/>
+
+            <ConditionalDerivedVariable name="r" exposure="r" dimension="per_time">
+                <Case condition="x .neq. 0" value="rate * x / (1 - exp(0 - x))"/>
+                <Case condition="x .eq. 0" value="rate"/>
+            </ConditionalDerivedVariable>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="baseVoltageDepVariable"
+                   description="Base ComponentType for voltage dependent variable  _x, which depends on _v. Can be used for inf/steady state of rate variable.">
+        <Exposure name="x" dimension="none"/>
+        <Requirement name="v" dimension="voltage"/>
+    </ComponentType>
+
+
+    <ComponentType name="baseVoltageConcDepVariable"
+                   description="Base ComponentType for voltage and calcium concentration dependent variable _x, which depends on _v and _caConc."
+                   extends="baseVoltageDepVariable">
+        <Requirement name="caConc" dimension="concentration"/>
+    </ComponentType>
+
+
+    <ComponentType name="baseHHVariable"
+                   description="Base ComponentType for voltage dependent dimensionless variable which follow one of the typical forms for variable equations in the standard HH formalism, using the parameters _rate, _midpoint, _scale"
+                   extends="baseVoltageDepVariable">
+        <Parameter name="rate" dimension="none"/>
+        <Parameter name="midpoint" dimension="voltage"/>
+        <Parameter name="scale" dimension="voltage"/>
+    </ComponentType>
+
+
+    <ComponentType name="HHExpVariable"
+                   extends="baseHHVariable"
+                   description="Exponential form for variable equation">
+        <Dynamics>
+            <DerivedVariable name="x" dimension="none" exposure="x" value="rate * exp((v - midpoint)/scale)"/>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="HHSigmoidVariable"
+                   extends="baseHHVariable"
+                   description="Sigmoidal form for variable equation">
+        <Dynamics>
+            <DerivedVariable name="x" dimension="none" exposure="x" value="rate / (1 + exp(0 - (v - midpoint)/scale))"/>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="HHExpLinearVariable"
+                   extends="baseHHVariable"
+                   description="Exponential linear form for variable equation. Linear for large positive _v, exponentially decays for large negative _v.">
+        <Dynamics>
+            <DerivedVariable name="a" dimension="none" value="(v - midpoint) / scale"/>
+            <DerivedVariable name="x" dimension="none" exposure="x" value="rate * a / (1 - exp(0 - a))"/>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="baseVoltageDepTime"
+                   description="Base ComponentType for voltage dependent ComponentType producing value _t with dimension time (e.g. for time course of rate variable). Note: time course would not normally be fit to exp/sigmoid etc.">
+        <Exposure name="t" dimension="time"/>
+        <Requirement name="v" dimension="voltage"/>
+    </ComponentType>
+
+
+    <ComponentType name="baseVoltageConcDepTime"
+                   description="Base type for voltage and calcium concentration dependent ComponentType producing value _t with dimension time (e.g. for time course of rate variable)."
+                   extends="baseVoltageDepTime">
+        <Requirement name="caConc" dimension="concentration"/>
+    </ComponentType>
+
+
+    <ComponentType name="fixedTimeCourse"
+                   extends="baseVoltageDepTime"
+                   description="Time course of a fixed magnitude _tau which can be used for the time course in _gateHHtauInf_, _gateHHratesTau_ or _gateHHratesTauInf_">
+
+        <Parameter name="tau" dimension="time"/>
+        <Dynamics>
+            <DerivedVariable name="t" dimension="time" exposure="t" value="tau"/>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="baseQ10Settings"
+                   description="Base ComponentType for a scaling to apply to gating variable time course, usually temperature dependent">
+
+        <Exposure name="q10" dimension="none"/>
+        <Requirement name="temperature" dimension="temperature"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="q10Fixed"
+                   extends="baseQ10Settings"
+                   description="A fixed value, _fixedQ10, for the scaling of the time course of the gating variable">
+        <Parameter name="fixedQ10" dimension="none"/>
+        <Dynamics>
+            <DerivedVariable name="q10" exposure="q10" dimension="none" value="fixedQ10"/>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="q10ExpTemp"
+                   extends="baseQ10Settings"
+                   description="A value for the Q10 scaling which varies as a standard function of the difference between the current temperature, _temperature, and the temperature at which the gating variable equations were determined, _experimentalTemp">
+
+        <Parameter name="q10Factor" dimension="none"/>
+        <Parameter name="experimentalTemp" dimension="temperature"/>
+
+        <Constant name="TENDEGREES" dimension="temperature" value="10K"/>
+
+        <Dynamics>
+            <!-- TODO: make sure correct dimensions in exponent, even though LEMS doesn't seem to mind...-->
+            <DerivedVariable name="q10" exposure="q10" dimension="none" value="q10Factor^((temperature - experimentalTemp)/TENDEGREES)"/>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="baseConductanceScaling"
+                   description="Base ComponentType for a scaling to apply to a gate's conductance, e.g. temperature dependent scaling">
+
+        <Exposure name="factor" dimension="none"/>
+        <Requirement name="temperature" dimension="temperature"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="q10ConductanceScaling"
+                   extends="baseConductanceScaling"
+                   description="A value for the conductance scaling which varies as a standard function of the difference between the current temperature, _temperature, and the temperature at which the conductance was originally determined, _experimentalTemp">
+
+        <Parameter name="q10Factor" dimension="none"/>
+        <Parameter name="experimentalTemp" dimension="temperature"/>
+        <Constant name="TENDEGREES" dimension="temperature" value="10K"/>
+
+
+        <Dynamics>
+            <DerivedVariable name="factor" exposure="factor" dimension="none" value="q10Factor^((temperature - experimentalTemp)/TENDEGREES)"/>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="baseConductanceScalingCaDependent"
+                   extends="baseConductanceScaling"
+                   description="Base ComponentType for a scaling to apply to a gate's conductance which depends on Ca concentration. Usually a generic expression of _caConc (so no standard, non-base form here).">
+
+        <Requirement name="caConc" dimension="concentration"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="baseGate"
+                   description="Base ComponentType for a voltage and/or concentration dependent gate">
+
+        <Parameter name="instances" dimension="none"/>
+
+        <Child name="notes" type="notes"/>
+
+        <Exposure name="fcond" dimension="none"/>
+        <Exposure name="q" dimension="none"/>
+
+    </ComponentType>
+
+    <ComponentType name="gate"
+                   extends="baseGate"
+                   description="Conveniently named baseGate">
+    </ComponentType>
+
+    <ComponentType name="gateHHrates"
+                   extends="gate"
+                   description="Gate which follows the general Hodgkin Huxley formalism">
+
+        <Child name="forwardRate" type="baseVoltageDepRate"/>
+        <Child name="reverseRate" type="baseVoltageDepRate"/>
+        <Children name="q10Settings" type="baseQ10Settings"/>
+
+
+        <Exposure name="alpha" dimension="per_time"/>
+        <Exposure name="beta" dimension="per_time"/>
+
+        <Exposure name="tau" dimension="time"/>
+        <Exposure name="inf" dimension="none"/>
+
+        <Exposure name="rateScale" dimension="none"/>
+
+        <Dynamics>
+            <StateVariable name="q" exposure="q" dimension="none"/>
+
+            <DerivedVariable name="rateScale" exposure="rateScale" dimension="none" select="q10Settings[*]/q10" reduce="multiply"/>
+
+            <DerivedVariable name="alpha" dimension="per_time" exposure="alpha" select="forwardRate/r"/>
+            <DerivedVariable name="beta" dimension="per_time" exposure="beta" select="reverseRate/r"/>
+
+            <DerivedVariable name="fcond" exposure="fcond" dimension="none" value="q^instances"/>
+
+
+            <DerivedVariable name="inf" dimension="none" exposure="inf" value="alpha/(alpha+beta)"/>
+
+            <DerivedVariable name="tau" dimension="time" exposure="tau" value="1/((alpha+beta) * rateScale)"/>
+
+            <TimeDerivative variable="q" value="(inf - q) / tau"/>
+
+            <OnStart>
+                <StateAssignment variable="q" value="inf"/>
+            </OnStart>
+
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="gateHHtauInf"
+                   extends="gate"
+                   description="Gate which follows the general Hodgkin Huxley formalism">
+
+        <Child name="timeCourse" type="baseVoltageDepTime" />
+        <Child name="steadyState" type="baseVoltageDepVariable" />
+        <Children name="q10Settings" type="baseQ10Settings"/>
+
+        <Exposure name="tau" dimension="time"/>
+        <Exposure name="inf" dimension="none"/>
+
+        <Exposure name="rateScale" dimension="none"/>
+
+        <Dynamics>
+            <StateVariable name="q" exposure="q" dimension="none"/>
+
+            <DerivedVariable name="rateScale" exposure="rateScale" dimension="none" select="q10Settings[*]/q10" reduce="multiply"/>
+
+            <DerivedVariable name="fcond" exposure="fcond" dimension="none" value="q^instances"/>
+
+            <DerivedVariable name="inf" dimension="none" exposure="inf" select="steadyState/x"/>
+
+            <DerivedVariable name="tauUnscaled" dimension="time" select="timeCourse/t"/>
+            <DerivedVariable name="tau" dimension="time" exposure="tau" value="tauUnscaled / rateScale"/>
+
+            <TimeDerivative variable="q" value="(inf - q) / tau"/>
+
+            <OnStart>
+                <StateAssignment variable="q" value="inf"/>
+            </OnStart>
+
+        </Dynamics>
+    </ComponentType>
+
+    <ComponentType name="gateHHInstantaneous"
+                   extends="gate"
+                   description="Gate which follows the general Hodgkin Huxley formalism but is instantaneous, so tau = 0 and gate follows exactly inf value">
+
+        <Constant name="SEC" dimension="time" value="1 s"/>
+
+        <Child name="steadyState" type="baseVoltageDepVariable" />
+
+        <Exposure name="tau" dimension="time"/>
+        <Exposure name="inf" dimension="none"/>
+
+        <Dynamics>
+
+            <DerivedVariable name="inf" dimension="none" exposure="inf" select="steadyState/x"/>
+
+            <DerivedVariable name="tau" dimension="time" exposure="tau" value="0 * SEC"/>
+
+            <DerivedVariable name="q"  exposure="q" dimension="none" value="inf"/>
+
+            <DerivedVariable name="fcond" exposure="fcond" dimension="none" value="q^instances"/>
+
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="gateHHratesTau"
+                   extends="gate"
+                   description="Gate which follows the general Hodgkin Huxley formalism">
+
+        <Child name="forwardRate" type="baseVoltageDepRate"/>
+        <Child name="reverseRate" type="baseVoltageDepRate"/>
+        <Child name="timeCourse" type="baseVoltageDepTime" />
+        <Children name="q10Settings" type="baseQ10Settings"/>
+
+        <Exposure name="alpha" dimension="per_time"/>
+        <Exposure name="beta" dimension="per_time"/>
+
+        <Exposure name="tau" dimension="time"/>
+        <Exposure name="inf" dimension="none"/>
+
+        <Exposure name="rateScale" dimension="none"/>
+
+        <Dynamics>
+            <StateVariable name="q" exposure="q" dimension="none"/>
+
+            <DerivedVariable name="rateScale" exposure="rateScale" dimension="none" select="q10Settings[*]/q10" reduce="multiply"/>
+
+            <DerivedVariable name="alpha" dimension="per_time" exposure="alpha" select="forwardRate/r"/>
+            <DerivedVariable name="beta" dimension="per_time" exposure="beta" select="reverseRate/r"/>
+
+            <DerivedVariable name="fcond" exposure="fcond" dimension="none" value="q^instances"/>
+
+            <DerivedVariable name="inf" dimension="none" exposure="inf" value="alpha/(alpha+beta)"/>
+
+            <DerivedVariable name="tauUnscaled" dimension="time" select="timeCourse/t"/>
+            <DerivedVariable name="tau" dimension="time" exposure="tau" value="tauUnscaled / rateScale"/>
+
+            <TimeDerivative variable="q" value="(inf - q) / tau"/>
+
+            <OnStart>
+                <StateAssignment variable="q" value="inf"/>
+            </OnStart>
+
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="gateHHratesInf"
+                   extends="gate"
+                   description="Gate which follows the general Hodgkin Huxley formalism">
+
+        <Child name="forwardRate" type="baseVoltageDepRate"/>
+        <Child name="reverseRate" type="baseVoltageDepRate"/>
+        <Child name="steadyState" type="baseVoltageDepVariable" />
+        <Children name="q10Settings" type="baseQ10Settings"/>
+
+
+        <Exposure name="alpha" dimension="per_time"/>
+        <Exposure name="beta" dimension="per_time"/>
+
+        <Exposure name="tau" dimension="time"/>
+        <Exposure name="inf" dimension="none"/>
+
+        <Exposure name="rateScale" dimension="none"/>
+
+        <Dynamics>
+            <StateVariable name="q" exposure="q" dimension="none"/>
+
+            <DerivedVariable name="rateScale" exposure="rateScale" dimension="none" select="q10Settings[*]/q10" reduce="multiply"/>
+            <DerivedVariable name="alpha" dimension="per_time" exposure="alpha" select="forwardRate/r"/>
+            <DerivedVariable name="beta" dimension="per_time" exposure="beta" select="reverseRate/r"/>
+            <DerivedVariable name="fcond" exposure="fcond" dimension="none" value="q^instances"/>
+            <DerivedVariable name="inf" dimension="none" exposure="inf" select="steadyState/x"/>
+            <DerivedVariable name="tau" dimension="time" exposure="tau" value="1/((alpha+beta) * rateScale)"/>
+
+            <TimeDerivative variable="q" value="(inf - q) / tau"/>
+
+            <OnStart>
+                <StateAssignment variable="q" value="inf"/>
+            </OnStart>
+
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="gateHHratesTauInf"
+                   extends="gate"
+                   description="Gate which follows the general Hodgkin Huxley formalism">
+
+        <Child name="forwardRate" type="baseVoltageDepRate"/>
+        <Child name="reverseRate" type="baseVoltageDepRate"/>
+        <Child name="timeCourse" type="baseVoltageDepTime" />
+        <Child name="steadyState" type="baseVoltageDepVariable" />
+        <Children name="q10Settings" type="baseQ10Settings"/>
+
+        <Exposure name="alpha" dimension="per_time"/>
+        <Exposure name="beta" dimension="per_time"/>
+
+        <Exposure name="tau" dimension="time"/>
+        <Exposure name="inf" dimension="none"/>
+
+        <Exposure name="rateScale" dimension="none"/>
+
+        <Dynamics>
+            <StateVariable name="q" exposure="q" dimension="none"/>
+
+            <DerivedVariable name="rateScale" exposure="rateScale" dimension="none" select="q10Settings[*]/q10" reduce="multiply"/>
+            <DerivedVariable name="alpha" dimension="per_time" exposure="alpha" select="forwardRate/r"/>
+            <DerivedVariable name="beta" dimension="per_time" exposure="beta" select="reverseRate/r"/>
+            <DerivedVariable name="inf" dimension="none" exposure="inf" select="steadyState/x"/>
+            <DerivedVariable name="tauUnscaled" dimension="time" select="timeCourse/t"/>
+            <DerivedVariable name="tau" dimension="time" exposure="tau" value="tauUnscaled / rateScale"/>
+            <DerivedVariable name="fcond" exposure="fcond" dimension="none" value="q^instances"/>
+
+            <TimeDerivative variable="q" value="(inf - q) / tau"/>
+
+            <OnStart>
+                <StateAssignment variable="q" value="inf"/>
+            </OnStart>
+
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="gateFractional"
+                   extends="gate"
+                   description="Gate composed of subgates contributing with fractional conductance">
+
+        <Children name="q10Settings" type="baseQ10Settings"/>
+        <Children name="subGate" type="subGate"/>
+        <Exposure name="rateScale" dimension="none"/>
+
+        <Dynamics>
+            <DerivedVariable name="q" exposure="q" dimension="none" select="subGate[*]/qfrac" reduce="add"/>
+            <DerivedVariable name="fcond" exposure="fcond" dimension="none" value="q^instances"/>
+            <DerivedVariable name="rateScale" exposure="rateScale" dimension="none" select="q10Settings[*]/q10" reduce="multiply"/>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="subGate"
+                   description="Gate composed of subgates contributing with fractional conductance">
+
+        <Parameter name="fractionalConductance" dimension="none"/>
+
+        <Child name="notes" type="notes"/>
+
+        <Child name="timeCourse" type="baseVoltageDepTime" />
+        <Child name="steadyState" type="baseVoltageDepVariable" />
+
+        <Exposure name="tau" dimension="time"/>
+        <Exposure name="inf" dimension="none"/>
+        <Exposure name="qfrac" dimension="none"/>
+        <Exposure name="q" dimension="none"/>
+        <Requirement name="rateScale" dimension="none"/>
+
+        <Dynamics>
+            <StateVariable name="q" exposure="q" dimension="none"/>
+            <DerivedVariable name="inf" dimension="none" exposure="inf" select="steadyState/x"/>
+            <DerivedVariable name="tauUnscaled" dimension="time" select="timeCourse/t"/>
+            <DerivedVariable name="tau" dimension="time" exposure="tau" value="tauUnscaled / rateScale"/>
+            <DerivedVariable name="qfrac" dimension="none" exposure="qfrac" value="q * fractionalConductance"/>
+            <TimeDerivative variable="q" value="(inf - q) / tau"/>
+            <OnStart>
+                <StateAssignment variable="q" value="inf"/>
+            </OnStart>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="baseIonChannel"
+                   description="Base for all ion channel ComponentTypes">
+
+        <Parameter name="conductance" dimension="conductance"/>
+
+        <Child name="notes" type="notes"/>
+        <Child name="annotation" type="annotation"/>
+
+        <Exposure name="g" dimension="conductance"/>
+        <Exposure name="fopen" dimension="none"/>
+        <Requirement name="v" dimension="voltage"/>
+
+        <Text name="neuroLexId"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="ionChannelPassive"
+                   extends="ionChannel"
+                   description="Simple passive ion channel where the constant conductance through the channel is equal to _conductance">
+      <Text name="species"/> <!-- quick and dirty workaround - sould inherit that from IonChannelHH-->
+        <Dynamics>
+            <DerivedVariable name="fopen" exposure="fopen" value="1" dimension="none"/>
+            <DerivedVariable name="g" exposure="g" value="conductance" dimension="conductance"/>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="ionChannelHH"
+                   extends="baseIonChannel"
+                   description="Note _ionChannel_ and _ionChannelHH_ are currently functionally identical. This is needed since many existing examples use ionChannel, some use ionChannelHH. NeuroML v2beta4 should remove one of these, probably ionChannelHH.">
+
+        <Children name="conductanceScaling" type="baseConductanceScaling"/>
+        <Children name="gates" type="gate"/>
+
+        <Text name="species"/>
+
+        <Dynamics>
+            <DerivedVariable name="conductanceScale" dimension="none" select="conductanceScaling[*]/factor" reduce="multiply"/>
+            <DerivedVariable name="fopen0" dimension="none" select="gates[*]/fcond" reduce="multiply"/>
+            <DerivedVariable name="fopen" exposure="fopen" dimension="none" value="conductanceScale * fopen0"/>
+            <DerivedVariable name="g" exposure="g" value="conductance * fopen" dimension="conductance"/>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="ionChannel"
+                   extends="ionChannelHH"
+                   description="Note _ionChannel_ and _ionChannelHH_ are currently functionally identical. This is needed since many existing examples use ionChannel, some use ionChannelHH. NeuroML v2beta4 should remove one of these, probably ionChannelHH.">
+
+        <Dynamics>
+            <DerivedVariable name="conductanceScale" dimension="none" select="conductanceScaling[*]/factor" reduce="multiply"/>
+            <DerivedVariable name="fopen0" dimension="none" select="gates[*]/fcond" reduce="multiply"/>
+            <DerivedVariable name="fopen" exposure="fopen" dimension="none" value="conductanceScale * fopen0"/>
+            <DerivedVariable name="g" exposure="g" value="conductance * fopen" dimension="conductance"/>
+        </Dynamics>
+
+    </ComponentType>
+
+    <ComponentType name="ionChannelVShift"
+                   extends="ionChannel"
+                   description="Same as _ionChannel_, but with a _vShift parameter to change voltage activation of gates. The exact usage of _vShift in expressions for rates is determined by the individual gates.">
+
+
+        <Parameter name="vShift" dimension="voltage"/>
+        <!-- TODO: Ensure Text elements are inherited from base type -->
+        <Text name="species"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="KSState"
+                   description="One of the states in which a _gateKS_ can be. The rates of transitions between these states are given by _KSTransition_s">
+        <Parameter name="relativeConductance" dimension="none"/>
+
+        <Exposure name="occupancy" dimension="none"/>
+        <Exposure name="q" dimension="none"/>
+
+        <Dynamics>
+            <StateVariable name="occupancy" exposure="occupancy" dimension="none"/>
+            <DerivedVariable name="q" dimension="none" exposure="q" value="relativeConductance * occupancy"/>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="closedState"
+                   extends="KSState"
+                   description="A _KSState_ with _relativeConductance of 0">
+        <Fixed parameter="relativeConductance" value="0"/>
+    </ComponentType>
+
+
+    <ComponentType name="openState"
+                   extends="KSState"
+                   description="A _KSState_ with _relativeConductance of 1">
+        <Fixed parameter="relativeConductance" value="1"/>
+    </ComponentType>
+
+
+    <ComponentType name="ionChannelKS"
+                   extends="baseIonChannel"
+                   description="A kinetic scheme based ion channel with multiple _gateKS_s, each of which consists of multiple _KSState_s and _KSTransition_s giving the rates of transition between them">
+
+        <Children name="conductanceScaling" type="baseConductanceScaling"/>
+        <Children name="gates" type="gateKS"/>
+
+        <Text name="species"/>
+
+        <Dynamics>
+            <DerivedVariable name="fopen" exposure="fopen" dimension="none" select="gates[*]/fcond" reduce="multiply"/>
+            <DerivedVariable name="g" exposure="g" dimension="conductance" value="fopen * conductance"/>
+
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="KSTransition" description="Specified the forward and reverse rates of transition between two _KSState_s in a _gateKS_">
+        <Link name="from" type="KSState"/>
+        <Link name="to" type="KSState"/>
+        <Exposure name="rf" dimension="per_time"/>
+        <Exposure name="rr" dimension="per_time"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="forwardTransition"
+                   extends="KSTransition"
+                   description="A forward only _KSTransition_ for a _gateKS_ which specifies a _rate (type _baseHHRate_) which follows one of the standard Hodgkin Huxley forms (e.g. _HHExpRate_, _HHSigmoidRate_, _HHExpLinearRate_">
+
+        <Constant name="SEC" dimension="time" value="1s"/>
+        <Child name="rate" type="baseHHRate"/>
+        <!--Note these should be inherited from the base KSTransition, but they're not...-->
+        <Link name="from" type="KSState"/>
+        <Link name="to" type="KSState"/>
+
+        <Dynamics>
+            <DerivedVariable name="rf0" dimension="per_time" select="rate/r"/>
+            <DerivedVariable name="rf" exposure="rf" dimension="per_time" value="rf0"/>
+            <DerivedVariable name="rr" exposure="rr" dimension="per_time" value="0/SEC"/>
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="reverseTransition"
+                   extends="KSTransition"
+                   description="A reverse only _KSTransition_ for a _gateKS_ which specifies a _rate (type _baseHHRate_) which follows one of the standard Hodgkin Huxley forms (e.g. _HHExpRate_, _HHSigmoidRate_, _HHExpLinearRate_">
+
+        <Constant name="SEC" dimension="time" value="1s"/>
+        <Child name="rate" type="baseHHRate"/>
+        <!--Note these should be inherited from the base KSTransition, but they're not...-->
+        <Link name="from" type="KSState"/>
+        <Link name="to" type="KSState"/>
+
+        <Dynamics>
+            <DerivedVariable name="rr0" dimension="per_time" select="rate/r"/>
+            <DerivedVariable name="rr" exposure="rr" dimension="per_time" value="rr0"/>
+            <DerivedVariable name="rf" exposure="rf" dimension="per_time" value="0/SEC"/>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="vHalfTransition"
+                   extends="KSTransition"
+                   description="Transition which specifies both the forward and reverse rates of transition">
+        <Parameter name="vHalf" dimension="voltage"/>
+        <Parameter name="z" dimension="none"/>
+        <Parameter name="gamma" dimension="none"/>
+        <Parameter name="tau" dimension="time"/>
+        <Parameter name="tauMin" dimension="time"/>
+        <Constant name="kte" dimension="voltage" value="25.3mV"/>
+        <Requirement name="v" dimension="voltage"/>
+
+        <Dynamics>
+            <DerivedVariable name="rf0" dimension="per_time" value="exp(z * gamma * (v - vHalf) / kte) / tau"/>
+            <DerivedVariable name="rr0" dimension="per_time" value="exp(-z * (1 - gamma) * (v - vHalf) / kte) / tau"/>
+            <DerivedVariable name="rf" exposure="rf" dimension="per_time" value="1 / (1/rf0 + tauMin)"/>
+            <DerivedVariable name="rr" exposure="rr" dimension="per_time" value="1 / (1/rr0 + tauMin)"/>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="tauInfTransition"
+                   extends="KSTransition"
+                   description="KS Transition specified in terms of time constant _tau_ and steady state _inf_">
+        <Child name="timeCourse" type="baseVoltageDepTime" />
+        <Child name="steadyState" type="baseVoltageDepVariable" />
+        <Link name="from" type="KSState"/>
+        <Link name="to" type="KSState"/>
+
+        <Dynamics>
+            <DerivedVariable name="tau" dimension="time" select="timeCourse/t"/>
+            <DerivedVariable name="inf" dimension="none" select="steadyState/x"/>
+            <DerivedVariable name="rf" exposure="rf" dimension="per_time" value="inf/tau"/>
+            <DerivedVariable name="rr" exposure="rr" dimension="per_time" value="(1-inf)/tau"/>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="gateKS"
+                   extends="baseGate"
+                   description="A gate which consists of multiple _KSState_s and _KSTransition_s giving the rates of transition between them">
+        <Children name="states" type="KSState"/>
+        <Children name="transitions" type="KSTransition"/>
+        <Children name="q10Settings" type="baseQ10Settings"/>
+
+        <Exposure name="rateScale" dimension="none"/>
+
+        <Dynamics>
+
+            <DerivedVariable name="rateScale" exposure="rateScale" dimension="none" select="q10Settings[*]/q10" reduce="multiply"/>
+            <DerivedVariable name="q" exposure="q" dimension="none" select="states[*]/q" reduce="add"/>
+            <DerivedVariable name="fcond" exposure="fcond" dimension="none" value="q^instances"/>
+
+
+            <KineticScheme name="ks" nodes="states" stateVariable="occupancy"
+                           edges="transitions" edgeSource="from" edgeTarget="to"
+                           forwardRate="rf" reverseRate="rr"/>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+</Lems>
diff --git a/lems/test/NeuroML2CoreTypes/Inputs.xml b/lems/test/NeuroML2CoreTypes/Inputs.xml
new file mode 100644
index 0000000..31f3016
--- /dev/null
+++ b/lems/test/NeuroML2CoreTypes/Inputs.xml
@@ -0,0 +1,859 @@
+<Lems xmlns="http://www.neuroml.org/lems/0.7.5"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.neuroml.org/lems/0.7.5 ../../LEMS/Schemas/LEMS/LEMS_v0.7.5.xsd"
+      description="A number of ComponentTypes for providing spiking and current inputs to other ComponentTypes">
+
+
+    <Include file="NeuroMLCoreDimensions.xml"/>
+
+
+    <ComponentType name="basePointCurrent"
+                   description="Base type for all ComponentTypes which produce a current _i (with dimension current)"
+                   extends="baseStandalone">
+
+        <Exposure name="i" dimension="current" description="The total (usually time varying) current produced by this ComponentType"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="baseVoltageDepPointCurrent"
+                   extends="basePointCurrent"
+                   description="Base type for all ComponentTypes which produce a current _i (with dimension current) and require a voltage _v exposed on the parent Component, which would often be the membrane potential of a Component extending _baseCellMembPot_">
+
+        <Requirement name="v" dimension="voltage" description="The current may vary with the voltage exposed by the ComponentType on which this is placed"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="baseVoltageDepPointCurrentSpiking"
+                   extends="baseVoltageDepPointCurrent"
+                   description="Base type for all ComponentTypes which produce a current _i, require a membrane potential _v exposed on the parent and emit spikes (on a port _spike). The exposed variable _tsince can be used for plotting the time since the Component has spiked last">
+
+        <EventPort name="spike"
+                   direction="out"
+                   description="Port on which spikes are emitted"/>
+
+        <Exposure name="tsince"
+                  dimension="time"
+                  description="Time since the last spike was emitted"/>
+    </ComponentType>
+
+
+
+    <ComponentType name="basePointCurrentDL"
+                   description="Base type for all ComponentTypes which produce a dimensionless current _I. There are many dimensionless equivalents of all the core current producing ComponentTypes such as _pulseGenerator_ / _pulseGeneratorDL_, _sineGenerator_ / _sineGeneratorDL_ and _rampGenerator_ / _rampGeneratorDL_">
+
+        <Exposure name="I" dimension="none" description="The total (time varying) current produced by this ComponentType"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="baseVoltageDepPointCurrentDL"
+                   extends="basePointCurrentDL"
+                   description="Base type for all ComponentTypes which produce a dimensionless current _I and require a dimensionless membrane potential _V exposed on the parent Component">
+
+        <Requirement name="V" dimension="none" description="The current may vary with the dimensionless voltage exposed by the ComponentType on which this is placed"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="baseSpikeSource"
+                   description="Base for any ComponentType whose main purpose is to emit spikes (on a port _spike). The exposed variable _tsince can be used for plotting the time since the Component has spiked last.">
+
+        <EventPort name="spike"
+                   direction="out"
+                   description="Port on which spikes are emitted"/>
+
+        <Exposure name="tsince"
+                  dimension="time"
+                  description="Time since the last spike was emitted"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="spikeGenerator"
+                   extends="baseSpikeSource"
+                   description="Simple generator of spikes at a regular interval set by _period">
+
+        <Parameter name="period" dimension="time" description="Time between spikes. The first spike will be emitted after this time."/>
+
+        <Constant name="SMALL_TIME" dimension="time" value="1e-9ms" description="A useful constant for use as a non zero time increment"/> <!-- See below for usage -->
+
+        <Exposure name="tnext" dimension="time" description="When the next spike should ideally be emitted (dt permitting)"/>
+
+        <Dynamics>
+
+            <!-- This is mainly useful as an exposed variable to plot/save to see actual spike times... -->
+            <StateVariable name="tsince" dimension="time" exposure="tsince"/>
+            <!-- This is the ideal next spike time, but dt precision will mean that it's usually slightly later than this... -->
+            <StateVariable name="tnext" dimension="time" exposure="tnext"/>
+
+            <TimeDerivative variable="tsince" value="1"/>
+            <!-- Required to keep NEURON happy; needs tnext as 'real' state variable to use in condition below... -->
+            <TimeDerivative variable="tnext" value="0"/>
+
+            <OnStart>
+                <StateAssignment variable="tsince" value="0"/>
+                <StateAssignment variable="tnext" value="period"/>
+            </OnStart>
+
+            <!-- This is to require that the spike is emitted as close as possible to tnext.-->
+            <OnCondition test="tnext - t .lt. SMALL_TIME">
+                <StateAssignment variable="tsince" value="0"/>
+                <!-- Note the spike is emitted period after the last planned spike time, NOT period after the current spike time -->
+                <!-- This is important if period is close in size to to dt -->
+                <StateAssignment variable="tnext" value="tnext+period"/>
+                <EventOut port="spike"/>
+            </OnCondition>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="spikeGeneratorRandom" extends="baseSpikeSource"
+                   description="Generator of spikes with a random interspike interval of at least _minISI and at most _maxISI">
+
+        <Parameter name="maxISI" dimension="time" description="Maximum interspike interval"/>
+        <Parameter name="minISI" dimension="time" description="Minimum interspike interval"/>
+
+        <Constant name="MSEC" dimension="time" value="1ms" description="Required for converting time values to/from dimensionless quantities"/>
+
+        <Exposure name="isi" dimension="time" description="The interval until the next spike"/>
+        <Exposure name="tnext" dimension="time" description="When the next spike should ideally be emitted (dt permitting)"/>
+
+        <Dynamics>
+            <StateVariable name="tsince" dimension="time" exposure="tsince"/>
+            <StateVariable name="tnext" dimension="time" exposure="tnext"/>
+
+            <StateVariable name="isi" dimension="time" exposure="isi"/>
+
+            <TimeDerivative variable="tsince" value="1"/>
+            <!-- Required to keep Neuron happy; needs this as 'real' state variable to use in condition below... -->
+            <TimeDerivative variable="tnext" value="0"/>
+
+            <OnStart>
+                <StateAssignment variable="tsince" value="0"/>
+                <StateAssignment variable="isi" value="minISI + MSEC * random((maxISI - minISI) / MSEC)"/>
+                <StateAssignment variable="tnext" value="isi"/>
+            </OnStart>
+
+
+            <OnCondition test="t .gt. tnext">
+                <StateAssignment variable="isi" value="minISI + MSEC * random((maxISI - minISI) / MSEC)"/>
+                <StateAssignment variable="tsince" value="0"/>
+                <!-- Important to set this to the time which is isi from the last value for tnext NOT from the current time! -->
+                <StateAssignment variable="tnext" value="tnext+isi"/>
+                <EventOut port="spike"/>
+            </OnCondition>
+
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="spikeGeneratorPoisson" extends="baseSpikeSource"
+                   description="Generator of spikes whose ISI is distributed according to an exponential PDF with scale: 1 / _averageRate">
+
+        <Parameter name="averageRate" dimension="per_time" description="The average rate at which spikes are emitted"/>
+
+        <Constant name="SMALL_TIME" dimension="time" value="1e-9ms"/> <!-- See below for usage -->
+
+        <Exposure name="isi" dimension="time" description="The interval until the next spike"/> <!-- See below for usage -->
+        <Exposure name="tnextIdeal" dimension="time" description="This is the ideal/perfect next spike time, based on a newly generated isi, but dt precision will mean that it's usually slightly later than this"/> <!-- See below for usage -->
+        <Exposure name="tnextUsed" dimension="time" description="This is the next spike time for practical purposes, ensuring that it's later than the current time"/> <!-- See below for usage -->
+
+        <Dynamics>
+
+            <!-- This is mainly useful as an exposed variable to plot/save to see actual spike times... -->
+            <StateVariable name="tsince" dimension="time" exposure="tsince"/>
+
+            <!-- This is the ideal next spike time, but dt precision will mean that it's usually slightly later than this... -->
+            <StateVariable name="tnextIdeal" dimension="time" exposure="tnextIdeal"/>
+            <!-- This is the next spike time for practical purposes, ensuring that it's later than the current time... -->
+            <StateVariable name="tnextUsed" dimension="time" exposure="tnextUsed"/>
+            <!-- This is the calculated next interspike interval... -->
+            <StateVariable name="isi" dimension="time" exposure="isi"/>
+
+            <!-- So that tsince will increase each time step smoothly -->
+            <TimeDerivative variable="tsince" value="1"/>
+            <!-- Required to keep Neuron happy; needs these as 'real' state variables... -->
+            <TimeDerivative variable="tnextUsed" value="0"/>
+            <TimeDerivative variable="tnextIdeal" value="0"/>
+
+            <OnStart>
+                <StateAssignment variable="tsince" value="0"/>
+                <StateAssignment variable="isi" value="-1 * log(random(1)) / averageRate"/>
+                <StateAssignment variable="tnextIdeal" value="isi"/>
+                <StateAssignment variable="tnextUsed" value="isi"/>
+            </OnStart>
+
+            <OnCondition test="t .gt. tnextUsed">
+
+                <!-- Reset... -->
+                <StateAssignment variable="tsince" value="0"/>
+
+                <!-- isi is the ideal next time for a spike ... -->
+                <StateAssignment variable="isi" value="-1 * log(random(1)) / averageRate"/>
+
+                <!-- IF (tnextIdeal+isi) is greater than current time (i.e. (tnextIdeal+isi)-t > 0), then set (tnextIdeal+isi) to the time of the next spike (tnextUsed) -->
+                <!-- OTHERWISE in the case of v small isi (i.e. smaller than dt), set tnextUsed to current time plus a small amount -->
+                <!-- This extra amount is so that tnextUsed != current time, which NEURON doesn't like for its WATCH expressions -->
+
+                <StateAssignment variable="tnextIdeal" value="(tnextIdeal+isi)"/>
+                <StateAssignment variable="tnextUsed" value="tnextIdeal*H( (tnextIdeal-t)/t ) + (t+SMALL_TIME)*H( (t-tnextIdeal)/t )"/>
+
+                <EventOut port="spike"/>
+            </OnCondition>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="spikeGeneratorRefPoisson"
+                 extends="spikeGeneratorPoisson"
+                 description="Generator of spikes whose ISI distribution is the maximum entropy distribution over [ _minimumISI, +infinity ) with mean: 1 / _averageRate">
+
+        <Parameter name="minimumISI" dimension="time" description="The minimum interspike interval"/>
+
+        <DerivedParameter name="averageIsi" dimension="time" value="1 / averageRate" description="The average interspike interval"/>
+
+
+        <Dynamics>
+            <StateVariable name="tsince" dimension="time" exposure="tsince"/>
+            <StateVariable name="tnextIdeal" dimension="time" exposure="tnextIdeal"/>
+            <StateVariable name="tnextUsed" dimension="time" exposure="tnextUsed"/>
+            <StateVariable name="isi" dimension="time" exposure="isi"/>
+
+            <TimeDerivative variable="tsince" value="1"/>
+            <TimeDerivative variable="tnextUsed" value="0"/>
+            <TimeDerivative variable="tnextIdeal" value="0"/>
+
+            <OnStart>
+                <StateAssignment variable="tsince" value="0"/>
+                <StateAssignment variable="isi" value="minimumISI - (averageIsi-minimumISI) * log(random(1))"/>
+                <StateAssignment variable="tnextIdeal" value="isi"/>
+                <StateAssignment variable="tnextUsed" value="isi"/>
+            </OnStart>
+
+            <OnCondition test="t .gt. tnextUsed">
+                <StateAssignment variable="tsince" value="0"/>
+                <StateAssignment variable="isi" value="minimumISI - (averageIsi-minimumISI) * log(random(1))"/>
+
+                <StateAssignment variable="tnextIdeal" value="(tnextIdeal+isi)"/>
+                <StateAssignment variable="tnextUsed" value="tnextIdeal*H( (tnextIdeal-t)/t ) + (t+SMALL_TIME)*H( (t-tnextIdeal)/t )"/>
+
+                <EventOut port="spike"/>
+            </OnCondition>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="poissonFiringSynapse"
+                   description="Poisson spike generator firing at _averageRate, which is connected to single _synapse that is triggered every time a spike is generated, producing an input current. See also _transientPoissonFiringSynapse_."
+                   extends="baseVoltageDepPointCurrentSpiking">
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <Parameter name="averageRate" dimension="per_time" description="The average rate at which spikes are emitted"/>
+
+        <DerivedParameter name="averageIsi" dimension="time" value="1 / averageRate" description="The average interspike interval"/>
+
+        <Constant name="SMALL_TIME" dimension="time" value="1e-9ms"/> <!-- See below for usage -->
+
+        <ComponentReference name="synapse" type="baseSynapse"/>
+
+        <EventPort name="spike" direction="out" description="Port on which spikes are emitted"/>
+
+        <!--TODO: remove! Only required as EventConnection is used in explicitInput to
+        connect inputs to cells. Events aren't passed! ... -->
+        <EventPort name="in" direction="in" description="Note this is not used here. Will be removed in future"/>
+
+
+        <Exposure name="tsince" dimension="time" description="Time since the last spike was emitted"/>
+        <Exposure name="isi" dimension="time" description="The interval until the next spike"/> <!-- See below for usage -->
+        <Exposure name="tnextIdeal" dimension="time"/> <!-- See below for usage -->
+        <Exposure name="tnextUsed" dimension="time"/> <!-- See below for usage -->
+
+        <Path name="spikeTarget"  description="The target of the spikes, i.e. the synapse"/>
+
+        <Dynamics>
+            <StateVariable name="tsince" dimension="time" exposure="tsince"/>
+            <StateVariable name="tnextIdeal" dimension="time" exposure="tnextIdeal"/>
+            <StateVariable name="tnextUsed" dimension="time" exposure="tnextUsed"/>
+            <StateVariable name="isi" dimension="time" exposure="isi"/>
+
+            <DerivedVariable name="iSyn" dimension="current" select="synapse/i"/>
+            <DerivedVariable name="i" dimension="current" exposure="i" value="weight * iSyn"/>
+
+            <TimeDerivative variable="tsince" value="1"/>
+            <TimeDerivative variable="tnextUsed" value="0"/>
+            <TimeDerivative variable="tnextIdeal" value="0"/>
+
+            <OnStart>
+                <StateAssignment variable="tsince" value="0"/>
+                <StateAssignment variable="isi" value="- averageIsi * log(random(1))"/>
+                <StateAssignment variable="tnextIdeal" value="isi"/>
+                <StateAssignment variable="tnextUsed" value="isi"/>
+            </OnStart>
+
+            <OnCondition test="t .gt. tnextUsed">
+                   <StateAssignment variable="tsince" value="0"/>
+                   <StateAssignment variable="isi" value="- averageIsi * log(1 - random(1))"/>
+                <StateAssignment variable="tnextIdeal" value="(tnextIdeal+isi)"/>
+                <StateAssignment variable="tnextUsed" value="tnextIdeal*H( (tnextIdeal-t)/t ) + (t+SMALL_TIME)*H( (t-tnextIdeal)/t )"/>
+                   <EventOut port="spike"/>
+              </OnCondition>
+
+        </Dynamics>
+        <Structure>
+            <ChildInstance component="synapse"/>
+
+            <With instance="this" as="a"/>
+            <With instance="spikeTarget" as="b"/>
+
+            <EventConnection from="a" to="b"/>
+        </Structure>
+
+    </ComponentType>
+
+
+    <ComponentType name="transientPoissonFiringSynapse"
+                   description="Poisson spike generator firing at _averageRate after a _delay and for a _duration, connected to single _synapse that is triggered every time a spike is generated, providing an input current.
+                      Similar to ComponentType _poissonFiringSynapse_."
+                   extends="baseVoltageDepPointCurrentSpiking">
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <Parameter name="averageRate" dimension="per_time"/>
+
+        <Parameter name="delay" dimension="time"/>
+        <Parameter name="duration" dimension="time" />
+
+        <DerivedParameter name="averageIsi" dimension="time" value="1 / averageRate"/>
+
+        <Constant name="SMALL_TIME" dimension="time" value="1e-9ms"/> <!-- See below for usage -->
+        <Constant name="LONG_TIME" dimension="time" value="1e9hour"/>
+
+        <ComponentReference name="synapse" type="baseSynapse"/>
+
+        <EventPort name="spike" direction="out" description="Port on which spikes are emitted"/>
+
+        <!--TODO: remove! Only required as EventConnection is used in explicitInput to
+        connect inputs to cells. Events aren't passed! ... -->
+        <EventPort name="in" direction="in" description="Note this is not used here. Will be removed in future"/>
+
+        <Exposure name="tsince" dimension="time" description="Time since the last spike was emitted"/>
+        <Exposure name="isi" dimension="time"/> <!-- See below for usage -->
+        <Exposure name="tnextIdeal" dimension="time"/> <!-- See below for usage -->
+        <Exposure name="tnextUsed" dimension="time"/> <!-- See below for usage -->
+
+        <Path name="spikeTarget"/>
+
+        <Dynamics>
+            <StateVariable name="tsince" dimension="time" exposure="tsince"/>
+            <StateVariable name="tnextIdeal" dimension="time" exposure="tnextIdeal"/>
+            <StateVariable name="tnextUsed" dimension="time" exposure="tnextUsed"/>
+            <StateVariable name="isi" dimension="time" exposure="isi"/>
+
+            <DerivedVariable name="iSyn" dimension="current" select="synapse/i"/>
+            <DerivedVariable name="i" dimension="current" exposure="i" value="weight * iSyn"/>
+
+            <TimeDerivative variable="tsince" value="1"/>
+            <TimeDerivative variable="tnextUsed" value="0"/>
+            <TimeDerivative variable="tnextIdeal" value="0"/>
+
+            <OnStart>
+                <StateAssignment variable="tsince" value="0"/>
+                <StateAssignment variable="isi" value="- averageIsi * log(1 - random(1))  +delay"/>
+                <StateAssignment variable="tnextIdeal" value="isi"/>
+                <StateAssignment variable="tnextUsed" value="isi"/>
+            </OnStart>
+
+
+
+            <OnCondition test="t .gt. tnextUsed">
+                <StateAssignment variable="tsince" value="0"/>
+                <StateAssignment variable="isi" value="- averageIsi * log(1 - random(1))"/>
+                <!--
+                Check to see whether current time + next ISI is greater than delay+duration and if so set it to a long time in the future...
+                The use of H() is necessary here (as opposed to checking this in the test of OnCondition) since NEURON requires a single boolean expression in test above
+                -->
+                <StateAssignment variable="tnextIdeal" value="(tnextIdeal+isi) + H(((t+isi) - (delay+duration))/duration)*LONG_TIME"/>
+                <StateAssignment variable="tnextUsed" value="tnextIdeal*H( (tnextIdeal-t)/t ) + (t+SMALL_TIME)*H( (t-tnextIdeal)/t )"/>
+                <EventOut port="spike"/>
+            </OnCondition>
+
+        </Dynamics>
+        <Structure>
+            <ChildInstance component="synapse"/>
+
+            <With instance="this" as="a"/>
+            <With instance="spikeTarget" as="b"/>
+
+            <EventConnection from="a" to="b"/>
+        </Structure>
+
+    </ComponentType>
+
+
+    <ComponentType name="timedSynapticInput"
+                   description="Spike array connected to a single _synapse, producing a current triggered by each _spike_ in the array."
+                   extends="baseVoltageDepPointCurrentSpiking">
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <Children name="spikes" type="spike"/>
+
+        <ComponentReference name="synapse" type="baseSynapse"/>
+
+        <EventPort name="in" direction="in" description="This will receive events from the children"/>
+
+        <Exposure name="tsince" dimension="time" description="Time since the last spike was emitted"/>
+
+        <Path name="spikeTarget"/>
+
+        <Dynamics>
+            <StateVariable name="tsince" dimension="time" exposure="tsince"/>
+
+            <DerivedVariable name="iSyn" dimension="current" select="synapse/i"/>
+            <DerivedVariable name="i" dimension="current" exposure="i" value="weight * iSyn"/>
+
+            <TimeDerivative variable="tsince" value="1"/>
+            <OnEvent port="in">
+                <StateAssignment variable="tsince" value="0"/>
+                <EventOut port="spike"/>
+            </OnEvent>
+
+        </Dynamics>
+
+        <Structure>
+            <ChildInstance component="synapse"/>
+
+            <With instance="this" as="a"/>
+            <With instance="spikeTarget" as="b"/>
+
+            <EventConnection from="a" to="b"/>
+        </Structure>
+
+    </ComponentType>
+
+    <ComponentType name="spikeArray" extends="baseSpikeSource"
+                   description="Set of spike ComponentTypes, each emitting one spike at a certain time. Can be used to feed a predetermined spike train into a cell">
+
+        <Children name="spikes" type="spike"/>
+        <EventPort name="in" direction="in" description="This will receive events from the children"/>
+
+        <Dynamics>
+            <StateVariable name="tsince" dimension="time" exposure="tsince"/>
+
+            <TimeDerivative variable="tsince" value="1"/>
+
+            <OnStart>
+                <StateAssignment variable="tsince" value="0"/>
+            </OnStart>
+
+            <OnEvent port="in">
+                <StateAssignment variable="tsince" value="0"/>
+                <EventOut port="spike"/>
+            </OnEvent>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="spike" extends="baseSpikeSource"
+                   description="Emits a single spike at the specified _time">
+
+        <Parameter name="time" dimension="time" description="Time at which to emit one spike event"/>
+        <Exposure name="spiked" dimension="none" description="0 signals not yet spiked, 1 signals has spiked"/>
+
+        <Dynamics>
+
+            <StateVariable name="tsince" dimension="time" exposure="tsince"/>
+            <StateVariable name="spiked" dimension="none" exposure="spiked"/>
+
+            <TimeDerivative variable="tsince" value="1"/>
+
+            <OnStart>
+                <StateAssignment variable="tsince" value="0"/>
+            </OnStart>
+
+            <OnCondition test="(t .geq. time) .and. (spiked .eq. 0)">
+                <StateAssignment variable="spiked" value="1"/>
+                <StateAssignment variable="tsince" value="0"/>
+                <EventOut port="spike"/>
+            </OnCondition>
+        </Dynamics>
+
+        <Structure>
+            <With instance="this" as="a"/>
+            <With instance="parent" as="b"/>
+            <EventConnection from="a" to="b"/>
+        </Structure>
+
+    </ComponentType>
+
+
+    <ComponentType name="pulseGenerator" extends="basePointCurrent"
+                   description="Generates a constant current pulse of a certain _amplitude for a specified _duration after a _delay. Scaled by _weight, if set"> <!-- Note: a synpase also extends basePointCurrent -->
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <Parameter name="delay" dimension="time" description="Delay before change in current. Current is zero  prior to this."/>
+        <Parameter name="duration" dimension="time" description="Duration for holding current at amplitude. Current is zero after delay + duration."/>
+        <Parameter name="amplitude" dimension="current" description="Amplitude of current pulse"/>
+
+        <!--TODO: remove! Only required as EventConnection is used in explicitInput to
+        connect inputs to cells. Events aren't passed! ... -->
+        <EventPort name="in" direction="in" description="Note: this is not used here. Will be removed in future"/>
+
+        <Dynamics>
+
+            <StateVariable name="i" exposure="i" dimension="current"/>
+
+            <OnEvent port="in"><!--TODO: remove, see above...
+            <StateAssignment variable="i" value="0"/>-->
+            </OnEvent>
+
+            <OnCondition test="t .lt. delay">
+                <StateAssignment variable="i" value="0"/>
+            </OnCondition>
+
+            <OnCondition test="t .geq. delay .and. t .lt. duration + delay">
+                <StateAssignment variable="i" value="weight * amplitude"/>
+            </OnCondition>
+
+            <OnCondition test="t .geq. duration + delay">
+                <StateAssignment variable="i" value="0"/>
+            </OnCondition>
+
+        </Dynamics>
+    </ComponentType>
+
+
+
+    <ComponentType name="compoundInput" extends="basePointCurrent"
+                   description="Generates a current which is the sum of all its child _basePointCurrent_ element, e.g. can be a combination of _pulseGenerator_, _sineGenerator_ elements producing a single _i. Scaled by _weight, if set">
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <Children name="currents" type="basePointCurrent"/>
+
+        <!--TODO: remove! Only required as EventConnection is used in explicitInput to
+        connect inputs to cells. Events aren't passed! ... -->
+        <EventPort name="in" direction="in" description="Note this is not used here. Will be removed in future"/>
+
+        <Dynamics>
+
+            <DerivedVariable name="i_total" dimension="current" select="currents[*]/i" reduce="add"/>
+
+            <DerivedVariable name="i" dimension="current" exposure="i" value="weight * i_total"/>
+
+            <OnEvent port="in"><!--TODO: remove, see above... -->
+            </OnEvent>
+
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="compoundInputDL" extends="basePointCurrentDL"
+                   description="Generates a current which is the sum of all its child _basePointCurrentDL_ elements, e.g. can be a combination of _pulseGeneratorDL_, _sineGeneratorDL_ elements producing a single _i. Scaled by _weight, if set">
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <Children name="currents" type="basePointCurrentDL"/>
+
+        <!--TODO: remove! Only required as EventConnection is used in explicitInput to
+        connect inputs to cells. Events aren't passed! ... -->
+        <EventPort name="in" direction="in" description="Note this is not used here. Will be removed in future"/>
+
+        <Dynamics>
+
+            <DerivedVariable name="I_total" dimension="none" select="currents[*]/I" reduce="add"/>
+
+            <DerivedVariable name="I" dimension="none" exposure="I" value="weight * I_total"/>
+
+            <OnEvent port="in"><!--TODO: remove, see above... -->
+            </OnEvent>
+
+
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="pulseGeneratorDL" extends="basePointCurrentDL"
+                   description="Dimensionless equivalent of _pulseGenerator_. Generates a constant current pulse of a certain _amplitude for a specified _duration after a _delay. Scaled by _weight, if set"> <!-- Note: a synpase also extends basePointCurrent -->
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <Parameter name="delay" dimension="time" description="Delay before change in current. Current is zero  prior to this."/>
+        <Parameter name="duration" dimension="time" description="Duration for holding current at amplitude. Current is zero after delay + duration."/>
+        <Parameter name="amplitude" dimension="none" description="Amplitude of current pulse"/>
+
+        <!--TODO: remove! Only required as EventConnection is used in explicitInput to
+        connect inputs to cells. Events aren't passed! ... -->
+        <EventPort name="in" direction="in" description="Note this is not used here. Will be removed in future"/>
+
+        <Dynamics>
+
+            <StateVariable name="I" exposure="I" dimension="none"/>
+
+            <OnEvent port="in"><!--TODO: remove, see above...-->
+            </OnEvent>
+
+            <OnCondition test="t .lt. delay">
+                <StateAssignment variable="I" value="0"/>
+            </OnCondition>
+
+            <OnCondition test="t .geq. delay .and. t .lt. duration + delay">
+                <StateAssignment variable="I" value="weight * amplitude"/>
+            </OnCondition>
+
+            <OnCondition test="t .geq. duration + delay">
+                <StateAssignment variable="I" value="0"/>
+            </OnCondition>
+
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="sineGenerator" extends="basePointCurrent"
+                   description="Generates a sinusoidally varying current after a time _delay, for a fixed _duration. The _period and maximum _amplitude of the current can be set as well as the _phase at which to start. Scaled by _weight, if set">
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <Parameter name="phase" dimension="none" description="Phase (between 0 and 2*pi) at which to start the varying current (i.e. at time given by delay)"/>
+        <Parameter name="delay" dimension="time" description="Delay before change in current. Current is zero  prior to this."/>
+        <Parameter name="duration" dimension="time" description="Duration for holding current at amplitude. Current is zero after delay + duration."/>
+        <Parameter name="amplitude" dimension="current" description="Maximum amplitude of current"/>
+        <Parameter name="period" dimension="time" description="Time period of oscillation"/>
+
+        <EventPort name="in" direction="in"/>
+
+        <Dynamics>
+
+            <StateVariable name="i" exposure="i" dimension="current"/>
+
+            <OnEvent port="in"><!--TODO: remove-->
+            </OnEvent>
+
+            <OnCondition test="t .lt. delay">
+                <StateAssignment variable="i" value="0"/>
+            </OnCondition>
+
+            <OnCondition test="t .geq. delay .and. t .lt. duration+delay">
+                <StateAssignment variable="i" value="weight * amplitude * sin(phase + (2 * 3.14159265 * (t-delay)/period) )"/>
+            </OnCondition>
+
+            <OnCondition test="t .geq. duration+delay">
+                <StateAssignment variable="i" value="0"/>
+            </OnCondition>
+
+        </Dynamics>
+    </ComponentType>
+
+    <ComponentType name="sineGeneratorDL" extends="basePointCurrentDL"
+                   description="Dimensionless equivalent of _sineGenerator_. Generates a sinusoidally varying current after a time _delay, for a fixed _duration. The _period and maximum _amplitude of the current can be set as well as the _phase at which to start. Scaled by _weight, if set">
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <Parameter name="phase" dimension="none" description="Phase (between 0 and 2*pi) at which to start the varying current (i.e. at time given by delay)"/>
+        <Parameter name="delay" dimension="time" description="Delay before change in current. Current is zero  prior to this."/>
+        <Parameter name="duration" dimension="time" description="Duration for holding current at amplitude. Current is zero after delay + duration."/>
+        <Parameter name="amplitude" dimension="none" description="Maximum amplitude of current"/>
+        <Parameter name="period" dimension="time" description="Time period of oscillation"/>
+
+        <EventPort name="in" direction="in"/>
+
+        <Dynamics>
+
+            <StateVariable name="I" exposure="I" dimension="none"/>
+
+            <OnEvent port="in"><!--TODO: remove-->
+            </OnEvent>
+
+            <OnCondition test="t .lt. delay">
+                <StateAssignment variable="I" value="0"/>
+            </OnCondition>
+
+            <OnCondition test="t .geq. delay .and. t .lt. duration+delay">
+                <StateAssignment variable="I" value="weight * amplitude * sin(phase + (2 * 3.14159265 * (t-delay)/period) )"/>
+            </OnCondition>
+
+            <OnCondition test="t .geq. duration+delay">
+                <StateAssignment variable="I" value="0"/>
+            </OnCondition>
+
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="rampGenerator" extends="basePointCurrent"
+                   description="Generates a ramping current after a time _delay, for a fixed _duration. During this time the current steadily changes from _startAmplitude to _finishAmplitude. Scaled by _weight, if set">
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <Parameter name="delay" dimension="time" description="Delay before change in current. Current is baselineAmplitude prior to this."/>
+        <Parameter name="duration" dimension="time" description="Duration for holding current at amplitude. Current is baselineAmplitude after delay + duration."/>
+        <Parameter name="startAmplitude" dimension="current" description="Amplitude of linearly varying current at time delay"/>
+        <Parameter name="finishAmplitude" dimension="current" description="Amplitude of linearly varying current at time delay + duration"/>
+        <Parameter name="baselineAmplitude" dimension="current" description="Amplitude of current before time delay, and after time delay + duration"/>
+
+        <EventPort name="in" direction="in"/>
+
+        <Dynamics>
+
+            <StateVariable name="i" exposure="i" dimension="current"/>
+
+            <OnStart>
+                <StateAssignment variable="i" value="baselineAmplitude"/>
+            </OnStart>
+
+            <OnEvent port="in"><!--TODO: remove-->
+            </OnEvent>
+
+
+            <OnCondition test="t .lt. delay">
+                <StateAssignment variable="i" value="weight * baselineAmplitude"/>
+            </OnCondition>
+
+            <OnCondition test="t .geq. delay .and. t .lt. duration+delay">
+                <StateAssignment variable="i" value="weight * (startAmplitude + (finishAmplitude - startAmplitude) * (t - delay) / (duration))"/>
+            </OnCondition>
+
+            <OnCondition test="t .geq. duration+delay">
+                <StateAssignment variable="i" value="weight * baselineAmplitude"/>
+            </OnCondition>
+
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="rampGeneratorDL" extends="basePointCurrentDL"
+                   description="Dimensionless equivalent of _rampGenerator_. Generates a ramping current after a time _delay, for a fixed _duration. During this time the dimensionless current steadily changes from _startAmplitude to _finishAmplitude. Scaled by _weight, if set">
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <Parameter name="delay" dimension="time" description="Delay before change in current. Current is baselineAmplitude prior to this."/>
+        <Parameter name="duration" dimension="time" description="Duration for holding current at amplitude. Current is baselineAmplitude after delay + duration."/>
+        <Parameter name="startAmplitude" dimension="none" description="Amplitude of linearly varying current at time delay"/>
+        <Parameter name="finishAmplitude" dimension="none" description="Amplitude of linearly varying current at time delay + duration"/>
+        <Parameter name="baselineAmplitude" dimension="none" description="Amplitude of current before time delay, and after time delay + duration"/>
+
+        <EventPort name="in" direction="in"/>
+
+        <Dynamics>
+
+            <StateVariable name="I" exposure="I" dimension="none"/>
+
+            <OnStart>
+                <StateAssignment variable="I" value="baselineAmplitude"/>
+            </OnStart>
+
+            <OnEvent port="in"><!--TODO: remove-->
+            </OnEvent>
+
+            <OnCondition test="t .lt. delay">
+                <StateAssignment variable="I" value="weight * baselineAmplitude"/>
+            </OnCondition>
+
+            <OnCondition test="t .geq. delay .and. t .lt. duration+delay">
+                <StateAssignment variable="I" value="weight * (startAmplitude + (finishAmplitude - startAmplitude) * (t - delay) / (duration))"/>
+            </OnCondition>
+
+            <OnCondition test="t .geq. duration+delay">
+                <StateAssignment variable="I" value="weight * baselineAmplitude"/>
+            </OnCondition>
+
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="voltageClamp" extends="baseVoltageDepPointCurrent"
+                   description="Voltage clamp. Applies a variable current _i to try to keep parent at _targetVoltage. Not yet fully tested!!! Consider using voltageClampTriple!!">
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <Parameter name="delay" dimension="time" description="Delay before change in current. Current is zero prior to this."/>
+        <Parameter name="duration" dimension="time" description="Duration for attempting to keep parent at targetVoltage. Current is zero after delay + duration."/>
+        <Parameter name="targetVoltage" dimension="voltage" description="Current will be applied to try to get parent to this target voltage"/>
+
+        <!-- seriesResistance renamed to simpleSeriesResistance & factor of 1e-5 removed from calculation of current. Still being tested... -->
+        <Parameter name="simpleSeriesResistance" dimension="resistance" description="Current will be calculated by the difference in voltage between the target and parent, divided by this value"/>
+
+        <!--TODO: remove! Only required as EventConnection is used in explicitInput to
+        connect inputs to cells. Events aren't passed! ... -->
+        <EventPort name="in" direction="in" description="Note this is not used here. Will be removed in future"/>
+
+        <Dynamics>
+
+            <StateVariable name="i" exposure="i" dimension="current"/>
+
+            <OnEvent port="in"><!--TODO: remove, see above...
+            <StateAssignment variable="i" value="0"/>-->
+            </OnEvent>
+
+            <OnCondition test="t .lt. delay">
+                <StateAssignment variable="i" value="0"/>
+            </OnCondition>
+
+            <OnCondition test="t .geq. delay">
+                <!-- seriesResistance renamed to simpleSeriesResistance & factor of 1e-5 removed from calculation of current. Still being tested... -->
+                <StateAssignment variable="i" value="weight * (targetVoltage - v) / simpleSeriesResistance"/>
+            </OnCondition>
+
+            <OnCondition test="t .gt. duration + delay">
+                <StateAssignment variable="i" value="0"/>
+            </OnCondition>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+
+    <ComponentType name="voltageClampTriple" extends="baseVoltageDepPointCurrent"
+                   description="Voltage clamp with 3 clamp levels. Applies a variable current _i (through _simpleSeriesResistance) to try to keep parent cell at _conditioningVoltage until time _delay, _testingVoltage until _delay + _duration, and _returnVoltage afterwards. Only enabled if _active = 1. ">
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <Parameter name="active" dimension="none" description="Whether the voltage clamp is active (1) or inactive (0)."/>
+
+        <Parameter name="delay" dimension="time" description="Delay before switching from conditioningVoltage to testingVoltage."/>
+        <Parameter name="duration" dimension="time" description="Duration to hold at testingVoltage."/>
+        <Parameter name="conditioningVoltage" dimension="voltage" description="Target voltage before time delay"/>
+        <Parameter name="testingVoltage" dimension="voltage" description="Target voltage between times delay and delay + duration"/>
+        <Parameter name="returnVoltage" dimension="voltage" description="Target voltage after time duration"/>
+
+        <Parameter name="simpleSeriesResistance" dimension="resistance" description="Current will be calculated by the difference in voltage between the target and parent, divided by this value"/>
+
+        <!--TODO: remove! Only required as EventConnection is used in explicitInput to
+        connect inputs to cells. Events aren't passed! ... -->
+        <EventPort name="in" direction="in" description="Note this is not used here. Will be removed in future"/>
+
+        <Dynamics>
+
+            <StateVariable name="i" exposure="i" dimension="current"/>
+
+            <OnEvent port="in"><!--TODO: remove, see above...
+            <StateAssignment variable="i" value="0"/>-->
+            </OnEvent>
+
+            <OnCondition test="active .eq. 1 .and. t .lt. delay">
+                <StateAssignment variable="i" value="weight * (conditioningVoltage - v) / simpleSeriesResistance"/>
+            </OnCondition>
+
+            <OnCondition test="active .eq. 1 .and. t .geq. delay">
+                <StateAssignment variable="i" value="weight * (testingVoltage - v) / simpleSeriesResistance"/>
+            </OnCondition>
+
+            <OnCondition test="active .eq. 1 .and. t .gt. duration + delay">
+                <StateAssignment variable="i" value="weight * (returnVoltage - v) / simpleSeriesResistance"/>
+            </OnCondition>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+</Lems>
diff --git a/lems/test/NeuroML2CoreTypes/Networks.xml b/lems/test/NeuroML2CoreTypes/Networks.xml
new file mode 100644
index 0000000..f511262
--- /dev/null
+++ b/lems/test/NeuroML2CoreTypes/Networks.xml
@@ -0,0 +1,443 @@
+<Lems xmlns="http://www.neuroml.org/lems/0.7.5"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.neuroml.org/lems/0.7.5 ../../LEMS/Schemas/LEMS/LEMS_v0.7.5.xsd"
+      description="Network descriptions in NeuroML 2. Describes _network_ elements containing _population_s ">
+
+    <!-- A number of network elements for use in NeuroML 2 documents  -->
+
+    <Include file="NeuroMLCoreDimensions.xml"/>
+    <Include file="Synapses.xml"/>
+
+
+    <ComponentType name="network"
+                   description="Network containing _population_s, _projection_s and lists of _explicitConnection_s (either directly between components of the populations or via synapses)"
+                   extends="baseStandalone">
+
+        <Children name="regions" type="region"/>
+        <Children name="populations" type="basePopulation"/>
+
+        <Children name="projections" type="projection"/>
+        <Children name="synapticConnections" type="explicitConnection"/>  <!-- Connection either directly between cells or to synapse attachment on post cell-->
+
+        <Children name="electricalProjection" type="electricalProjection"/>
+        <Children name="continuousProjection" type="continuousProjection"/>
+
+        <Children name="explicitInputs" type="explicitInput"/>
+        <Children name="inputs" type="inputList"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="networkWithTemperature" description="Network containing _population_s, _projection_s and lists of _explicitConnection_s (either directly between components of the populations or via synapses), and an explicit temperature" extends="network">
+
+        <Parameter name="temperature" dimension="temperature"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="basePopulation"
+                   description="A population of cells (anything which extends _baseCell_)"
+                   extends="baseStandalone">
+
+        <Child name="notes" type="notes"/>
+        <Child name="annotation" type="annotation"/>
+        <Children name="property" type="property"/>
+
+        <ComponentReference name="component" type="baseCell"/>
+    </ComponentType>
+
+
+    <ComponentType name="population" extends="basePopulation" description="A population of components, with just one parameter for the _size">
+        <Parameter name="size" dimension="none" description="Number of instances of this Component to create when the population is instantiated"/>
+        <Structure>
+            <MultiInstantiate number="size" component="component"/>
+        </Structure>
+    </ComponentType>
+
+
+    <ComponentType name="populationList" extends="basePopulation" description="An explicit list of the cells in the population. ">
+        <Children name="instances" type="instance"/>
+
+        <Text name="size"/> <!--Note: Text, not Parameter, as this is not actually used by LEMS, the <instance> elements determine the size, this attribute is really just metadata, though the two should be consistent-->
+    </ComponentType>
+
+
+    <ComponentType name="instance" description="Specifies a single instance of a component in a population (placed at _location_).">
+        <Child name="location" type="location"/>
+        <Structure>
+            <ChildInstance component="../component"/>
+        </Structure>
+
+    </ComponentType>
+
+
+    <ComponentType name="location" description="Specifies location of a single _instance_ of a component in a population">
+        <Parameter name="x" dimension="none"/>
+        <Parameter name="y" dimension="none"/>
+        <Parameter name="z" dimension="none"/>
+    </ComponentType>
+
+
+    <ComponentType name="region" description="Initial attempt to specify 3D region for placing cells. Work in progress...">
+        <Child name="rectangularExtent" type="rectangularExtent"/>
+    </ComponentType>
+
+
+    <ComponentType name="rectangularExtent" description="For defining a 3D rectangular box">
+        <Parameter name="xStart" dimension="none"/>
+        <Parameter name="yStart" dimension="none"/>
+        <Parameter name="zStart" dimension="none"/>
+        <Parameter name="xLength" dimension="none"/>
+        <Parameter name="yLength" dimension="none"/>
+        <Parameter name="zLength" dimension="none"/>
+    </ComponentType>
+
+
+    <ComponentType name="projection"
+        description="Projection from one population, _presynapticPopulation to another, _postsynapticPopulation, through _synapse. Contains lists of _connection_ or _connectionWD_ elements.">
+
+        <Children name="connections" type="connection"/>
+        <Children name="connectionsWD" type="connectionWD"/>
+        <ComponentReference name="synapse" type="baseSynapse"/>
+        <Path name="presynapticPopulation"/>
+        <Path name="postsynapticPopulation"/>
+    </ComponentType>
+
+
+    <ComponentType name="explicitConnection"
+        description="Explicit event connection between components">
+        <Path name="from"/>
+        <Path name="to"/>
+        <Text name="targetPort"/>
+    </ComponentType>
+
+    <ComponentType name="connection"
+        description="Event connection directly between named components, which gets processed via a new instance of a _synapse component which is created on the target component. Normally contained inside a _projection_ element.">
+
+        <Path name="preCellId"/>
+        <Path name="postCellId"/>
+        <Text name="destination"/>
+        <Text name="preFractionAlong"/>
+        <Text name="postFractionAlong"/>
+        <Text name="preSegmentId"/>
+        <Text name="postSegmentId"/>
+
+        <Structure>
+            <With instance="preCellId" as="a"/>
+            <With instance="postCellId" as="b"/>
+            <EventConnection from="a" to="b" receiver="../synapse" receiverContainer="destination" sourcePort="sourcePort" targetPort="targetPort"/>
+        </Structure>
+
+    </ComponentType>
+
+
+    <ComponentType name="synapticConnection"
+        description="Explicit event connection between named components, which gets processed via a new instance of a _synapse component which is created on the target component"
+        extends="explicitConnection">
+
+        <ComponentReference name="synapse" type="baseSynapse"/>
+        <Path name="from"/>
+        <Path name="to"/>
+        <Text name="destination"/>
+
+        <Structure>
+            <With instance="from" as="a"/>
+            <With instance="to" as="b"/>
+            <EventConnection from="a" to="b" receiver="synapse" receiverContainer="destination" sourcePort="sourcePort" targetPort="targetPort"/>
+        </Structure>
+    </ComponentType>
+
+
+    <ComponentType name="synapticConnectionWD"
+                   description="Explicit event connection between named components, which gets processed via a new instance of a _synapse component which is created on the target component, includes setting of _weight and _delay for the synaptic connection"
+                   extends="synapticConnection">
+
+        <Parameter name="weight" dimension="none"/>
+        <Parameter name="delay" dimension="time"/>
+
+        <Path name="from"/> <!-- Ideally this should be taken from extended comp type -->
+        <Path name="to"/>   <!-- Ideally this should be taken from extended comp type -->
+
+        <Structure>
+            <With instance="from" as="a"/>
+            <With instance="to" as="b"/>
+            <EventConnection from="a" to="b" receiver="synapse" delay="delay">
+                <Assign property="weight" value="weight"/>
+            </EventConnection>
+        </Structure>
+
+    </ComponentType>
+
+    <ComponentType name="connectionWD"
+                   description="Event connection between named components, which gets processed via a new instance of a synapse component which is created on the target component, includes setting of _weight and _delay for the synaptic connection"
+                   extends="connection">
+
+        <Parameter name="weight" dimension="none"/>
+        <Parameter name="delay" dimension="time"/>
+        <Path name="preCellId"/>
+        <Path name="postCellId"/>
+        <Text name="destination"/>
+        <Text name="preFractionAlong"/>
+        <Text name="postFractionAlong"/>
+        <Text name="preSegmentId"/>
+        <Text name="postSegmentId"/>
+
+        <Structure>
+            <With instance="preCellId" as="a"/>
+            <With instance="postCellId" as="b"/>
+            <EventConnection from="a" to="b" receiver="../synapse" delay="delay">
+                <Assign property="weight" value="weight"/>
+            </EventConnection>
+        </Structure>
+
+    </ComponentType>
+
+
+    <ComponentType name="electricalConnection"
+                   description="To enable connections between populations through gap junctions.">
+
+        <IndexParameter name="preCell"/>
+        <IndexParameter name="postCell"/>
+
+        <ComponentReference name="synapse" type="gapJunction"/>
+
+        <ComponentRequirement name="presynapticPopulation"/>
+        <ComponentRequirement name="postsynapticPopulation"/>
+
+        <Structure>
+            <With list="presynapticPopulation" index="preCell" as="a"/>
+            <With list="postsynapticPopulation" index="postCell" as="b"/>
+            <Tunnel name="peer" endA="a" endB="b" componentA="synapse" componentB="synapse"/>
+        </Structure>
+
+    </ComponentType>
+
+    <ComponentType name="electricalConnectionInstance"
+                   description="To enable connections between populations through gap junctions. Populations need to be of type _populationList_ and contain _instance_ and _location_ elements.">
+
+        <ComponentReference name="synapse" type="gapJunction"/>
+
+        <Path name="preCell"/>
+        <Path name="postCell"/>
+
+        <Text name="preFractionAlong"/>
+        <Text name="postFractionAlong"/>
+        <Text name="preSegment"/>
+        <Text name="postSegment"/>
+
+        <Structure>
+            <With instance="preCell" as="a"/>
+            <With instance="postCell" as="b"/>
+            <Tunnel name="peer" endA="a" endB="b" componentA="synapse" componentB="synapse"/>
+        </Structure>
+
+    </ComponentType>
+
+
+    <ComponentType name="electricalConnectionInstanceW"
+                   description="To enable connections between populations through gap junctions. Populations need to be of type _populationList_ and contain _instance_ and _location_ elements. Includes setting of _weight for the connection"
+                   extends="electricalConnectionInstance">
+
+        <Parameter name="weight" dimension="none"/>
+
+        <!-- Ideally these should be inherited from the extended CT, but jLEMS
+        complains about this... adding them here for a quieter life... -->
+        <Path name="preCell"/>
+        <Path name="postCell"/>
+        <Text name="preFractionAlong"/>
+        <Text name="postFractionAlong"/>
+        <Text name="preSegment"/>
+        <Text name="postSegment"/>
+
+        <Structure>
+            <With instance="preCell" as="a"/>
+            <With instance="postCell" as="b"/>
+            <Tunnel name="peer" endA="a" endB="b" componentA="synapse" componentB="synapse">
+                <Assign property="weight" value="weight"/>
+            </Tunnel>
+        </Structure>
+
+    </ComponentType>
+
+
+    <ComponentType name="electricalProjection"
+                   description="A projection between _presynapticPopulation to another _postsynapticPopulation through gap junctions.">
+        <Children name="connections" type="electricalConnection"/>
+        <Children name="connectionInstances" type="electricalConnectionInstance"/>
+        <ComponentReference name="presynapticPopulation" type="population" local="true"/>
+        <ComponentReference name="postsynapticPopulation" type="population" local="true"/>
+    </ComponentType>
+
+
+    <ComponentType name="continuousConnection"
+                   description="An instance of a connection in a _continuousProjection_ between _presynapticPopulation to another _postsynapticPopulation through a _preComponent at the start and _postComponent at the end. Can be used for analog synapses.">
+
+        <IndexParameter name="preCell"/>
+        <IndexParameter name="postCell"/>
+
+        <ComponentReference name="preComponent" type="baseGradedSynapse"/>
+        <ComponentReference name="postComponent" type="baseGradedSynapse"/>
+
+        <ComponentRequirement name="presynapticPopulation"/>
+        <ComponentRequirement name="postsynapticPopulation"/>
+
+        <Structure>
+            <With list="presynapticPopulation" index="preCell" as="a"/>
+            <With list="postsynapticPopulation" index="postCell" as="b"/>
+            <Tunnel name="peer" endA="a" endB="b" componentA="preComponent" componentB="postComponent"/>
+        </Structure>
+
+    </ComponentType>
+
+    <ComponentType name="continuousConnectionInstance"
+                   description="An instance of a connection in a _continuousProjection_ between _presynapticPopulation to another _postsynapticPopulation through a _preComponent at the start and _postComponent at the end. Populations need to be of type _populationList_ and contain _instance_ and _location_ elements. Can be used for analog synapses.">
+
+        <ComponentReference name="preComponent" type="baseGradedSynapse"/>
+        <ComponentReference name="postComponent" type="baseGradedSynapse"/>
+
+        <Path name="preCell"/>
+        <Path name="postCell"/>
+
+        <Text name="preFractionAlong"/>
+        <Text name="postFractionAlong"/>
+        <Text name="preSegment"/>
+        <Text name="postSegment"/>
+
+        <Structure>
+            <With instance="preCell" as="a"/>
+            <With instance="postCell" as="b"/>
+            <Tunnel name="peer" endA="a" endB="b" componentA="preComponent" componentB="postComponent"/>
+        </Structure>
+
+    </ComponentType>
+
+    <ComponentType name="continuousConnectionInstanceW"
+
+
+                   description="An instance of a connection in a _continuousProjection_ between _presynapticPopulation to another _postsynapticPopulation through a _preComponent at the start and _postComponent at the end. Populations need to be of type _populationList_ and contain _instance_ and _location_ elements. Can be used for analog synapses. Includes setting of _weight for the connection"
+                   extends="continuousConnectionInstance">
+
+        <Parameter name="weight" dimension="none"/>
+
+        <!-- Ideally these should be inherited from the extended CT, but jLEMS
+        complains about this... adding them here for a quieter life... -->
+        <Path name="preCell"/>
+        <Path name="postCell"/>
+        <Text name="preFractionAlong"/>
+        <Text name="postFractionAlong"/>
+        <Text name="preSegment"/>
+        <Text name="postSegment"/>
+
+        <Structure>
+            <With instance="preCell" as="a"/>
+            <With instance="postCell" as="b"/>
+            <Tunnel name="peer" endA="a" endB="b" componentA="preComponent" componentB="postComponent">
+                <Assign property="weight" value="weight"/>
+            </Tunnel>
+        </Structure>
+
+    </ComponentType>
+
+
+    <ComponentType name="continuousProjection"
+                   description="A projection between _presynapticPopulation and _postsynapticPopulation through components _preComponent at the start and _postComponent at the end of a _continuousConnection_ or _continuousConnectionInstance_. Can be used for analog synapses.">
+
+        <Children name="connections" type="continuousConnection"/>
+        <Children name="connectionInstances" type="continuousConnectionInstance"/>
+
+        <ComponentReference name="presynapticPopulation" type="population" local="true"/>
+        <ComponentReference name="postsynapticPopulation" type="population" local="true"/>
+
+    </ComponentType>
+
+
+    <!--   Not yet stable...
+
+    <Component Type name="EventConnectivity">
+        <Child name="Connections" type="ConnectionPattern"/>
+        <Link name="source" type="population"/>
+        <Link name="target" type="population"/>
+    </ComponentType>
+
+    <Component Type name="ConnectionPattern">
+    </ComponentType>
+
+    <Component Type name="AllAll" extends="ConnectionPattern">
+        <Dynamics>
+            <Build>
+                <ForEach instances="../source" as="a">
+                     <ForEach instances="../target" as="b">
+                          <EventConnection from="a" to="b"/>
+                     </ForEach>
+                </ForEach>
+            </Build>
+        </Dynamics>
+    </ComponentType>-->
+
+
+    <ComponentType name="explicitInput" description="An explicit input (anything which extends _basePointCurrent_) to a target cell in a population">
+
+        <ComponentReference name="input" type="basePointCurrent"/>
+
+        <Path name="target"/>
+
+        <Text name="destination"/>
+        <Text name="sourcePort"/>
+        <Text name="targetPort"/>
+
+        <Structure>
+            <With instance="target" as="a"/>
+            <With instance="target" as="b"/>
+
+            <EventConnection from="a" to="b" receiver="input" receiverContainer="destination"/>
+        </Structure>
+    </ComponentType>
+
+
+    <ComponentType name="inputList" description="An explicit list of inputs. Not yet stable...">
+
+        <Children name="inputs" type="input"/>
+        <ComponentReference name="component" type="basePointCurrent"/>
+        <Text name="population"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="input" description="Specifies input lists.">
+
+        <Path name="target"/>
+
+        <Text name="segmentId"/>
+        <Text name="fractionAlong"/>
+
+        <Text name="destination"/>
+        <Structure>
+
+            <With instance="target" as="a"/>
+            <With instance="target" as="b"/>
+
+            <EventConnection from="a" to="b" receiver="../component" receiverContainer="destination"/>
+        </Structure>
+
+    </ComponentType>
+
+    <ComponentType name="inputW" description="Specifies input lists. Can set _weight to scale individual inputs." extends="input">
+
+        <Parameter name="weight" dimension="none"/>
+
+        <Path name="target"/> <!-- Ideally this should be taken from extended comp type -->
+        <Text name="destination"/> <!-- Ideally this should be taken from extended comp type -->
+
+        <Structure>
+
+            <With instance="target" as="a"/>
+            <With instance="target" as="b"/>
+
+            <EventConnection from="a" to="b" receiver="../component" receiverContainer="destination">
+                <Assign property="weight" value="weight"/>
+            </EventConnection>
+        </Structure>
+
+    </ComponentType>
+
+</Lems>
diff --git a/lems/test/NeuroML2CoreTypes/NeuroML2CoreTypes.xml b/lems/test/NeuroML2CoreTypes/NeuroML2CoreTypes.xml
new file mode 100644
index 0000000..f1d186f
--- /dev/null
+++ b/lems/test/NeuroML2CoreTypes/NeuroML2CoreTypes.xml
@@ -0,0 +1,9 @@
+<Lems xmlns="http://www.neuroml.org/lems/0.7.5"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.neuroml.org/lems/0.7.5 ../../LEMS/Schemas/LEMS/LEMS_v0.7.5.xsd"
+      description="All NeuroML2 Component Types">
+
+    <Include file="Cells.xml"/>
+    <Include file="Networks.xml"/>
+
+</Lems>
diff --git a/lems/test/NeuroML2CoreTypes/NeuroMLCoreCompTypes.xml b/lems/test/NeuroML2CoreTypes/NeuroMLCoreCompTypes.xml
new file mode 100644
index 0000000..dea364f
--- /dev/null
+++ b/lems/test/NeuroML2CoreTypes/NeuroMLCoreCompTypes.xml
@@ -0,0 +1,137 @@
+<Lems xmlns="http://www.neuroml.org/lems/0.7.5"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.neuroml.org/lems/0.7.5 ../../LEMS/Schemas/LEMS/LEMS_v0.7.5.xsd">
+
+    <!-- A number of common component types for use in NeuroML 2 documents  -->
+
+    <!-- Including standard unit definitions for NeuroML 2 -->
+    <Include file="NeuroMLCoreDimensions.xml"/>
+
+    <!-- Potentially needed for any NeuroML 2 file...-->
+    <ComponentType name="notes" description="Human readable notes/description for a Component">
+    </ComponentType>
+
+
+    <ComponentType name="annotation" description="A structured annotation containing metadata, specifically RDF or _property_ elements">
+        <Child name="rdf:RDF" type="rdf_RDF"/>
+        <Children name="property" type="property"/>
+        <Dynamics/>
+    </ComponentType>
+
+
+    <ComponentType name="property" description="A property (a _tag and _value pair), which can be on any _baseStandalone_ either as a direct child, or within an _Annotation_. Generally something which helps the visual display or facilitates simulation of a Component, but is not a core physiological property. Common examples include: _numberInternalDivisions, equivalent of nseg in NEURON; _radius, for a radius to use in graphical displays for abstract cells (i.e. without defined morphologies); _color, the color to use for a _Population_ or _populationList_ of cells; _recommended_dt_ms, the recommended timestep to use for simulating a _Network_, _recommended_duration_ms the recommended duration to use when running a _Network_ ">
+        <Text name="tag" description="Name of the property"/>
+        <Text name="value" description="Value of the property"/>
+        <Dynamics/>
+    </ComponentType>
+
+    <ComponentType name="baseStandalone"
+        description="Base type of any Component which can have _Notes_, _Annotation_, or a _property_ list.">
+        <Child name="notes" type="notes"/>
+        <Child name="annotation" type="annotation"/>
+        <Children name="property" type="property"/>
+    </ComponentType>
+
+
+    <ComponentType name="rdf_RDF" description="Structured block in an _annotation_ based on RDF. See https://github.com/OpenSourceBrain/OSB_API/blob/master/python/examples/grancelllayer.xml">
+        <Child name="rdf:Description" type="rdf_Description"/>
+        <Text name="xmlns:rdf"/>
+        <Dynamics/>
+    </ComponentType>
+
+
+    <ComponentType name="rdf_Description" description="Structured block in an _annotation_ based on RDF.">
+
+        <Child name="bqbiol:encodes" type="bqbiol_encodes"/>
+        <Child name="bqbiol:hasPart" type="bqbiol_hasPart"/>
+        <Child name="bqbiol:hasProperty" type="bqbiol_hasProperty"/>
+        <Child name="bqbiol:hasVersion" type="bqbiol_hasVersion"/>
+        <Child name="bqbiol:is" type="bqbiol_is"/>
+        <Child name="bqbiol:isDescribedBy" type="bqbiol_isDescribedBy"/>
+        <Child name="bqbiol:isEncodedBy" type="bqbiol_isEncodedBy"/>
+        <Child name="bqbiol:isHomologTo" type="bqbiol_isHomologTo"/>
+        <Child name="bqbiol:isPartOf" type="bqbiol_isPartOf"/>
+        <Child name="bqbiol:isPropertyOf" type="bqbiol_isPropertyOf"/>
+        <Child name="bqbiol:isVersionOf" type="bqbiol_isVersionOf"/>
+        <Child name="bqbiol:occursIn" type="bqbiol_occursIn"/>
+        <Child name="bqbiol:hasTaxon" type="bqbiol_hasTaxon"/>
+        <Child name="bqmodel:is" type="bqmodel_is"/>
+        <Child name="bqmodel:isDescribedBy" type="bqmodel_isDescribedBy"/>
+        <Child name="bqmodel:isDerivedFrom" type="bqmodel_isDerivedFrom"/>
+        <Text name="rdf:about"/>
+        <Dynamics/>
+    </ComponentType>
+
+
+    <ComponentType name="baseBqbiol" description="Structured block in an _annotation_ based on RDF.">
+        <Child name="rdf:Bag" type="rdf_Bag"/>
+        <Dynamics/>
+    </ComponentType>
+
+
+    <ComponentType name="bqbiol_encodes" description="See http://co.mbine.org/standards/qualifiers" extends="baseBqbiol"/>
+
+    <ComponentType name="bqbiol_hasPart" description="See http://co.mbine.org/standards/qualifiers" extends="baseBqbiol"/>
+
+    <ComponentType name="bqbiol_hasProperty" description="See http://co.mbine.org/standards/qualifiers" extends="baseBqbiol"/>
+
+    <ComponentType name="bqbiol_hasVersion" description="See http://co.mbine.org/standards/qualifiers" extends="baseBqbiol"/>
+
+    <ComponentType name="bqbiol_is" description="See http://co.mbine.org/standards/qualifiers" extends="baseBqbiol"/>
+
+    <ComponentType name="bqbiol_isDescribedBy" description="See http://co.mbine.org/standards/qualifiers" extends="baseBqbiol"/>
+
+    <ComponentType name="bqbiol_isEncodedBy" description="See http://co.mbine.org/standards/qualifiers" extends="baseBqbiol"/>
+
+    <ComponentType name="bqbiol_isHomologTo" description="See http://co.mbine.org/standards/qualifiers" extends="baseBqbiol"/>
+
+    <ComponentType name="bqbiol_isPartOf" description="See http://co.mbine.org/standards/qualifiers" extends="baseBqbiol"/>
+
+    <ComponentType name="bqbiol_isPropertyOf" description="See http://co.mbine.org/standards/qualifiers" extends="baseBqbiol"/>
+
+    <ComponentType name="bqbiol_isVersionOf" description="See http://co.mbine.org/standards/qualifiers" extends="baseBqbiol">
+        <Text name="xmlns:bqbiol"/>
+    </ComponentType>
+
+    <ComponentType name="bqbiol_occursIn" description="See http://co.mbine.org/standards/qualifiers" extends="baseBqbiol"/>
+
+    <ComponentType name="bqbiol_hasTaxon" description="See http://co.mbine.org/standards/qualifiers" extends="baseBqbiol"/>
+
+    <ComponentType name="bqmodel_is" description="See http://co.mbine.org/standards/qualifiers" extends="baseBqbiol"/>
+
+    <ComponentType name="bqmodel_isDescribedBy" description="See http://co.mbine.org/standards/qualifiers" extends="baseBqbiol">
+        <Text name="xmlns:bqmodel"/>
+    </ComponentType>
+
+    <ComponentType name="bqmodel_isDerivedFrom" description="See http://co.mbine.org/standards/qualifiers" extends="baseBqbiol"/>
+
+
+    <ComponentType name="rdf_Bag" description="Structured block in an _annotation_ based on RDF.">
+        <Children name="rdf:li" type="rdf:li"/>
+        <Dynamics/>
+    </ComponentType>
+
+
+    <ComponentType name="rdf:li" description="Structured block in an _annotation_ based on RDF.">
+        <Text name="rdf:resource"/>
+        <Dynamics/>
+    </ComponentType>
+
+
+    <ComponentType name="point3DWithDiam"
+                   description="Base type for ComponentTypes which specify an ( _x, _y, _z ) coordinate along with a _diameter. Note: no dimension used in the attributes for these coordinates! These are assumed to have dimension micrometer (10^-6 m). This is due to micrometers being the default option for the majority of neuronal morphology formats, and dimensions are omitted here to facilitate reading and writing of morphologies in NeuroML.">
+        <Parameter name="x" dimension="none" description="x coordinate of the point. Note: no dimension used, see description of _point3DWithDiam_ for details."/>
+        <Parameter name="y" dimension="none" description="y coordinate of the ppoint. Note: no dimension used, see description of _point3DWithDiam_ for details."/>
+        <Parameter name="z" dimension="none" description="z coordinate of the ppoint. Note: no dimension used, see description of _point3DWithDiam_ for details."/>
+        <Parameter name="diameter" dimension="none" description="Diameter of the ppoint. Note: no dimension used, see description of _point3DWithDiam_ for details."/> <!-- TODO decide whether this or radius should be default input field!!! -->
+
+        <DerivedParameter name="radius" dimension="length" value="MICRON * diameter / 2" description="A dimensional quantity given by half the _diameter."/>
+        <DerivedParameter name="xLength" dimension="length" value="MICRON * x" description="A version of _x with dimension length."/>  <!-- conversion to SI units... -->
+        <DerivedParameter name="yLength" dimension="length" value="MICRON * y" description="A version of _y with dimension length."/>  <!-- conversion to SI units... -->
+        <DerivedParameter name="zLength" dimension="length" value="MICRON * z" description="A version of _z with dimension length."/>  <!-- conversion to SI units... -->
+
+        <Constant name="MICRON" dimension="length" value="1um"/>
+    </ComponentType>
+
+
+</Lems>
diff --git a/lems/test/NeuroML2CoreTypes/NeuroMLCoreDimensions.xml b/lems/test/NeuroML2CoreTypes/NeuroMLCoreDimensions.xml
new file mode 100644
index 0000000..ec2707e
--- /dev/null
+++ b/lems/test/NeuroML2CoreTypes/NeuroMLCoreDimensions.xml
@@ -0,0 +1,150 @@
+<Lems xmlns="http://www.neuroml.org/lems/0.7.5"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.neuroml.org/lems/0.7.5 ../../LEMS/Schemas/LEMS/LEMS_v0.7.5.xsd">
+
+    <!-- The core dimensional quantities as used in NeuroML version 2.0 -->
+    <!-- Will be used in Type definitions, e.g. <StateVariable name="v" dimension="voltage"/> -->
+
+    <Dimension name="time" t="1"/>
+    <Dimension name="per_time" t="-1"/>
+
+    <Dimension name="voltage"     m="1" l="2" t="-3" i="-1"/>
+    <Dimension name="per_voltage" m="-1" l="-2" t="3" i="1"/>
+
+    <Dimension name="conductance" m="-1" l="-2" t="3" i="2"/>
+    <Dimension name="conductanceDensity" m="-1" l="-4" t="3" i="2"/>
+
+    <Dimension name="capacitance" m="-1" l="-2" t="4" i="2"/>
+    <Dimension name="specificCapacitance" m="-1" l="-4" t="4" i="2"/>
+
+    <Dimension name="resistance"  m="1" l="2" t="-3" i="-2"/>
+    <Dimension name="resistivity" m="2" l="2" t="-3" i="-2"/>
+
+    <Dimension name="charge" i="1" t="1"/>
+
+    <Dimension name="charge_per_mole" i="1" t="1" n="-1"/>
+
+    <Dimension name="current" i="1"/>
+
+    <Dimension name="currentDensity" i="1" l="-2"/>
+
+    <Dimension name="length" l="1"/>
+    <Dimension name="area" l="2"/>
+    <Dimension name="volume" l="3"/>
+
+    <Dimension name="concentration" l="-3" n="1"/>
+
+    <Dimension name="substance" n="1"/>
+
+    <Dimension name="permeability" l="1" t="-1"/>
+
+    <Dimension name="temperature" k="1"/>
+
+    <Dimension name="idealGasConstantDims" m="1" l="2" t="-2" k="-1" n="-1"/>
+
+    <Dimension name="conductance_per_voltage" m="-2" l="-4" t="6" i="3"/>
+
+    <!-- Note: it's unlikely that this dimension/unit for rho in fixedFactorConcentrationModel will be needed anywhere else-->
+    <Dimension name="rho_factor" l="-1" n="1" i="-1" t="-1"/>
+
+    <!-- The core units as used in NeuroML version 2.0.   -->
+    <!-- Will be used in Component definitions, e.g. duration="60ms" amplitude="0.2 nA" -->
+    <!-- Note, new units can be defined in a NeuroML file based on the dimensions above -->
+
+    <Unit symbol="s" dimension="time" power="0"/>
+    <Unit symbol="per_s" dimension="per_time" power="0"/>
+    <Unit symbol="Hz" dimension="per_time" power="0"/>
+    <Unit symbol="ms" dimension="time" power="-3"/>                <!-- Physiological Units -->
+    <Unit symbol="per_ms" dimension="per_time" power="3"/>         <!-- Physiological Units -->
+
+    <Unit symbol="min" dimension="time" power="0" scale="60"/>
+    <Unit symbol="per_min" dimension="per_time" power="0" scale="0.01666666667"/>
+    <Unit symbol="hour" dimension="time" power="0" scale="3600"/>
+    <Unit symbol="per_hour" dimension="per_time" power="0" scale="0.00027777777778"/>
+
+    <Unit symbol="m" dimension="length" power="0"/>
+    <Unit symbol="cm" dimension="length" power="-2"/>              <!-- Physiological Units -->
+    <Unit symbol="um" dimension="length" power="-6"/>
+
+    <Unit symbol="m2" dimension="area" power="0"/>
+    <Unit symbol="cm2" dimension="area" power="-4"/>               <!-- Physiological Units -->
+    <Unit symbol="um2" dimension="area" power="-12"/>
+
+    <Unit symbol="m3" dimension="volume" power="0"/>
+    <Unit symbol="cm3" dimension="volume" power="-6"/>             <!-- Physiological Units -->
+    <Unit symbol="litre" dimension="volume" power="-3"/>
+    <Unit symbol="um3" dimension="volume" power="-18"/>
+
+    <Unit symbol="V" dimension="voltage" power="0"/>
+    <Unit symbol="mV" dimension="voltage" power="-3"/>             <!-- Physiological Units -->
+    <Unit symbol="per_V" dimension="per_voltage" power="0"/>
+    <Unit symbol="per_mV" dimension="per_voltage" power="3"/>
+
+    <Unit symbol="ohm" dimension="resistance" power="0"/>
+    <Unit symbol="kohm" dimension="resistance" power="3"/>         <!-- Physiological Units -->
+    <Unit symbol="Mohm" dimension="resistance" power="6"/>
+
+    <Unit symbol="S" dimension="conductance" power="0"/>
+    <Unit symbol="mS" dimension="conductance" power="-3"/>         <!-- Physiological Units -->
+    <Unit symbol="uS" dimension="conductance" power="-6"/>
+    <Unit symbol="nS" dimension="conductance" power="-9"/>
+    <Unit symbol="pS" dimension="conductance" power="-12"/>
+
+    <Unit symbol="S_per_m2" dimension="conductanceDensity" power="0"/>
+    <Unit symbol="mS_per_cm2" dimension="conductanceDensity" power="1"/>   <!-- Physiological Units -->
+    <Unit symbol="S_per_cm2" dimension="conductanceDensity" power="4"/>   <!-- NEURON preferred Units -->
+
+    <Unit symbol="F" dimension="capacitance" power="0"/>
+    <Unit symbol="uF" dimension="capacitance" power="-6"/>         <!-- Physiological Units -->
+    <Unit symbol="nF" dimension="capacitance" power="-9"/>
+    <Unit symbol="pF" dimension="capacitance" power="-12"/>
+
+    <Unit symbol="F_per_m2" dimension="specificCapacitance" power="0"/>
+    <Unit symbol="uF_per_cm2" dimension="specificCapacitance" power="-2"/>  <!-- Physiological Units -->
+
+    <Unit symbol="ohm_m" dimension="resistivity" power="0"/>
+    <Unit symbol="kohm_cm" dimension="resistivity" power="1"/>    <!-- Physiological Units -->
+    <Unit symbol="ohm_cm" dimension="resistivity" power="-2"/>    <!-- NEURON preferred Units -->
+
+    <Unit symbol="C" dimension="charge" power="0"/>
+    <Unit symbol="e" dimension="charge" power="0" scale="1.602176634e-19"/>
+
+    <Unit symbol="C_per_mol" dimension="charge_per_mole" power="0"/>
+    <Unit symbol="nA_ms_per_amol" dimension="charge_per_mole" power="6"/>   <!-- NEURON preferred Units -->
+
+    <Unit symbol="A" dimension="current" power="0"/>
+    <Unit symbol="uA" dimension="current" power="-6"/>             <!-- Physiological Units -->
+    <Unit symbol="nA" dimension="current" power="-9"/>
+    <Unit symbol="pA" dimension="current" power="-12"/>
+
+    <Unit symbol="A_per_m2" dimension="currentDensity" power="0"/>
+    <Unit symbol="uA_per_cm2" dimension="currentDensity" power="-2"/>         <!-- Physiological Units -->
+    <Unit symbol="mA_per_cm2" dimension="currentDensity" power="1"/>          <!-- NEURON preferred Units -->
+
+    <Unit symbol="mol_per_m3" dimension="concentration" power="0"/>
+    <Unit symbol="mol_per_cm3" dimension="concentration" power="6"/>  <!-- Physiological Units -->
+    <Unit symbol="M" dimension="concentration" power="3"/>
+    <Unit symbol="mM" dimension="concentration" power="0"/>
+
+    <Unit symbol="mol" dimension="substance" power="0"/>
+
+    <Unit symbol="m_per_s" dimension="permeability" power="0"/>
+    <Unit symbol="cm_per_s" dimension="permeability" power="-2"/>
+    <Unit symbol="um_per_ms" dimension="permeability" power="-3"/>
+    <Unit symbol="cm_per_ms" dimension="permeability" power="1"/>
+
+
+    <Unit symbol="degC" dimension="temperature" offset="273.15"/>
+
+    <Unit symbol="K" dimension="temperature" power="0"/>
+
+    <Unit symbol="J_per_K_per_mol" dimension="idealGasConstantDims" power="0"/>
+
+    <Unit symbol="S_per_V" dimension="conductance_per_voltage" power="0"/>
+    <Unit symbol="nS_per_mV" dimension="conductance_per_voltage" power="-6"/>       <!-- NEURON preferred Units -->
+
+    <!-- Note: it's unlikely that this dimension/unit for rho in fixedFactorConcentrationModel will be needed anywhere else-->
+    <Unit symbol="mol_per_m_per_A_per_s" dimension="rho_factor" power="0"/> <!-- SI -->
+    <Unit symbol="mol_per_cm_per_uA_per_ms" dimension="rho_factor" power="11"/> <!-- SI -->
+
+</Lems>
diff --git a/lems/test/NeuroML2CoreTypes/PyNN.xml b/lems/test/NeuroML2CoreTypes/PyNN.xml
new file mode 100644
index 0000000..6f088ae
--- /dev/null
+++ b/lems/test/NeuroML2CoreTypes/PyNN.xml
@@ -0,0 +1,618 @@
+<Lems xmlns="http://www.neuroml.org/lems/0.7.5"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.neuroml.org/lems/0.7.5 ../../LEMS/Schemas/LEMS/LEMS_v0.7.5.xsd"
+      description="A number of ComponentType description of PyNN standard cells. All of the cells extend _basePyNNCell_, and the synapses extend _basePynnSynapse_.">
+
+    <!-- Set of definitions in LEMS for PyNN standard cell types & synapses  -->
+
+    <!-- See https://github.com/NeuroML/NeuroML2/issues/73 for more details on current status-->
+
+    <Include file="Cells.xml"/>
+    <Include file="Synapses.xml"/>
+
+
+    <ComponentType name="basePyNNCell"
+                   description="Base type of any PyNN standard cell model. Note: membrane potential _v has dimensions voltage, but all other parameters are dimensionless. This is to facilitate translation to and from PyNN scripts in Python, where these parameters have implicit units, see http://neuralensemble.org/trac/PyNN/wiki/StandardModels"
+                   extends="baseCellMembPot">
+
+        <Parameter name="cm" dimension="none"/>
+        <Parameter name="i_offset" dimension="none"/>
+
+        <Parameter name="tau_syn_E" dimension="none" description="This parameter is never used in the NeuroML2 description of this cell! Any synapse producing a current can be placed on this cell"/>
+        <Parameter name="tau_syn_I" dimension="none" description="This parameter is never used in the NeuroML2 description of this cell! Any synapse producing a current can be placed on this cell"/>
+
+        <!-- Temp parameter for initial value while LEMS support for setting these is updated -->
+        <Parameter name="v_init" dimension="none"/>
+
+        <Constant name="MSEC" dimension="time" value="1ms"/>
+        <Constant name="MVOLT" dimension="voltage" value="1mV"/>
+        <Constant name="NFARAD" dimension="capacitance" value="1nF"/>
+
+        <EventPort name="spike_in_E" direction="in"/>
+        <EventPort name="spike_in_I" direction="in"/>
+
+        <Exposure name="iSyn" dimension="current"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="basePyNNIaFCell"
+                   extends="basePyNNCell"
+                   description="Base type of any PyNN standard integrate and fire model">
+
+        <Parameter name="tau_refrac" dimension="none"/>
+        <Parameter name="v_thresh" dimension="none"/>
+        <Parameter name="tau_m" dimension="none"/>
+        <Parameter name="v_rest" dimension="none"/>
+        <Parameter name="v_reset" dimension="none"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="basePyNNIaFCondCell"
+                   extends="basePyNNIaFCell"
+                   description="Base type of conductance based PyNN IaF cell models">
+
+        <Parameter name="e_rev_E" dimension="none" description="This parameter is never used in the NeuroML2 description of this cell! Any synapse producing a current can be placed on this cell"/>
+        <Parameter name="e_rev_I" dimension="none" description="This parameter is never used in the NeuroML2 description of this cell! Any synapse producing a current can be placed on this cell"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="IF_curr_alpha"
+                   extends="basePyNNIaFCell"
+                   description="Leaky integrate and fire model with fixed threshold and alpha-function-shaped post-synaptic current">
+
+        <Attachments name="synapses" type="baseSynapse"/> <!-- Note, any NeuroML2 synapse producing a current can be used-->
+
+        <Dynamics>
+            <StateVariable name="v" exposure="v" dimension="voltage"/>
+            <StateVariable name="lastSpikeTime" dimension="time"/>
+
+            <DerivedVariable name="iSyn" dimension="current" exposure="iSyn" select="synapses[*]/i" reduce="add" />
+
+            <OnStart>
+                <StateAssignment variable="v" value="v_init * MVOLT"/>
+            </OnStart>
+
+            <Regime name="refractory">
+                <OnEntry>
+                    <StateAssignment variable="lastSpikeTime" value="t" />
+                    <StateAssignment variable="v" value="v_reset * MVOLT" />
+                </OnEntry>
+                <OnCondition test="t .gt. lastSpikeTime + (tau_refrac*MSEC)">
+                    <Transition regime="integrating" />
+                </OnCondition>
+            </Regime>
+
+            <Regime name="integrating" initial="true">
+                <TimeDerivative variable="v" value="(MVOLT * ((i_offset/cm) +  ((v_rest - (v/MVOLT)) / tau_m))/MSEC) + (iSyn / (cm * NFARAD))" />
+                <OnCondition test="v .gt. v_thresh * MVOLT">
+                    <EventOut port="spike"/>
+                    <Transition regime="refractory" />
+                </OnCondition>
+            </Regime>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="IF_curr_exp"
+                   extends="basePyNNIaFCell"
+                   description="Leaky integrate and fire model with fixed threshold and decaying-exponential post-synaptic current">
+
+        <Attachments name="synapses" type="baseSynapse"/> <!-- Note, any NeuroML2 synapse producing a current can be used-->
+
+        <Dynamics>
+            <StateVariable name="v" exposure="v" dimension="voltage"/>
+            <StateVariable name="lastSpikeTime" dimension="time"/>
+
+            <DerivedVariable name="iSyn" dimension="current" exposure="iSyn" select="synapses[*]/i" reduce="add" />
+
+            <OnStart>
+                <StateAssignment variable="v" value="v_init * MVOLT"/>
+            </OnStart>
+
+            <Regime name="refractory">
+                <OnEntry>
+                    <StateAssignment variable="lastSpikeTime" value="t" />
+                    <StateAssignment variable="v" value="v_reset * MVOLT" />
+                </OnEntry>
+                <OnCondition test="t .gt. lastSpikeTime + (tau_refrac*MSEC)">
+                    <Transition regime="integrating" />
+                </OnCondition>
+            </Regime>
+
+            <Regime name="integrating" initial="true">
+                <TimeDerivative variable="v" value="(MVOLT * (((i_offset)/cm) +  ((v_rest - (v/MVOLT)) / tau_m))/MSEC) + (iSyn / (cm * NFARAD))" />
+                <OnCondition test="v .gt. v_thresh * MVOLT">
+                    <EventOut port="spike"/>
+                    <Transition regime="refractory" />
+                </OnCondition>
+            </Regime>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="IF_cond_alpha"
+                   extends="basePyNNIaFCondCell"
+                   description="Leaky integrate and fire model with fixed threshold and alpha-function-shaped post-synaptic conductance">
+
+        <Attachments name="synapses" type="baseSynapse"/> <!-- Note, any NeuroML2 synapse producing a current can be used-->
+
+        <Dynamics>
+            <StateVariable name="v" exposure="v" dimension="voltage"/>
+            <StateVariable name="lastSpikeTime" dimension="time"/>
+
+            <DerivedVariable name="iSyn" dimension="current" exposure="iSyn" select="synapses[*]/i" reduce="add" />
+
+            <OnStart>
+                <StateAssignment variable="v" value="v_init * MVOLT"/>
+            </OnStart>
+
+            <Regime name="refractory">
+                <OnEntry>
+                    <StateAssignment variable="lastSpikeTime" value="t" />
+                    <StateAssignment variable="v" value="v_reset * MVOLT" />
+                </OnEntry>
+                <OnCondition test="t .gt. lastSpikeTime + (tau_refrac*MSEC)">
+                    <Transition regime="integrating" />
+                </OnCondition>
+            </Regime>
+
+            <Regime name="integrating" initial="true">
+                <TimeDerivative variable="v" value="(MVOLT * (((i_offset) / cm) +  ((v_rest - (v / MVOLT)) / tau_m)) / MSEC) + (iSyn / (cm * NFARAD))" />
+                <OnCondition test="v .gt. v_thresh * MVOLT">
+                    <EventOut port="spike"/>
+                    <Transition regime="refractory" />
+                </OnCondition>
+            </Regime>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="IF_cond_exp"
+                   extends="basePyNNIaFCondCell"
+                   description="Leaky integrate and fire model with fixed threshold and exponentially-decaying post-synaptic conductance">
+
+        <Attachments name="synapses" type="baseSynapse"/> <!-- Note, any NeuroML2 synapse producing a current can be used-->
+
+        <Dynamics>
+            <StateVariable name="v" exposure="v" dimension="voltage"/>
+            <StateVariable name="lastSpikeTime" dimension="time"/>
+
+            <DerivedVariable name="iSyn" dimension="current" exposure="iSyn" select="synapses[*]/i" reduce="add" />
+
+            <OnStart>
+                <StateAssignment variable="v" value="v_init * MVOLT"/>
+            </OnStart>
+
+            <Regime name="refractory">
+                <OnEntry>
+                    <StateAssignment variable="lastSpikeTime" value="t" />
+                    <StateAssignment variable="v" value="v_reset * MVOLT" />
+                </OnEntry>
+                <OnCondition test="t .gt. lastSpikeTime + (tau_refrac*MSEC)">
+                    <Transition regime="integrating" />
+                </OnCondition>
+            </Regime>
+
+            <Regime name="integrating" initial="true">
+                <TimeDerivative variable="v" value="(MVOLT * (((i_offset)/cm) +  ((v_rest - (v / MVOLT)) / tau_m)) / MSEC) + (iSyn / (cm * NFARAD))" />
+                <OnCondition test="v .gt. v_thresh * MVOLT">
+                    <EventOut port="spike"/>
+                    <Transition regime="refractory" />
+                </OnCondition>
+            </Regime>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="EIF_cond_exp_isfa_ista"
+                   extends="basePyNNIaFCondCell"
+                   description="Adaptive exponential integrate and fire neuron according to Brette R and Gerstner W (2005) with exponentially-decaying post-synaptic conductance">
+
+        <Parameter name="v_rest" dimension="none"/>
+        <Parameter name="v_spike" dimension="none"/>
+        <Parameter name="delta_T" dimension="none"/>
+        <Parameter name="tau_w" dimension="none"/>
+
+        <Parameter name="a" dimension="none"/>
+        <Parameter name="b" dimension="none"/>
+
+        <Parameter name="i_offset" dimension="none"/>
+
+        <Parameter name="tau_refrac" dimension="none"/>
+
+        <DerivedParameter name="eif_threshold" dimension="none" value="v_spike * H(delta_T-1e-12) + v_thresh * H(-1*delta_T+1e-9)"/>
+
+        <Attachments name="synapses" type="baseSynapse"/> <!-- Note, any NeuroML2 synapse producing a current can be used-->
+
+        <Exposure name="w" dimension="none"/>
+
+        <Dynamics>
+
+            <StateVariable name="v" dimension="voltage" exposure="v"/>
+            <StateVariable name="w" dimension="none" exposure="w"/>
+            <StateVariable name="lastSpikeTime" dimension="time"/>
+
+            <DerivedVariable name="iSyn" dimension="current" exposure="iSyn" select="synapses[*]/i" reduce="add" />
+
+            <ConditionalDerivedVariable name="delta_I" dimension="none">
+                <Case condition="delta_T .gt. 0" value="delta_T * exp(((v / MVOLT) - v_thresh) / delta_T)"/>
+                <Case condition="delta_T .eq. 0" value="0"/>
+            </ConditionalDerivedVariable>
+
+            <OnStart>
+                <StateAssignment variable="v" value="v_init * MVOLT"/>
+                <StateAssignment variable="w" value="0"/>
+            </OnStart>
+
+            <Regime name="refractory">
+
+                <TimeDerivative variable="w" value="(1 / tau_w) * (a * ((v / MVOLT) - v_rest) - w) / MSEC"/>
+
+                <OnEntry>
+                    <StateAssignment variable="lastSpikeTime" value="t" />
+                    <StateAssignment variable="v" value="v_reset * MVOLT" />
+                    <StateAssignment variable="w" value="w+b"/>
+                </OnEntry>
+
+                <OnCondition test="t .gt. lastSpikeTime + (tau_refrac*MSEC)">
+                    <Transition regime="integrating" />
+                </OnCondition>
+            </Regime>
+
+
+            <Regime name="integrating" initial="true">
+
+                <TimeDerivative variable="v" value="(MVOLT * ((-1 * ((v / MVOLT) - v_rest) + delta_I) / tau_m + (i_offset - w) / cm) / MSEC) + (iSyn / (cm * NFARAD))"/>
+                <TimeDerivative variable="w" value="(1 / tau_w) * (a * ((v / MVOLT) - v_rest) - w) / MSEC"/>
+
+                <OnCondition test="v .gt. eif_threshold * MVOLT">
+                    <EventOut port="spike"/>
+                    <Transition regime="refractory" />
+                </OnCondition>
+
+            </Regime>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="EIF_cond_alpha_isfa_ista"
+                   extends="basePyNNIaFCondCell"
+                   description="Adaptive exponential integrate and fire neuron according to Brette R and Gerstner W (2005) with alpha-function-shaped post-synaptic conductance">
+
+        <Parameter name="v_rest" dimension="none"/>
+        <Parameter name="v_spike" dimension="none"/>
+        <Parameter name="delta_T" dimension="none"/>
+        <Parameter name="tau_w" dimension="none"/>
+
+        <Parameter name="a" dimension="none"/>
+        <Parameter name="b" dimension="none"/>
+
+        <Parameter name="i_offset" dimension="none"/>
+
+        <Parameter name="tau_refrac" dimension="none"/>
+
+        <DerivedParameter name="eif_threshold" dimension="none" value="v_spike * H(delta_T-1e-12) + v_thresh * H(-1*delta_T+1e-9)"/>
+
+        <Attachments name="synapses" type="baseSynapse"/> <!-- Note, any NeuroML2 synapse producing a current can be used-->
+
+        <Exposure name="w" dimension="none"/>
+
+        <Dynamics>
+
+            <StateVariable name="v" dimension="voltage" exposure="v"/>
+            <StateVariable name="w" dimension="none" exposure="w"/>
+            <StateVariable name="lastSpikeTime" dimension="time"/>
+
+            <DerivedVariable name="iSyn" dimension="current" exposure="iSyn" select="synapses[*]/i" reduce="add" />
+
+
+            <ConditionalDerivedVariable name="delta_I" dimension="none">
+                <Case condition="delta_T .gt. 0" value="delta_T * exp(((v / MVOLT) - v_thresh) / delta_T)"/>
+                <Case condition="delta_T .eq. 0" value="0"/>
+            </ConditionalDerivedVariable>
+
+            <OnStart>
+                <StateAssignment variable="v" value="v_init * MVOLT"/>
+                <StateAssignment variable="w" value="0"/>
+            </OnStart>
+
+            <Regime name="refractory">
+
+                <TimeDerivative variable="w" value="(1 / tau_w) * (a * ((v / MVOLT) - v_rest) - w) / MSEC"/>
+
+                <OnEntry>
+                    <StateAssignment variable="lastSpikeTime" value="t" />
+                    <StateAssignment variable="v" value="v_reset * MVOLT" />
+                    <StateAssignment variable="w" value="w + b"/>
+                </OnEntry>
+
+                <OnCondition test="t .gt. lastSpikeTime + (tau_refrac * MSEC)">
+                    <Transition regime="integrating" />
+                </OnCondition>
+            </Regime>
+
+
+            <Regime name="integrating" initial="true">
+
+                <TimeDerivative variable="v" value="(MVOLT * ((-1 * ( (v / MVOLT) - v_rest) + delta_I) / tau_m + (i_offset - w) / cm) / MSEC) + (iSyn / (cm * NFARAD))"/>
+                <TimeDerivative variable="w" value="(1/ tau_w) * (a*((v/MVOLT)-v_rest) - w) /MSEC"/>
+
+                <OnCondition test="v .gt. eif_threshold * MVOLT">
+                    <EventOut port="spike"/>
+                    <Transition regime="refractory" />
+                </OnCondition>
+
+            </Regime>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <!-- Based on equations used for specifying cell behaviour for Brian in PyNN -->
+    <ComponentType name="HH_cond_exp"
+                   extends="basePyNNCell"
+                   description="Single-compartment Hodgkin-Huxley-type neuron with transient sodium and delayed-rectifier potassium currents using the ion channel models from Traub.">
+
+        <Parameter name="gbar_K" dimension="none"/>
+        <Parameter name="gbar_Na" dimension="none"/>
+        <Parameter name="g_leak" dimension="none"/>
+
+        <Parameter name="e_rev_K" dimension="none"/>
+        <Parameter name="e_rev_Na" dimension="none"/>
+        <Parameter name="e_rev_leak" dimension="none"/>
+
+        <Parameter name="v_offset" dimension="none"/>
+
+        <Parameter name="e_rev_E" dimension="none"/>
+        <Parameter name="e_rev_I" dimension="none"/>
+
+        <Attachments name="synapses" type="baseSynapse"/> <!-- Note, any NeuroML2 synapse producing a current can be used-->
+
+        <Exposure name="m" dimension="none"/>
+        <Exposure name="h" dimension="none"/>
+        <Exposure name="n" dimension="none"/>
+
+        <Dynamics>
+            <StateVariable name="v" dimension="voltage" exposure="v"/>
+            <StateVariable name="m" dimension="none" exposure="m"/>
+            <StateVariable name="h" dimension="none" exposure="h"/>
+            <StateVariable name="n" dimension="none" exposure="n"/>
+
+            <DerivedVariable name="iSyn" dimension="current" exposure="iSyn" select="synapses[*]/i" reduce="add" />
+
+            <DerivedVariable name="iLeak" dimension="none" value="g_leak * (e_rev_leak - (v / MVOLT))"/>
+            <DerivedVariable name="iNa" dimension="none" value="gbar_Na * (m * m * m) * h * (e_rev_Na - (v / MVOLT))"/>
+            <DerivedVariable name="iK" dimension="none" value="gbar_K * (n * n * n * n) * (e_rev_K - (v / MVOLT))"/>
+            <DerivedVariable name="iMemb" dimension="none" value="iLeak + iNa + iK + i_offset"/>
+
+            <DerivedVariable name="alpham" dimension="none" value="0.32 * (13 - (v / MVOLT) + v_offset) / (exp((13 - (v / MVOLT) + v_offset) / 4.0) - 1)"/>
+            <DerivedVariable name="betam" dimension="none"  value="0.28 * ((v / MVOLT) - v_offset - 40) / (exp(((v / MVOLT) - v_offset - 40) / 5.0) - 1)"/>
+            <DerivedVariable name="alphah" dimension="none" value="0.128 * exp((17 - (v / MVOLT) + v_offset) / 18.0)"/>
+            <DerivedVariable name="betah" dimension="none" value="4.0 / (1 + exp((40 - (v / MVOLT) + v_offset) / 5))"/>
+            <DerivedVariable name="alphan" dimension="none" value="0.032 * (15 - (v / MVOLT) + v_offset) / (exp((15 - (v / MVOLT) + v_offset) / 5) - 1)"/>
+            <DerivedVariable name="betan" dimension="none" value="0.5 * exp((10 - (v / MVOLT) + v_offset) / 40)"/>
+
+            <TimeDerivative variable="v" value="(MVOLT * (iMemb / cm) / MSEC) + (iSyn / (cm * NFARAD))"/>
+
+            <TimeDerivative variable="m" value="(alpham * (1 - m) - betam * m) / MSEC"/>
+            <TimeDerivative variable="h" value="(alphah * (1 - h) - betah * h) / MSEC"/>
+            <TimeDerivative variable="n" value="(alphan * (1 - n) - betan * n) / MSEC"/>
+
+            <OnStart>
+                <StateAssignment variable="v" value="v_init * MVOLT"/>
+            </OnStart>
+
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <!--  Synapses   -->
+
+    <ComponentType name="basePynnSynapse"
+                   description="Base type for all PyNN synapses. Note, the current _I produced is dimensionless, but it requires a membrane potential _v with dimension voltage"
+                   extends="baseVoltageDepSynapse">
+
+        <Parameter name="tau_syn" dimension="none"/>
+
+        <Constant name="MSEC" dimension="time" value="1ms"/>
+        <Constant name="MVOLT" dimension="voltage" value="1mV"/>
+        <Constant name="NAMP" dimension="current" value="1nA"/>
+
+        <!-- <Exposure name="i" dimension="current"/> Defined in basePointCurrent -->
+
+    </ComponentType>
+
+
+    <ComponentType name="expCondSynapse"
+                   extends="basePynnSynapse"
+                   description="Conductance based synapse with instantaneous rise and single exponential decay (with time constant tau_syn)">
+
+        <Property name="weight" dimension="none"  defaultValue="1"/>
+
+        <Parameter name="e_rev" dimension="none"/>
+
+        <Exposure name="g" dimension="none"/>
+
+        <Dynamics>
+            <StateVariable name="g" dimension="none" exposure="g"/>
+
+            <DerivedVariable name="i" exposure="i" dimension="current" value="g * (e_rev - (v/MVOLT)) * NAMP" />
+
+            <TimeDerivative variable="g" value="-g / (tau_syn*MSEC)" />
+
+            <OnEvent port="in">
+                <StateAssignment variable="g" value="g+weight" />
+            </OnEvent>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="expCurrSynapse"
+                   extends="basePynnSynapse"
+                   description="Current based synapse with instantaneous rise and single exponential decay (with time constant tau_syn)">
+
+        <Property name="weight" dimension="none"  defaultValue="1"/>
+
+        <Dynamics>
+            <StateVariable name="I" dimension="none"/>
+
+            <DerivedVariable name="i" exposure="i" dimension="current" value="I * NAMP" />
+
+            <TimeDerivative variable="I" value="-I / (tau_syn*MSEC)" />
+
+            <OnEvent port="in">
+                <StateAssignment variable="I" value="I + weight" />
+            </OnEvent>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="alphaCondSynapse"
+                   extends="basePynnSynapse"
+                   description="Alpha synapse: rise time and decay time are both tau_syn. Conductance based synapse.">
+
+        <Property name="weight" dimension="none"  defaultValue="1"/>
+
+        <Parameter name="e_rev" dimension="none"/>
+
+        <Exposure name="g" dimension="none"/>
+        <Exposure name="A" dimension="none"/> <!-- For some reason y gives an error in NEURON mod files... -->
+
+        <Dynamics>
+            <StateVariable name="g" exposure="g" dimension="none"/>
+            <StateVariable name="A" exposure="A" dimension="none"/>
+            <!--
+            Inspired by Brian impl in PyNN...
+            g(t) = e/tau * t * e^(-t/tau)   // after syn input
+            define y(t) = e^(-t/tau)
+            dy/dt = -1/tau * e^(-t/tau) = -1/tau * y
+                  = -y / tau
+            dg/dt = e/tau * e^(-t/tau) + (-1/tau) * e/tau * t * e^(-t/tau)
+                  = e/tau * y          + (-1/tau) * g
+                  = (e*y - g) / tau
+            -->
+
+            <DerivedVariable name="i" exposure="i" dimension="current" value="g * (e_rev - (v/MVOLT)) * NAMP" />
+
+            <TimeDerivative variable="g" value="(2.7182818*A - g)/(tau_syn*MSEC)" />
+            <TimeDerivative variable="A" value="-A /(tau_syn*MSEC)" />
+
+            <OnEvent port="in">
+                <StateAssignment variable="A" value="A + weight" />
+            </OnEvent>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="alphaCurrSynapse"
+                   extends="basePynnSynapse"
+                   description="Alpha synapse: rise time and decay time are both tau_syn. Current based synapse.">
+
+        <Property name="weight" dimension="none"  defaultValue="1"/>
+
+        <Exposure name="A" dimension="current"/>
+
+        <Dynamics>
+            <StateVariable name="I" dimension="none"/>
+            <StateVariable name="A" exposure="A" dimension="none"/>
+
+            <DerivedVariable name="i" exposure="i" dimension="current" value="I * NAMP" />
+
+            <TimeDerivative variable="I" value="(2.7182818*A - I)/(tau_syn*MSEC)" />
+            <TimeDerivative variable="A" value="-A /(tau_syn*MSEC)" />
+
+            <OnEvent port="in">
+                <StateAssignment variable="A" value="A + weight" />
+            </OnEvent>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <!--  Spike sources  -->
+
+    <ComponentType name="SpikeSourcePoisson"
+                   extends="baseSpikeSource"
+                   description="Spike source, generating spikes according to a Poisson process.">
+
+        <Parameter name="start" dimension="time"/>
+        <Parameter name="duration" dimension="time"/>
+        <Parameter name="rate" dimension="per_time"/>
+
+        <DerivedParameter name="end" dimension="time" value="start + duration"/>
+
+        <Constant name="LONG_TIME" dimension="time" value="1e9hour"/>
+        <Constant name="SMALL_TIME" dimension="time" value="1e-9ms"/> <!-- See below for usage -->
+
+        <!--TODO: remove! Only required as EventConnection is used in explicitInput to
+        connect inputs to cells. Events aren't passed! ... -->
+        <EventPort name="in" direction="in"/>
+
+        <!-- See spikeGeneratorPoisson for full description of tnextIdeal/tnextUsed etc. -->
+        <Exposure name="isi" dimension="time"/>
+        <Exposure name="tnextIdeal" dimension="time"/>
+        <Exposure name="tnextUsed" dimension="time"/>
+
+        <Dynamics>
+
+            <StateVariable name="tsince" dimension="time" exposure="tsince"/>
+            <StateVariable name="tnextIdeal" dimension="time" exposure="tnextIdeal"/>
+            <StateVariable name="tnextUsed" dimension="time" exposure="tnextUsed"/>
+            <StateVariable name="isi" dimension="time" exposure="isi"/>
+
+            <TimeDerivative variable="tsince" value="1"/>
+            <TimeDerivative variable="tnextUsed" value="0"/>
+            <TimeDerivative variable="tnextIdeal" value="0"/>
+
+            <OnStart>
+                <StateAssignment variable="isi" value="start - log(random(1))/rate"/>
+                <StateAssignment variable="tsince" value="0"/>
+
+                <!-- See spikeGeneratorPoisson for full description of tnextIdeal/tnextUsed etc. -->
+                <StateAssignment variable="tnextIdeal" value="isi + H(((isi) - (start+duration))/duration)*LONG_TIME"/>
+                <StateAssignment variable="tnextUsed" value="tnextIdeal"/>
+            </OnStart>
+
+
+            <OnCondition test="t .gt. tnextUsed">
+                <StateAssignment variable="isi" value="-1 * log(random(1))/rate"/>
+
+                <!--
+                Check to see whether tnextIdeal+isi is greater than start+duration and if so set it to a long time in the future...
+                The use of H() is necessary here (as opposed to checking this in the test of OnCondition) since NEURON requires a single boolean expression in test above
+                -->
+                <StateAssignment variable="tnextIdeal" value="(tnextIdeal+isi) + H(((tnextIdeal+isi) - (start+duration))/duration)*LONG_TIME"/>
+                <StateAssignment variable="tnextUsed" value="tnextIdeal*H( (tnextIdeal-t)/t ) + (t+SMALL_TIME)*H( (t-tnextIdeal)/t )"/>
+
+                <StateAssignment variable="tsince" value="0"/>
+
+                <EventOut port="spike"/>
+            </OnCondition>
+
+        </Dynamics>
+    </ComponentType>
+
+</Lems>
diff --git a/lems/test/NeuroML2CoreTypes/Simulation.xml b/lems/test/NeuroML2CoreTypes/Simulation.xml
new file mode 100644
index 0000000..f1a9f2c
--- /dev/null
+++ b/lems/test/NeuroML2CoreTypes/Simulation.xml
@@ -0,0 +1,105 @@
+<Lems xmlns="http://www.neuroml.org/lems/0.7.5"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.neuroml.org/lems/0.7.5 ../../LEMS/Schemas/LEMS/LEMS_v0.7.5.xsd">
+
+    <!-- A number of Simulation types for use in NeuroML 2 documents  -->
+
+    <!-- Including standard unit definitions for NeuroML v2.0 -->
+
+    <Include file="NeuroMLCoreDimensions.xml"/>
+
+
+    <ComponentType name="Display">
+        <Parameter name="xmin" dimension="none"/>
+        <Parameter name="xmax" dimension="none"/>
+        <Parameter name="ymin" dimension="none"/>
+        <Parameter name="ymax" dimension="none"/>
+        <Parameter name="timeScale" dimension="time"/>
+
+        <Children name="lines" type="Line"/>
+
+        <Text name="title"/>
+
+        <Simulation>
+            <DataDisplay title="title" dataRegion="xmin,xmax,ymin,ymax"/>
+        </Simulation>
+    </ComponentType>
+
+
+    <ComponentType name="Line">
+        <Parameter name="scale" dimension="*"/>
+        <Parameter name="timeScale" dimension="*"/>
+        <Path name="quantity"/>
+        <Text name="color"/>
+        <Simulation>
+            <Record quantity="quantity" timeScale="timeScale" scale="scale" color="color"/>
+        </Simulation>
+    </ComponentType>
+
+
+    <ComponentType name="Simulation">
+        <Parameter name="length" dimension="time"/>
+        <Parameter name="step" dimension="time"/>
+
+        <Children name="displays" type="Display"/>
+        <Children name="outputs" type="OutputFile"/>
+        <Children name="events" type="EventOutputFile"/>
+
+        <ComponentReference name="target" type="Component"/>
+
+        <Text name="seed"/>
+
+        <Dynamics>
+            <StateVariable name="t" dimension="time"/>
+        </Dynamics>
+
+        <Simulation>
+            <Run component="target" variable="t" increment="step" total="length"/>
+        </Simulation>
+    </ComponentType>
+
+
+    <ComponentType name="OutputFile">
+
+    	<Children name="outputColumn" type="OutputColumn"/>
+
+        <Text name="path"/>
+        <Text name="fileName"/>
+
+    	<Simulation>
+    		<DataWriter path="path" fileName="fileName"/>
+    	</Simulation>
+
+    </ComponentType>
+
+    <ComponentType name="OutputColumn">
+        <Path name="quantity"/>
+        <Simulation>
+            <Record quantity="quantity"/>
+        </Simulation>
+    </ComponentType>
+
+
+    <ComponentType name="EventOutputFile">
+
+        <Children name="eventSelection" type="EventSelection"/>
+
+        <Text name="path"/>
+        <Text name="fileName"/>
+        <Text name="format"/>
+
+        <Simulation>
+            <EventWriter path="path" fileName="fileName" format="format"/>
+        </Simulation>
+
+    </ComponentType>
+
+    <ComponentType name="EventSelection">
+        <Path name="select"/>
+        <Text name="eventPort"/>
+        <Simulation>
+            <EventRecord quantity="select" eventPort="eventPort"/>
+        </Simulation>
+    </ComponentType>
+
+</Lems>
diff --git a/lems/test/NeuroML2CoreTypes/Synapses.xml b/lems/test/NeuroML2CoreTypes/Synapses.xml
new file mode 100644
index 0000000..a1aa3ed
--- /dev/null
+++ b/lems/test/NeuroML2CoreTypes/Synapses.xml
@@ -0,0 +1,621 @@
+<Lems xmlns="http://www.neuroml.org/lems/0.7.5"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.neuroml.org/lems/0.7.5 ../../LEMS/Schemas/LEMS/LEMS_v0.7.5.xsd"
+      description="A number of synaptic ComponentTypes for use in NeuroML 2 documents. These generally extend the _baseSynapse_ ComponentType.">
+ 
+
+    <!-- These definitions reference entries in the Computational Neuroscience Ontology. To translate
+    the cnoTerms into URLs, follow example of synapse, e.g. cno_0000009 ->
+    https://bioportal.bioontology.org/ontologies/CNO/?p=classes&conceptid=cno_0000009
+    alternatively download the OWL file from https://github.com/INCF and open in Protege: http://protege.stanford.edu
+
+    'cnoTerm' MAY be added as a new attribute, but that would add neuroscience specific terms to LEMS. May be better to add
+    'reference' or 'ontRef' as a new attribute -->
+
+    <!-- Including standard unit comp types & units for NeuroML v2.0 -->
+    <Include file="NeuroMLCoreCompTypes.xml"/>
+    <Include file="Inputs.xml"/>
+
+
+    <ComponentType name="baseSynapse"
+                   extends="basePointCurrent"
+                   description="Base type for all synapses, i.e. ComponentTypes which produce a current (dimension current) and change Dynamics in response to an incoming event. cno_0000009">
+
+        <!-- Todo: see why Property isn't inherited by extended types
+        <Property name="weight" dimension="none" defaultValue="1"/>-->
+        <EventPort name="in" direction="in"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="baseVoltageDepSynapse"
+                   extends="baseSynapse"
+                   description="Base type for synapses with a dependence on membrane potential">
+
+        <Requirement name="v" dimension="voltage" description="The current may vary with the voltage exposed by the ComponentType on which this is placed"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="baseSynapseDL"
+                   extends="baseVoltageDepPointCurrentDL"
+                   description="Base type for all synapses, i.e. ComponentTypes which produce a dimensionless current and change Dynamics in response to an incoming event. cno_0000009">
+
+    </ComponentType>
+
+
+    <ComponentType name="baseCurrentBasedSynapse"
+                   extends="baseSynapse"
+                   description="Synapse model which produces a synaptic current.">
+
+    </ComponentType>
+
+
+    <ComponentType name="alphaCurrentSynapse"
+                   extends="baseCurrentBasedSynapse"
+                   description="Alpha current synapse: rise time and decay time are both _tau.">
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+        <Parameter name="tau" dimension="time" description="Time course for rise and decay"/>
+        <Parameter name="ibase" dimension="current" description="Baseline current increase after receiving a spike"/>
+
+        <Dynamics>
+
+            <StateVariable name="I" dimension="current"/>
+            <StateVariable name="J" dimension="current"/>
+
+            <DerivedVariable name="i" exposure="i" dimension="current" value="I" />
+
+            <TimeDerivative variable="I" value="(2.7182818284590451*J - I)/tau" />
+            <TimeDerivative variable="J" value="-J/tau" />
+
+            <OnStart>
+                <StateAssignment variable="I" value="0" />
+                <StateAssignment variable="J" value="0" />
+            </OnStart>
+
+            <OnEvent port="in">
+                <StateAssignment variable="J" value="J + weight * ibase" />
+            </OnEvent>
+
+        </Dynamics>
+    </ComponentType>
+
+
+
+    <ComponentType name="baseConductanceBasedSynapse"
+                   extends="baseVoltageDepSynapse"
+                   description="Synapse model which exposes a conductance _g in addition to producing a current. Not necessarily ohmic!! cno_0000027">
+
+        <Parameter name="gbase" dimension="conductance" description="Baseline conductance, generally the maximum conductance following a single spike"/>
+        <Parameter name="erev" dimension="voltage" description="Reversal potential of the synapse"/>
+
+        <Exposure name="g" dimension="conductance" description="Time varying conductance through the synapse"/>
+
+    </ComponentType>
+
+
+   <ComponentType name="baseConductanceBasedSynapseTwo"
+                   extends="baseVoltageDepSynapse"
+                   description="Synapse model suited for a sum of two expTwoSynapses which exposes a conductance _g in addition to producing a current. Not necessarily ohmic!! cno_0000027">
+
+        <Parameter name="gbase1" dimension="conductance" description="Baseline conductance 1"/>
+        <Parameter name="gbase2" dimension="conductance" description="Baseline conductance 2"/>
+        <Parameter name="erev" dimension="voltage" description="Reversal potential of the synapse"/>
+
+        <Exposure name="g" dimension="conductance" description="Time varying conductance through the synapse"/>
+
+    </ComponentType>
+
+
+
+    <ComponentType name="expOneSynapse"
+                   extends="baseConductanceBasedSynapse"
+                   description="Ohmic synapse model whose conductance rises instantaneously by (_gbase * _weight) on receiving an event, and which decays exponentially to zero with time course _tauDecay">
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <Parameter name="tauDecay" dimension="time" description="Time course of decay"/>
+
+        <Dynamics>
+
+            <StateVariable name="g" dimension="conductance" exposure="g"/>
+
+            <DerivedVariable name="i" exposure="i" dimension="current" value="g * (erev - v)" />
+
+            <TimeDerivative variable="g" value="-g / tauDecay" />
+
+            <OnStart>
+                <StateAssignment variable="g" value="0" />
+            </OnStart>
+
+            <OnEvent port="in">
+                <StateAssignment variable="g" value="g + (weight * gbase)" />
+            </OnEvent>
+
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="alphaSynapse"
+                   extends="baseConductanceBasedSynapse"
+                   description="Ohmic synapse model where rise time and decay time are both _tau. Max conductance reached during this time (assuming zero conductance before) is _gbase * _weight.">
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <Parameter name="tau" dimension="time" description="Time course of rise/decay"/>
+
+        <Dynamics>
+
+            <StateVariable name="g" dimension="conductance" exposure="g"/>
+            <StateVariable name="A" dimension="conductance"/>
+
+            <DerivedVariable name="i" exposure="i" dimension="current" value="g * (erev - v)" />
+
+            <TimeDerivative variable="g" value="(2.7182818284590451 * A - g)/tau" />
+            <TimeDerivative variable="A" value="-A / tau" />
+
+            <OnStart>
+                <StateAssignment variable="g" value="0" />
+                <StateAssignment variable="A" value="0" />
+            </OnStart>
+
+            <OnEvent port="in">
+                <StateAssignment variable="A" value="A + (gbase*weight)" />
+            </OnEvent>
+
+        </Dynamics>
+    </ComponentType>
+
+
+
+    <ComponentType name="expTwoSynapse"
+                   extends="baseConductanceBasedSynapse"
+                   description="Ohmic synapse model whose conductance waveform on receiving an event has a rise time of _tauRise and a decay time of _tauDecay. Max conductance reached during this time (assuming zero conductance before) is _gbase * _weight.">
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <Parameter name="tauRise" dimension="time" />
+        <Parameter name="tauDecay" dimension="time" />
+
+        <DerivedParameter name="peakTime" dimension="time" value="log(tauDecay / tauRise) * (tauRise * tauDecay)/(tauDecay - tauRise)"/>
+        <DerivedParameter name="waveformFactor" dimension="none" value="1 / (-exp(-peakTime / tauRise) + exp(-peakTime / tauDecay))"/>
+
+        <Dynamics>
+            <StateVariable name="A" dimension="none"/>
+            <StateVariable name="B" dimension="none"/>
+
+            <!-- TODO: catch tauRise = 0..! -->
+
+            <DerivedVariable name="g" dimension="conductance" exposure="g" value="gbase * (B - A)" />
+            <DerivedVariable name="i" exposure="i" dimension="current" value="g * (erev - v)" />
+
+            <TimeDerivative variable="A" value="-A / tauRise" />
+            <TimeDerivative variable="B" value="-B / tauDecay" />
+
+            <OnStart>
+                <StateAssignment variable="A" value="0" />
+                <StateAssignment variable="B" value="0" />
+            </OnStart>
+
+            <OnEvent port="in">
+                <StateAssignment variable="A" value="A + (weight * waveformFactor)" />
+                <StateAssignment variable="B" value="B + (weight * waveformFactor)" />
+            </OnEvent>
+
+        </Dynamics>
+    </ComponentType>
+
+
+
+   <ComponentType name="expThreeSynapse"
+                   extends="baseConductanceBasedSynapseTwo"
+                   description="Ohmic synapse similar to expTwoSynapse but consisting of two components that can differ in decay times and max conductances but share the same rise time.">
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <Parameter name="tauRise" dimension="time" />
+        <Parameter name="tauDecay1" dimension="time" />
+        <Parameter name="tauDecay2" dimension="time" />
+
+        <DerivedParameter name="peakTime1" dimension="time" value="log(tauDecay1 / tauRise) * (tauRise * tauDecay1)/(tauDecay1 - tauRise)"/>
+        <DerivedParameter name="waveformFactor1" dimension="none" value="1 / (-exp(-peakTime1 / tauRise) + exp(-peakTime1 / tauDecay1))"/>
+
+        <DerivedParameter name="peakTime2" dimension="time" value="log(tauDecay2 / tauRise) * (tauRise * tauDecay2)/(tauDecay2 - tauRise)"/>
+        <DerivedParameter name="waveformFactor2" dimension="none" value="1 / (-exp(-peakTime2 / tauRise) + exp(-peakTime2 / tauDecay2))"/>
+
+        <Dynamics>
+            <StateVariable name="A" dimension="none"/>
+            <StateVariable name="B" dimension="none"/>
+            <StateVariable name="C" dimension="none"/>
+
+
+            <DerivedVariable name="g" dimension="conductance" exposure="g" value="gbase1*(B - A) + gbase2*(C-A)" />
+            <DerivedVariable name="i" exposure="i" dimension="current" value="g * (erev - v)" />
+
+            <TimeDerivative variable="A" value="-A / tauRise" />
+            <TimeDerivative variable="B" value="-B / tauDecay1" />
+            <TimeDerivative variable="C" value="-C / tauDecay2" />
+
+            <OnStart>
+                <StateAssignment variable="A" value="0" />
+                <StateAssignment variable="B" value="0" />
+                <StateAssignment variable="C" value="0" />
+            </OnStart>
+
+            <OnEvent port="in">
+                <StateAssignment variable="A" value="A + (gbase1*weight * waveformFactor1 + gbase2*weight*waveformFactor2 )/(gbase1+gbase2)" />
+
+                <StateAssignment variable="B" value="B + (weight * waveformFactor1)" />
+                <StateAssignment variable="C" value="C + (weight * waveformFactor2)" />
+
+            </OnEvent>
+
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="baseBlockMechanism"
+                   description="Base of any ComponentType which produces a varying scaling (or blockage) of synaptic strength of magnitude _scaling">
+
+        <Exposure name="blockFactor" dimension="none"/>
+
+    </ComponentType>
+
+
+    <ComponentType name="voltageConcDepBlockMechanism"
+                   extends="baseBlockMechanism"
+                   description="Synaptic blocking mechanism which varys with membrane potential across the synapse, e.g. in NMDA receptor mediated synapses">
+
+        <Parameter name="blockConcentration" dimension="concentration" />
+        <Parameter name="scalingConc" dimension="concentration" />
+        <Parameter name="scalingVolt" dimension="voltage" />
+
+        <Requirement name="v" dimension="voltage"/>
+
+        <Text name="species"/>
+
+        <Dynamics>
+            <DerivedVariable name="blockFactor" dimension="none" exposure="blockFactor" value="1/(1 + (blockConcentration / scalingConc)* exp(-1 * (v / scalingVolt)))" />
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="basePlasticityMechanism"
+                   description="Base plasticity mechanism.">
+        <EventPort name="in" direction="in" description="This is where the plasticity mechanism receives spike events from the parent synapse."/>
+        <Exposure name="plasticityFactor" dimension="none"/>
+    </ComponentType>
+
+
+    <ComponentType name="tsodyksMarkramDepMechanism"
+                   extends="basePlasticityMechanism"
+                   description="Depression-only Tsodyks-Markram model, as in Tsodyks and Markram 1997.">
+        <Parameter name="initReleaseProb" dimension="none" />
+        <Parameter name="tauRec" dimension="time" />
+
+        <Dynamics>
+            <StateVariable name="R" dimension="none"/>
+
+            <DerivedVariable name="U" dimension="none" value="initReleaseProb"/>
+            <DerivedVariable name="plasticityFactor" dimension="none" exposure="plasticityFactor" value="R * U" />
+
+            <TimeDerivative variable="R" value="(1 - R) / tauRec"/>
+
+            <OnStart>
+                <StateAssignment variable="R" value="1" />
+            </OnStart>
+
+            <OnEvent port="in">
+                <StateAssignment variable="R" value="R * (1 - U)" />
+            </OnEvent>
+        </Dynamics>
+
+        <Structure>
+            <With instance="parent" as="a"/>
+            <With instance="this" as="b"/>
+            <EventConnection from="a" to="b"/>
+        </Structure>
+
+    </ComponentType>
+
+
+    <ComponentType name="tsodyksMarkramDepFacMechanism"
+                   extends="basePlasticityMechanism"
+                   description="Full Tsodyks-Markram STP model with both depression and facilitation, as in Tsodyks, Pawelzik and Markram 1998.">
+        <Parameter name="initReleaseProb" dimension="none" />
+        <Parameter name="tauRec" dimension="time" />
+        <Parameter name="tauFac" dimension="time" />
+
+        <Dynamics>
+            <StateVariable name="R" dimension="none"/>
+            <StateVariable name="U" dimension="none"/>
+
+            <DerivedVariable name="plasticityFactor" dimension="none" exposure="plasticityFactor" value="R * U" />
+
+            <TimeDerivative variable="R" value="(1 - R) / tauRec"/>
+            <TimeDerivative variable="U" value="(initReleaseProb - U) / tauFac"/>
+
+            <OnStart>
+                <StateAssignment variable="R" value="1" />
+                <StateAssignment variable="U" value="initReleaseProb" />
+            </OnStart>
+
+            <OnEvent port="in">
+                <StateAssignment variable="R" value="R * (1 - U)" />
+                <StateAssignment variable="U" value="U + initReleaseProb * (1 - U)" />
+            </OnEvent>
+        </Dynamics>
+
+        <Structure>
+            <With instance="parent" as="a"/>
+            <With instance="this" as="b"/>
+            <EventConnection from="a" to="b"/>
+        </Structure>
+
+    </ComponentType>
+
+
+
+    <ComponentType name="blockingPlasticSynapse"
+                   extends="expTwoSynapse"
+                   description="Biexponential synapse that allows for
+				optional block and plasticity
+				mechanisms, which can be expressed as
+				child elements.">
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <Children name="plasticityMechanisms" type="basePlasticityMechanism"/>
+        <Children name="blockMechanisms" type="baseBlockMechanism"/>
+
+        <EventPort name="relay" direction="out" description="Used to relay incoming spikes to child plasticity mechanism"/>
+        <Dynamics>
+            <StateVariable name="A" dimension="none"/>
+            <StateVariable name="B" dimension="none"/>
+
+            <DerivedVariable name="plasticityFactor" dimension="none"
+                             select="plasticityMechanisms[*]/plasticityFactor"
+                             reduce="multiply"/>
+
+            <DerivedVariable name="blockFactor" dimension="none"
+                             select="blockMechanisms[*]/blockFactor"
+                             reduce="multiply"/>
+
+            <DerivedVariable name="g" dimension="conductance" exposure="g"
+                             value="blockFactor * gbase * (B - A)" />
+            <DerivedVariable name="i" exposure="i" dimension="current"
+                             value="g * (erev - v)" />
+
+            <TimeDerivative variable="A" value="-A / tauRise" />
+            <TimeDerivative variable="B" value="-B / tauDecay" />
+
+            <OnStart>
+                <StateAssignment variable="A" value="0" />
+                <StateAssignment variable="B" value="0" />
+            </OnStart>
+
+            <OnEvent port="in">
+                <StateAssignment variable="A" value="A + (weight * plasticityFactor * waveformFactor)" />
+                <StateAssignment variable="B" value="B + (weight * plasticityFactor * waveformFactor)" />
+                <EventOut port="relay"/>
+            </OnEvent>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="doubleSynapse"
+                   extends="baseVoltageDepSynapse"
+                   description="Synapse consisting of two independent synaptic mechanisms (e.g. AMPA-R and NMDA-R), which can be easily colocated in connections">
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <ComponentReference name="synapse1" type="baseSynapse"/>
+        <ComponentReference name="synapse2" type="baseSynapse"/>
+
+        <EventPort name="relay" direction="out" description="Used to relay incoming spikes to child mechanisms"/>
+
+        <Path name="synapse1Path"/>
+        <Path name="synapse2Path"/>
+
+        <Dynamics>
+            <StateVariable name="weightFactor" dimension="none"/>
+
+            <DerivedVariable name="i1" dimension="current" select="synapse1/i"/>
+            <DerivedVariable name="i2" dimension="current" select="synapse2/i"/>
+            <DerivedVariable name="i" exposure="i" dimension="current" value="weightFactor * (i1 + i2)"/>
+
+            <OnEvent port="in">
+                <StateAssignment variable="weightFactor" value="weight" />
+                <EventOut port="relay"/>
+            </OnEvent>
+
+        </Dynamics>
+
+        <Structure>
+            <ChildInstance component="synapse1"/>
+            <ChildInstance component="synapse2"/>
+
+            <With instance="this" as="a"/>
+            <With instance="synapse1Path" as="b"/>
+            <With instance="synapse2Path" as="c"/>
+
+            <EventConnection from="a" to="c"/>
+            <EventConnection from="a" to="b"/>
+        </Structure>
+
+    </ComponentType>
+
+
+
+    <ComponentType name="stdpSynapse"
+                   extends="expTwoSynapse"
+                   description="Spike timing dependent plasticity mechanism,  NOTE: EXAMPLE NOT YET WORKING!!!! cno_0000034">
+
+        <Constant name="tsinceRate" dimension="none" value="1"/>
+        <Constant name="longTime" dimension="time" value="1000s"/>
+
+        <Exposure name="tsince" dimension="time"/>
+
+        <Exposure name="M" dimension="none"/>
+        <Exposure name="P" dimension="none"/>
+
+        <Dynamics>
+            <StateVariable name="A" dimension="none"/>
+            <StateVariable name="B" dimension="none"/>
+
+            <StateVariable name="M" dimension="none" exposure="M"/>
+            <StateVariable name="P" dimension="none" exposure="P"/>
+
+            <StateVariable name="tsince" dimension="time" exposure="tsince"/>
+
+            <DerivedVariable name="g" dimension="conductance" exposure="g" value="gbase * (B - A)" />
+
+            <DerivedVariable name="i" exposure="i" dimension="current" value="g * (erev - v)" />
+
+
+            <TimeDerivative variable="A" value="-A / tauRise" />
+            <TimeDerivative variable="B" value="-B / tauDecay" />
+
+            <TimeDerivative variable="tsince" value="tsinceRate" />
+
+            <OnStart>
+                <StateAssignment variable="A" value="0" />
+                <StateAssignment variable="B" value="0" />
+
+                <StateAssignment variable="M" value="1" />
+                <StateAssignment variable="P" value="1" />
+
+                <StateAssignment variable="tsince" value="longTime" />
+            </OnStart>
+
+            <OnEvent port="in">
+                <StateAssignment variable="A" value="A + waveformFactor" />
+                <StateAssignment variable="B" value="B + waveformFactor" />
+                <StateAssignment variable="tsince" value="0" />
+            </OnEvent>
+
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="gapJunction"
+                   extends="baseSynapse"
+                   description="Gap junction/single electrical connection">
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <Parameter name="conductance" dimension="conductance"/>
+
+        <Exposure name="i" dimension="current"/>
+
+        <Requirement name="v" dimension="voltage"/>
+
+        <InstanceRequirement name="peer" type="gapJunction"/>
+
+        <Dynamics>
+            <DerivedVariable name="vpeer" dimension="voltage" select="peer/v"/>
+            <DerivedVariable name="i" exposure="i"  value="weight * conductance * (vpeer - v)"/>
+        </Dynamics>
+
+    </ComponentType>
+
+
+
+    <ComponentType name="baseGradedSynapse"
+                   extends="baseSynapse"
+                   description="Base type for graded synapses">
+    </ComponentType>
+
+
+    <ComponentType name="silentSynapse"
+                   extends="baseGradedSynapse"
+                   description="Dummy synapse which emits no current. Used as presynaptic endpoint for analog synaptic connection.">
+
+        <Property name="weight" dimension="none" defaultValue="1"/> <!-- Not used...-->
+
+        <Exposure name="i" dimension="current"/>
+
+        <Requirement name="v" dimension="voltage"/>
+
+        <InstanceRequirement name="peer" type="baseGradedSynapse"/>
+
+        <Dynamics>
+            <DerivedVariable name="vpeer" dimension="voltage" select="peer/v"/>
+            <DerivedVariable name="i" exposure="i"  value="0"/>
+        </Dynamics>
+
+    </ComponentType>
+
+
+    <ComponentType name="linearGradedSynapse"
+                   extends="baseGradedSynapse"
+                   description="Behaves just like a one way gap junction.">
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <Parameter name="conductance" dimension="conductance"/>
+
+        <Exposure name="i" dimension="current"/>
+
+        <Requirement name="v" dimension="voltage"/>
+
+        <InstanceRequirement name="peer" type="baseGradedSynapse"/>
+
+        <Dynamics>
+            <DerivedVariable name="vpeer" dimension="voltage" select="peer/v"/>
+            <DerivedVariable name="i" exposure="i"  value="weight * conductance * (vpeer - v)"/>
+        </Dynamics>
+    </ComponentType>
+
+
+    <ComponentType name="gradedSynapse"
+                   extends="baseGradedSynapse"
+                   description="Graded/analog synapse. Based on synapse in Methods of http://www.nature.com/neuro/journal/v7/n12/abs/nn1352.html">
+
+        <Property name="weight" dimension="none" defaultValue="1"/>
+
+        <Parameter name="conductance" dimension="conductance"/>
+
+        <Parameter name="delta" dimension="voltage" description="Slope of the activation curve"/>
+        <Parameter name="k" dimension="per_time" description="Rate constant for transmitter-receptor dissociation rate"/>
+        <Parameter name="Vth" dimension="voltage" description="The half-activation voltage of the synapse"/>
+        <Parameter name="erev" dimension="voltage" description="The reversal potential of the synapse"/>
+
+        <Exposure name="i" dimension="current"/>
+        <Exposure name="inf" dimension="none"/>
+        <Exposure name="tau" dimension="time"/>
+
+        <Requirement name="v" dimension="voltage"/>
+
+        <InstanceRequirement name="peer" type="baseGradedSynapse"/>
+
+        <Dynamics>
+            <StateVariable name="s" dimension="none"/>
+
+            <DerivedVariable name="vpeer" dimension="voltage" select="peer/v"/>
+
+            <DerivedVariable name="inf" dimension="none" value="1/(1 + exp((Vth - vpeer)/delta))" exposure="inf"/>
+            <DerivedVariable name="tau" dimension="time" value="(1-inf)/k" exposure="tau"/>
+
+            <DerivedVariable name="i" exposure="i"  value="weight * conductance * s * (erev-v)"/>
+
+            <!-- To catch case where tau ~ 0 => too fast a change in s => numerical instability -->
+            <ConditionalDerivedVariable name="s_rate" dimension="per_time">
+                <Case condition="(1-inf) .gt. 1e-4" value="(inf - s)/tau"/>
+                <Case value="0"/>
+            </ConditionalDerivedVariable>
+
+            <TimeDerivative variable="s" value="s_rate" />
+
+            <!-- To catch case where tau ~ 0 => too fast a change in s => numerical instability -->
+            <OnCondition test="(1-inf) .lt. 1e-4">
+                <StateAssignment variable="s" value="inf"/>
+            </OnCondition>
+
+        </Dynamics>
+    </ComponentType>
+
+</Lems>
diff --git a/lems/test/reg_test_20.py b/lems/test/reg_test_20.py
new file mode 100644
index 0000000..da8adf4
--- /dev/null
+++ b/lems/test/reg_test_20.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python3
+"""
+Regression test for https://github.com/LEMS/pylems/issues/20
+
+File: reg_test_20.py
+
+Copyright 2021 LEMS contributors
+Author: Ankur Sinha <sanjay DOT ankur AT gmail DOT com>
+"""
+
+
+import unittest
+import os
+import textwrap
+import tempfile
+import typing
+
+from lems.run import run as lems_run
+
+
+class TestIssue20Regression(unittest.TestCase):
+
+    """Regression test for issue #20
+
+    PyLEMS does not initialise initMembPotential correctly.
+    """
+
+    def test_initMembPotential_init(self):
+        """Test for https://github.com/LEMS/pylems/issues/20"""
+        initmembpot = -20.000000000000000000000
+        reg_20_nml = textwrap.dedent(
+            """<neuroml xmlns="http://www.neuroml.org/schema/neuroml2"  xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.neuroml.org/schema/neuroml2 https://raw.github.com/NeuroML/NeuroML2/development/Schemas/NeuroML2/NeuroML_v2beta3.xsd" id="TestDoc">
+
+        <!-- regression test data for https://github.com/LEMS/pylems/issues/20 -->
+        <ionChannel id="chnl_lk" type="ionChannelPassive" conductance="1nS" />
+
+        <cell id="cell1">
+          <morphology id="morpho">
+            <segment id ="0" name="Soma">
+              <proximal x="0" y="0" z="0" diameter="10"/>
+              <distal x="10" y="0" z="0" diameter="10"/>
+            </segment>
+
+            <!-- Segment group probably not needed? -->
+            <segmentGroup id="segs_soma">
+              <member segment="0" />
+            </segmentGroup>
+          </morphology>
+
+          <biophysicalProperties id="bio_cell">
+            <membraneProperties>
+              <channelPopulation id="chn_pop_lk" ionChannel="chnl_lk" number="1" erev="-50mV" />
+              <spikeThresh value="20mV" />
+              <specificCapacitance value="1.0 uF_per_cm2" segmentGroup="segs_soma" />
+              <initMembPotential value="{}mV" />
+            </membraneProperties>
+            <intracellularProperties />
+          </biophysicalProperties>
+        </cell>
+    </neuroml>
+            """.format(
+                initmembpot
+            )
+        )
+        nml_file = tempfile.NamedTemporaryFile(mode="w+b")
+        nml_file.write(str.encode(reg_20_nml))
+        nml_file.flush()
+
+        reg_20_xml = textwrap.dedent(
+            """<Lems>
+        <!-- regression test data for https://github.com/LEMS/pylems/issues/20 -->
+        <Target component="sim1"/>
+
+        <Include file="Simulation.xml"/>
+        <Include file="Cells.xml"/>
+        <Include file="{}"/>
+
+        <Simulation id="sim1" length="100ms" step="0.1ms" target="cell1">
+          <!-- (x|y)(min|max) don't appear to do anything with PyLEMS, but error if not included... -->
+            <OutputFile path="." fileName="reg_20.dat">
+                <OutputColumn quantity="v" />
+            </OutputFile>
+        </Simulation>
+    </Lems>
+            """.format(
+                nml_file.name
+            )
+        )
+
+        xml_file = tempfile.NamedTemporaryFile(mode="w+b")
+        xml_file.write(str.encode(reg_20_xml))
+        xml_file.flush()
+
+        # TODO: replace this with pynml's extract LEMS files function when that has
+        # been merged and released. We won't need to carry a copy of the coretypes
+        # then.
+        coretype_files_dir = (
+            os.path.dirname(os.path.abspath(__file__)) + "/NeuroML2CoreTypes"
+        )
+        lems_run(xml_file.name, include_dirs=[coretype_files_dir])
+
+        # Deletes the files also
+        nml_file.close()
+        xml_file.close()
+
+        with open("reg_20.dat", "r") as res:
+            for line in res:
+                ln = line.split()
+                time = float(ln[0])
+                value = float(ln[1])
+                assert time == 0
+                self.assertAlmostEqual(value, initmembpot / 1000.0, delta=0.01)
+                # We only want to check the first line
+                break
+        os.remove("reg_20.dat")
diff --git a/lems/test/test_exposure_listing.xml b/lems/test/test_exposure_listing.xml
new file mode 100644
index 0000000..c94c706
--- /dev/null
+++ b/lems/test/test_exposure_listing.xml
@@ -0,0 +1,81 @@
+<Lems>
+    <!-- Dummy file for test -->
+    <Target component="sim1" />
+
+    <Dimension name="voltage" m="1" l="2" t="-3" i="-1" />
+    <Dimension name="time" t="1" />
+    <Dimension name="per_time" t="-1" />
+    <Dimension name="conductance" m="-1" l="-2" t="3" i="2" />
+    <Dimension name="capacitance" m="-1" l="-2" t="4" i="2" />
+    <Dimension name="current" i="1" />
+
+    <Unit symbol="mV" dimension="voltage" power="-3" />
+    <Unit symbol="ms" dimension="time" power="-3" />
+    <Unit symbol="pS" dimension="conductance" power="-12" />
+    <Unit symbol="nS" dimension="conductance" power="-9" />
+    <Unit symbol="uF" dimension="capacitance" power="-6" />
+    <Unit symbol="nF" dimension="capacitance" power="-9" />
+    <Unit symbol="pF" dimension="capacitance" power="-12" />
+    <Unit symbol="per_ms" dimension="per_time" power="3" />
+    <Unit symbol="pA" dimension="current" power="-12" />
+
+    <ComponentType name="Network">
+        <Children name="populations" type="Population"/>
+    </ComponentType>
+
+
+    <ComponentType name="Population">
+        <ComponentReference name="component" type="Component"/>
+        <Parameter name="size" dimension="none"/>
+        <Structure>
+            <MultiInstantiate number="size" component="component"/>
+        </Structure>
+    </ComponentType>
+
+    <ComponentType name="Simulation">
+        <Parameter name="length" dimension="time"/>
+        <Parameter name="step" dimension="time"/>
+
+        <ComponentReference name="target" type="Component"/>
+
+        <Dynamics>
+            <StateVariable name="t" dimension="time"/>
+        </Dynamics>
+
+        <Simulation>
+            <Run component="target" variable="t" increment="step" total="length"/>
+        </Simulation>
+    </ComponentType>
+
+    <ComponentType name="iaf1">
+        <Parameter name="threshold" dimension="voltage" />
+        <Parameter name="refractoryPeriod" dimension="time" />
+        <Parameter name="capacitance" dimension="capacitance" />
+        <Parameter name="leakConductance" dimension="conductance" />
+        <Parameter name="leakReversal" dimension="voltage" />
+        <Parameter name="deltaV" dimension="voltage" />
+
+        <Exposure name="v" dimension="voltage" />
+        <EventPort name="spikes-in" direction="in" />
+        <Dynamics>
+            <StateVariable name="v" exposure="v" dimension="voltage" />
+            <TimeDerivative variable="v" value="leakConductance * (leakReversal - v) / capacitance" />
+
+            <OnEvent port="spikes-in">
+                <StateAssignment variable="v" value="v + deltaV" />
+            </OnEvent>
+        </Dynamics>
+    </ComponentType>
+
+    <ComponentType name="iaf2" extends="iaf1" />
+
+    <!-- dummy components with nonsensical values -->
+    <Component id="example_iaf1_cell" type="iaf1" threshold="-30 mV" refractoryPeriod="2 ms" capacitance="1uF" leakConductance="1nS" leakReversal="1mV" deltaV="1mV"/>
+    <Component id="example_iaf2_cell" type="iaf2" threshold="-30 mV" refractoryPeriod="2 ms" capacitance="1uF" leakConductance="1nS" leakReversal="1mV" deltaV="1mV"/>
+
+    <Network id="net1">
+        <Population id="p1" component="example_iaf1_cell" size="5" />
+        <Population id="p2" component="example_iaf2_cell" size="1" />
+    </Network>
+    <Simulation id="sim1" length="80ms" step="0.01ms" target="net1" />
+</Lems>
diff --git a/lems/test/test_load_write.py b/lems/test/test_load_write.py
index 5c4cfac..bdea25e 100644
--- a/lems/test/test_load_write.py
+++ b/lems/test/test_load_write.py
@@ -10,16 +10,16 @@
 class TestLoadWrite(unittest.TestCase):
     def test_load_write_xml(self):
         model = Model()
-        file_name = 'lems/test/hhcell_resaved2.xml'
+        file_name = "lems/test/hhcell_resaved2.xml"
         model.import_from_file(file_name)
-        file_name2 = 'lems/test/hhcell_resaved3.xml'
+        file_name2 = "lems/test/hhcell_resaved3.xml"
         model.export_to_file(file_name2)
 
         print("----------------------------------------------")
-        print(open(file_name2,'r').read())
+        print(open(file_name2, "r").read())
         print("----------------------------------------------")
 
-        print("Written generated LEMS to %s"%file_name2)
+        print("Written generated LEMS to %s" % file_name2)
 
         from lems.base.util import validate_lems
 
@@ -27,6 +27,6 @@ def test_load_write_xml(self):
 
     def test_load_get_dom(self):
         model = Model()
-        file_name = 'lems/test/hhcell_resaved2.xml'
+        file_name = "lems/test/hhcell_resaved2.xml"
         model.import_from_file(file_name)
         dom0 = model.export_to_dom()
diff --git a/lems/test/test_misc.py b/lems/test/test_misc.py
index b851113..11d76ad 100644
--- a/lems/test/test_misc.py
+++ b/lems/test/test_misc.py
@@ -9,6 +9,7 @@
 
 
 import unittest
+import os
 from lems.model.model import Model
 
 
@@ -18,17 +19,27 @@ class TestExposure(unittest.TestCase):
 
     def test_exposure_getters(self):
         model = Model(include_includes=True, fail_on_missing_includes=True)
-        file_name = 'examples/example1.xml'
+        file_name = (
+            os.path.dirname(os.path.abspath(__file__)) + "/test_exposure_listing.xml"
+        )
         model.import_from_file(file_name)
         exp_list = model.list_exposures()
         for c, es in exp_list.items():
-            if c.id == "celltype_c":
-                self.assertTrue('v' in es)
-                self.assertTrue('tsince' not in es)
-            if c.id == "gen1":
-                self.assertTrue('v' not in es)
-                self.assertTrue('tsince' in es)
-
-
-if __name__ == '__main__':
+            # iaf1 defines v as an exposure
+            if c.id == "example_iaf1_cell":
+                self.assertTrue("v" in es)
+            # iaf2 extends iaf1 and so should inherit v
+            if c.id == "example_iaf2_cell":
+                self.assertTrue("v" in es)
+
+        paths = model.list_recording_paths_for_exposures(substring="", target="net1")
+        self.assertTrue("net1/p1[0]/v" in paths)
+        self.assertTrue("net1/p1[1]/v" in paths)
+        self.assertTrue("net1/p1[2]/v" in paths)
+        self.assertTrue("net1/p1[3]/v" in paths)
+        self.assertTrue("net1/p1[4]/v" in paths)
+        self.assertTrue("net1/p2[0]/v" in paths)
+
+
+if __name__ == "__main__":
     unittest.main()
diff --git a/lems/test/test_parser.py b/lems/test/test_parser.py
index 4af3ed4..4beb888 100644
--- a/lems/test/test_parser.py
+++ b/lems/test/test_parser.py
@@ -1,7 +1,7 @@
-'''
+"""
 Unit tests for Parser
 
-'''
+"""
 
 
 import unittest
@@ -14,72 +14,86 @@ def test_parser(self):
         x = 0.5
 
         exprs = {}
-        exprs['x'] = '{x}'
-        exprs['exp(x)'] = '(exp {x})'
+        exprs["x"] = "{x}"
+        exprs["exp(x)"] = "(exp {x})"
 
         all = False
         all = True
 
         if all:
-            exprs['(R * temperature / (zCa * F)) * log(caConcExt / caConc)'] = '(* (/ (* {R} {temperature}) (* {zCa} {F})) (log (/ {caConcExt} {caConc})))'
-            exprs['( (V - ((V^3) / 3)) - W + I) / SEC'] = '(/ (+ (- (- {V} (/ (^ {V} {3.0}) {3.0})) {W}) {I}) {SEC})'
-            exprs['(V - (V^3) / 3 - W + I) / SEC']      = '(/ (- {V} (+ (- (/ (^ {V} {3.0}) {3.0}) {W}) {I})) {SEC})'
-            exprs['120+300'] = '(+ {120.0} {300.0})'
-            exprs['12e-22'] = '{1.2e-21}'
-            exprs['1e+22'] = '{1e+22}'
-            exprs['1-1E+2+2'] = '(+ (- {1.0} {100.0}) {2.0})'
-            exprs['5.0E-11'] = '{5e-11}'
-            exprs['a + (b + c) * d'] = '(+ {a} (* (+ {b} {c}) {d}))'
-            exprs['1 + (exp(x))'] = '(+ {1.0} (exp {x}))'
-            exprs['exp(x)'] = '(exp {x})'
-            exprs['x / y * z']   = '(* (/ {x} {y}) {z})'
-            exprs['x / (y) * z'] = '(* (/ {x} {y}) {z})'
-            exprs['(y - z) + t'] = '(+ (- {y} {z}) {t})'
-            exprs['x + (y) - z'] = '(- (+ {x} {y}) {z})'
-            exprs['exp(v*2)'] = '(exp (* {v} {2.0}))'
-            exprs['exp(-x)'] = '(exp (- {0.0} {x}))'
-            exprs['sin(y)'] = '(sin {y})'
-            exprs['H(y)'] = '(H {y})'
-            exprs['a / b'] = '(/ {a} {b})'
-            exprs['a / (b)'] = '(/ {a} {b})'
-
-            exprs['(120 + 300/( (exp ((V + 55)/9)) + (exp ((V + 65)/(-16)))))'] = '(+ {120.0} (/ {300.0} (+ (exp (/ (+ {V} {55.0}) {9.0})) (exp (/ (+ {V} {65.0}) (- {0.0} {16.0}))))))'
-
-            exprs['(43.4 - 42.6/(1.0 + (exp ((V + 68.1)/(-20.5)))))'] = '(- {43.4} (/ {42.6} (+ {1.0} (exp (/ (+ {V} {68.1}) (- {0.0} {20.5}))))))'
-
-            exprs['(2.64 - 2.52/(1.0 + (exp ((V+120)/(-25)))))'] = '(- {2.64} (/ {2.52} (+ {1.0} (exp (/ (+ {V} {120.0}) (- {0.0} {25.0}))))))'
-
-            exprs['(1.34 / (1.0 + (exp ((V + 62.9)/(-10)))) * (1.5 + 1.0/(1.0 + (exp ((V+34.9)/3.6)))))'] = '(* (/ {1.34} (+ {1.0} (exp (/ (+ {V} {62.9}) (- {0.0} {10.0}))))) (+ {1.5} (/ {1.0} (+ {1.0} (exp (/ (+ {V} {34.9}) {3.6}))))))'
+            exprs[
+                "(R * temperature / (zCa * F)) * log(caConcExt / caConc)"
+            ] = "(* (/ (* {R} {temperature}) (* {zCa} {F})) (log (/ {caConcExt} {caConc})))"
+            exprs[
+                "( (V - ((V^3) / 3)) - W + I) / SEC"
+            ] = "(/ (+ (- (- {V} (/ (^ {V} {3.0}) {3.0})) {W}) {I}) {SEC})"
+            exprs[
+                "(V - (V^3) / 3 - W + I) / SEC"
+            ] = "(/ (- {V} (+ (- (/ (^ {V} {3.0}) {3.0}) {W}) {I})) {SEC})"
+            exprs["120+300"] = "(+ {120.0} {300.0})"
+            exprs["12e-22"] = "{1.2e-21}"
+            exprs["1e+22"] = "{1e+22}"
+            exprs["1-1E+2+2"] = "(+ (- {1.0} {100.0}) {2.0})"
+            exprs["5.0E-11"] = "{5e-11}"
+            exprs["a + (b + c) * d"] = "(+ {a} (* (+ {b} {c}) {d}))"
+            exprs["1 + (exp(x))"] = "(+ {1.0} (exp {x}))"
+            exprs["exp(x)"] = "(exp {x})"
+            exprs["x / y * z"] = "(* (/ {x} {y}) {z})"
+            exprs["x / (y) * z"] = "(* (/ {x} {y}) {z})"
+            exprs["(y - z) + t"] = "(+ (- {y} {z}) {t})"
+            exprs["x + (y) - z"] = "(- (+ {x} {y}) {z})"
+            exprs["exp(v*2)"] = "(exp (* {v} {2.0}))"
+            exprs["exp(-x)"] = "(exp (- {0.0} {x}))"
+            exprs["sin(y)"] = "(sin {y})"
+            exprs["H(y)"] = "(H {y})"
+            exprs["a / b"] = "(/ {a} {b})"
+            exprs["a / (b)"] = "(/ {a} {b})"
+
+            exprs[
+                "(120 + 300/( (exp ((V + 55)/9)) + (exp ((V + 65)/(-16)))))"
+            ] = "(+ {120.0} (/ {300.0} (+ (exp (/ (+ {V} {55.0}) {9.0})) (exp (/ (+ {V} {65.0}) (- {0.0} {16.0}))))))"
+
+            exprs[
+                "(43.4 - 42.6/(1.0 + (exp ((V + 68.1)/(-20.5)))))"
+            ] = "(- {43.4} (/ {42.6} (+ {1.0} (exp (/ (+ {V} {68.1}) (- {0.0} {20.5}))))))"
+
+            exprs[
+                "(2.64 - 2.52/(1.0 + (exp ((V+120)/(-25)))))"
+            ] = "(- {2.64} (/ {2.52} (+ {1.0} (exp (/ (+ {V} {120.0}) (- {0.0} {25.0}))))))"
+
+            exprs[
+                "(1.34 / (1.0 + (exp ((V + 62.9)/(-10)))) * (1.5 + 1.0/(1.0 + (exp ((V+34.9)/3.6)))))"
+            ] = "(* (/ {1.34} (+ {1.0} (exp (/ (+ {V} {62.9}) (- {0.0} {10.0}))))) (+ {1.5} (/ {1.0} (+ {1.0} (exp (/ (+ {V} {34.9}) {3.6}))))))"
 
         for expr in exprs.keys():
             self.parse_expr(expr, exprs[expr])
 
         bad_exprs = {}
-        bad_exprs['exxp(x)'] = '(exxp {x})'
-        bad_exprs['ln(x)'] = '(ln {x})'  # Use log instead!!
+        bad_exprs["exxp(x)"] = "(exxp {x})"
+        bad_exprs["ln(x)"] = "(ln {x})"  # Use log instead!!
 
         for expr in bad_exprs.keys():
             self.parse_expr(expr, bad_exprs[expr], True)
 
     def parse_expr(self, expr, val, should_fail=False):
-        print('\n---  Parsing %s, checking against %s'%(expr, val))
+        print("\n---  Parsing %s, checking against %s" % (expr, val))
         ep = ExprParser(expr)
         try:
             pt = ep.parse()
-            print("Expr:       %s "%expr)
-            print("Parsed as:  %s "%(str(pt)))
-            print("Expected :  %s "%(val))
-            print("Math :      %s "%(pt.to_python_expr()))
+            print("Expr:       %s " % expr)
+            print("Parsed as:  %s " % (str(pt)))
+            print("Expected :  %s " % (val))
+            print("Math :      %s " % (pt.to_python_expr()))
 
             assert str(pt) == val
             print("Success")
         except Exception as e:
             if not should_fail:
-                print("Exception thrown %s"%e)
-                assert 1==2
+                print("Exception thrown %s" % e)
+                assert 1 == 2
             else:
                 print("Successfully failed")
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     TestParser().test_parser()
diff --git a/lems/test/test_units.py b/lems/test/test_units.py
index 7552ad6..cb324a8 100644
--- a/lems/test/test_units.py
+++ b/lems/test/test_units.py
@@ -6,7 +6,7 @@
 
 
 import unittest
-from lems.model.fundamental import Dimension,Unit
+from lems.model.fundamental import Dimension, Unit
 from lems.model.model import Model
 
 
@@ -15,48 +15,51 @@ def get_model(self):
 
         model = Model()
 
-        model.add(Dimension('voltage', m=1, l=3, t=-3, i=-1))
-        model.add(Dimension('time', t=1))
-        model.add(Dimension('capacitance', m=-1, l=-2, t=4, i=2))
-        model.add(Dimension('conductanceDensity', m="-1", l="-4", t="3", i="2"))
-        model.add(Dimension('temperature', k=1))
+        model.add(Dimension("voltage", m=1, l=3, t=-3, i=-1))
+        model.add(Dimension("time", t=1))
+        model.add(Dimension("capacitance", m=-1, l=-2, t=4, i=2))
+        model.add(Dimension("conductanceDensity", m="-1", l="-4", t="3", i="2"))
+        model.add(Dimension("temperature", k=1))
 
-        model.add(Unit('volt', 'V', 'voltage', 0))
-        model.add(Unit('milliVolt', 'mV', 'voltage', -3))
-        model.add(Unit('milliSecond', 'ms', 'time', -3))
-        model.add(Unit('microFarad', 'uF', 'capacitance', -12))
-        model.add(Unit('mS_per_cm2', 'mS_per_cm2', 'conductanceDensity', 1))
+        model.add(Unit("volt", "V", "voltage", 0))
+        model.add(Unit("milliVolt", "mV", "voltage", -3))
+        model.add(Unit("milliSecond", "ms", "time", -3))
+        model.add(Unit("microFarad", "uF", "capacitance", -12))
+        model.add(Unit("mS_per_cm2", "mS_per_cm2", "conductanceDensity", 1))
 
-        model.add(Unit('Kelvin', 'K', 'temperature', 0))
-        model.add(Unit('celsius', 'degC', 'temperature', 0, offset=273.15))
+        model.add(Unit("Kelvin", "K", "temperature", 0))
+        model.add(Unit("celsius", "degC", "temperature", 0, offset=273.15))
 
-        model.add(Unit('hour', 'hour', 'time', scale=3600))
-        model.add(Unit('min', 'min', 'time', scale=60))
+        model.add(Unit("hour", "hour", "time", scale=3600))
+        model.add(Unit("min", "min", "time", scale=60))
 
         return model
 
     def check_num_val(self, unit_str, val, dimension=None):
         val2 = self.get_model().get_numeric_value(unit_str, dimension)
-        print("Ensuring %s returns %f in SI units of %s; it returns %f"%(unit_str, val, dimension, val2))
+        print(
+            "Ensuring %s returns %f in SI units of %s; it returns %f"
+            % (unit_str, val, dimension, val2)
+        )
         self.assertAlmostEqual(val, val2)
 
     def test_parse_units(self):
-        self.check_num_val('-60mV', -0.06, 'voltage')
-        self.check_num_val('1V', 1, 'voltage')
-        self.check_num_val('10 K', 10)
-        self.check_num_val('0 K', 0)
-        self.check_num_val('0 degC', 273.15)
-        self.check_num_val('-40 degC', 233.15)
-
-        self.check_num_val('1.1e-2 ms', 0.000011, 'time')
-        self.check_num_val('5E-24', 5E-24)
-        self.check_num_val('1.1ms', 0.0011)
-        self.check_num_val('-60mV', -0.060)
-        self.check_num_val('-60', -60)
-        self.check_num_val('1.1e-2 ms', 0.000011)
-
-        self.check_num_val('10.5 mS_per_cm2', 105, 'conductanceDensity')
-        self.check_num_val('10.5 mS_per_cm2', 105)
-
-        self.check_num_val('1 hour', 3600)
-        self.check_num_val('30 min', 30*60)
+        self.check_num_val("-60mV", -0.06, "voltage")
+        self.check_num_val("1V", 1, "voltage")
+        self.check_num_val("10 K", 10)
+        self.check_num_val("0 K", 0)
+        self.check_num_val("0 degC", 273.15)
+        self.check_num_val("-40 degC", 233.15)
+
+        self.check_num_val("1.1e-2 ms", 0.000011, "time")
+        self.check_num_val("5E-24", 5e-24)
+        self.check_num_val("1.1ms", 0.0011)
+        self.check_num_val("-60mV", -0.060)
+        self.check_num_val("-60", -60)
+        self.check_num_val("1.1e-2 ms", 0.000011)
+
+        self.check_num_val("10.5 mS_per_cm2", 105, "conductanceDensity")
+        self.check_num_val("10.5 mS_per_cm2", 105)
+
+        self.check_num_val("1 hour", 3600)
+        self.check_num_val("30 min", 30 * 60)