Repository: LEMS/pylems (language: python)

Issue:
Feat/get exposures
Adds methods to `Model` to get the exposures from defined `Component`s. Also adds simple tests.


Discussion / hints:

Fix patch:
diff --git a/.flake8 b/.flake8
new file mode 100644
index 0000000..39fa7d4
--- /dev/null
+++ b/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+exclude = NeuroML2
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..a2cfdad
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,59 @@
+name: Build
+
+on:
+  push:
+    branches: [ master, development ]
+  pull_request:
+    branches: [ master, development ]
+
+jobs:
+  build:
+
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        python-version: [2.7, 3.7, 3.8, 3.9]
+
+    steps:
+    - uses: actions/checkout@v2
+
+    - name: Set up Python ${{ matrix.python-version }}
+      uses: actions/setup-python@v2
+      with:
+        python-version: ${{ matrix.python-version }}
+
+    - name: Install dependencies
+      run: |
+        python -m pip install --upgrade pip
+        python -m pip install flake8 pytest
+        if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
+
+    - name: Checkout NeuroML2
+      uses: actions/checkout@v2
+      with:
+        repository: NeuroML/NeuroML2
+        ref: development
+        path: NeuroML2
+
+    - name: Build package
+      run: |
+        pip install .
+
+    - name: Test with pytest
+      run: |
+        pytest
+
+    - name: Test examples
+      run: |
+        ./ci/run-examples-ghactions.sh
+
+    - name: Test API tests
+      run: |
+        ./ci/run-apitest.sh
+
+    - name: Lint with flake8
+      run: |
+        # stop the build if there are Python syntax errors or undefined names
+        flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
+        # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
+        flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
diff --git a/.gitignore b/.gitignore
index 5d60493..00f8a01 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,7 +5,7 @@ results
 test*.sh
 build
 *~
-doc
+doc/_build
 *.pyc
 *.pyo
 .project
diff --git a/.travis.yml b/.travis.yml
index 9380914..f45a0da 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,6 +9,7 @@ python:
 # command to install dependencies
 install:
   - "pip install ."
+  - "pip install pytest"
   - git clone https://github.com/NeuroML/NeuroML2
   - cd NeuroML2
   # Use the development branch of NeuroML2
@@ -20,7 +21,7 @@ install:
 script:
   ###       Run main python unit tests (not many yet...)
 
-  - nosetests -vs
+  - pytest -v
 
   ###      Try running "standard" LEMS examples
   - ./pylems examples/example1.xml -nogui
diff --git a/README.md b/README.md
index 236a865..f54b5eb 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,8 @@
 ## PyLEMS 
 
+[![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.
 
 For more about PyLEMS see:
diff --git a/ci/run-examples-ghactions.sh b/ci/run-examples-ghactions.sh
new file mode 100755
index 0000000..8d54972
--- /dev/null
+++ b/ci/run-examples-ghactions.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+# Copyright 2021 LEMS contributors
+# Author: Ankur Sinha <sanjay DOT ankur AT gmail DOT com> 
+# File : run-examples-ghactions.sh
+#
+# Run tests on GitHub actions
+
+mkdir results
+
+###      Try running "standard" LEMS examples
+echo "Running standard LEMS examples"
+./pylems examples/example1.xml -nogui
+./pylems examples/example2.xml -nogui
+./pylems examples/example3.xml -nogui
+#./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
+# 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
+echo "Running NeuroML2 examples"
+./pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex0_IaF.xml -nogui
+./pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex1_HH.xml -nogui
+./pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex2_Izh.xml -nogui
+./pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex3_Net.xml -nogui
+#./pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex4_KS.xml -nogui  # Not working (Unsupported in PyLEMS: KSChannel)
+./pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex5_DetCell.xml -nogui
+./pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex6_NMDA.xml -nogui
+./pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex7_STP.xml -nogui
+./pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex8_AdEx.xml -nogui
+./pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex9_FN.xml -nogui
+#./pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex10_Q10.xml -nogui
+./pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex11_STDP.xml -nogui
+
+./pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex13_Instances.xml -nogui
+
+#./pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex15_CaDynamics.xml -nogui
+
+#./pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex17_Tissue.xml -nogui
+#./pylems -I NeuroML2/NeuroML2CoreTypes/ NeuroML2/LEMSexamples/LEMS_NML2_Ex18_GHK.xml -nogui  # Mismatch...
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000..337d573
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,153 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = _build
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html       to make standalone HTML files"
+	@echo "  dirhtml    to make HTML files named index.html in directories"
+	@echo "  singlehtml to make a single large HTML file"
+	@echo "  pickle     to make pickle files"
+	@echo "  json       to make JSON files"
+	@echo "  htmlhelp   to make HTML files and a HTML help project"
+	@echo "  qthelp     to make HTML files and a qthelp project"
+	@echo "  devhelp    to make HTML files and a Devhelp project"
+	@echo "  epub       to make an epub"
+	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
+	@echo "  text       to make text files"
+	@echo "  man        to make manual pages"
+	@echo "  texinfo    to make Texinfo files"
+	@echo "  info       to make Texinfo files and run them through makeinfo"
+	@echo "  gettext    to make PO message catalogs"
+	@echo "  changes    to make an overview of all changed/added/deprecated items"
+	@echo "  linkcheck  to check all external links for integrity"
+	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+	-rm -rf $(BUILDDIR)/*
+
+html:
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+	@echo
+	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+json:
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+	@echo
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
+	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/PyLEMS.qhcp"
+	@echo "To view the help file:"
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PyLEMS.qhc"
+
+devhelp:
+	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+	@echo
+	@echo "Build finished."
+	@echo "To view the help file:"
+	@echo "# mkdir -p $$HOME/.local/share/devhelp/PyLEMS"
+	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/PyLEMS"
+	@echo "# devhelp"
+
+epub:
+	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+	@echo
+	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+	@echo "Run \`make' in that directory to run these through (pdf)latex" \
+	      "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo "Running LaTeX files through pdflatex..."
+	$(MAKE) -C $(BUILDDIR)/latex all-pdf
+	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+	@echo
+	@echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+	@echo
+	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo
+	@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+	@echo "Run \`make' in that directory to run these through makeinfo" \
+	      "(use \`make info' here to do that automatically)."
+
+info:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo "Running Texinfo files through makeinfo..."
+	make -C $(BUILDDIR)/texinfo info
+	@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+	$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+	@echo
+	@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+	@echo
+	@echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+	@echo "Testing of doctests in the sources finished, look at the " \
+	      "results in $(BUILDDIR)/doctest/output.txt."
diff --git a/doc/conf.py b/doc/conf.py
new file mode 100644
index 0000000..5217193
--- /dev/null
+++ b/doc/conf.py
@@ -0,0 +1,256 @@
+# -*- coding: utf-8 -*-
+#
+# PyLEMS documentation build configuration file, created by
+# sphinx-quickstart on Wed Mar 21 08:17:12 2012.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys
+import os
+
+# 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('../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'
+
+# 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']
+
+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']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+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
+# built documents.
+#
+# The short X.Y version.
+version = ""
+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]
+# 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
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#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']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#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
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#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'
+
+# 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 = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+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
+
+# 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']
+
+# 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'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is 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 = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'pylemsdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+latex_elements = {}
+
+# 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'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# 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)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (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'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
diff --git a/doc/index.rst b/doc/index.rst
new file mode 100644
index 0000000..a90f17b
--- /dev/null
+++ b/doc/index.rst
@@ -0,0 +1,14 @@
+PyLEMS: documentation
+==========================
+
+Welcome to the PyLEMS API documentation.
+For more information on LEMS, please see: http://lems.github.io/LEMS/
+
+User documentation
+************************
+
+.. toctree::
+   :maxdepth: 3
+
+   modules
+
diff --git a/doc/lems.base.rst b/doc/lems.base.rst
new file mode 100644
index 0000000..940b512
--- /dev/null
+++ b/doc/lems.base.rst
@@ -0,0 +1,53 @@
+lems.base package
+=================
+
+Submodules
+----------
+
+lems.base.base module
+---------------------
+
+.. automodule:: lems.base.base
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+lems.base.errors module
+-----------------------
+
+.. automodule:: lems.base.errors
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+lems.base.map module
+--------------------
+
+.. automodule:: lems.base.map
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+lems.base.stack module
+----------------------
+
+.. automodule:: lems.base.stack
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+lems.base.util module
+---------------------
+
+.. automodule:: lems.base.util
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+Module contents
+---------------
+
+.. automodule:: lems.base
+   :members:
+   :undoc-members:
+   :show-inheritance:
diff --git a/doc/lems.dlems.rst b/doc/lems.dlems.rst
new file mode 100644
index 0000000..fa36c19
--- /dev/null
+++ b/doc/lems.dlems.rst
@@ -0,0 +1,21 @@
+lems.dlems package
+==================
+
+Submodules
+----------
+
+lems.dlems.exportdlems module
+-----------------------------
+
+.. automodule:: lems.dlems.exportdlems
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+Module contents
+---------------
+
+.. automodule:: lems.dlems
+   :members:
+   :undoc-members:
+   :show-inheritance:
diff --git a/doc/lems.model.rst b/doc/lems.model.rst
new file mode 100644
index 0000000..50413b8
--- /dev/null
+++ b/doc/lems.model.rst
@@ -0,0 +1,61 @@
+lems.model package
+==================
+
+Submodules
+----------
+
+lems.model.component module
+---------------------------
+
+.. automodule:: lems.model.component
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+lems.model.dynamics module
+--------------------------
+
+.. automodule:: lems.model.dynamics
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+lems.model.fundamental module
+-----------------------------
+
+.. automodule:: lems.model.fundamental
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+lems.model.model module
+-----------------------
+
+.. automodule:: lems.model.model
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+lems.model.simulation module
+----------------------------
+
+.. automodule:: lems.model.simulation
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+lems.model.structure module
+---------------------------
+
+.. automodule:: lems.model.structure
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+Module contents
+---------------
+
+.. automodule:: lems.model
+   :members:
+   :undoc-members:
+   :show-inheritance:
diff --git a/doc/lems.parser.rst b/doc/lems.parser.rst
new file mode 100644
index 0000000..0bc918b
--- /dev/null
+++ b/doc/lems.parser.rst
@@ -0,0 +1,29 @@
+lems.parser package
+===================
+
+Submodules
+----------
+
+lems.parser.LEMS module
+-----------------------
+
+.. automodule:: lems.parser.LEMS
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+lems.parser.expr module
+-----------------------
+
+.. automodule:: lems.parser.expr
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+Module contents
+---------------
+
+.. automodule:: lems.parser
+   :members:
+   :undoc-members:
+   :show-inheritance:
diff --git a/doc/lems.rst b/doc/lems.rst
new file mode 100644
index 0000000..24b5c5c
--- /dev/null
+++ b/doc/lems.rst
@@ -0,0 +1,41 @@
+lems package
+============
+
+Subpackages
+-----------
+
+.. toctree::
+   :maxdepth: 4
+
+   lems.base
+   lems.dlems
+   lems.model
+   lems.parser
+   lems.sim
+
+Submodules
+----------
+
+lems.api module
+---------------
+
+.. automodule:: lems.api
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+lems.run module
+---------------
+
+.. automodule:: lems.run
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+Module contents
+---------------
+
+.. automodule:: lems
+   :members:
+   :undoc-members:
+   :show-inheritance:
diff --git a/doc/lems.sim.rst b/doc/lems.sim.rst
new file mode 100644
index 0000000..b61a78b
--- /dev/null
+++ b/doc/lems.sim.rst
@@ -0,0 +1,45 @@
+lems.sim package
+================
+
+Submodules
+----------
+
+lems.sim.build module
+---------------------
+
+.. automodule:: lems.sim.build
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+lems.sim.recording module
+-------------------------
+
+.. automodule:: lems.sim.recording
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+lems.sim.runnable module
+------------------------
+
+.. automodule:: lems.sim.runnable
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+lems.sim.sim module
+-------------------
+
+.. automodule:: lems.sim.sim
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+Module contents
+---------------
+
+.. automodule:: lems.sim
+   :members:
+   :undoc-members:
+   :show-inheritance:
diff --git a/doc/migrate_docstrings.sh b/doc/migrate_docstrings.sh
new file mode 100755
index 0000000..3d86b10
--- /dev/null
+++ b/doc/migrate_docstrings.sh
@@ -0,0 +1,58 @@
+#!/usr/bin/env bash
+#
+# Script for migrating from epydoc to Sphinx style docstrings.
+#
+# WARNING: THIS SCRIPT MODIFIES FILES IN PLACE. BE SURE TO BACKUP THEM BEFORE
+# RUNNING IT.
+
+DIRECTORY=$1
+
+SED=`which gsed gnused sed`
+
+for value in $SED
+do
+    SED=${value}
+    break
+done
+
+if [ ! $DIRECTORY ]; then
+    echo "Usage: ./migrate_docstrings.sh <directory with your code>"
+    exit 1
+fi
+
+OLD_VALUES[0]='@type'
+OLD_VALUES[1]='@keyword'
+OLD_VALUES[2]='@param'
+OLD_VALUES[3]='@return'
+OLD_VALUES[4]='@rtype'
+OLD_VALUES[5]='L{\([^}]\+\)}'
+OLD_VALUES[6]='C{\(int\|float\|str\|list\|tuple\|dict\|bool\|None\|generator\|object\)}'
+OLD_VALUES[7]='@\(ivar\|cvar\|var\)'
+OLD_VALUES[8]='@raise'
+OLD_VALUES[9]='@author'
+OLD_VALUES[10]='@organization'
+OLD_VALUES[11]='@contact'
+
+NEW_VALUES[0]=':type'
+NEW_VALUES[1]=':keyword'
+NEW_VALUES[2]=':param'
+NEW_VALUES[3]=':return'
+NEW_VALUES[4]=':rtype'
+NEW_VALUES[5]=':class:`\1`'
+NEW_VALUES[6]='``\1``'
+NEW_VALUES[7]=':\1'
+NEW_VALUES[8]=':raises'
+NEW_VALUES[9]=':codeauthor'
+NEW_VALUES[10]=':organization'
+NEW_VALUES[11]=':contact'
+
+for (( i = 0 ; i < ${#OLD_VALUES[@]} ; i++ ))
+do
+    old_value=${OLD_VALUES[$i]}
+    new_value=${NEW_VALUES[$i]}
+
+    cmd="find ${DIRECTORY} -name '*.py' -type f -print0 | xargs -0 ${SED} -i -e 's/${old_value}/${new_value}/g'"
+
+    echo "Migrating: ${old_value} -> ${new_value}"
+    eval "$cmd"
+done
diff --git a/doc/modules.rst b/doc/modules.rst
new file mode 100644
index 0000000..5e27e70
--- /dev/null
+++ b/doc/modules.rst
@@ -0,0 +1,7 @@
+lems
+====
+
+.. toctree::
+   :maxdepth: 4
+
+   lems
diff --git a/doc/requirements.txt b/doc/requirements.txt
new file mode 100644
index 0000000..ef36add
--- /dev/null
+++ b/doc/requirements.txt
@@ -0,0 +1,1 @@
+sphinxcontrib-bibtex
diff --git a/lems/__init__.py b/lems/__init__.py
index 443be22..b443f56 100644
--- a/lems/__init__.py
+++ b/lems/__init__.py
@@ -1,11 +1,14 @@
 """
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
 
 import logging
 
 logger = logging.getLogger('LEMS')
 
-__version__ = '0.5.2'
+__version__ = '0.5.4'
+
+__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__)
diff --git a/lems/api.py b/lems/api.py
index fed2702..232199b 100644
--- a/lems/api.py
+++ b/lems/api.py
@@ -1,9 +1,8 @@
 """
 PyLEMS API module.
 
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
 
 from lems.model.fundamental import *
diff --git a/lems/base/__init__.py b/lems/base/__init__.py
index aaeb1c4..e6b819c 100644
--- a/lems/base/__init__.py
+++ b/lems/base/__init__.py
@@ -1,5 +1,4 @@
 """
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
diff --git a/lems/base/base.py b/lems/base/base.py
index 3fa5823..dd42a32 100644
--- a/lems/base/base.py
+++ b/lems/base/base.py
@@ -1,9 +1,8 @@
 """
 PyLEMS base class.
 
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
 
 import copy
diff --git a/lems/base/errors.py b/lems/base/errors.py
index a0b21db..19064db 100644
--- a/lems/base/errors.py
+++ b/lems/base/errors.py
@@ -1,9 +1,8 @@
 """
 Error classes.
 
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
 
 class LEMSError(Exception):
@@ -15,19 +14,19 @@ def __init__(self, message, *params, **key_params):
         """
         Constructor
 
-        @param message: Error message.
-        @type message: string
+        :param message: Error message.
+        :type message: string
 
-        @param params: Optional arguments for formatting.
-        @type params: list
+        :param params: Optional arguments for formatting.
+        :type params: list
 
-        @param key_params: Named arguments for formatting.
-        @type key_params: dict
+        :param key_params: Named arguments for formatting.
+        :type key_params: dict
         """
         
         self.message = None
         """ Error message
-        @type: string """
+        :type: string """
 
         if params:
             if key_params:
@@ -44,8 +43,8 @@ def __str__(self):
         """
         Returns the error message string.
 
-        @return: The error message
-        @rtype: string
+        :return: The error message
+        :rtype: string
         """
         
         return self.message
diff --git a/lems/base/map.py b/lems/base/map.py
index c8de244..3435438 100644
--- a/lems/base/map.py
+++ b/lems/base/map.py
@@ -1,9 +1,8 @@
 """
 Map class.
 
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
 
 from lems.base.base import LEMSBase
diff --git a/lems/base/stack.py b/lems/base/stack.py
index a9c6ddc..abfd09b 100644
--- a/lems/base/stack.py
+++ b/lems/base/stack.py
@@ -1,9 +1,8 @@
 """
 Stack class.
 
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
 
 from lems.base.base import LEMSBase
@@ -21,14 +20,14 @@ def __init__(self):
 
         self.stack = []
         """ List used to store the stack contents.
-        @type: list """
+        :type: list """
 
     def push(self, val):
         """
         Pushed a value onto the stack.
 
-        @param val: Value to be pushed.
-        @type val: *
+        :param val: Value to be pushed.
+        :type val: *
         """
 
         self.stack = [val] + self.stack
@@ -37,10 +36,10 @@ def pop(self):
         """
         Pops a value off the top of the stack.
 
-        @return: Value popped off the stack.
-        @rtype: *
+        :return: Value popped off the stack.
+        :rtype: *
 
-        @raise StackError: Raised when there is a stack underflow.
+        :raises StackError: Raised when there is a stack underflow.
         """
 
         if self.stack:
@@ -54,10 +53,10 @@ def top(self):
         """
         Returns the value off the top of the stack without popping.
 
-        @return: Value on the top of the stack.
-        @rtype: *
+        :return: Value on the top of the stack.
+        :rtype: *
 
-        @raise StackError: Raised when there is a stack underflow.
+        :raises StackError: Raised when there is a stack underflow.
         """
 
         if self.stack:
@@ -69,8 +68,8 @@ def is_empty(self):
         """
         Checks if the stack is empty.
 
-        @return: True if the stack is empty, otherwise False.
-        @rtype: Boolean
+        :return: True if the stack is empty, otherwise False.
+        :rtype: Boolean
         """
 
         return self.stack == []
diff --git a/lems/base/util.py b/lems/base/util.py
index 19e48f0..3425455 100644
--- a/lems/base/util.py
+++ b/lems/base/util.py
@@ -1,11 +1,13 @@
 """
 PyLEMS utility classes / functions
 
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
 
+from lems import __schema_location__
+
+
 id_counter = 0
 
 def make_id():
@@ -17,11 +19,11 @@ 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 m: Map to be merged into.
+    :type m: lems.util.Map
     
-    @param base: Map to be merged into.
-    @type base: lems.util.Map
+    :param base: Map to be merged into.
+    :type base: lems.util.Map
     """
     
     for k in base.keys():
@@ -32,11 +34,11 @@ def merge_lists(l, base):
     """
     Merge in undefined list entries from given list.
     
-    @param l: List to be merged into.
-    @type l: list
+    :param l: List to be merged into.
+    :type l: list
     
-    @param base: List to be merged into.
-    @type base: list
+    :param base: List to be merged into.
+    :type base: list
     """
     
     for i in base:
@@ -52,7 +54,7 @@ def validate_lems(file_name):
     except:
         from urllib.request import urlopen # Python 3
         
-    schema_file = urlopen("https://raw.githubusercontent.com/LEMS/LEMS/development/Schemas/LEMS/LEMS_v0.7.3.xsd")
+    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))
diff --git a/lems/dlems/__init__.py b/lems/dlems/__init__.py
index 8e85ac2..21249e8 100644
--- a/lems/dlems/__init__.py
+++ b/lems/dlems/__init__.py
@@ -1,4 +1,4 @@
 """
-@author: Padraig Gleeson
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
+:author: Padraig Gleeson
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
diff --git a/lems/dlems/exportdlems.py b/lems/dlems/exportdlems.py
index fb3642b..1298fc2 100644
--- a/lems/dlems/exportdlems.py
+++ b/lems/dlems/exportdlems.py
@@ -2,7 +2,7 @@
 """
 Exporter for dLEMS (formerly SOM). See https://github.com/borismarin/som-codegen
 
-@author: Boris Marin
+:author: Boris Marin
 """
 
 import sys
diff --git a/lems/model/__init__.py b/lems/model/__init__.py
index aaeb1c4..e6b819c 100644
--- a/lems/model/__init__.py
+++ b/lems/model/__init__.py
@@ -1,5 +1,4 @@
 """
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
diff --git a/lems/model/component.py b/lems/model/component.py
index 245c13d..18d59b4 100644
--- a/lems/model/component.py
+++ b/lems/model/component.py
@@ -1,9 +1,8 @@
 """
 Parameter, ComponentType and Component class definitions.
 
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
 
 from lems.base.base import LEMSBase
@@ -29,31 +28,31 @@ def __init__(self, name, dimension, description = ''):
         
         self.name = name
         """ Name of the parameter.
-        @type: str """
+        :type: str """
          
         self.dimension = dimension
         """ Physical dimension of the parameter.
-        @type: str """
+        :type: str """
 
         self.fixed = False
         """ Whether the parameter has been fixed or not.
-        @type: bool """
+        :type: bool """
         
         self.fixed_value = None
         """ Value if fixed.
-        @type: str """
+        :type: str """
 
         self.value = None
         """ Value of the parameter.
-        @type: str """
+        :type: str """
 
         self.numeric_value = None
         """ Resolved numeric value.
-        @type: float """
+        :type: float """
 
         self.description = description
         """ Description of this parameter.
-        @type: str """
+        :type: str """
 
     def toxml(self):
         """
@@ -111,19 +110,19 @@ def __init__(self, name, dimension = None, default_value = None, description = '
 
         self.name = name
         """ Name of the property.
-        @type: str """
+        :type: str """
 
         self.dimension = dimension
         """ Physical dimensions of the property.
-        @type: str """
+        :type: str """
         
         self.description = description
         """ Description of the property.
-        @type: str """
+        :type: str """
         
         self.default_value = default_value
         """ Default value of the property.
-        @type: float """
+        :type: float """
 
     def toxml(self):
         """
@@ -148,11 +147,11 @@ def __init__(self, name, description = ''):
 
         self.name = name
         """ Name of the parameter.
-        @type: str """
+        :type: str """
         
         self.description = description
         """ Description of this parameter.
-        @type: str """
+        :type: str """
         
         
     def toxml(self):
@@ -179,19 +178,19 @@ def __init__(self, name, value, dimension = None, description = ''):
 
         self.name = name
         """ Name of the derived parameter.
-        @type: str """
+        :type: str """
 
         self.dimension = dimension
         """ Physical dimensions of the derived parameter.
-        @type: str """
+        :type: str """
         
         self.value = value
         """ Value of the derived parameter.
-        @type: str """
+        :type: str """
         
         self.description = description
         """ Description of the derived parameter.
-        @type: str """
+        :type: str """
         
         try:
             ep = ExprParser(self.value)
@@ -211,6 +210,7 @@ def toxml(self):
 
         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 '') +\
           '/>'
 
@@ -228,27 +228,27 @@ def __init__(self, name, value, dimension = None, symbol = None, description = '
         
         self.name = name
         """ Name of the constant.
-        @type: str """
+        :type: str """
         
         self.symbol = symbol
         """ Symbol of the constant.
-        @type: str """
+        :type: str """
 
         self.value = value
         """ Value of the constant.
-        @type: str """
+        :type: str """
 
         self.dimension = dimension
         """ Physical dimensions of the constant.
-        @type: str """
+        :type: str """
 
         self.description = description
         """ Description of the constant.
-        @type: str """
+        :type: str """
 
         self.numeric_value = None
         """ Numeric value of the constant.
-        @type: float """
+        :type: float """
 
     def toxml(self):
         """
@@ -278,15 +278,15 @@ def __init__(self, name, dimension, description = ''):
         
         self.name = name
         """ Name of the exposure.
-        @type: str """
+        :type: str """
          
         self.dimension = dimension
         """ Physical dimension of the exposure.
-        @type: str """
+        :type: str """
 
         self.description = description
         """ Description of this exposure.
-        @type: str """
+        :type: str """
 
     def toxml(self):
         """
@@ -311,15 +311,15 @@ def __init__(self, name, dimension, description = ''):
         
         self.name = name
         """ Name of the requirement.
-        @type: str """
+        :type: str """
          
         self.dimension = dimension
         """ Physical dimension of the requirement.
-        @type: str """
+        :type: str """
         
         self.description = description
         """ Description of this requirement.
-        @type: str """
+        :type: str """
 
     def toxml(self):
         """
@@ -343,11 +343,11 @@ def __init__(self, name, description = ''):
 
         self.name = name
         """ Name of the Component required.
-        @type: str """
+        :type: str """
         
         self.description = description
         """ Description of this ComponentRequirement.
-        @type: str """
+        :type: str """
         
         
     def toxml(self):
@@ -372,15 +372,15 @@ def __init__(self, name, type, description = ''):
         
         self.name = name
         """ Name of the instance requirement.
-        @type: str """
+        :type: str """
          
         self.type = type
         """ Type of the instance required.
-        @type: str """
+        :type: str """
         
         self.description = description
         """ Description of this InstanceRequirement.
-        @type: str """
+        :type: str """
 
     def toxml(self):
         """
@@ -396,7 +396,7 @@ class Children(LEMSBase):
     Stores children specification.
     """
     
-    def __init__(self, name, type_, multiple = False):
+    def __init__(self, name, type_, description = "", multiple = False):
         """
         Constructor.
 
@@ -405,22 +405,26 @@ def __init__(self, name, type_, multiple = False):
         
         self.name = name
         """ Name of the children.
-        @type: str """
+        :type: str """
          
         self.type = type_
         """ Component type of the children.
-        @type: str """
+        :type: str """
+
+        self.description = description
+        """ Description of the children.
+        :type: str """
 
         self.multiple = multiple
         """ Single child / multiple children.
-        @type: bool """
+        :type: bool """
 
     def toxml(self):
         """
         Exports this object into a LEMS XML object
         """
 
-        return '<{2} name="{0}" type="{1}"/>'.format(self.name, self.type, 'Children' if self.multiple else 'Child')
+        return '<{3} name="{0}" type="{1}" description="{2}"/>'.format(self.name, self.type, self.description, 'Children' if self.multiple else 'Child')
 
 class Text(LEMSBase):
     """
@@ -436,15 +440,15 @@ def __init__(self, name, description = ''):
         
         self.name = name
         """ Name of the text entry.
-        @type: str """
+        :type: str """
          
         self.description = description
         """ Description of the text entry.
-        @type: str """
+        :type: str """
 
         self.value = None
         """ Value of the text entry.
-        @type: str """
+        :type: str """
 
     def toxml(self):
         """
@@ -479,19 +483,19 @@ def __init__(self, name, type_, description = ''):
         
         self.name = name
         """ Name of the link entry.
-        @type: str """
+        :type: str """
 
         self.type = type_
         """ Type of the link.
-        @type: str """
+        :type: str """
          
         self.description = description
         """ Description of the link.
-        @type: str """
+        :type: str """
 
         self.value = None
         """ Value of the link.
-        @type: str """
+        :type: str """
 
     def toxml(self):
         """
@@ -517,15 +521,15 @@ def __init__(self, name, description = ''):
         
         self.name = name
         """ Name of the path entry.
-        @type: str """
+        :type: str """
          
         self.description = description
         """ Description of the path entry.
-        @type: str """
+        :type: str """
 
         self.value = None
         """ Value of the path entry.
-        @type: str """
+        :type: str """
 
     def toxml(self):
         """
@@ -550,7 +554,7 @@ def __init__(self, name, direction, description = ''):
         
         self.name = name
         """ Name of the event port.
-        @type: str """
+        :type: str """
 
         d = direction.lower()
         if d != 'in' and d != 'out':
@@ -558,11 +562,11 @@ def __init__(self, name, direction, description = ''):
          
         self.direction = direction
         """ Direction - IN/OUT .
-        @type: str """
+        :type: str """
 
         self.description = description
         """ Description of the event port.
-        @type: str """
+        :type: str """
 
     def toxml(self):
         """
@@ -587,19 +591,19 @@ def __init__(self, name, type_, local=None):
 
         self.name = name
         """ Name of the component reference.
-        @type: str """
+        :type: str """
 
         self.type = type_
         """ Type of the component reference.
-        @type: str """
+        :type: str """
 
         self.local = local
         """ ???
-        @type: str """
+        :type: str """
 
         self.referenced_component = None
         """ Component being referenced.
-        @type: FatComponent """
+        :type: FatComponent """
 
     def toxml(self):
         """
@@ -624,15 +628,15 @@ def __init__(self, name, type_, description = ''):
 
         self.name = name
         """ Name of the attachment collection.
-        @type: str """
+        :type: str """
 
         self.type = type_
         """ Type of attachment.
-        @type: str """
+        :type: str """
 
         self.description = description
         """ Description about the attachment.
-        @type: str """
+        :type: str """
 
     def toxml(self):
         """
@@ -657,90 +661,90 @@ def __init__(self):
         
         self.parameters = Map()
         """ Map of parameters in this component type.
-        @type: Map(str -> lems.model.component.Parameter) """
+        :type: Map(str -> lems.model.component.Parameter) """
         
         self.properties = Map()
         """ Map of properties in this component type.
-        @type: Map(str -> lems.model.component.Property) """
+        :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) """
+        :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) """
+        :type: Map(str -> lems.model.component.IndexParameter) """
 
         self.constants = Map()
         """ Map of constants in this component type.
-        @type: Map(str -> lems.model.component.Constant) """
+        :type: Map(str -> lems.model.component.Constant) """
 
         self.exposures = Map()
         """ Map of exposures in this component type.
-        @type: Map(str -> lems.model.component.Exposure) """
+        :type: Map(str -> lems.model.component.Exposure) """
 
         self.requirements = Map()
         """ Map of requirements.
-        @type: Map(str -> lems.model.component.Requirement) """
+        :type: Map(str -> lems.model.component.Requirement) """
 
         self.component_requirements = Map()
         """ Map of component requirements.
-        @type: Map(str -> lems.model.component.ComponentRequirement) """
+        :type: Map(str -> lems.model.component.ComponentRequirement) """
 
         self.instance_requirements = Map()
         """ Map of instance requirements.
-        @type: Map(str -> lems.model.component.InstanceRequirement) """
+        :type: Map(str -> lems.model.component.InstanceRequirement) """
 
         self.children = Map()
         """ Map of children.
-        @type: Map(str -> lems.model.component.Children) """
+        :type: Map(str -> lems.model.component.Children) """
 
         self.texts = Map()
         """ Map of text entries.
-        @type: Map(str -> lems.model.component.Text) """
+        :type: Map(str -> lems.model.component.Text) """
 
         self.links = Map()
         """ Map of links.
-        @type: Map(str -> lems.model.component.Link) """
+        :type: Map(str -> lems.model.component.Link) """
 
         self.paths = Map()
         """ Map of path entries.
-        @type: Map(str -> lems.model.component.Path) """
+        :type: Map(str -> lems.model.component.Path) """
 
         self.event_ports = Map()
         """ Map of event ports.
-        @type: Map(str -> lems.model.component.EventPort """
+        :type: Map(str -> lems.model.component.EventPort """
 
         self.component_references = Map()
         """ Map of component references.
-        @type: Map(str -> lems.model.component.ComponentReference) """
+        :type: Map(str -> lems.model.component.ComponentReference) """
 
         self.attachments = Map()
         """ Map of attachment type specifications.
-        @type: Map(str -> lems.model.component.Attachments) """
+        :type: Map(str -> lems.model.component.Attachments) """
 
         self.dynamics = Dynamics()
         """ Behavioural dynamics object.
-        @type: lems.model.dynamics.Dynamics """
+        :type: lems.model.dynamics.Dynamics """
 
         self.structure = Structure()
         """ Structural properties object.
-        @type: lems.model.structure.Structure """
+        :type: lems.model.structure.Structure """
 
         self.simulation = Simulation()
         """ Simulation attributes.
-        @type: lems.model.simulation.Simulation """
+        :type: lems.model.simulation.Simulation """
 
         self.types = set()
         """ Set of compatible component types.
-        @type: set(str) """
+        :type: set(str) """
         
     def add_parameter(self, parameter):
         """
         Adds a paramter to this component type.
 
-        @param parameter: Parameter to be added.
-        @type parameter: lems.model.component.Parameter
+        :param parameter: Parameter to be added.
+        :type parameter: lems.model.component.Parameter
         """
 
         self.parameters[parameter.name] = parameter
@@ -750,8 +754,8 @@ def add_property(self, property):
         """
         Adds a property to this component type.
 
-        @param property: Property to be added.
-        @type property: lems.model.component.Property
+        :param property: Property to be added.
+        :type property: lems.model.component.Property
         """
 
         self.properties[property.name] = property
@@ -760,8 +764,8 @@ def add_derived_parameter(self, derived_parameter):
         """
         Adds a derived_parameter to this component type.
 
-        @param derived_parameter: Derived Parameter to be added.
-        @type derived_parameter: lems.model.component.DerivedParameter
+        :param derived_parameter: Derived Parameter to be added.
+        :type derived_parameter: lems.model.component.DerivedParameter
         """
 
         self.derived_parameters[derived_parameter.name] = derived_parameter
@@ -771,8 +775,8 @@ def add_index_parameter(self, index_parameter):
         """
         Adds an index_parameter to this component type.
 
-        @param index_parameter: Index Parameter to be added.
-        @type index_parameter: lems.model.component.IndexParameter
+        :param index_parameter: Index Parameter to be added.
+        :type index_parameter: lems.model.component.IndexParameter
         """
 
         self.index_parameters[index_parameter.name] = index_parameter
@@ -782,8 +786,8 @@ def add_constant(self, constant):
         """
         Adds a paramter to this component type.
 
-        @param constant: Constant to be added.
-        @type constant: lems.model.component.Constant
+        :param constant: Constant to be added.
+        :type constant: lems.model.component.Constant
         """
 
         self.constants[constant.name] = constant
@@ -793,8 +797,8 @@ def add_exposure(self, exposure):
         """
         Adds a exposure to this component type.
 
-        @param exposure: Exposure to be added.
-        @type exposure: lems.model.component.Exposure
+        :param exposure: Exposure to be added.
+        :type exposure: lems.model.component.Exposure
         """
 
         self.exposures[exposure.name] = exposure
@@ -804,8 +808,8 @@ def add_requirement(self, requirement):
         """
         Adds a requirement to this component type.
 
-        @param requirement: Requirement to be added.
-        @type requirement: lems.model.component.Requirement
+        :param requirement: Requirement to be added.
+        :type requirement: lems.model.component.Requirement
         """
 
         self.requirements[requirement.name] = requirement
@@ -815,8 +819,8 @@ def add_component_requirement(self, component_requirement):
         """
         Adds a component requirement to this component type.
 
-        @param component_requirement: ComponentRequirement to be added.
-        @type component_requirement: lems.model.component.ComponentRequirement
+        :param component_requirement: ComponentRequirement to be added.
+        :type component_requirement: lems.model.component.ComponentRequirement
         """
 
         self.component_requirements[component_requirement.name] = component_requirement
@@ -826,8 +830,8 @@ def add_instance_requirement(self, instance_requirement):
         """
         Adds an instance requirement to this component type.
 
-        @param instance_requirement: InstanceRequirement to be added.
-        @type instance_requirement: lems.model.component.InstanceRequirement
+        :param instance_requirement: InstanceRequirement to be added.
+        :type instance_requirement: lems.model.component.InstanceRequirement
         """
 
         self.instance_requirements[instance_requirement.name] = instance_requirement
@@ -837,8 +841,8 @@ def add_children(self, children):
         """
         Adds children to this component type.
 
-        @param children: Children to be added.
-        @type children: lems.model.component.Children
+        :param children: Children to be added.
+        :type children: lems.model.component.Children
         """
 
         self.children[children.name] = children
@@ -847,8 +851,8 @@ def add_text(self, text):
         """
         Adds a text to this component type.
 
-        @param text: Text to be added.
-        @type text: lems.model.component.Text
+        :param text: Text to be added.
+        :type text: lems.model.component.Text
         """
 
         self.texts[text.name] = text
@@ -857,8 +861,8 @@ def add_link(self, link):
         """
         Adds a link to this component type.
 
-        @param link: Link to be added.
-        @type link: lems.model.component.Link
+        :param link: Link to be added.
+        :type link: lems.model.component.Link
         """
 
         self.links[link.name] = link
@@ -867,8 +871,8 @@ def add_path(self, path):
         """
         Adds a path to this component type.
 
-        @param path: Path to be added.
-        @type path: lems.model.component.Path
+        :param path: Path to be added.
+        :type path: lems.model.component.Path
         """
 
         self.paths[path.name] = path
@@ -877,8 +881,8 @@ def add_event_port(self, event_port):
         """
         Adds a event port to this component type.
 
-        @param event_port: Event port to be added.
-        @type event_port: lems.model.component.EventPort
+        :param event_port: Event port to be added.
+        :type event_port: lems.model.component.EventPort
         """
 
         self.event_ports[event_port.name] = event_port
@@ -887,8 +891,8 @@ def add_component_reference(self, component_reference):
         """
         Adds a component reference to this component type.
 
-        @param component_reference: Component reference to be added.
-        @type component_reference: lems.model.component.ComponentReference
+        :param component_reference: Component reference to be added.
+        :type component_reference: lems.model.component.ComponentReference
         """
 
         self.component_references[component_reference.name] = component_reference
@@ -897,8 +901,8 @@ def add_attachments(self, attachments):
         """
         Adds an attachments type specification to this component type.
 
-        @param attachments: Attachments specification to be added.
-        @type attachments: lems.model.component.Attachments
+        :param attachments: Attachments specification to be added.
+        :type attachments: lems.model.component.Attachments
         """
 
         self.attachments[attachments.name] = attachments
@@ -907,7 +911,7 @@ def add(self, child):
         """
         Adds a typed child object to the component type.
 
-        @param child: Child object to be added.
+        :param child: Child object to be added.
         """
 
         if isinstance(child, Parameter):
@@ -961,15 +965,15 @@ def __init__(self, name, description = '', extends = None):
     
         self.name = name
         """ Name of the component type.
-        @type: str """
+        :type: str """
          
         self.extends = extends
         """ Base component type.
-        @type: str """
+        :type: str """
 
         self.description = description
         """ Description of this component type.
-        @type: str """
+        :type: str """
 
         self.types.add(name)
 
@@ -1069,25 +1073,25 @@ def __init__(self, id_, type_, **params):
 
         self.id = id_
         """ ID of the component.
-        @type: str """
+        :type: str """
 
         self.type = type_
         """ Type of the component.
-        @type: str """
+        :type: str """
 
         self.parameters = dict()
         """ Dictionary of parameter values.
-        @type: str """
+        :type: str """
         for key in params.keys():
             self.parameters[key] = params[key]
 
         self.children = list()
         """ List of child components.
-        @type: list(lems.model.component.Component) """
+        :type: list(lems.model.component.Component) """
         
         self.parent_id = None
         """ Optional id of parent
-        @type: str """
+        :type: str """
         
 
     def __str__(self):
@@ -1100,11 +1104,11 @@ def set_parameter(self, parameter, value):
         """
         Set a parameter.
 
-        @param parameter: Parameter to be set.
-        @type parameter: str
+        :param parameter: Parameter to be set.
+        :type parameter: str
 
-        @param value: Value to be set to.
-        @type value: str
+        :param value: Value to be set to.
+        :type value: str
         """
 
         self.parameters[parameter] = value
@@ -1113,8 +1117,8 @@ def add_child(self, child):
         """
         Adds a child component.
 
-        @param child: Child component to be added.
-        @type child: lems.model.component.Component
+        :param child: Child component to be added.
+        :type child: lems.model.component.Component
         """
 
         self.children.append(child)
@@ -1123,7 +1127,7 @@ def add(self, child):
         """
         Adds a typed child object to the component.
 
-        @param child: Child object to be added.
+        :param child: Child object to be added.
         """
 
         if isinstance(child, Component):
@@ -1135,8 +1139,8 @@ 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
+        :param parent_id: id of the parent Component
+        :type parent_id: str
         """
         
         self.parent_id = parent_id
@@ -1179,19 +1183,19 @@ def __init__(self, id_, type_):
 
         self.id = id_
         """ ID of the component.
-        @type: str """
+        :type: str """
 
         self.type = type_
         """ Type of the component.
-        @type: str """
+        :type: str """
 
         self.child_components = list()
         """ List of child components.
-        @type: lems.model.component.FatComponent """
+        :type: lems.model.component.FatComponent """
         
         self.parent_id = None
         """ Optional id of parent
-        @type: str """
+        :type: str """
         
 
     def __str__(self):
@@ -1203,8 +1207,8 @@ def add_child_component(self, child_component):
         """
         Adds a child component to this fat component.
 
-        @param child_component: Child component to be added.
-        @type child_component: lems.model.component.FatComponent
+        :param child_component: Child component to be added.
+        :type child_component: lems.model.component.FatComponent
         """
 
         self.child_components.append(child_component)
@@ -1213,7 +1217,7 @@ def add(self, child):
         """
         Adds a typed child object to the component type.
 
-        @param child: Child object to be added.
+        :param child: Child object to be added.
         """
 
         if isinstance(child, FatComponent):
@@ -1225,8 +1229,8 @@ 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
+        :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 e96ce63..a4fa763 100644
--- a/lems/model/dynamics.py
+++ b/lems/model/dynamics.py
@@ -1,9 +1,8 @@
 """
 Behavioral dynamics of component types.
 
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
 
 from lems.base.base import LEMSBase
@@ -25,15 +24,15 @@ def __init__(self, name, dimension, exposure = None):
 
         self.name = name
         """ Name of the state variable.
-        @type: str """
+        :type: str """
 
         self.dimension = dimension
         """ Dimension of the state variable.
-        @type: str """
+        :type: str """
 
         self.exposure = exposure
         """ Exposure name for the state variable.
-        @type: str """
+        :type: str """
 
     def __str__(self):
         return 'StateVariable name="{0}" dimension="{1}"'.format(self.name, self.dimension) +\
@@ -63,35 +62,35 @@ def __init__(self, name, **params):
 
         self.name = name
         """ Name of the derived variable.
-        @type: str """
+        :type: str """
 
         self.dimension = params['dimension'] if 'dimension' in params else None
         """ Dimension of the derived variable or None if computed.
-        @type: str """
+        :type: str """
 
         self.exposure = params['exposure'] if 'exposure' in params else None
         """ Exposure name for the derived variable.
-        @type: str """
+        :type: str """
 
         self.select = params['select'] if 'select' in params else None
         """ Selection path/expression for the derived variable.
-        @type: str """
+        :type: str """
 
         self.value = params['value'] if 'value' in params else None
         """ Value of the derived variable.
-        @type: str """
+        :type: str """
 
         self.reduce = params['reduce'] if 'reduce' in params else None
         """ Reduce method for the derived variable.
-        @type: str """
+        :type: str """
 
         self.required = params['required'] if 'required' in params else None
         """ Requried or not.
-        @type: str """
+        :type: str """
 
         self.expression_tree = None
         """ Parse tree for the time derivative expression.
-        @type: lems.parser.expr.ExprNode """
+        :type: lems.parser.expr.ExprNode """
 
         if self.value != None:
             try:
@@ -128,19 +127,19 @@ def __init__(self, condition, value):
 
         self.condition = condition
         """ Condition for this case.
-        @type: str """
+        :type: str """
 
         self.value = value
         """ Value if the condition is true.
-        @type: str """
+        :type: str """
 
         self.condition_expression_tree = None
         """ Parse tree for the case condition expression.
-        @type: lems.parser.expr.ExprNode """
+        :type: lems.parser.expr.ExprNode """
         
         self.value_expression_tree = None
         """ Parse tree for the case condition expression.
-        @type: lems.parser.expr.ExprNode """
+        :type: lems.parser.expr.ExprNode """
         
         try:
             self.value_expression_tree = ExprParser(self.value).parse()
@@ -175,27 +174,27 @@ def __init__(self, name, dimension, exposure = None):
 
         self.name = name
         """ Name of the derived variable.
-        @type: str """
+        :type: str """
 
         self.dimension = dimension
         """ Dimension of the state variable.
-        @type: str """
+        :type: str """
 
         self.exposure = exposure
         """ Exposure name for the state variable.
-        @type: str """
+        :type: str """
         
         self.cases = list()
         """ List of cases related to this conditional derived variable.
-        @type: list(lems.model.dynamics.Case) """
+        :type: list(lems.model.dynamics.Case) """
         
         
     def add_case(self, case):
         """
         Adds a case to this conditional derived variable.
 
-        @param case: Case to be added.
-        @type case: lems.model.dynamics.Case
+        :param case: Case to be added.
+        :type case: lems.model.dynamics.Case
         """
 
         self.cases.append(case)
@@ -204,7 +203,7 @@ def add(self, child):
         """
         Adds a typed child object to the conditional derived variable.
 
-        @param child: Child object to be added.
+        :param child: Child object to be added.
         """
 
         if isinstance(child, Case):
@@ -248,15 +247,15 @@ def __init__(self, variable, value):
 
         self.variable = variable
         """ Name of the variable for which the time derivative is being specified.
-        @type: str """
+        :type: str """
 
         self.value = value
         """ Derivative expression.
-        @type: str """
+        :type: str """
 
         self.expression_tree = None
         """ Parse tree for the time derivative expression.
-        @type: lems.parser.expr.ExprNode """
+        :type: lems.parser.expr.ExprNode """
         
         try:
             self.expression_tree = ExprParser(value).parse()
@@ -295,15 +294,15 @@ def __init__(self, variable, value):
 
         self.variable = variable
         """ Name of the variable for which the time derivative is being specified.
-        @type: str """
+        :type: str """
 
         self.value = value
         """ Derivative expression.
-        @type: str """
+        :type: str """
 
         self.expression_tree = None
         """ Parse tree for the time derivative expression.
-        @type: lems.parser.expr.ExprNode """
+        :type: lems.parser.expr.ExprNode """
 
         try:
             self.expression_tree = ExprParser(value).parse()
@@ -337,7 +336,7 @@ def __init__(self, port):
 
         self.port = port
         """ Port on which the event comes in.
-        @type: str """
+        :type: str """
         
     def toxml(self):
         """
@@ -362,7 +361,7 @@ def __init__(self, regime):
 
         self.regime = regime
         """ Regime to transition to.
-        @type: str """
+        :type: str """
 
     def toxml(self):
         """
@@ -383,7 +382,7 @@ def __init__(self):
 
         self.actions = list()
         """ List of actions to be performed in response to this event.
-        @type: list(lems.model.dynamics.Action) """
+        :type: list(lems.model.dynamics.Action) """
 
     def __str__(self):
         istr = 'EventHandler...'
@@ -393,8 +392,8 @@ def add_action(self, action):
         """
         Adds an action to this event handler.
 
-        @param action: Action to be added.
-        @type action: lems.model.dynamics.Action
+        :param action: Action to be added.
+        :type action: lems.model.dynamics.Action
         """
 
         self.actions.append(action)
@@ -403,7 +402,7 @@ def add(self, child):
         """
         Adds a typed child object to the event handler.
 
-        @param child: Child object to be added.
+        :param child: Child object to be added.
         """
 
         if isinstance(child, Action):
@@ -465,7 +464,7 @@ def __init__(self, test):
 
         self.test = test
         """ Condition to be tested for.
-        @type: str """
+        :type: str """
 
         try:
             self.expression_tree = ExprParser(test).parse()
@@ -511,7 +510,7 @@ def __init__(self, port):
 
         self.port = port
         """ Port on which the event comes in.
-        @type: str """
+        :type: str """
 
     def __str__(self):
         istr = 'OnEvent, port: %s'%self.port
@@ -583,35 +582,35 @@ def __init__(self, name, nodes, state_variable,
 
         self.name = name
         """ Name of the kinetic scheme.
-        @type: str """
+        :type: str """
 
         self.nodes = nodes
         """ Nodes to be used for the kinetic scheme.
-        @type: str """
+        :type: str """
 
         self.state_variable = state_variable
         """ State variable updated by the kinetic scheme.
-        @type: str """
+        :type: str """
 
         self.edges = edges
         """ Edges to be used for the kinetic scheme.
-        @type: str """
+        :type: str """
 
         self.edge_source = edge_source
         """ Attribute that defines the source of the transition.
-        @type: str """
+        :type: str """
 
         self.edge_target = edge_target
         """ Attribute that defines the target of the transition.
-        @type: str """
+        :type: str """
 
         self.forward_rate = forward_rate
         """ Name of the forward rate exposure.
-        @type: str """
+        :type: str """
 
         self.reverse_rate = reverse_rate
         """ Name of the reverse rate exposure.
-        @type: str """
+        :type: str """
 
     def toxml(self):
         """
@@ -649,31 +648,31 @@ def __init__(self):
 
         self.parent_behavioral = None
         """ Parent behavioral object.
-        @type: lems.model.dynamics.Behavioral """
+        :type: lems.model.dynamics.Behavioral """
 
         self.state_variables = Map()
         """ Map of state variables in this behavior regime.
-        @type: dict(str -> lems.model.dynamics.StateVariable """
+        :type: dict(str -> lems.model.dynamics.StateVariable """
 
         self.derived_variables = Map()
         """ Map of derived variables in this behavior regime.
-        @type: dict(str -> lems.model.dynamics.DerivedVariable """
+        :type: dict(str -> lems.model.dynamics.DerivedVariable """
 
         self.conditional_derived_variables = Map()
         """ Map of conditional derived variables in this behavior regime.
-        @type: dict(str -> lems.model.dynamics.ConditionalDerivedVariable """
+        :type: dict(str -> lems.model.dynamics.ConditionalDerivedVariable """
 
         self.time_derivatives = Map()
         """ Map of time derivatives in this behavior regime.
-        @type: dict(str -> lems.model.dynamics.TimeDerivative) """
+        :type: dict(str -> lems.model.dynamics.TimeDerivative) """
 
         self.event_handlers = list()
         """ List of event handlers in this behavior regime.
-        @type: list(lems.model.dynamics.EventHandler) """
+        :type: list(lems.model.dynamics.EventHandler) """
 
         self.kinetic_schemes = Map()
         """ Map of kinetic schemes in this behavior regime.
-        @type: dict(str -> lems.model.dynamics.KineticScheme) """
+        :type: dict(str -> lems.model.dynamics.KineticScheme) """
         
         
     def has_content(self):
@@ -698,8 +697,8 @@ def add_state_variable(self, sv):
         """
         Adds a state variable to this behavior regime.
 
-        @param sv: State variable.
-        @type sv: lems.model.dynamics.StateVariable
+        :param sv: State variable.
+        :type sv: lems.model.dynamics.StateVariable
         """
 
         self.state_variables[sv.name] = sv
@@ -708,8 +707,8 @@ def add_derived_variable(self, dv):
         """
         Adds a derived variable to this behavior regime.
 
-        @param dv: Derived variable.
-        @type dv: lems.model.dynamics.DerivedVariable
+        :param dv: Derived variable.
+        :type dv: lems.model.dynamics.DerivedVariable
         """
 
         self.derived_variables[dv.name] = dv
@@ -718,8 +717,8 @@ def add_conditional_derived_variable(self, cdv):
         """
         Adds a conditional derived variable to this behavior regime.
 
-        @param cdv: Conditional Derived variable.
-        @type cdv: lems.model.dynamics.ConditionalDerivedVariable
+        :param cdv: Conditional Derived variable.
+        :type cdv: lems.model.dynamics.ConditionalDerivedVariable
         """
 
         self.conditional_derived_variables[cdv.name] = cdv
@@ -728,8 +727,8 @@ def add_time_derivative(self, td):
         """
         Adds a time derivative to this behavior regime.
 
-        @param td: Time derivative.
-        @type td: lems.model.dynamics.TimeDerivative
+        :param td: Time derivative.
+        :type td: lems.model.dynamics.TimeDerivative
         """
 
         self.time_derivatives[td.variable] = td
@@ -738,8 +737,8 @@ def add_event_handler(self, eh):
         """
         Adds an event handler to this behavior regime.
 
-        @param eh: Event handler.
-        @type eh: lems.model.dynamics.EventHandler
+        :param eh: Event handler.
+        :type eh: lems.model.dynamics.EventHandler
         """
         
         self.event_handlers.append(eh)
@@ -748,8 +747,8 @@ def add_kinetic_scheme(self, ks):
         """
         Adds a kinetic scheme to this behavior regime.
 
-        @param ks: Kinetic scheme.
-        @type ks: lems.model.dynamics.KineticScheme
+        :param ks: Kinetic scheme.
+        :type ks: lems.model.dynamics.KineticScheme
         """
 
         self.kinetic_schemes[ks.name] = ks
@@ -758,7 +757,7 @@ def add(self, child):
         """
         Adds a typed child object to the behavioral object.
 
-        @param child: Child object to be added.
+        :param child: Child object to be added.
         """
 
         if isinstance(child, StateVariable):
@@ -838,15 +837,15 @@ def __init__(self, name, parent_behavioral, initial = False):
         
         self.name = name
         """ Name of this behavior regime.
-        @type: str """
+        :type: str """
 
         self.parent_behavioral = parent_behavioral
         """ Parent behavioral object.
-        @type: lems.model.dynamics.Behavioral """
+        :type: lems.model.dynamics.Behavioral """
 
         self.initial = initial
         """ Initial behavior regime.
-        @type: bool """
+        :type: bool """
         
 class Dynamics(Behavioral):
     """
@@ -862,14 +861,14 @@ def __init__(self):
 
         self.regimes = Map()
         """ Map of behavior regimes.
-        @type: Map(str -> lems.model.dynamics.Regime) """
+        :type: Map(str -> lems.model.dynamics.Regime) """
 
     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 """
+        :param regime: Behavior regime to be added.
+        :type regime: lems.model.dynamics.Regime """
 
         self.regimes[regime.name] = regime
 
@@ -877,7 +876,7 @@ def add(self, child):
         """
         Adds a typed child object to the dynamics object.
 
-        @param child: Child object to be added.
+        :param child: Child object to be added.
         """
 
         if isinstance(child, Regime):
diff --git a/lems/model/fundamental.py b/lems/model/fundamental.py
index 02600f9..640822d 100644
--- a/lems/model/fundamental.py
+++ b/lems/model/fundamental.py
@@ -1,9 +1,8 @@
 """
 Dimension and Unit definitions in terms of the fundamental SI units.
 
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
 
 from lems.base.base import LEMSBase
@@ -17,14 +16,14 @@ def __init__(self, filename):
         """
         Constructor.
 
-        @param filename: Name of the file.
-        @type name: str
+        :param filename: Name of the file.
+        :type name: str
 
         """
         
         self.file = filename
         """ Name of the file.
-        @type: str """
+        :type: str """
         
 
     def toxml(self):
@@ -43,49 +42,49 @@ def __init__(self, name, description = '', **params):
         """
         Constructor.
 
-        @param name: Name of the dimension.
-        @type name: str
+        :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()
+        :type params: dict()
         """
         
         self.name = name
         """ Name of the dimension.
-        @type: str """
+        :type: str """
 
         self.m = params['m'] if 'm' in params else 0
         """ Power for the mass dimension.
-        @type: int """
+        :type: int """
         
         self.l = params['l'] if 'l' in params else 0
         """ Power for the length dimension.
-        @type: int """
+        :type: int """
         
         self.t = params['t'] if 't' in params else 0
         """ Power for the time dimension.
-        @type: int """
+        :type: int """
         
         self.i = params['i'] if 'i' in params else 0
         """ Power for the electic current dimension.
-        @type: int """
+        :type: int """
         
         self.k = params['k'] if 'k' in params else 0
         """ Power for the temperature dimension.
-        @type: int """
+        :type: int """
         
         self.n = params['n'] if 'n' in params else 0
         """ Power for the quantity dimension.
-        @type: int """
+        :type: int """
         
         self.j = params['j'] if 'j' in params else 0
         """ Power for the luminous intensity dimension.
-        @type: int """
+        :type: int """
 
         self.description = description
         """ Description of this dimension.
-        @type: str """
+        :type: str """
         
 
     def toxml(self):
@@ -117,31 +116,31 @@ def __init__(self, name, symbol, dimension, power = 0, scale = 1.0, offset = 0.0
         
         self.name = name
         """ Name of the unit.
-        @type: str """
+        :type: str """
         
         self.symbol = symbol
         """ Symbol for the unit.
-        @type: str """
+        :type: str """
         
         self.dimension = dimension
         """ Dimension for the unit.
-        @type: str """
+        :type: str """
         
         self.power = power
         """ Scaling by power of 10.
-        @type: int """
+        :type: int """
         
         self.scale = scale
         """ Scaling.
-        @type: float """
+        :type: float """
         
         self.offset = offset
         """ Offset for non-zero units.
-        @type: float """
+        :type: float """
 
         self.description = description
         """ Description of this unit.
-        @type: str """
+        :type: str """
         
     def toxml(self):
         """
diff --git a/lems/model/model.py b/lems/model/model.py
index 71c5f10..02a6671 100644
--- a/lems/model/model.py
+++ b/lems/model/model.py
@@ -1,14 +1,15 @@
 """
 Model storage.
 
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
 
 import os
 from os.path import dirname
+from typing import List, Dict
 
+from lems import __schema_location__, __schema_version__
 from lems.base.base import LEMSBase
 from lems.base.util import merge_maps, merge_lists
 from lems.base.map import Map
@@ -17,7 +18,7 @@
 from lems.base.errors import SimBuildError
 
 from lems.model.fundamental import Dimension,Unit,Include
-from lems.model.component import Constant,ComponentType,Component,FatComponent
+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
 
@@ -25,6 +26,7 @@
 
 import logging
 
+
 class Model(LEMSBase):
     """
     Stores a model.
@@ -32,97 +34,95 @@ class Model(LEMSBase):
 
     logging.basicConfig(level=logging.INFO)
 
-    target_lems_version = '0.7.3'
-    branch = 'development'
-    schema_location = 'https://raw.githubusercontent.com/LEMS/LEMS/{0}/Schemas/LEMS/LEMS_v{1}.xsd'.format(branch, target_lems_version)
+    target_lems_version = __schema_version__
+    schema_location = __schema_location__
     #schema_location = '/home/padraig/LEMS/Schemas/LEMS/LEMS_v%s.xsd'%target_lems_version
-    
+
     debug = False
-    
+
     def __init__(self, include_includes=True, fail_on_missing_includes=True):
         """
         Constructor.
         """
-        
+
         self.targets = list()
         """ List of targets to be run on startup.
-        @type: list(str) """
-        
+        :type: list(str) """
+
         self.includes = Map()
         """ Dictionary of includes defined in the model.
-        @type: dict(str -> lems.model.fundamental.Include """
-        
+        :type: dict(str -> lems.model.fundamental.Include """
+
         self.dimensions = Map()
         """ Dictionary of dimensions defined in the model.
-        @type: dict(str -> lems.model.fundamental.Dimension """
-        
+        :type: dict(str -> lems.model.fundamental.Dimension """
+
         self.units = Map()
         """ Map of units defined in the model.
-        @type: dict(str -> lems.model.fundamental.Unit """
-        
+        :type: dict(str -> lems.model.fundamental.Unit """
+
         self.component_types = Map()
         """ Map of component types defined in the model.
-        @type: dict(str -> lems.model.component.ComponentType) """
-        
+        :type: dict(str -> lems.model.component.ComponentType) """
+
         self.components = Map()
         """ Map of root components defined in the model.
-        @type: dict(str -> lems.model.component.Component) """
+        :type: dict(str -> lems.model.component.Component) """
 
         self.fat_components = Map()
         """ Map of root fattened components defined in the model.
-        @type: dict(str -> lems.model.component.FatComponent) """
+        :type: dict(str -> lems.model.component.FatComponent) """
 
         self.constants = Map()
         """ Map of constants in this component type.
-        @type: dict(str -> lems.model.component.Constant) """
+        :type: dict(str -> lems.model.component.Constant) """
 
         self.include_directories = []
         """ List of include directories to search for included LEMS files.
-        @type: list(str) """
-        
+        :type: list(str) """
+
         self.included_files = []
         """ List of files already included.
-        @type: list(str) """
-        
+        :type: list(str) """
+
         self.description = None
         """ Short description of contents of LEMS file
-        @type: str """
-        
+        :type: str """
+
         self.include_includes = include_includes
         """ Whether to include LEMS definitions in <Include> elements
-        @type: boolean """
-        
+        :type: boolean """
+
         self.fail_on_missing_includes = fail_on_missing_includes
         """ Whether to raise an Exception when a file in an <Include> element is not found
-        @type: boolean """
+        :type: boolean """
 
     def add_target(self, target):
         """
         Adds a simulation target to the model.
 
-        @param target: Name of the component to be added as a
-        simulation target.
-        @type target: str
+        :param target: Name of the component to be added as a simulation target.
+        :type target: str
         """
-        
+
         self.targets.append(target)
-        
+
     def add_include(self, include):
         """
         Adds an include to the model.
 
-        @param include: Include to be added.
-        @type include: lems.model.fundamental.Include
+        :param include: Include to be added.
+        :type include: lems.model.fundamental.Include
         """
 
         self.includes[include.file] = include
-        
+
     def add_dimension(self, dimension):
         """
         Adds a dimension to the model.
 
-        @param dimension: Dimension to be added.
-        @type dimension: lems.model.fundamental.Dimension
+        :param dimension: Dimension to be added.
+        :type dimension: lems.model.fundamental.Dimension
         """
 
         self.dimensions[dimension.name] = dimension
@@ -131,8 +131,8 @@ def add_unit(self, unit):
         """
         Adds a unit to the model.
 
-        @param unit: Unit to be added.
-        @type unit: lems.model.fundamental.Unit
+        :param unit: Unit to be added.
+        :type unit: lems.model.fundamental.Unit
         """
 
         self.units[unit.symbol] = unit
@@ -141,24 +141,24 @@ def add_component_type(self, component_type):
         """
         Adds a component type to the model.
 
-        @param component_type: Component type to be added.
-        @type component_type: lems.model.fundamental.ComponentType
+        :param component_type: Component type to be added.
+        :type component_type: lems.model.fundamental.ComponentType
         """
         name = component_type.name
-        
+
         # To handle colons in names in LEMS
         if ':' in name:
             name = name.replace(':', '_')
             component_type.name = name
-            
+
         self.component_types[name] = component_type
 
     def add_component(self, component):
         """
         Adds a component to the model.
 
-        @param component: Component to be added.
-        @type component: lems.model.fundamental.Component
+        :param component: Component to be added.
+        :type component: lems.model.fundamental.Component
         """
 
         self.components[component.id] = component
@@ -167,8 +167,8 @@ def add_fat_component(self, fat_component):
         """
         Adds a fattened component to the model.
 
-        @param fat_component: Fattened component to be added.
-        @type fat_component: lems.model.fundamental.Fat_component
+        :param fat_component: Fattened component to be added.
+        :type fat_component: lems.model.fundamental.Fat_component
         """
 
         self.fat_components[fat_component.id] = fat_component
@@ -177,8 +177,8 @@ def add_constant(self, constant):
         """
         Adds a paramter to the model.
 
-        @param constant: Constant to be added.
-        @type constant: lems.model.component.Constant
+        :param constant: Constant to be added.
+        :type constant: lems.model.component.Constant
         """
 
         self.constants[constant.name] = constant
@@ -187,7 +187,7 @@ def add(self, child):
         """
         Adds a typed child object to the model.
 
-        @param child: Child object to be added.
+        :param child: Child object to be added.
         """
 
         if isinstance(child, Include):
@@ -211,21 +211,21 @@ def add_include_directory(self, path):
         """
         Adds a directory to the include file search path.
 
-        @param path: Directory to be added.
-        @type path: str
+        :param path: Directory to be added.
+        :type path: str
         """
-        
+
         self.include_directories.append(path)
 
     def include_file(self, path, include_dirs = []):
         """
         Includes a file into the current model.
 
-        @param path: Path to the file to be included.
-        @type path: str
+        :param path: Path to the file to be included.
+        :type path: str
 
-        @param include_dirs: Optional alternate include search path.
-        @type include_dirs: list(str)
+        :param include_dirs: Optional alternate include search path.
+        :type include_dirs: list(str)
         """
         if self.include_includes:
             if self.debug: print("------------------                   Including a file: %s"%path)
@@ -234,7 +234,7 @@ def include_file(self, path, include_dirs = []):
             parser = LEMSFileParser(self, inc_dirs, self.include_includes)
             if os.access(path, os.F_OK):
                 if not path in self.included_files:
-                    parser.parse(open(path).read()) 
+                    parser.parse(open(path).read())
                     self.included_files.append(path)
                     return
                 else:
@@ -254,24 +254,24 @@ def include_file(self, path, include_dirs = []):
             msg = 'Unable to open ' + path
             if self.fail_on_missing_includes:
                 raise Exception(msg)
-            elif self.debug: 
+            elif self.debug:
                 print(msg)
-            
+
     def import_from_file(self, filepath):
         """
         Import a model from a file.
 
-        @param filepath: File to be imported.
-        @type filepath: str
+        :param filepath: File to be imported.
+        :type filepath: str
         """
-        
+
         inc_dirs = self.include_directories[:]
         inc_dirs.append(dirname(filepath))
-                        
+
         parser = LEMSFileParser(self, inc_dirs, self.include_includes)
         with open(filepath) as f:
             parser.parse(f.read())
-        
+
     def export_to_dom(self):
         """
         Exports this model to a DOM.
@@ -292,19 +292,19 @@ def export_to_dom(self):
 
         for dimension in self.dimensions:
             xmlstr += dimension.toxml()
-            
+
         for unit in self.units:
             xmlstr += unit.toxml()
-            
+
         for constant in self.constants:
             xmlstr += constant.toxml()
-            
+
         for component_type in self.component_types:
             xmlstr += component_type.toxml()
-            
+
         for component in self.components:
             xmlstr += component.toxml()
-            
+
         xmlstr += '</Lems>'
 
         xmldom = minidom.parseString(xmlstr)
@@ -314,8 +314,8 @@ def export_to_file(self, filepath, level_prefix = '  '):
         """
         Exports this model to a file.
 
-        @param filepath: File to be exported to.
-        @type filepath: str
+        :param filepath: File to be exported to.
+        :type filepath: str
         """
         xmldom = self.export_to_dom()
         xmlstr = xmldom.toprettyxml(level_prefix, '\n',)
@@ -331,7 +331,7 @@ def resolve(self):
         """
 
         model = self.copy()
-        
+
         for ct in model.component_types:
             model.resolve_component_type(ct)
 
@@ -343,17 +343,17 @@ def resolve(self):
             c2 = c.copy()
             c2.numeric_value = model.get_numeric_value(c2.value, c2.dimension)
             model.add(c2)
-            
+
         return model
 
     def resolve_component_type(self, component_type):
         """
         Resolves references in the specified component type.
 
-        @param component_type: Component type to be resolved.
-        @type component_type: lems.model.component.ComponentType
+        :param component_type: Component type to be resolved.
+        :type component_type: lems.model.component.ComponentType
         """
-        
+
         # Resolve component type from base types if present.
         if component_type.extends:
             try:
@@ -369,14 +369,14 @@ def resolve_component_type(self, component_type):
 
     def merge_component_types(self, ct, base_ct):
         """
-        Merge various maps in the given component type from a base 
+        Merge various maps in the given component type from a base
         component type.
 
-        @param ct: Component type to be resolved.
-        @type ct: lems.model.component.ComponentType
+        :param ct: Component type to be resolved.
+        :type ct: lems.model.component.ComponentType
 
-        @param base_ct: Component type to be resolved.
-        @type base_ct: lems.model.component.ComponentType
+        :param base_ct: Component type to be resolved.
+        :type base_ct: lems.model.component.ComponentType
         """
 
         #merge_maps(ct.parameters, base_ct.parameters)
@@ -389,9 +389,9 @@ def merge_component_types(self, ct, base_ct):
                     p.dimension = basep.dimension
             else:
                 ct.parameters[parameter.name] = base_ct.parameters[parameter.name]
-            
+
         merge_maps(ct.properties, base_ct.properties)
-        
+
         merge_maps(ct.derived_parameters, base_ct.derived_parameters)
         merge_maps(ct.index_parameters, base_ct.index_parameters)
         merge_maps(ct.constants, base_ct.constants)
@@ -411,9 +411,9 @@ def merge_component_types(self, ct, base_ct):
         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.time_derivatives, base_ct.dynamics.time_derivatives)
-        
+
         #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)
@@ -431,19 +431,19 @@ def fatten_component(self, c):
         """
         Fatten a component but resolving all references into the corresponding component type.
 
-        @param c: Lean component to be fattened.
-        @type c: lems.model.component.Component
+        :param c: Lean component to be fattened.
+        :type c: lems.model.component.Component
 
-        @return: Fattened component.
-        @rtype: lems.model.component.FatComponent
+        :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())
-        
+
         fc = FatComponent(c.id, c.type)
         if c.parent_id: fc.set_parent_id(c.parent_id)
 
@@ -467,18 +467,18 @@ def fatten_component(self, c):
         for property in ct.properties:
             property2 = property.copy()
             fc.add(property2)
-            
+
         ### Resolve derived_parameters
         for derived_parameter in ct.derived_parameters:
             derived_parameter2 = derived_parameter.copy()
             fc.add(derived_parameter2)
-            
+
         ### Resolve derived_parameters
         for index_parameter in ct.index_parameters:
             raise ModelError("IndexParameter not yet implemented in PyLEMS!")
             index_parameter2 = index_parameter.copy()
             fc.add(index_parameter2)
-            
+
         ### Resolve constants
         for constant in ct.constants:
             constant2 = constant.copy()
@@ -490,7 +490,7 @@ def fatten_component(self, c):
             t = text.copy()
             t.value = c.parameters[text.name] if text.name in c.parameters else ''
             fc.add(t)
-                
+
         ### Resolve texts
         for link in ct.links:
             if link.name in c.parameters:
@@ -500,7 +500,7 @@ def fatten_component(self, c):
             else:
                 raise ModelError("Link parameter '{0}' not initialized for component '{1}'",
                                  link.name, c.id)
-                
+
         ### Resolve paths
         for path in ct.paths:
             if path.name in c.parameters:
@@ -532,7 +532,7 @@ def fatten_component(self, c):
             else:
                 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)
         merge_maps(fc.component_requirements, ct.component_requirements)
@@ -547,7 +547,7 @@ def fatten_component(self, c):
         fc.dynamics = ct.dynamics.copy()
         if len(fc.dynamics.regimes) != 0:
             fc.dynamics.clear()
-               
+
         self.resolve_structure(fc, ct)
         self.resolve_simulation(fc, ct)
 
@@ -558,33 +558,30 @@ def fatten_component(self, c):
             fc.add(self.fatten_component(child))
 
         return fc
-    
-    
+
     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 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("2) It is "+child.id)
                                 parent_comp = child
                                 break
                             else:
                                 if self.debug: print("No..."   )
         return parent_comp
-                        
-
 
     def resolve_structure(self, fc, ct):
         """
@@ -603,26 +600,26 @@ def resolve_structure(self, fc, ct):
                                  "'{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!");
-            
+
         for fe in ct.structure.for_eachs:
             fc.structure.add_for_each(fe)
-            
+
         for ev in ct.structure.event_connections:
             try:
-                
+
                 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 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
-                    
+
                     if self.debug: print("sp: %s"%source_port)
                     if self.debug: print("tp: %s"%target_port)
 
@@ -633,11 +630,11 @@ def resolve_structure(self, fc, ct):
                         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)))
-                        
+
                         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))
@@ -645,7 +642,7 @@ def resolve_structure(self, fc, ct):
                                         if self.debug: print("Got it: "+receiver_id)
                                         break
 
-                        if receiver_id is not None:            
+                        if receiver_id is not None:
                             for comp in self.fat_components:
                                 if comp.id == receiver_id:
                                         receiver = comp
@@ -664,8 +661,8 @@ def resolve_structure(self, fc, ct):
                 else:
                     #if from_inst == 'parent':
                         #par = fc.component_references[ev.receiver]
-                    
-                    if self.debug: 
+
+                    if self.debug:
                         print("+++++++++++++++++++")
                         print(ev.toxml())
                         print(ev.source_port)
@@ -674,14 +671,14 @@ def resolve_structure(self, fc, ct):
                     target_port = ev.target_port
                     receiver = None
                     receiver_container = None
-                    
+
                 ev2 = EventConnection(from_inst,
                                       to_inst,
                                       source_port,
                                       target_port,
                                       receiver,
                                       receiver_container)
-                if self.debug: 
+                if self.debug:
                     print("Created EC: "+ev2.toxml())
                     print(receiver)
                     print(receiver_container)
@@ -689,7 +686,7 @@ def resolve_structure(self, fc, ct):
                 logging.exception("Something awful happened!")
                 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())
@@ -701,7 +698,7 @@ def resolve_structure(self, fc, ct):
                     comp_id = parent.parameters[comp_ref]
                     comp = self.fat_components[comp_id]
                     ch2 = ChildInstance(ch.component, comp)
-                else:    
+                else:
                     ref_comp = fc.component_references[ch.component].referenced_component
                     ch2 = ChildInstance(ch.component, ref_comp)
             except Exception as e:
@@ -718,7 +715,7 @@ def resolve_structure(self, fc, ct):
                                            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))                    
+                                           number=int(fc.parameters[mi.number].numeric_value))
             except:
                 raise ModelError("Unable to resolve multi-instantiate parameters for "
                                  "'{0}' in component '{1}'",
@@ -770,26 +767,26 @@ def resolve_simulation(self, fc, ct):
                 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 = '.'
                 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)
             except:
                 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 = '.'
                 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)
@@ -797,17 +794,16 @@ def resolve_simulation(self, fc, ct):
                 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):
         """
         Get the numeric value for a parameter value specification.
 
-        @param value_str: Value string
-        @type value_str: str
+        :param value_str: Value string
+        :type value_str: str
 
-        @param dimension: Dimension of the value
-        @type dimension: str
+        :param dimension: Dimension of the value
+        :type dimension: str
         """
 
         n = None
@@ -821,7 +817,6 @@ def get_numeric_value(self, value_str, dimension = None):
             except ValueError:
                 i = i-1
 
-
         number = n
         sym = s
 
@@ -844,6 +839,69 @@ def get_numeric_value(self, value_str, dimension = None):
             else:
                 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.
+
+        :param substring: substring to match for in component names
+        :type substring: str
+        :returns: dictionary of components and their exposures
+
+        The returned dictionary is of the form:
+        {
+            "component": ["exp1", "exp2"]
+        }
+
+        """
+        exposures = {}
+        comp_list = []
+        if substring:
+            for comp in self.components:
+                if substring in comp.id:
+                    comp_list.append(comp)
+        else:
+            comp_list = self.components
+
+        for comp in comp_list:
+            try:
+                exposures[comp] = self.component_types[comp.type].exposures
+            except KeyError:
+                pass  # found a component without any exposures
+        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.
+
+        :param comp: component
+        :type comp: Component
+        :param exposures: list of exposures
+        :type exposures: [Exposure]
+        :returns: list of strings, one for each recording path
+
+        """
+        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.
+
+        :param substring: substring to match component ids against
+        :type substring: str
+        :returns: list of recording paths
+
+        """
+        recording_paths = []
+        exposures = self.list_exposures(substring)
+
+        for comp, exps in exposures.items():
+            recording_paths.extend(self.get_recording_path(comp, exps))
+        return recording_paths
diff --git a/lems/model/simulation.py b/lems/model/simulation.py
index 2175958..500d83e 100644
--- a/lems/model/simulation.py
+++ b/lems/model/simulation.py
@@ -1,9 +1,8 @@
 """
 Simulation specification classes.
 
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
 
 from lems.base.base import LEMSBase
@@ -26,20 +25,20 @@ def __init__(self, component, variable, increment, total):
         self.component = component
         """ Name of the target component to be run according to the
         specification given for an independent state variable.
-        @type: str """
+        :type: str """
 
         self.variable = variable
         """ The name of an independent state variable according to which the
         target component will be run.
-        @type: str """
+        :type: str """
 
         self.increment = increment
         """ Increment of the state variable on each step.
-        @type: str """
+        :type: str """
 
         self.total = total
         """ Final value of the state variable.
-        @type: str """
+        :type: str """
 
     def toxml(self):
         """
@@ -65,23 +64,23 @@ def __init__(self, quantity, scale = None, color = None, id = None):
 
         self.id = ''
         """ Id of the quantity
-        @type: str """
+        :type: str """
         
         self.quantity = quantity
         """ Path to the quantity to be recorded.
-        @type: str """
+        :type: str """
 
         self.scale = scale
         """ Text parameter to be used for scaling the quantity before display.
-        @type: str """
+        :type: str """
 
         self.color = color
         """ Text parameter to be used to specify the color for display.
-        @type: str """
+        :type: str """
 
         self.id = id
         """ Text parameter to be used to specify an id for the record
-        @type: str """
+        :type: str """
 
     def toxml(self):
         """
@@ -106,15 +105,15 @@ def __init__(self, quantity, eventPort):
 
         self.id = ''
         """ Id of the quantity
-        @type: str """
+        :type: str """
         
         self.quantity = quantity
         """ Path to the quantity to be recorded.
-        @type: str """
+        :type: str """
 
         self.eventPort = eventPort
         """ eventPort to be used for the event record
-        @type: str """
+        :type: str """
 
     def toxml(self):
         """
@@ -152,15 +151,15 @@ def __init__(self, title, data_region):
 
         self.title = title
         """ Title for the display.
-        @type: string """
+        :type: string """
 
         self.data_region = data_region
         """ Display position
-        @type: string """
+        :type: string """
 
         self.time_scale = 1
         """ Time scale
-        @type: Number """
+        :type: Number """
         
     def toxml(self):
         """
@@ -186,11 +185,11 @@ def __init__(self, path, file_name):
         
         self.path = path
         """ Path to the quantity to be saved to file.
-        @type: string """
+        :type: string """
 
         self.file_name = file_name
         """ Text parameter to be used for the file name
-        @type: string """
+        :type: string """
 
 
     def toxml(self):
@@ -221,15 +220,15 @@ def __init__(self, path, file_name, format):
         
         self.path = path
         """ Path to the quantity to be saved to file.
-        @type: string """
+        :type: string """
 
         self.file_name = file_name
         """ Text parameter to be used for the file name
-        @type: string """
+        :type: string """
 
         self.format = format
         """ Text parameter to be used for the format
-        @type: string """
+        :type: string """
 
 
     def toxml(self):
@@ -257,35 +256,35 @@ def __init__(self):
 
         self.runs = Map()
         """ Map of runs in this dynamics regime.
-        @type: Map(string -> lems.model.simulation.Run) """
+        :type: Map(string -> lems.model.simulation.Run) """
 
         self.records = Map()
         """ Map of recorded variables in this dynamics regime.
-        @type: Map(string -> lems.model.simulation.Record """
+        :type: Map(string -> lems.model.simulation.Record """
 
         self.event_records = Map()
         """ Map of recorded events in this dynamics regime.
-        @type: Map(string -> lems.model.simulation.EventRecord """
+        :type: Map(string -> lems.model.simulation.EventRecord """
 
         self.data_displays = Map()
         """ Map of data displays mapping titles to regions.
-        @type: Map(string -> string) """
+        :type: Map(string -> string) """
 
         self.data_writers = Map()
         """ Map of recorded variables to data writers.
-        @type: Map(string -> lems.model.simulation.DataWriter """
+        :type: Map(string -> lems.model.simulation.DataWriter """
 
         self.event_writers = Map()
         """ Map of recorded variables to event writers.
-        @type: Map(string -> lems.model.simulation.EventWriter """
+        :type: Map(string -> lems.model.simulation.EventWriter """
 
     def add_run(self, run):
         """
         Adds a runnable target component definition to the list of runnable
         components stored in this context.
 
-        @param run: Run specification
-        @type run: lems.model.simulation.Run
+        :param run: Run specification
+        :type run: lems.model.simulation.Run
         """
 
         self.runs[run.component] = run
@@ -295,8 +294,8 @@ def add_record(self, record):
         Adds a record object to the list of record objects in this dynamics
         regime.
 
-        @param record: Record object to be added.
-        @type record: lems.model.simulation.Record
+        :param record: Record object to be added.
+        :type record: lems.model.simulation.Record
         """
 
         self.records[record.quantity] = record
@@ -306,8 +305,8 @@ def add_event_record(self, event_record):
         Adds an eventrecord object to the list of event_record objects in this dynamics
         regime.
 
-        @param event_record: EventRecord object to be added.
-        @type event_record: lems.model.simulation.EventRecord
+        :param event_record: EventRecord object to be added.
+        :type event_record: lems.model.simulation.EventRecord
         """
 
         self.event_records[event_record.quantity] = event_record
@@ -316,8 +315,8 @@ def add_data_display(self, data_display):
         """
         Adds a data display to this simulation section.
 
-        @param data_display: Data display to be added.
-        @type data_display: lems.model.simulation.DataDisplay
+        :param data_display: Data display to be added.
+        :type data_display: lems.model.simulation.DataDisplay
         """
 
         self.data_displays[data_display.title] = data_display
@@ -326,8 +325,8 @@ def add_data_writer(self, data_writer):
         """
         Adds a data writer to this simulation section.
 
-        @param data_writer: Data writer to be added.
-        @type data_writer: lems.model.simulation.DataWriter
+        :param data_writer: Data writer to be added.
+        :type data_writer: lems.model.simulation.DataWriter
         """
 
         self.data_writers[data_writer.path] = data_writer
@@ -336,8 +335,8 @@ def add_event_writer(self, event_writer):
         """
         Adds an event writer to this simulation section.
 
-        @param event_writer: event writer to be added.
-        @type event_writer: lems.model.simulation.EventWriter
+        :param event_writer: event writer to be added.
+        :type event_writer: lems.model.simulation.EventWriter
         """
 
         self.event_writers[event_writer.path] = event_writer
@@ -346,7 +345,7 @@ def add(self, child):
         """
         Adds a typed child object to the simulation spec.
 
-        @param child: Child object to be added.
+        :param child: Child object to be added.
         """
 
         if isinstance(child, Run):
diff --git a/lems/model/structure.py b/lems/model/structure.py
index cb89bd6..31fa2ee 100644
--- a/lems/model/structure.py
+++ b/lems/model/structure.py
@@ -1,9 +1,8 @@
 """
 Structural properties of component types.
 
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
 
 from lems.base.base import LEMSBase
@@ -23,19 +22,19 @@ def __init__(self, instance, as_, list=None, index=None):
 
         self.instance = instance
         """ Instance to be referenced.
-        @type: str """
+        :type: str """
 
         self.as_ = as_
         """ Alternative name.
-        @type: str """
+        :type: str """
 
         self.list = list
         """ list of components, e.g. population
-        @type: str """
+        :type: str """
 
         self.index = index
         """ index in list to be referenced.
-        @type: str """
+        :type: str """
         
 
     def toxml(self):
@@ -63,23 +62,23 @@ def __init__(self, name, end_a, end_b, component_a, component_b):
 
         self.name = name
         """ name of Tunnel.
-        @type: str """
+        :type: str """
 
         self.end_a = end_a
         """ 'A' end of Tunnel.
-        @type: str """
+        :type: str """
 
         self.end_b = end_b
         """ 'B' end of Tunnel.
-        @type: str """
+        :type: str """
 
         self.component_a = component_a
         """ Component to create at A.
-        @type: str """
+        :type: str """
         
         self.component_b = component_b
         """ Component to create at B.
-        @type: str """
+        :type: str """
 
         
 
@@ -110,27 +109,27 @@ def __init__(self, from_, to,
 
         self.from_ = from_
         """ Name of the source component for event.
-        @type: str """
+        :type: str """
 
         self.to = to
         """ Name of the target component for the event.
-        @type: str """
+        :type: str """
 
         self.source_port = source_port
         """ Source port name.
-        @type: str """
+        :type: str """
 
         self.target_port = target_port
         """ Target port name.
-        @type: str """
+        :type: str """
 
         self.receiver = receiver
         """ Name of the proxy receiver component attached to the target component that actually receiving the event.
-        @type: str """
+        :type: str """
 
         self.receiver_container = receiver_container
         """ Name of the child component grouping to add the receiver to.
-        @type: str """
+        :type: str """
 
     def __eq__(self, o):
         return (self.from_ == o.from_ and self.to == o.to and
@@ -165,11 +164,11 @@ def __init__(self, component, referenced_component = None):
 
         self.component = component
         """ Name of the component reference to be used for instantiation.
-        @type: str """
+        :type: str """
 
         self.referenced_component = referenced_component
         """ Target component being referenced after resolution.
-        @type: lems.model.component.FatComponent """
+        :type: lems.model.component.FatComponent """
         
     def __eq__(self, o):
         return self.component == o.component
@@ -195,11 +194,11 @@ def __init__(self, property, value):
 
         self.property_ = property
         """ Name of the property reference to be used for instantiation.
-        @type: str """
+        :type: str """
 
         self.value = value
         """ Value of the property.
-        @type: str"""
+        :type: str"""
 
     def __eq__(self, o):
         return self.property_ == o.property_ and self.value == o.value
@@ -229,20 +228,20 @@ def __init__(self, component=None, number=None, component_type=None):
 
         self.component = component
         """ Name of the component reference to be used for instantiation.
-        @type: str """
+        :type: str """
 
         self.component_type = component_type
         """ Name of the component type reference to be used for instantiation.
-        @type: str """
+        :type: str """
 
         self.number = number
         """ Name of the paramter specifying the number of times the component 
         reference is to be instantiated.
-        @type: str"""
+        :type: str"""
 
         self.assignments = []
         """ List of assignments included in MultiInstantiate.
-        @type: list(Assign) """
+        :type: list(Assign) """
         
     def __eq__(self, o):
         if self.component:
@@ -255,8 +254,8 @@ def add_assign(self, assign):
         """
         Adds an Assign to the structure.
 
-        @param assign: Assign structure.
-        @type assign: lems.model.structure.Assign
+        :param assign: Assign structure.
+        :type assign: lems.model.structure.Assign
         """
         self.assignments.append(assign)
 
@@ -264,7 +263,7 @@ def add(self, child):
         """
         Adds a typed child object to the structure object.
 
-        @param child: Child object to be added.
+        :param child: Child object to be added.
         """
 
         if isinstance(child, Assign):
@@ -303,19 +302,19 @@ def __init__(self, instances, as_):
         
         self.event_connections = list()
         """ List of event connections.
-        @type: list(lems.model.structure.EventConnection) """
+        :type: list(lems.model.structure.EventConnection) """
         
         self.for_eachs = list()
         """ List of for each specs.
-        @type: list(lems.model.structure.ForEach) """
+        :type: list(lems.model.structure.ForEach) """
         
         
     def add_for_each(self, fe):
         """
         Adds a for-each specification.
 
-        @param fe: For-each specification.
-        @type fe: lems.model.structure.ForEach
+        :param fe: For-each specification.
+        :type fe: lems.model.structure.ForEach
         """
 
         self.for_eachs.append(fe)
@@ -325,8 +324,8 @@ def add_event_connection(self, ec):
         """
         Adds an event conenction to the structure.
 
-        @param ec: Event connection.
-        @type ec: lems.model.structure.EventConnection
+        :param ec: Event connection.
+        :type ec: lems.model.structure.EventConnection
         """
 
         self.event_connections.append(ec)
@@ -359,27 +358,27 @@ def __init__(self):
 
         self.withs = Map()
         """ Map of With statements.
-        @type: Map(str -> lems.model.structure.With) """
+        :type: Map(str -> lems.model.structure.With) """
         
         self.tunnels = Map()
         """ Map of tunnel statements.
-        @type: Map(str -> lems.model.structure.Tunnel) """
+        :type: Map(str -> lems.model.structure.Tunnel) """
 
         self.event_connections = list()
         """ List of event connections.
-        @type: list(lems.model.structure.EventConnection) """
+        :type: list(lems.model.structure.EventConnection) """
 
         self.child_instances = list()
         """ List of child instantations.
-        @type: list(lems.model.structure.ChildInstance) """
+        :type: list(lems.model.structure.ChildInstance) """
 
         self.multi_instantiates = list()
         """ List of child multi-instantiations.
-        @type: list(lems.model.structure.MultiInstantiate) """
+        :type: list(lems.model.structure.MultiInstantiate) """
 
         self.for_eachs = list()
         """ List of for each specs.
-        @type: list(lems.model.structure.ForEach) """
+        :type: list(lems.model.structure.ForEach) """
         
     def has_content(self):
         if len(self.withs)==0 and \
@@ -395,8 +394,8 @@ def add_with(self, with_):
         """
         Adds a with-as specification to the structure.
 
-        @param with_: With-as specification.
-        @type with_: lems.model.structure.With
+        :param with_: With-as specification.
+        :type with_: lems.model.structure.With
         """
 
         self.withs[with_.as_] = with_
@@ -405,8 +404,8 @@ def add_tunnel(self, tunnel):
         """
         Adds a tunnel specification to the structure.
 
-        @param tunnel: tunnel specification.
-        @type tunnel: lems.model.structure.Tunnel
+        :param tunnel: tunnel specification.
+        :type tunnel: lems.model.structure.Tunnel
         """
 
         self.tunnels[tunnel.name] = tunnel
@@ -415,8 +414,8 @@ def add_event_connection(self, ec):
         """
         Adds an event conenction to the structure.
 
-        @param ec: Event connection.
-        @type ec: lems.model.structure.EventConnection
+        :param ec: Event connection.
+        :type ec: lems.model.structure.EventConnection
         """
 
         self.event_connections.append(ec)
@@ -425,8 +424,8 @@ def add_child_instance(self, ci):
         """
         Adds a child instantiation specification.
 
-        @param ci: Child instantiation specification.
-        @type ci: lems.model.structure.ChildInstance
+        :param ci: Child instantiation specification.
+        :type ci: lems.model.structure.ChildInstance
         """
 
         self.child_instances.append(ci)
@@ -435,8 +434,8 @@ def add_multi_instantiate(self, mi):
         """
         Adds a child multi-instantiation specification.
 
-        @param mi: Child multi-instantiation specification.
-        @type mi: lems.model.structure.MultiInstantiate
+        :param mi: Child multi-instantiation specification.
+        :type mi: lems.model.structure.MultiInstantiate
         """
 
         self.multi_instantiates.append(mi)
@@ -445,8 +444,8 @@ def add_for_each(self, fe):
         """
         Adds a for-each specification.
 
-        @param fe: For-each specification.
-        @type fe: lems.model.structure.ForEach
+        :param fe: For-each specification.
+        :type fe: lems.model.structure.ForEach
         """
 
         self.for_eachs.append(fe)
@@ -455,7 +454,7 @@ def add(self, child):
         """
         Adds a typed child object to the structure object.
 
-        @param child: Child object to be added.
+        :param child: Child object to be added.
         """
 
         if isinstance(child, With):
diff --git a/lems/parser/LEMS.py b/lems/parser/LEMS.py
index b93e466..de33c4f 100644
--- a/lems/parser/LEMS.py
+++ b/lems/parser/LEMS.py
@@ -1,9 +1,8 @@
 """
 LEMS XML file format parser.
 
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
 
 import xml.etree.ElementTree as xe
@@ -53,15 +52,15 @@ def __init__(self, pyxmlnode):
         self.children = list()
         for pyxmlchild in pyxmlnode:
             self.children.append(LEMSXMLNode(pyxmlchild))
-            
+
     def __str__(self):
         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):
         """
         Constructor.
@@ -71,28 +70,28 @@ def __init__(self, model, include_dirs = [], include_includes=True):
 
         self.model = model
         """ Model instance to be populated from the parsed file.
-        @type: lems.model.model.Model """
+        :type: lems.model.model.Model """
 
         self.include_dirs = include_dirs
         """ List of directories to search for included files.
-        @type: list(str) """
+        :type: list(str) """
 
         self.tag_parse_table = None
         """ Dictionary of xml tags to parse methods
-        @type: dict(string -> function) """
+        :type: dict(string -> function) """
 
         self.valid_children = None
         """ Dictionary mapping each tag to it's list of valid child tags.
-        @type: dict(string -> string) """
+        :type: dict(string -> string) """
 
         self.id_counter = None
         """ Counter generator for generating unique ids.
-        @type: generator(int) """
-        
+        :type: generator(int) """
+
         self.include_includes = include_includes
         """ Whether to include LEMS definitions in <Include> elements
-        @type: boolean """
-        
+        :type: boolean """
+
         self.init_parser()
 
     def init_parser(self):
@@ -107,10 +106,10 @@ def init_parser(self):
         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',
@@ -124,18 +123,18 @@ def init_parser(self):
                                                 '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']
@@ -147,9 +146,9 @@ def init_parser(self):
                                             'multiinstantiate',
                                             'with',
                                             'tunnel']
-                                       
-        self.valid_children['foreach'] = ['foreach', 'eventconnection']     
-                                            
+
+        self.valid_children['foreach'] = ['foreach', 'eventconnection']
+
         self.valid_children['simulation'] = ['record', 'eventrecord', 'run',
                                              'datadisplay', 'datawriter', 'eventwriter']
 
@@ -160,7 +159,7 @@ def init_parser(self):
         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['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
@@ -195,7 +194,7 @@ def init_parser(self):
         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['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
@@ -219,7 +218,7 @@ def init_parser(self):
         self.current_structure = None
         self.current_simulation = None
         self.current_component = None
-        
+
         def counter():
             count = 1
             while True:
@@ -228,15 +227,15 @@ def counter():
 
         self.id_counter = counter()
 
-        
+
     def process_nested_tags(self, node, tag = ''):
         """
         Process child tags.
 
-        @param node: Current node being parsed.
-        @type node: xml.etree.Element
+        :param node: Current node being parsed.
+        :type node: xml.etree.Element
 
-        @raise ParseError: Raised when an unexpected nested tag is found.
+        :raises ParseError: Raised when an unexpected nested tag is found.
         """
         ##print("---------Processing: %s, %s"%(node.tag,tag))
 
@@ -244,7 +243,7 @@ def process_nested_tags(self, node, tag = ''):
             t = node.ltag
         else:
             t = tag.lower()
-        
+
         for child in node.children:
             self.xml_node_stack = [child] + self.xml_node_stack
 
@@ -263,19 +262,18 @@ def parse(self, xmltext):
         """
         Parse a string containing LEMS XML text.
 
-        @param xmltext: String containing LEMS XML formatted text.
-        @type xmltext: str
+        :param xmltext: String containing LEMS XML formatted text.
+        :type xmltext: str
         """
-        
+
         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':
             if 'description' in xml.lattrib:
-                self.description = xml.lattrib['description']
-        '''
+                self.model.description = xml.lattrib['description']
 
         self.process_nested_tags(xml)
 
@@ -284,7 +282,7 @@ def raise_error(self, message, *params, **key_params):
         """
         Raise a parse error.
         """
-        
+
         s = 'Parser error in '
 
         self.xml_node_stack.reverse()
@@ -359,8 +357,8 @@ def parse_assertion(self, node):
         """
         Parses <Assertion>
 
-        @param node: Node containing the <Assertion> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Assertion> element
+        :type node: xml.etree.Element
         """
 
         print('TODO - <Assertion>')
@@ -370,8 +368,8 @@ def parse_attachments(self, node):
         """
         Parses <Attachments>
 
-        @param node: Node containing the <Attachments> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Attachments> element
+        :type node: xml.etree.Element
         """
 
         if 'name' in node.lattrib:
@@ -392,8 +390,8 @@ def parse_child(self, node):
         """
         Parses <Child>
 
-        @param node: Node containing the <Child> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Child> element
+        :type node: xml.etree.Element
         """
 
         if 'name' in node.lattrib:
@@ -406,14 +404,15 @@ def parse_child(self, node):
         else:
             self.raise_error("Child '{0}' must specify a type.", name)
 
-        self.current_component_type.add_children(Children(name, type_, False))
+        description = node.lattrib.get('description', '')
+        self.current_component_type.add_children(Children(name, type_, description, multiple=False))
 
     def parse_child_instance(self, node):
         """
         Parses <ChildInstance>
 
-        @param node: Node containing the <ChildInstance> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <ChildInstance> element
+        :type node: xml.etree.Element
         """
 
         if 'component' in node.lattrib:
@@ -427,8 +426,8 @@ def parse_children(self, node):
         """
         Parses <Children>
 
-        @param node: Node containing the <Children> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Children> element
+        :type node: xml.etree.Element
         """
 
         if 'name' in node.lattrib:
@@ -441,19 +440,20 @@ def parse_children(self, node):
         else:
             self.raise_error("Children '{0}' must specify a type.", name)
 
-        self.current_component_type.add_children(Children(name, type_, 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_):
         """
         Parses components defined directly by component name.
 
-        @param node: Node containing the <Component> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Component> element
+        :type node: xml.etree.Element
 
-        @param type_: Type of this component.
-        @type type_: string
+        :param type_: Type of this component.
+        :type type_: string
 
-        @raise ParseError: Raised when the component does not have an id.
+        :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:
@@ -472,7 +472,7 @@ def parse_component_by_typename(self, node, type_):
         if self.current_component:
             component.set_parent_id(self.current_component.id)
             self.current_component.add_child(component)
-            
+
         else:
             self.model.add_component(component)
 
@@ -489,8 +489,8 @@ def parse_component(self, node):
         """
         Parses <Component>
 
-        @param node: Node containing the <Component> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Component> element
+        :type node: xml.etree.Element
         """
 
         if 'id' in node.lattrib:
@@ -512,7 +512,7 @@ def parse_component(self, node):
             self.current_component.add_child(component)
         else:
             self.model.add_component(component)
-                
+
         for key in node.attrib:
             if key.lower() not in ['id', 'type']:
                 component.set_parameter(key, node.attrib[key])
@@ -526,8 +526,8 @@ def parse_component_reference(self, node):
         """
         Parses <ComponentReference>
 
-        @param node: Node containing the <ComponentTypeRef> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <ComponentTypeRef> element
+        :type node: xml.etree.Element
         """
 
         if 'name' in node.lattrib:
@@ -541,7 +541,7 @@ def parse_component_reference(self, node):
         else:
             self.raise_error('<ComponentReference> must specify a type for the ' +
                              'reference.')
-                             
+
         if 'local' in node.lattrib:
             local = node.lattrib['local']
         else:
@@ -553,11 +553,10 @@ def parse_component_type(self, node):
         """
         Parses <ComponentType>
 
-        @param node: Node containing the <ComponentType> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <ComponentType> element
+        :type node: xml.etree.Element
 
-        @raise ParseError: Raised when the component type does not have a
-        name.
+        :raises ParseError: Raised when the component type does not have a name.
         """
 
         try:
@@ -586,8 +585,8 @@ def parse_constant(self, node):
         """
         Parses <Constant>
 
-        @param node: Node containing the <Constant> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Constant> element
+        :type node: xml.etree.Element
         """
 
         try:
@@ -602,7 +601,10 @@ def parse_constant(self, node):
         except:
             self.raise_error("Constant '{0}' must have a value.", name)
 
-        description = node.lattrib.get('description', '')
+        if 'description' in node.lattrib:
+            description = node.lattrib['description']
+        else:
+            description = None
 
         constant = Constant(name, value, dimension, description)
 
@@ -615,8 +617,8 @@ def parse_data_display(self, node):
         """
         Parses <DataDisplay>
 
-        @param node: Node containing the <DataDisplay> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <DataDisplay> element
+        :type node: xml.etree.Element
         """
 
         if 'title' in node.lattrib:
@@ -635,8 +637,8 @@ def parse_data_writer(self, node):
         """
         Parses <DataWriter>
 
-        @param node: Node containing the <DataWriter> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <DataWriter> element
+        :type node: xml.etree.Element
         """
 
         if 'path' in node.lattrib:
@@ -656,8 +658,8 @@ def parse_event_writer(self, node):
         """
         Parses <EventWriter>
 
-        @param node: Node containing the <EventWriter> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <EventWriter> element
+        :type node: xml.etree.Element
         """
 
         if 'path' in node.lattrib:
@@ -670,7 +672,7 @@ def parse_event_writer(self, node):
         else:
             self.raise_error("Event writer for '{0}' must specify a filename.",
                              path)
-                             
+
         if 'format' in node.lattrib:
             format = node.lattrib['format']
         else:
@@ -683,8 +685,8 @@ def parse_derived_parameter(self, node):
         """
         Parses <DerivedParameter>
 
-        @param node: Node containing the <DerivedParameter> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <DerivedParameter> element
+        :type node: xml.etree.Element
         """
 
         #if self.current_context.context_type != Context.COMPONENT_TYPE:
@@ -706,22 +708,27 @@ def parse_derived_parameter(self, node):
         else:
             value = None
 
+        # TODO: this is not used in the DerivedParameter constructor
         if 'select' in node.lattrib:
             select = node.lattrib['select']
         else:
             select = None
 
-        self.current_component_type.add_derived_parameter(DerivedParameter(name, value,
-                                                                    dimension, select))
+        if 'description' in node.lattrib:
+            description = node.lattrib['description']
+        else:
+            description = None
+
+        self.current_component_type.add_derived_parameter(DerivedParameter(name, value, dimension, description))
 
     def parse_derived_variable(self, node):
         """
         Parses <DerivedVariable>
 
-        @param node: Node containing the <DerivedVariable> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <DerivedVariable> element
+        :type node: xml.etree.Element
 
-        @raise ParseError: Raised when no name of specified for the derived variable.
+        :raises ParseError: Raised when no name of specified for the derived variable.
         """
 
         if 'name' in node.lattrib:
@@ -737,16 +744,16 @@ def parse_derived_variable(self, node):
                 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>
 
-        @param node: Node containing the <ConditionalDerivedVariable> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <ConditionalDerivedVariable> element
+        :type node: xml.etree.Element
 
-        @raise ParseError: Raised when no name or value is specified for the conditional derived variable.
+        :raises ParseError: Raised when no name or value is specified for the conditional derived variable.
         """
 
         if 'name' in node.lattrib:
@@ -755,41 +762,41 @@ def parse_conditional_derived_variable(self, node):
             name = node.lattrib['exposure']
         else:
             self.raise_error('<ConditionalDerivedVariable> must specify a name')
-            
+
         if 'exposure' in node.lattrib:
             exposure = node.lattrib['exposure']
         else:
             exposure = None
-            
+
         if 'dimension' in node.lattrib:
             dimension = node.lattrib['dimension']
         else:
             dimension = None
 
         conditional_derived_variable = ConditionalDerivedVariable(name, dimension, exposure)
-        
+
         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>
 
-        @param node: Node containing the <Case> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Case> element
+        :type node: xml.etree.Element
 
-        @raise ParseError: When no condition or value is specified
+        :raises ParseError: When no condition or value is specified
         """
-        
+
         try:
             condition = node.lattrib['condition']
         except:
             condition = None
-            
+
         try:
             value = node.lattrib['value']
         except:
@@ -801,11 +808,10 @@ def parse_dimension(self, node):
         """
         Parses <Dimension>
 
-        @param node: Node containing the <Dimension> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Dimension> element
+        :type node: xml.etree.Element
 
-        @raise ParseError: When the name is not a string or if the
-        dimension is not a signed integer.
+        :raises ParseError: When the name is not a string or if the dimension is not a signed integer.
         """
 
         try:
@@ -825,8 +831,8 @@ def parse_dynamics(self, node):
         """
         Parses <Dynamics>
 
-        @param node: Node containing the <Behaviour> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Behaviour> element
+        :type node: xml.etree.Element
         """
 
         self.current_dynamics = self.current_component_type.dynamics
@@ -839,8 +845,8 @@ def parse_event_connection(self, node):
         """
         Parses <EventConnection>
 
-        @param node: Node containing the <EventConnection> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <EventConnection> element
+        :type node: xml.etree.Element
         """
 
         if 'from' in node.lattrib:
@@ -865,8 +871,8 @@ def parse_event_out(self, node):
         """
         Parses <EventOut>
 
-        @param node: Node containing the <EventOut> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <EventOut> element
+        :type node: xml.etree.Element
         """
 
         try:
@@ -882,8 +888,8 @@ def parse_event_port(self, node):
         """
         Parses <EventPort>
 
-        @param node: Node containing the <EventPort> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <EventPort> element
+        :type node: xml.etree.Element
         """
 
         if 'name' in node.lattrib:
@@ -902,18 +908,17 @@ def parse_event_port(self, node):
                               'or \'out\''))
 
         description = node.lattrib.get('description', '')
-        
+
         self.current_component_type.add_event_port(EventPort(name, direction, description))
 
     def parse_exposure(self, node):
         """
         Parses <Exposure>
 
-        @param node: Node containing the <Exposure> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Exposure> element
+        :type node: xml.etree.Element
 
-        @raise ParseError: Raised when the exposure name is not
-        being defined in the context of a component type.
+        :raises ParseError: Raised when the exposure name is not being defined in the context of a component type.
         """
 
         if self.current_component_type == None:
@@ -938,8 +943,8 @@ def parse_fixed(self, node):
         """
         Parses <Fixed>
 
-        @param node: Node containing the <Fixed> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Fixed> element
+        :type node: xml.etree.Element
         """
 
         try:
@@ -953,17 +958,17 @@ def parse_fixed(self, node):
             self.raise_error("Fixed parameter '{0}'must specify a value.", parameter)
 
         description = node.lattrib.get('description', '')
-        
+
         self.current_component_type.add_parameter(Fixed(parameter, value, description))
 
     def parse_for_each(self, node):
         """
         Parses <ForEach>
 
-        @param node: Node containing the <ForEach> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <ForEach> element
+        :type node: xml.etree.Element
         """
-        
+
         if self.current_structure == None:
             self.raise_error('<ForEach> can only be made within ' +
                              'a structure definition')
@@ -984,7 +989,7 @@ def parse_for_each(self, node):
         fe = ForEach(instances, as_)
         self.current_structure.add_for_each(fe)
         self.current_structure = fe
-        
+
         self.process_nested_tags(node)
 
         self.current_structure = old_structure
@@ -993,10 +998,10 @@ def parse_include(self, node):
         """
         Parses <Include>
 
-        @param node: Node containing the <Include> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Include> element
+        :type node: xml.etree.Element
 
-        @raise ParseError: Raised when the file to be included is not specified. 
+        :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'])
@@ -1016,8 +1021,8 @@ def parse_kinetic_scheme(self, node):
         """
         Parses <KineticScheme>
 
-        @param node: Node containing the <KineticScheme> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <KineticScheme> element
+        :type node: xml.etree.Element
         """
 
         if 'name' in node.lattrib:
@@ -1068,8 +1073,8 @@ def parse_link(self, node):
         """
         Parses <Link>
 
-        @param node: Node containing the <Link> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Link> element
+        :type node: xml.etree.Element
         """
 
         if 'name' in node.lattrib:
@@ -1090,8 +1095,8 @@ def parse_multi_instantiate(self, node):
         """
         Parses <MultiInstantiate>
 
-        @param node: Node containing the <MultiInstantiate> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <MultiInstantiate> element
+        :type node: xml.etree.Element
         """
 
         if 'component' in node.lattrib:
@@ -1111,15 +1116,15 @@ def parse_on_condition(self, node):
         """
         Parses <OnCondition>
 
-        @param node: Node containing the <OnCondition> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <OnCondition> element
+        :type node: xml.etree.Element
         """
 
         try:
             test = node.lattrib['test']
         except:
             self.raise_error('<OnCondition> must specify a test.')
-            
+
         event_handler = OnCondition(test)
 
         self.current_regime.add_event_handler(event_handler)
@@ -1127,13 +1132,13 @@ def parse_on_condition(self, node):
         self.current_event_handler = event_handler
         self.process_nested_tags(node)
         self.current_event_handler = None
-        
+
     def parse_on_entry(self, node):
         """
         Parses <OnEntry>
 
-        @param node: Node containing the <OnEntry> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <OnEntry> element
+        :type node: xml.etree.Element
         """
 
         event_handler = OnEntry()
@@ -1149,15 +1154,15 @@ def parse_on_event(self, node):
         """
         Parses <OnEvent>
 
-        @param node: Node containing the <OnEvent> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <OnEvent> element
+        :type node: xml.etree.Element
         """
 
         try:
             port = node.lattrib['port']
         except:
             self.raise_error('<OnEvent> must specify a port.')
-            
+
         event_handler = OnEvent(port)
 
         self.current_regime.add_event_handler(event_handler)
@@ -1170,8 +1175,8 @@ def parse_on_start(self, node):
         """
         Parses <OnStart>
 
-        @param node: Node containing the <OnStart> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <OnStart> element
+        :type node: xml.etree.Element
         """
 
         event_handler = OnStart()
@@ -1186,12 +1191,11 @@ def parse_parameter(self, node):
         """
         Parses <Parameter>
 
-        @param node: Node containing the <Parameter> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Parameter> element
+        :type node: xml.etree.Element
 
-        @raise ParseError: Raised when the parameter does not have a name.
-        @raise ParseError: Raised when the parameter does not have a
-        dimension.
+        :raises ParseError: Raised when the parameter does not have a name.
+        :raises ParseError: Raised when the parameter does not have a dimension.
         """
 
         if self.current_component_type == None:
@@ -1209,7 +1213,8 @@ def parse_parameter(self, node):
             self.raise_error("Parameter '{0}' has no dimension",
                              name)
 
-        parameter = Parameter(name, dimension)
+        description = node.lattrib.get('description', '')
+        parameter = Parameter(name, dimension, description)
 
         self.current_component_type.add_parameter(parameter)
 
@@ -1217,12 +1222,11 @@ def parse_property(self, node):
         """
         Parses <Property>
 
-        @param node: Node containing the <Property> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Property> element
+        :type node: xml.etree.Element
 
-        @raise ParseError: Raised when the property does not have a name.
-        @raise ParseError: Raised when the property does not have a
-        dimension.
+        :raises ParseError: Raised when the property does not have a name.
+        :raises ParseError: Raised when the property does not have a dimension.
         """
 
         if self.current_component_type == None:
@@ -1239,22 +1243,22 @@ def parse_property(self, node):
         except:
             self.raise_error("Property '{0}' has no dimension",
                              name)
-                             
+
         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>
 
-        @param node: Node containing the <IndexParameter> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <IndexParameter> element
+        :type node: xml.etree.Element
 
-        @raise ParseError: Raised when the IndexParameter does not have a name.
+        :raises ParseError: Raised when the IndexParameter does not have a name.
         """
 
         if self.current_component_type == None:
@@ -1270,16 +1274,16 @@ def parse_index_parameter(self, node):
         index_parameter = IndexParameter(name)
 
         self.current_component_type.add_index_parameter(index_parameter)
-        
-        
+
+
     def parse_tunnel(self, node):
         """
         Parses <Tunnel>
 
-        @param node: Node containing the <Tunnel> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Tunnel> element
+        :type node: xml.etree.Element
 
-        @raise ParseError: Raised when the Tunnel does not have a name.
+        :raises ParseError: Raised when the Tunnel does not have a name.
         """
 
         try:
@@ -1307,14 +1311,14 @@ def parse_tunnel(self, node):
         tunnel = Tunnel(name, end_a, end_b, component_a, component_b)
 
         self.current_structure.add_tunnel(tunnel)
-        
+
 
     def parse_path(self, node):
         """
         Parses <Path>
 
-        @param node: Node containing the <Path> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Path> element
+        :type node: xml.etree.Element
         """
 
         if 'name' in node.lattrib:
@@ -1330,8 +1334,8 @@ def parse_record(self, node):
         """
         Parses <Record>
 
-        @param node: Node containing the <Record> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Record> element
+        :type node: xml.etree.Element
         """
 
         if self.current_simulation == None:
@@ -1353,8 +1357,8 @@ def parse_event_record(self, node):
         """
         Parses <EventRecord>
 
-        @param node: Node containing the <EventRecord> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <EventRecord> element
+        :type node: xml.etree.Element
         """
 
         if self.current_simulation == None:
@@ -1378,8 +1382,8 @@ def parse_regime(self, node):
         """
         Parses <Regime>
 
-        @param node: Node containing the <Behaviour> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Behaviour> element
+        :type node: xml.etree.Element
         """
 
         if 'name' in node.lattrib:
@@ -1405,8 +1409,8 @@ def parse_requirement(self, node):
         """
         Parses <Requirement>
 
-        @param node: Node containing the <Requirement> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Requirement> element
+        :type node: xml.etree.Element
         """
 
         if 'name' in node.lattrib:
@@ -1419,14 +1423,15 @@ def parse_requirement(self, node):
         else:
             self.raise_error("Requirement \{0}' must specify a dimension.", name)
 
-        self.current_component_type.add_requirement(Requirement(name, dimension))
-    
+        description = node.lattrib.get('description', '')
+        self.current_component_type.add_requirement(Requirement(name, dimension, description))
+
     def parse_component_requirement(self, node):
         """
         Parses <ComponentRequirement>
 
-        @param node: Node containing the <ComponentRequirement> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <ComponentRequirement> element
+        :type node: xml.etree.Element
         """
 
         if 'name' in node.lattrib:
@@ -1435,13 +1440,13 @@ def parse_component_requirement(self, node):
             self.raise_error('<ComponentRequirement> must specify a name')
 
         self.current_component_type.add_component_requirement(ComponentRequirement(name))
-    
+
     def parse_instance_requirement(self, node):
         """
         Parses <InstanceRequirement>
 
-        @param node: Node containing the <InstanceRequirement> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <InstanceRequirement> element
+        :type node: xml.etree.Element
         """
 
         if 'name' in node.lattrib:
@@ -1455,13 +1460,13 @@ def parse_instance_requirement(self, node):
             self.raise_error("InstanceRequirement \{0}' must specify a type.", name)
 
         self.current_component_type.add_instance_requirement(InstanceRequirement(name, type))
-    
+
     def parse_run(self, node):
         """
         Parses <Run>
 
-        @param node: Node containing the <Run> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Run> element
+        :type node: xml.etree.Element
         """
 
         if 'component' in node.lattrib:
@@ -1492,8 +1497,8 @@ def parse_show(self, node):
         """
         Parses <Show>
 
-        @param node: Node containing the <Show> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Show> element
+        :type node: xml.etree.Element
         """
 
         pass
@@ -1502,8 +1507,8 @@ def parse_simulation(self, node):
         """
         Parses <Simulation>
 
-        @param node: Node containing the <Simulation> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Simulation> element
+        :type node: xml.etree.Element
         """
 
         self.current_simulation = self.current_component_type.simulation
@@ -1516,8 +1521,8 @@ def parse_state_assignment(self, node):
         """
         Parses <StateAssignment>
 
-        @param node: Node containing the <StateAssignment> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <StateAssignment> element
+        :type node: xml.etree.Element
         """
 
         if 'variable' in node.lattrib:
@@ -1540,11 +1545,10 @@ def parse_state_variable(self, node):
         """
         Parses <StateVariable>
 
-        @param node: Node containing the <StateVariable> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <StateVariable> element
+        :type node: xml.etree.Element
 
-        @raise ParseError: Raised when the state variable is not
-        being defined in the context of a component type.
+        :raises ParseError: Raised when the state variable is not being defined in the context of a component type.
         """
 
         if 'name' in node.lattrib:
@@ -1568,8 +1572,8 @@ def parse_structure(self, node):
         """
         Parses <Structure>
 
-        @param node: Node containing the <Structure> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Structure> element
+        :type node: xml.etree.Element
         """
 
         self.current_structure = self.current_component_type.structure
@@ -1580,8 +1584,8 @@ def parse_target(self, node):
         """
         Parses <Target>
 
-        @param node: Node containing the <Target> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Target> element
+        :type node: xml.etree.Element
         """
 
         self.model.add_target(node.lattrib['component'])
@@ -1590,8 +1594,8 @@ def parse_text(self, node):
         """
         Parses <Text>
 
-        @param node: Node containing the <Text> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Text> element
+        :type node: xml.etree.Element
         """
 
         if 'name' in node.lattrib:
@@ -1607,11 +1611,10 @@ def parse_time_derivative(self, node):
         """
         Parses <TimeDerivative>
 
-        @param node: Node containing the <TimeDerivative> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <TimeDerivative> element
+        :type node: xml.etree.Element
 
-        @raise ParseError: Raised when the time derivative does not hava a variable
-        name of a value.
+        :raises ParseError: Raised when the time derivative does not hava a variable name of a value.
         """
 
         if 'variable' in node.lattrib:
@@ -1631,8 +1634,8 @@ def parse_transition(self, node):
         """
         Parses <Transition>
 
-        @param node: Node containing the <Transition> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Transition> element
+        :type node: xml.etree.Element
         """
 
         if 'regime' in node.lattrib:
@@ -1648,13 +1651,11 @@ def parse_unit(self, node):
         """
         Parses <Unit>
 
-        @param node: Node containing the <Unit> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <Unit> element
+        :type node: xml.etree.Element
 
-        @raise ParseError: When the name is not a string or the unit
-        specfications are incorrect.
-
-        @raise ModelError: When the unit refers to an undefined dimension.
+        :raises ParseError: When the name is not a string or the unit specfications are incorrect.
+        :raises ModelError: When the unit refers to an undefined dimension.
         """
 
         try:
@@ -1672,12 +1673,12 @@ def parse_unit(self, node):
             name = node.lattrib['name']
         else:
             name = ''
-            
+
         if 'scale' in node.lattrib:
             scale = float(node.lattrib['scale'])
         else:
             scale = 1.0
-            
+
         if 'offset' in node.lattrib:
             offset = float(node.lattrib['offset'])
         else:
@@ -1689,8 +1690,8 @@ def parse_with(self, node):
         """
         Parses <With>
 
-        @param node: Node containing the <With> element
-        @type node: xml.etree.Element
+        :param node: Node containing the <With> element
+        :type node: xml.etree.Element
         """
 
         if 'instance' in node.lattrib:
@@ -1711,4 +1712,3 @@ def parse_with(self, node):
                              'target instance')
 
         self.current_structure.add_with(With(instance, as_, list, index))
-
diff --git a/lems/parser/__init__.py b/lems/parser/__init__.py
index aaeb1c4..e6b819c 100644
--- a/lems/parser/__init__.py
+++ b/lems/parser/__init__.py
@@ -1,5 +1,4 @@
 """
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
diff --git a/lems/parser/expr.py b/lems/parser/expr.py
index 1a14252..46af8d5 100644
--- a/lems/parser/expr.py
+++ b/lems/parser/expr.py
@@ -1,9 +1,8 @@
 """
 Expression parser
 
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
 
 from lems.base.base import LEMSBase
@@ -24,13 +23,13 @@ def __init__(self, type):
         """
         Constructor.
 
-        @param type: Node type
-        @type type: enum(ExprNode.OP, ExprNode.VALUE)
+        :param type: Node type
+        :type type: enum(ExprNode.OP, ExprNode.VALUE)
         """
 
         self.type = type
         """ Node type.
-        @type: enum(ExprNode.OP, ExprNode.VALUE) """
+        :type: enum(ExprNode.OP, ExprNode.VALUE) """
 
 class ValueNode(ExprNode):
     """
@@ -41,14 +40,14 @@ def __init__(self, value):
         """
         Constructor.
 
-        @param value: Value to be stored in this node.
-        @type value: string
+        :param value: Value to be stored in this node.
+        :type value: string
         """
 
         ExprNode.__init__(self, ExprNode.VALUE)
         self.value = value
         """ Value to be stored in this node.
-        @type: string """
+        :type: string """
         
     def clean_up(self):
         """
@@ -82,29 +81,29 @@ def __init__(self, op, left, right):
         """
         Constructor.
 
-        @param op: Operation to be stored in this node.
-        @type op: string
+        :param op: Operation to be stored in this node.
+        :type op: string
 
-        @param left: Left operand.
-        @type left: lems.parser.expr.ExprNode
+        :param left: Left operand.
+        :type left: lems.parser.expr.ExprNode
 
-        @param right: Right operand.
-        @type right: lems.parser.expr.ExprNode
+        :param right: Right operand.
+        :type right: lems.parser.expr.ExprNode
         """
 
         ExprNode.__init__(self, ExprNode.OP)
 
         self.op = op
         """ Operation stored in this node.
-        @type: string """
+        :type: string """
 
         self.left = left
         """ Left operand.
-        @type: lems.parser.expr.ExprNode """
+        :type: lems.parser.expr.ExprNode """
 
         self.right = right
         """ Right operand.
-        @type: lems.parser.expr.ExprNode """
+        :type: lems.parser.expr.ExprNode """
 
     def __str__(self):
         """
@@ -133,22 +132,22 @@ def __init__(self, func, param):
         """
         Constructor.
 
-        @param func: Function to be stored in this node.
-        @type func: string
+        :param func: Function to be stored in this node.
+        :type func: string
 
-        @param param: Parameter.
-        @type param: lems.parser.expr.ExprNode
+        :param param: Parameter.
+        :type param: lems.parser.expr.ExprNode
         """
 
         ExprNode.__init__(self, ExprNode.FUNC1)
 
         self.func = func
         """ Funcion stored in this node.
-        @type: string """
+        :type: string """
 
         self.param = param
         """ Parameter.
-        @type: lems.parser.expr.ExprNode """
+        :type: lems.parser.expr.ExprNode """
 
     def __str__(self):
         """
@@ -195,33 +194,33 @@ class ExprParser(LEMSBase):
     depth = 0
 
     """ Dictionary mapping operators to their priorities.
-    @type: dict(string -> Integer) """
+    :type: dict(string -> Integer) """
 
     def __init__(self, parse_string):
         """
         Constructor.
 
-        @param parse_string: Expression to be parsed.
-        @type parse_string: string
+        :param parse_string: Expression to be parsed.
+        :type parse_string: string
         """
 
         self.parse_string = parse_string
         """ Expression to be parsed.
-        @type: string """
+        :type: string """
 
         self.token_list = None
         """ List of tokens from the expression to be parsed.
-        @type: list(string) """
+        :type: list(string) """
 
     def is_op(self, str):
         """
         Checks if a token string contains an operator.
 
-        @param str: Token string to be checked.
-        @type str: string
+        :param str: Token string to be checked.
+        :type str: string
 
-        @return: True if the token string contains an operator.
-        @rtype: Boolean
+        :return: True if the token string contains an operator.
+        :rtype: Boolean
         """
 
         return str in self.op_priority
@@ -230,11 +229,11 @@ def is_func(self, str):
         """
         Checks if a token string contains a function.
 
-        @param str: Token string to be checked.
-        @type str: string
+        :param str: Token string to be checked.
+        :type str: string
 
-        @return: True if the token string contains a function.
-        @rtype: Boolean
+        :return: True if the token string contains a function.
+        :rtype: Boolean
         """
 
         return str in known_functions
@@ -243,11 +242,11 @@ def is_sym(self, str):
         """
         Checks if a token string contains a symbol.
 
-        @param str: Token string to be checked.
-        @type str: string
+        :param str: Token string to be checked.
+        :type str: string
 
-        @return: True if the token string contains a symbol.
-        @rtype: Boolean
+        :return: True if the token string contains a symbol.
+        :rtype: Boolean
         """
 
         return str in ['+', '-', '~', '*', '/', '^', '(', ')']
@@ -354,8 +353,8 @@ def parse_token_list_rec(self, min_precedence):
         Parses a tokenized arithmetic expression into a parse tree. It calls
         itself recursively to handle bracketed subexpressions.
 
-        @return: Returns a token string.
-        @rtype: lems.parser.expr.ExprNode
+        :return: Returns a token string.
+        :rtype: lems.parser.expr.ExprNode
 
         @attention: Does not handle unary minuses at the moment. Needs to be
         fixed.
@@ -479,8 +478,8 @@ def parse(self):
         """
         Tokenizes and parses an arithmetic expression into a parse tree.
 
-        @return: Returns a token string.
-        @rtype: lems.parser.expr.ExprNode
+        :return: Returns a token string.
+        :rtype: lems.parser.expr.ExprNode
         """
         #print("Parsing: %s"%self.parse_string)
         self.tokenize()
diff --git a/lems/run.py b/lems/run.py
index 019a681..84a4097 100644
--- a/lems/run.py
+++ b/lems/run.py
@@ -1,9 +1,8 @@
 """
 Command line simulation driver.
 
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
 
 import argparse
diff --git a/lems/sim/__init__.py b/lems/sim/__init__.py
index aaeb1c4..e6b819c 100644
--- a/lems/sim/__init__.py
+++ b/lems/sim/__init__.py
@@ -1,5 +1,4 @@
 """
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
diff --git a/lems/sim/build.py b/lems/sim/build.py
index 82055f1..44e9a95 100644
--- a/lems/sim/build.py
+++ b/lems/sim/build.py
@@ -1,9 +1,8 @@
 """
 Simulation builder.
 
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
 
 import re
@@ -27,17 +26,17 @@ def __init__(self, model):
         """
         Constructor.
 
-        @param model: Model upon which the simulation is to be generated.
-        @type model: lems.model.model.Model
+        :param model: Model upon which the simulation is to be generated.
+        :type model: lems.model.model.Model
         """
 
         self.model = model
         """ Model to be used for constructing the simulation.
-        @type: lems.model.model.Model """
+        :type: lems.model.model.Model """
 
         self.sim = None
         """ Simulation built from the model.
-        @type: lems.sim.sim.Simulation """
+        :type: lems.sim.sim.Simulation """
 
         self.current_record_target = None
 
@@ -48,8 +47,8 @@ def build(self):
         """
         Build the simulation components from the model.
 
-        @return: A runnable simulation object
-        @rtype: lems.sim.sim.Simulation
+        :return: A runnable simulation object
+        :rtype: lems.sim.sim.Simulation
         """
 
         self.sim = Simulation()
@@ -70,17 +69,15 @@ def build_runnable(self, component, parent = None, id_ = None):
         Build a runnable component from a component specification and add
         it to the simulation.
 
-        @param component: Component specification
-        @type component: lems.model.component.FatComponent
+        :param component: Component specification
+        :type component: lems.model.component.FatComponent
 
-        @param parent: Parent runnable component.
-        @type parent: lems.sim.runnable.Runnable
+        :param parent: Parent runnable component.
+        :type parent: lems.sim.runnable.Runnable
 
-        @param id_: Optional id for therunnable. If it's not passed in,
-        the runnable will inherit the id of the component.
+        :param id_: Optional id for therunnable. If it's not passed in, the runnable will inherit the id of the component.
 
-        @raise SimBuildError: Raised when a component reference cannot be
-        resolved.
+        :raises SimBuildError: Raised when a component reference cannot be resolved.
         """
         if self.debug: print("++++++++ Calling build_runnable of %s with parent %s"%(component, parent))
 
@@ -233,15 +230,14 @@ def build_event_connections(self, component, runnable, structure):
         Adds event connections to a runnable component based on the structure
         specifications in the component model.
 
-        @param component: Component model containing structure specifications.
-        @type component: lems.model.component.FatComponent
+        :param component: Component model containing structure specifications.
+        :type component: lems.model.component.FatComponent
 
-        @param runnable: Runnable component to which structure is to be added.
-        @type runnable: lems.sim.runnable.Runnable
+        :param runnable: Runnable component to which structure is to be added.
+        :type runnable: lems.sim.runnable.Runnable
 
-        @param structure: The structure object to be used to add
-        structure code in the runnable component.
-        @type structure: lems.model.structure.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))
         # Process event connections
@@ -295,15 +291,14 @@ def build_structure(self, component, runnable, structure):
         Adds structure to a runnable component based on the structure
         specifications in the component model.
 
-        @param component: Component model containing structure specifications.
-        @type component: lems.model.component.FatComponent
+        :param component: Component model containing structure specifications.
+        :type component: lems.model.component.FatComponent
 
-        @param runnable: Runnable component to which structure is to be added.
-        @type runnable: lems.sim.runnable.Runnable
+        :param runnable: Runnable component to which structure is to be added.
+        :type runnable: lems.sim.runnable.Runnable
 
-        @param structure: The structure object to be used to add
-        structure code in the runnable component.
-        @type structure: lems.model.structure.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))
         
@@ -339,15 +334,14 @@ def build_foreach(self, component, runnable, foreach, name_mappings = {}):
         """
         Iterate over ForEach constructs and process nested elements.
 
-        @param component: Component model containing structure specifications.
-        @type component: lems.model.component.FatComponent
+        :param component: Component model containing structure specifications.
+        :type component: lems.model.component.FatComponent
 
-        @param runnable: Runnable component to which structure is to be added.
-        @type runnable: lems.sim.runnable.Runnable
+        :param runnable: Runnable component to which structure is to be added.
+        :type runnable: lems.sim.runnable.Runnable
 
-        @param foreach: The ForEach structure object to be used to add
-        structure code in the runnable component.
-        @type foreach: lems.model.structure.ForEach
+        :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))
 
@@ -401,27 +395,23 @@ def add_dynamics_1(self, component, runnable, regime, dynamics):
 
         This method builds dynamics necessary for building child components.
 
-        @param component: Component model containing dynamics specifications.
-        @type component: lems.model.component.FatComponent
+        :param component: Component model containing dynamics specifications.
+        :type component: lems.model.component.FatComponent
 
-        @param runnable: Runnable component to which dynamics is to be added.
-        @type runnable: lems.sim.runnable.Runnable
+        :param runnable: Runnable component to which dynamics is to be added.
+        :type runnable: lems.sim.runnable.Runnable
 
-        @param regime: The dynamics regime to be used to generate
-        dynamics code in the runnable component.
-        @type regime: lems.model.dynamics.Regime
+        :param regime: The dynamics regime to be used to generate dynamics code in the runnable component.
+        :type regime: lems.model.dynamics.Regime
 
-        @param dynamics: Shared dynamics specifications.
-        @type dynamics: lems.model.dynamics.Regime
+        :param dynamics: Shared dynamics specifications.
+        :type dynamics: lems.model.dynamics.Regime
 
-        @raise SimBuildError: Raised when a time derivative expression refers
-        to an undefined variable.
+        :raises SimBuildError: Raised when a time derivative expression refers to an undefined variable.
 
-        @raise SimBuildError: Raised when there are invalid time
-        specifications for the <Run> statement.
+        :raises SimBuildError: Raised when there are invalid time specifications for the <Run> statement.
 
-        @raise SimBuildError: Raised when the component reference for <Run>
-        cannot be resolved.
+        :raises SimBuildError: Raised when the component reference for <Run> cannot be resolved.
         """
 
         if isinstance(regime, Dynamics) or regime.name == '':
@@ -525,27 +515,23 @@ def add_dynamics_2(self, component, runnable, regime, dynamics):
 
         This method builds dynamics dependent on child components.
 
-        @param component: Component model containing dynamics specifications.
-        @type component: lems.model.component.FatComponent
+        :param component: Component model containing dynamics specifications.
+        :type component: lems.model.component.FatComponent
 
-        @param runnable: Runnable component to which dynamics is to be added.
-        @type runnable: lems.sim.runnable.Runnable
+        :param runnable: Runnable component to which dynamics is to be added.
+        :type runnable: lems.sim.runnable.Runnable
 
-        @param regime: The dynamics regime to be used to generate
-        dynamics code in the runnable component.
-        @type regime: lems.model.dynamics.Regime
+        :param regime: The dynamics regime to be used to generate dynamics code in the runnable component.
+        :type regime: lems.model.dynamics.Regime
 
-        @param dynamics: Shared dynamics specifications.
-        @type dynamics: lems.model.dynamics.Regime
+        :param dynamics: Shared dynamics specifications.
+        :type dynamics: lems.model.dynamics.Regime
 
-        @raise SimBuildError: Raised when a time derivative expression refers
-        to an undefined variable.
+        :raises SimBuildError: Raised when a time derivative expression refers to an undefined variable.
 
-        @raise SimBuildError: Raised when there are invalid time
-        specifications for the <Run> statement.
+        :raises SimBuildError: Raised when there are invalid time specifications for the <Run> statement.
 
-        @raise SimBuildError: Raised when the component reference for <Run>
-        cannot be resolved.
+        :raises SimBuildError: Raised when the component reference for <Run> cannot be resolved.
         """
 
         if isinstance(regime, Dynamics) or regime.name == '':
@@ -608,24 +594,20 @@ def process_simulation_specs(self, component, runnable, simulation):
         Process simulation-related aspects to a runnable component based on the
         dynamics specifications in the component model.
 
-        @param component: Component model containing dynamics specifications.
-        @type component: lems.model.component.FatComponent
+        :param component: Component model containing dynamics specifications.
+        :type component: lems.model.component.FatComponent
 
-        @param runnable: Runnable component to which dynamics is to be added.
-        @type runnable: lems.sim.runnable.Runnable
+        :param runnable: Runnable component to which dynamics is to be added.
+        :type runnable: lems.sim.runnable.Runnable
 
-        @param simulation: The simulation-related aspects to be implemented
-        in the runnable component.
-        @type simulation: lems.model.simulation.Simulation
+        :param simulation: The simulation-related aspects to be implemented in the runnable component.
+        :type simulation: lems.model.simulation.Simulation
 
-        @raise SimBuildError: Raised when a time derivative expression refers
-        to an undefined variable
+        :raises SimBuildError: Raised when a time derivative expression refers to an undefined variable
 
-        @raise SimBuildError: Raised when there are invalid time
-        specifications for the <Run> statement.
+        :raises SimBuildError: Raised when there are invalid time specifications for the <Run> statement.
 
-        @raise SimBuildError: Raised when the component reference for <Run>
-        cannot be resolved.
+        :raises SimBuildError: Raised when the component reference for <Run> cannot be resolved.
         """
 
         # Process runs
@@ -644,12 +626,12 @@ def convert_op(self, op):
         """
         Converts NeuroML arithmetic/logical operators to python equivalents.
 
-        @param op: NeuroML operator
-        @type op: string
+        :param op: NeuroML operator
+        :type op: string
 
 
-        @return: Python operator
-        @rtype: string
+        :return: Python operator
+        :rtype: string
         """
 
         if op == '.gt.':
@@ -679,12 +661,12 @@ def convert_func(self, func):
         """
         Converts NeuroML arithmetic/logical functions to python equivalents.
 
-        @param func: NeuroML function
-        @type func: string
+        :param func: NeuroML function
+        :type func: string
 
 
-        @return: Python operator
-        @rtype: string
+        :return: Python operator
+        :rtype: string
         """
 
         if func == 'ln':
@@ -704,18 +686,17 @@ def build_expression_from_tree(self, runnable, regime, tree_node):
         """
         Recursively builds a Python expression from a parsed expression tree.
 
-        @param runnable: Runnable object to which this expression would be added.
-        @type runnable: lems.sim.runnable.Runnable
+        :param runnable: Runnable object to which this expression would be added.
+        :type runnable: lems.sim.runnable.Runnable
 
-        @param regime: Dynamics regime being built.
-        @type regime: lems.model.dynamics.Regime
+        :param regime: Dynamics regime being built.
+        :type regime: lems.model.dynamics.Regime
 
-        @param tree_node: Root node for the tree from which the expression
-        is to be built.
-        @type tree_node: lems.parser.expr.ExprNode
+        :param tree_node: Root node for the tree from which the expression is to be built.
+        :type tree_node: lems.parser.expr.ExprNode
 
-        @return: Generated Python expression.
-        @rtype: string
+        :return: Generated Python expression.
+        :rtype: string
         """
 
         component_type = self.model.component_types[runnable.component.type]
@@ -770,11 +751,11 @@ def build_event_handler(self, runnable, regime, event_handler):
         """
         Build event handler code.
 
-        @param event_handler: Event handler object
-        @type event_handler: lems.model.dynamics.EventHandler
+        :param event_handler: Event handler object
+        :type event_handler: lems.model.dynamics.EventHandler
 
-        @return: Generated event handler code.
-        @rtype: list(string)
+        :return: Generated event handler code.
+        :rtype: list(string)
         """
 
         if isinstance(event_handler, OnCondition):
@@ -792,11 +773,11 @@ def build_on_condition(self, runnable, regime, on_condition):
         """
         Build OnCondition event handler code.
 
-        @param on_condition: OnCondition event handler object
-        @type on_condition: lems.model.dynamics.OnCondition
+        :param on_condition: OnCondition event handler object
+        :type on_condition: lems.model.dynamics.OnCondition
 
-        @return: Generated OnCondition code
-        @rtype: list(string)
+        :return: Generated OnCondition code
+        :rtype: list(string)
         """
 
         on_condition_code = []
@@ -817,11 +798,11 @@ def build_on_event(self, runnable, regime, on_event):
         """
         Build OnEvent event handler code.
 
-        @param on_event: OnEvent event handler object
-        @type on_event: lems.model.dynamics.OnEvent
+        :param on_event: OnEvent event handler object
+        :type on_event: lems.model.dynamics.OnEvent
 
-        @return: Generated OnEvent code
-        @rtype: list(string)
+        :return: Generated OnEvent code
+        :rtype: list(string)
         """
         on_event_code = []
 
@@ -847,11 +828,11 @@ def build_on_start(self, runnable, regime, on_start):
         """
         Build OnStart start handler code.
 
-        @param on_start: OnStart start handler object
-        @type on_start: lems.model.dynamics.OnStart
+        :param on_start: OnStart start handler object
+        :type on_start: lems.model.dynamics.OnStart
 
-        @return: Generated OnStart code
-        @rtype: list(string)
+        :return: Generated OnStart code
+        :rtype: list(string)
         """
 
         on_start_code = []
@@ -867,11 +848,11 @@ def build_on_entry(self, runnable, regime, on_entry):
         """
         Build OnEntry start handler code.
 
-        @param on_entry: OnEntry start handler object
-        @type on_entry: lems.model.dynamics.OnEntry
+        :param on_entry: OnEntry start handler object
+        :type on_entry: lems.model.dynamics.OnEntry
 
-        @return: Generated OnEntry code
-        @rtype: list(string)
+        :return: Generated OnEntry code
+        :rtype: list(string)
         """
 
         on_entry_code = []
@@ -890,11 +871,11 @@ def build_action(self, runnable, regime, action):
         """
         Build event handler action code.
 
-        @param action: Event handler action object
-        @type action: lems.model.dynamics.Action
+        :param action: Event handler action object
+        :type action: lems.model.dynamics.Action
 
-        @return: Generated action code
-        @rtype: string
+        :return: Generated action code
+        :rtype: string
         """
 
         if isinstance(action, StateAssignment):
@@ -910,11 +891,11 @@ def build_state_assignment(self, runnable, regime, state_assignment):
         """
         Build state assignment code.
 
-        @param state_assignment: State assignment object
-        @type state_assignment: lems.model.dynamics.StateAssignment
+        :param state_assignment: State assignment object
+        :type state_assignment: lems.model.dynamics.StateAssignment
 
-        @return: Generated state assignment code
-        @rtype: string
+        :return: Generated state assignment code
+        :rtype: string
         """
 
         return ['self.{0} = {1}'.format(\
@@ -927,11 +908,11 @@ def build_event_out(self, event_out):
         """
         Build event out code.
 
-        @param event_out: event out object
-        @type event_out: lems.model.dynamics.EventOut
+        :param event_out: event out object
+        :type event_out: lems.model.dynamics.EventOut
 
-        @return: Generated event out code
-        @rtype: string
+        :return: Generated event out code
+        :rtype: string
         """
 
         event_out_code = ['if "{0}" in self.event_out_callbacks:'.format(event_out.port),
@@ -944,11 +925,11 @@ def build_transition(self, transition):
         """
         Build regime transition code.
 
-        @param transition: Transition object
-        @type transition: lems.model.dynamics.Transition
+        :param transition: Transition object
+        :type transition: lems.model.dynamics.Transition
 
-        @return: Generated transition code
-        @rtype: string
+        :return: Generated transition code
+        :rtype: string
         """
 
         return ["self.new_regime = '{0}'".format(transition.regime)]
@@ -1040,12 +1021,11 @@ def add_recording_behavior(self, component, runnable):
         Adds recording-related dynamics to a runnable component based on
         the dynamics specifications in the component model.
 
-        @param component: Component model containing dynamics specifications.
-        @type component: lems.model.component.FatComponent runnable: Runnable component to which dynamics is to be added.
-        @type runnable: lems.sim.runnable.Runnable
+        :param component: Component model containing dynamics specifications.
+        :type component: lems.model.component.FatComponent runnable: Runnable component to which dynamics is to be added.
+        :type runnable: lems.sim.runnable.Runnable
 
-        @raise SimBuildError: Raised when a target for recording could not be
-        found.
+        :raises SimBuildError: Raised when a target for recording could not be found.
         """
 
         simulation = component.simulation
@@ -1060,14 +1040,13 @@ def order_derived_parameters(component):
     """
     Finds ordering of derived_parameters.
 
-    @param component: Component containing derived parameters.
-    @type component: lems.model.component.Component
+    :param component: Component containing derived parameters.
+    :type component: lems.model.component.Component
 
-    @return: Returns ordered list of derived parameters.
-    @rtype: list(string)
+    :return: Returns ordered list of derived parameters.
+    :rtype: list(string)
 
-    @raise SimBuildError: Raised when a proper ordering of derived
-    parameters could not be found.
+    :raises SimBuildError: Raised when a proper ordering of derived parameters could not be found.
     """
 
     if len(component.derived_parameters) == 0:
@@ -1111,14 +1090,13 @@ def order_derived_variables(regime):
     """
     Finds ordering of derived_variables.
 
-    @param regime: Dynamics Regime containing derived variables.
-    @type regime: lems.model.dynamics.regime
+    :param regime: Dynamics Regime containing derived variables.
+    :type regime: lems.model.dynamics.regime
 
-    @return: Returns ordered list of derived variables.
-    @rtype: list(string)
+    :return: Returns ordered list of derived variables.
+    :rtype: list(string)
 
-    @raise SimBuildError: Raised when a proper ordering of derived
-    variables could not be found.
+    :raises SimBuildError: Raised when a proper ordering of derived variables could not be found.
     """
 
     ordering = []
diff --git a/lems/sim/recording.py b/lems/sim/recording.py
index 1036248..1494d5b 100644
--- a/lems/sim/recording.py
+++ b/lems/sim/recording.py
@@ -1,9 +1,8 @@
 """
 Recording class(es).
 
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
 
 from lems.base.base import LEMSBase
diff --git a/lems/sim/runnable.py b/lems/sim/runnable.py
index b931b68..b1f770c 100644
--- a/lems/sim/runnable.py
+++ b/lems/sim/runnable.py
@@ -1,9 +1,8 @@
 """
 Base class for runnable components.
 
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
 
 from lems.base.base import LEMSBase
@@ -598,8 +597,8 @@ def copy(self):
         """
         Make a copy of this runnable.
 
-        @return: Copy of this runnable.
-        @rtype: lems.sim.runnable.Runnable
+        :return: Copy of this runnable.
+        :rtype: lems.sim.runnable.Runnable
         """
         if self.debug: print("Coping....."+self.id)
         r = Runnable(self.id, self.component, self.parent)
diff --git a/lems/sim/sim.py b/lems/sim/sim.py
index d2f289a..341c81b 100644
--- a/lems/sim/sim.py
+++ b/lems/sim/sim.py
@@ -1,9 +1,8 @@
 """
 Simulation.
 
-@author: Gautham Ganapathy
-@organization: LEMS (http://neuroml.org/lems/, https://github.com/organizations/LEMS)
-@contact: gautham@lisphacker.org
+:author: Gautham Ganapathy
+:organization: LEMS (https://github.com/organizations/LEMS)
 """
 
 from lems.base.base import LEMSBase
@@ -24,23 +23,23 @@ def __init__(self):
 
         self.runnables = {}
         """ Dictionary of runnable components in this simulation.
-        @type: dict(string -> lems.sim.runnable.Runnable) """
+        :type: dict(string -> lems.sim.runnable.Runnable) """
 
         self.run_queue = []
         """ Priority of pairs of (time-to-next run, runnable).
-        @type: list((Integer, lems.sim.runnable.Runnable)) """
+        :type: list((Integer, lems.sim.runnable.Runnable)) """
 
         self.event_queue = []
         """ List of posted events.
-        @type: list(lems.sim.sim.Event) """
+        :type: list(lems.sim.sim.Event) """
 
     def add_runnable(self, runnable):
         """
         Adds a runnable component to the list of runnable components in
         this simulation.
 
-        @param runnable: A runnable component
-        @type runnable: lems.sim.runnable.Runnable
+        :param runnable: A runnable component
+        :type runnable: lems.sim.runnable.Runnable
         """
 
         if runnable.id in self.runnables:
@@ -157,8 +156,8 @@ class Event:
     def __init__(self, from_id, to_id):
         self.from_id = from_id
         """ ID of the source runnable for this event.
-        @type: Integer """
+        :type: Integer """
 
         self.to_id = to_id
         """ ID of the destination runnable for this event.
-        @type: Integer """
+        :type: Integer """
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..72248c8
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,5 @@
+[flake8]
+# ignore:
+# spacing around operators, comment blocks, in argument lists
+# lines too long
+ignore = E501,E502,F403,F405,E231,E228,E225,E226,E265,E261
diff --git a/setup.py b/setup.py
index cc690e0..3f1c2f3 100644
--- a/setup.py
+++ b/setup.py
@@ -29,8 +29,6 @@
         '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/ci/run-apitest.sh b/ci/run-apitest.sh
new file mode 100755
index 0000000..d0fe75f
--- /dev/null
+++ b/ci/run-apitest.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+# Copyright 2021 LEMS contributors
+# Author: Ankur Sinha <sanjay DOT ankur AT gmail DOT com> 
+# File : run-apitest.sh
+#
+# Run api tests on GitHub actions
+
+python examples/apitest.py
+python examples/apitest2.py
+python examples/loadtest.py
+
+# Update NeuroML2 path for CI
+if [ "$CI" = "true" ]; then
+    sed -i 's|../NeuroML2|./NeuroML2|g' lems/dlems/exportdlems.py
+fi
+python lems/dlems/exportdlems.py
diff --git a/lems/test/test_load_write.py b/lems/test/test_load_write.py
index 2c5c264..5c4cfac 100644
--- a/lems/test/test_load_write.py
+++ b/lems/test/test_load_write.py
@@ -3,25 +3,15 @@
 
 """
 
+import unittest
 from lems.model.model import Model
 
-try:
-    import unittest2 as unittest
-except ImportError:
-    import unittest
-    
 
 class TestLoadWrite(unittest.TestCase):
-
-
     def test_load_write_xml(self):
-        
         model = Model()
-
         file_name = 'lems/test/hhcell_resaved2.xml'
-
         model.import_from_file(file_name)
-
         file_name2 = 'lems/test/hhcell_resaved3.xml'
         model.export_to_file(file_name2)
 
@@ -34,21 +24,9 @@ def test_load_write_xml(self):
         from lems.base.util import validate_lems
 
         validate_lems(file_name2)
-        
+
     def test_load_get_dom(self):
-        
         model = Model()
-
         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
new file mode 100644
index 0000000..b851113
--- /dev/null
+++ b/lems/test/test_misc.py
@@ -0,0 +1,34 @@
+"""
+Misc tests.
+
+File: test_misc.py
+
+Copyright 2021 LEMS contributors
+Author: Ankur Sinha <sanjay DOT ankur AT gmail DOT com>
+"""
+
+
+import unittest
+from lems.model.model import Model
+
+
+class TestExposure(unittest.TestCase):
+
+    """Test getting exposures from LEMS models"""
+
+    def test_exposure_getters(self):
+        model = Model(include_includes=True, fail_on_missing_includes=True)
+        file_name = 'examples/example1.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__':
+    unittest.main()
diff --git a/lems/test/test_parser.py b/lems/test/test_parser.py
index 7176a63..4af3ed4 100644
--- a/lems/test/test_parser.py
+++ b/lems/test/test_parser.py
@@ -4,30 +4,23 @@
 '''
 
 
+import unittest
 from lems.parser.expr import ExprParser
 
-try:
-    import unittest2 as unittest
-except ImportError:
-    import unittest
-    
 
 class TestParser(unittest.TestCase):
-
-
     def test_parser(self):
-        
+
         x = 0.5
-        
+
         exprs = {}
         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})'
@@ -49,28 +42,26 @@ def test_parser(self):
             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!!
-        
+
         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))
         ep = ExprParser(expr)
         try:
@@ -85,13 +76,10 @@ def parse_expr(self, expr, val, should_fail=False):
         except Exception as e:
             if not should_fail:
                 print("Exception thrown %s"%e)
-                assert 1==2 
+                assert 1==2
             else:
                 print("Successfully failed")
-        
-
 
 
 if __name__ == '__main__':
-    
-    TestParser.test_parser(None)
+    TestParser().test_parser()
diff --git a/lems/test/test_units.py b/lems/test/test_units.py
index 8179ed4..7552ad6 100644
--- a/lems/test/test_units.py
+++ b/lems/test/test_units.py
@@ -5,17 +5,12 @@
 """
 
 
+import unittest
 from lems.model.fundamental import Dimension,Unit
 from lems.model.model import Model
 
-try:
-    import unittest2 as unittest
-except ImportError:
-    import unittest
-    
 
 class TestUnitParsing(unittest.TestCase):
-
     def get_model(self):
 
         model = Model()
@@ -34,40 +29,34 @@ def get_model(self):
 
         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))
 
         return model
 
-
-    def check_num_val(self, unit_str, val, dimension = None):
-
+    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))
         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)
-        
-
-
diff --git a/testpy3.sh b/testpy3.sh
deleted file mode 100755
index 5cc69c0..0000000
--- a/testpy3.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-set -e
-sudo python3 setup.py clean
-sudo python3 setup.py install
-python3 examples/apitest.py
-python3 examples/apitest2.py
-python3 examples/loadtest.py
-python3 lems/dlems/exportdlems.py
-#python pylems ~/NeuroML2/NeuroML2CoreTypes/Test_pylems.xml