Repository: openworm/c302 (language: python)

Issue:
Development owmeta



Discussion / hints:

Fix patch:
diff --git a/.travis.yml b/.travis.yml
index 096b1e0c..0a9eb7c5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,23 +2,23 @@
 # See https://github.com/OpenSourceBrain/osb-model-validation for more details
 
 dist: xenial
-sudo: false
 
 addons:
   apt:
     packages:
        # Requirements for Neuron/OMV/etc
-    - python-numpy 
-    - python-scipy 
+    - python-numpy
+    - python-scipy
     - python-tornado
-    - python-matplotlib 
+    - python-matplotlib
     - python-tk
     - python-dev
 
 language: python
 python:
-     - "2.7"
-     - "3.6"
+     - "3.7"
+     - "3.8"
+     # - "3.9" # does version of neuron in omv work with py3.9?
 
 
 env:
@@ -26,7 +26,7 @@ env:
      - OMV_ENGINE=jNeuroML_NEURON
      - OMV_ENGINE=jNeuroML_validate
      - OMV_ENGINE=NON_OMV_TESTS
-     
+
 
 #before_install:
     # To run tests requiring a graphical user interface on Travis CI, use xvfb (X Virtual Framebuffer) to imitate a display.
@@ -36,21 +36,11 @@ env:
 install:
     # Required to run OMV tests
     - pip install git+https://github.com/OpenSourceBrain/osb-model-validation
-    
-    # Install specific version of PyOpenWorm
-    - git clone https://github.com/openworm/PyOpenWorm.git
-    - cd PyOpenWorm
-    - git checkout ow-0.9
-    - pip install pyparsing==2.0.3 Jinja2==2.11.1 configparser==4.0.2 GitPython==2.1.11 gitdb2==2.0.6 numpydoc==0.9.2
-    - python setup.py install
-    - pow clone https://github.com/openworm/OpenWormData.git
-    - cd examples
-    - python NetworkInfo.py # test example...
-    - cd ../..
-    
     # NeuroML & main install
     - pip install pyNeuroML
-    - python setup.py install
+    - pip install .
+    # Add openworm bundle owmeta remote
+    - owm bundle remote --user add ow 'https://raw.githubusercontent.com/openworm/owmeta-bundles/master/index.json'
 
 script:
     - omv all -V; export OMV_SUCCESS=$?; echo $OMV_SUCCESS
@@ -60,13 +50,12 @@ script:
     - echo "Running non OMV tests..."
     - python setup.py install
 
-    
+
     # Testing c302
-    - cd c302 
+    - cd c302
     - mkdir examples
-    - python c302_IClamp.py A    
+    - python c302_IClamp.py A
     #- omv install NEURON # Need to install NEURON
     #- export NEURON_HOME=/home/travis/neuron/nrn/x86_64/
     #- python runAndPlot.py -test
     #- python c302_utils.py -nogui
-
diff --git a/README.md b/README.md
index 6fbf1e7d..20e56fb0 100644
--- a/README.md
+++ b/README.md
@@ -21,8 +21,9 @@ The full set of dependencies for c302 can be installed with the following (see a
     git clone https://github.com/openworm/c302.git
     cd c302
     python setup.py install
+    owm bundle remote --user add ow 'https://raw.githubusercontent.com/openworm/owmeta-bundles/master/index.json'
 
-This will install c302 as well as all dependencies, including [pyNeuroML](https://github.com/NeuroML/pyNeuroML) and [PyOpenWorm](https://github.com/openworm/PyOpenWorm).
+This will install c302 as well as all dependencies, including [pyNeuroML](https://github.com/NeuroML/pyNeuroML) and [owmeta](https://github.com/openworm/owmeta).
 
 
 #### Quick test
diff --git a/c302/NeuroMLUtilities.py b/c302/NeuroMLUtilities.py
index d92d81d7..deb42098 100644
--- a/c302/NeuroMLUtilities.py
+++ b/c302/NeuroMLUtilities.py
@@ -29,6 +29,15 @@ def __str__(self):
     def short(self):
         return "Connection from %s to %s (%s)"%(self.pre_cell, self.post_cell, self.syntype)
     
+    def __eq__(self, other):
+        return other.pre_cell == self.pre_cell and other.post_cell == self.post_cell and  other.number == self.number and other.syntype == self.syntype and other.synclass == self.synclass 
+        
+    def __lt__(self, other):
+        if other.pre_cell+other.post_cell > self.pre_cell+self.post_cell:
+            return True
+        else: 
+            return False
+    
     def __repr__(self):
         return self.__str__()
 
diff --git a/c302/OpenWormReader.py b/c302/OpenWormReader.py
index d56a8dce..9ade9305 100644
--- a/c302/OpenWormReader.py
+++ b/c302/OpenWormReader.py
@@ -1,109 +1,188 @@
+import logging
+import re
+
 from c302.NeuroMLUtilities import ConnectionInfo
-from c302 import print_, pyopenworm_connect
+from c302 import print_, MUSCLE_RE
 
-from PyOpenWorm.context import Context
-from PyOpenWorm.neuron import Neuron
-from PyOpenWorm.worm import Worm
+from owmeta_core.bundle import Bundle
+from owmeta_core.context import Context
+from owmeta.neuron import Neuron
+from owmeta.muscle import BodyWallMuscle
+from owmeta.worm import Worm
 
 ############################################################
 
-#   A simple script to read the values in PyOpenWorm
+#   A simple script to read the values in owmeta
 #   Originally written by Mark Watts (github.com/mwatts15)
 
 ############################################################
 
+LOGGER = logging.getLogger(__name__)
 
-def get_cells_in_model(net):
 
-    cell_names = []
-    for n in set(net.neurons()):
-        cell_names.append(str(n.name()))
+class OpenWormReader(object):
+    def __init__(self):
+        self.cached = False
 
-    return sorted(cell_names)
+    def get_cells_in_model(self, net):
 
+        cell_names = set()
+        for n in net.neurons():
+            cell_names.add(str(n.name()))
 
-def read_data(include_nonconnected_cells=False):
-    print_("Initialising OpenWormReader")
+        return cell_names
 
-    with pyopenworm_connect() as conn:
-        ctx = Context(ident="http://openworm.org/data", conf=conn.conf).stored
-        #Extract the network object from the worm object.
-        net = ctx(Worm)().neuron_network()
-        all_connections = net.synapses()
+    def read_data(self, include_nonconnected_cells=False):
+        print_("Initialising OpenWormReader")
 
-        conns = []
-        cells = []
-
-        cell_names = get_cells_in_model(net)
-
-        for s in all_connections:
-            pre = str(s.pre_cell().name())
-            post = str(s.post_cell().name())
-
-            if isinstance(s.post_cell(), Neuron) and pre in cell_names and post in cell_names:
-                syntype = str(s.syntype())
-                syntype = syntype[0].upper()+syntype[1:]
-                num = int(s.number())
-                synclass = str(s.synclass())
-                ci = ConnectionInfo(pre, post, num, syntype, synclass)
-                conns.append(ci)
-                if pre not in cells:
-                    cells.append(pre)
-                if post not in cells:
-                    cells.append(post)
-
-        print_("Total cells %i (%i with connections)" % (len(cell_names), len(cells)))
-        print_("Total connections found %i " % len(conns))
+        cell_names, pre, post, conns = self._read_connections('neuron')
 
         if include_nonconnected_cells:
             return cell_names, conns
         else:
-            return cells, conns
+            return pre + post, conns
+
+    def read_muscle_data(self):
+        cell_names, neurons, muscles, conns = self._read_connections('muscle')
+        return neurons, muscles, conns
+
+    def _read_connections(self, termination=None):
+        if not self.cached:
+            with Bundle('openworm/owmeta-data', version=6) as bnd:
+                ctx = bnd(Context)(ident="http://openworm.org/data").stored
+                # Extract the network object from the worm object.
+                net = ctx(Worm).query().neuron_network()
+
+                syn = net.synapse.expr
+                pre = syn.pre_cell
+                post = syn.post_cell
+
+                (pre | post).rdf_type(multiple=True)
+
+                (pre | post).name()
+                pre()
+                post()
+                syn.syntype()
+                syn.synclass()
+                syn.number()
+                self.connlist = syn.to_objects()
+
+                self.cell_names = self.get_cells_in_model(net)
+            self.cached = True
+
+        if termination == 'neuron':
+            term_type = set([Neuron.rdf_type])
+        elif termination == 'muscle':
+            term_type = set([BodyWallMuscle.rdf_type])
+        else:
+            term_type = set([Neuron.rdf_type, BodyWallMuscle.rdf_type])
+
+        conns = []
+        pre_cell_names = set()
+        post_cell_names = set()
+        for conn in self.connlist:
+            if (Neuron.rdf_type in conn.pre_cell.rdf_type and
+                    term_type & set(conn.post_cell.rdf_type)):
+                num = conn.number
+                syntype = conn.syntype or ''
+                synclass = conn.synclass or ''
+                pre_name = conn.pre_cell.name
+                post_name = conn.post_cell.name
+                if BodyWallMuscle.rdf_type in conn.post_cell.rdf_type:
+                    post_name = format_muscle_name(post_name)
+
+                if not synclass:
+                    # Hack/guess
+                    if syntype and syntype.lower() == "gapjunction":
+                        synclass = "Generic_GJ"
+                    else:
+                        if pre_name.startswith("DD") or pre_name.startswith("VD"):
+                            synclass = "GABA"
+                        synclass = "Acetylcholine"
+                conns.append(ConnectionInfo(pre_name, post_name, num, syntype, synclass))
+
+                pre_cell_names.add(pre_name)
+                post_cell_names.add(post_name)
+
+        print_("Total cells %i (%i with connections)" % (
+            len(self.cell_names | pre_cell_names | post_cell_names),
+            len(pre_cell_names | post_cell_names)))
+        print_("Total connections found %i " % len(conns))
+
+        return list(self.cell_names), pre_cell_names, post_cell_names, conns
+
+
+def format_muscle_name(muscle_name):
+    md = MUSCLE_RE.fullmatch(muscle_name)
+    if md:
+        return muscle_name
+    else:
+        md = re.fullmatch(r'([VD][LR])(\d+)', muscle_name)
+        if md:
+            return 'M{0}{1:02d}'.format(md.group(1), int(md.group(2)))
+        else:
+            LOGGER.debug('Unrecognized muscle name format in %s', muscle_name)
+            return muscle_name
+
 
+READER = OpenWormReader()
+
+read_data = READER.read_data
+read_muscle_data = READER.read_muscle_data
 
 if __name__ == "__main__":
 
     cells, conns = read_data(include_nonconnected_cells=True)
 
-    print_("%i cells found using OpenWormReader: %s..."%(len(cells),sorted(cells)[0:3]))
+    print_("%i cells found using OpenWormReader: %s, etc..." % (len(cells), sorted(cells)[0:3]))
+    print_("Found %s cells: %s...\n"%(len(cells),cells))
+
+    print_("Found %s connections using OpenWormReader, First few: " % (len(conns), ))
+    for c in sorted(conns)[:min(len(conns),5)]:
+        print_('  %s'%c)
+
+    neurons, muscles, conns = read_muscle_data()
+
+    print_("Found %i neurons connected to muscles: %s\n"%(len(neurons), sorted(neurons)))
+    print_("Found %i muscles connected to neurons: %s\n"%(len(muscles), sorted(muscles)))
+    print_("Found %i connections between neurons and muscles, e.g. %s\n\n"%(len(conns), conns[0]))
 
-    print_("Found %s connections using OpenWormReader: %s..."%(len(conns),conns[0]))
 
     conn_map_OWR = {}
     for c in conns:
-        conn_map_OWR[c.short()] = c
+        conn_map_OWR[c.short().lower()] = c
 
-    from UpdatedSpreadsheetDataReader import read_data as read_data_usr
-    #from SpreadsheetDataReader import read_data as read_data_usr
+    from c302.UpdatedSpreadsheetDataReader import read_data as read_data_usr
+    #from c302.SpreadsheetDataReader import read_data as read_data_usr
 
     cells2, conns2 = read_data_usr(include_nonconnected_cells=True)
 
-    print_("%i cells found using UpdatedSpreadsheetDataReader: %s..."%(len(cells2),sorted(cells2)[0:3]))
-    print_("Found %s connections using UpdatedSpreadsheetDataReader: %s..."%(len(conns2),conns2[0]))
+    print_("%i cells found using UpdatedSpreadsheetDataReader2: %s..." % (len(cells2), sorted(cells2)[0:3]))
+    print_("Found %s connections using UpdatedSpreadsheetDataReader2, First few: " % (len(conns2), ))
+    for c in sorted(conns2)[:min(len(conns2),5)]:
+        print_('  %s'%c)
 
     conn_map_USR = {}
     for c2 in conns2:
-        conn_map_USR[c2.short()] = c2
+        conn_map_USR[c2.short().lower()] = c2
 
-    maxn = 30000
+    maxn = 3
 
     refs_OWR = list(conn_map_OWR.keys())
 
     matching = 0
 
     for i in range(min(maxn, len(refs_OWR))):
-        #print("\n-----  Connection in OWR: %s"%refs[i])
-        #print cm[refs[i]]
         ref = refs_OWR[i]
         if ref in conn_map_USR:
             if conn_map_OWR[ref].number != conn_map_USR[ref].number:
-                print_("Mismatch: %s != %s"%(conn_map_OWR[ref],conn_map_USR[ref]))
+                print_("Mismatch: %s != %s" % (conn_map_OWR[ref], conn_map_USR[ref]))
             else:
-                matching+=1
+                matching += 1
         else:
-            print_("Missing from UpdatedSpreadsheetDataReader: %s"%(conn_map_OWR[ref]))
+            print_("Missing from UpdatedSpreadsheetDataReader: %s" % (conn_map_OWR[ref]))
 
-    print_('Number matching: %i'%matching)
+    print_('Number matching: %i' % matching)
 
     matching = 0
 
@@ -111,14 +190,14 @@ def read_data(include_nonconnected_cells=False):
 
     for i in range(min(maxn, len(refs_USR))):
         #print("\n-----  Connection in USR: %s"%refs[i])
-        #print cm2[refs[i]]
+        # print cm2[refs[i]]
         ref = refs_USR[i]
         if ref in conn_map_OWR:
             if conn_map_OWR[ref].number != conn_map_USR[ref].number:
-                print_("Mismatch: %s != %s"%(conn_map_OWR[ref],conn_map_USR[ref]))
+                print_("Mismatch: %s != %s" % (conn_map_OWR[ref], conn_map_USR[ref]))
             else:
-                matching+=1
+                matching += 1
         else:
-            print_("* Missing from OpenWormReader: %s"%conn_map_USR[ref])
+            print_("* Missing from OpenWormReader: %s" % conn_map_USR[ref])
 
-    print_('Number matching: %i'%matching)
+    print_('Number matching: %i' % matching)
diff --git a/c302/SpreadsheetDataReader.py b/c302/SpreadsheetDataReader.py
index 1daf96e1..c4e954ec 100644
--- a/c302/SpreadsheetDataReader.py
+++ b/c302/SpreadsheetDataReader.py
@@ -5,7 +5,7 @@
 #    A simple script to read the values in CElegansNeuronTables.xls.
 
 #    Note: this file will be replaced with a call to PyOpenWorm
-#    when that package is updated to read all of this data from the 
+#    when that package is updated to read all of this data from the
 #    spreadseet
 
 ############################################################
@@ -23,7 +23,7 @@
 def read_data(include_nonconnected_cells=False, neuron_connect=False):
 
 
-    
+
 # reading the NeuronConnect.xls file if neuron_connect = True
     if neuron_connect:
         conns = []
@@ -114,15 +114,18 @@ def main():
     assert(len(cells) == 302)
 
     print_("Lengths are equal if include_nonconnected_cells=True")
-    
-    print_("Found %s cells: %s..."%(len(cells),cells))
-    print_("Found %s connections: %s..."%(len(conns),conns[0]))
+
+    print_("Found %s cells: %s...\n"%(len(cells),cells))
+
+    print_("Found %s connections..."%(len(conns)))
+    for c in conns[:5]: print_("   %s"%c)
+    print_("   ...\n")
 
     neurons, muscles, conns = read_muscle_data()
 
-    print_("Found %i neurons connected to muscles: %s"%(len(neurons), sorted(neurons)))
-    print_("Found %i muscles connected to neurons: %s"%(len(muscles), sorted(muscles)))
-    print_("Found %i connections between neurons and muscles, e.g. %s"%(len(conns), conns[0]))
+    print_("Found %i neurons connected to muscles: %s\n"%(len(neurons), sorted(neurons)))
+    print_("Found %i muscles connected to neurons: %s\n"%(len(muscles), sorted(muscles)))
+    print_("Found %i connections between neurons and muscles, e.g. %s\n"%(len(conns), conns[0]))
 
 if __name__ == '__main__':
 
diff --git a/c302/UpdatedSpreadsheetDataReader.py b/c302/UpdatedSpreadsheetDataReader.py
index 869b9bf8..726a780f 100644
--- a/c302/UpdatedSpreadsheetDataReader.py
+++ b/c302/UpdatedSpreadsheetDataReader.py
@@ -4,15 +4,15 @@
 
 #    A simple script to read the values in herm_full_edgelist.csv.
 
-#    Note: this file will be replaced with a call to PyOpenWorm
-#    when that package is updated to read all of this data from the 
+#    Note: this file will be replaced with a call to owmeta
+#    when that package is updated to read all of this data from the
 #    spreadseet
 
 ############################################################
 
 import csv
 
-from NeuroMLUtilities import ConnectionInfo
+from c302.NeuroMLUtilities import ConnectionInfo
 import os
 
 from c302 import print_
@@ -70,7 +70,7 @@ def get_syntype(syntype):
         return "Send"
     else:
         raise NotImplementedError("Cannot parse syntype '%s'" % syntype)
-    
+
 def get_synclass(cell, syntype):
     #dirty hack
     if syntype == "GapJunction":
@@ -114,7 +114,7 @@ def read_data(include_nonconnected_cells=False):
 
             pre = remove_leading_index_zero(pre)
             post = remove_leading_index_zero(post)
-            
+
             conns.append(ConnectionInfo(pre, post, num, syntype, synclass))
             #print ConnectionInfo(pre, post, num, syntype, synclass)
             if pre not in cells:
@@ -149,8 +149,7 @@ def read_muscle_data():
         for row in reader:
             pre, post, num, syntype, synclass = parse_row(row)
 
-            if (not is_neuron(pre) and not is_body_wall_muscle(pre)) or not is_body_wall_muscle(post):
-                # Don't add connections unless pre=neuron and post=body_wall_muscle
+            if not (is_neuron(pre) or is_body_wall_muscle(pre)) or not is_body_wall_muscle(post):
                 continue
 
             if is_neuron(pre):
@@ -160,7 +159,6 @@ def read_muscle_data():
             post = get_old_muscle_name(post)
 
             conns.append(ConnectionInfo(pre, post, num, syntype, synclass))
-            #print ConnectionInfo(pre, post, num, syntype, synclass)
             if is_neuron(pre) and pre not in neurons:
                 neurons.append(pre)
             elif is_body_wall_muscle(pre) and pre not in muscles:
@@ -172,21 +170,24 @@ def read_muscle_data():
 
 
 def main():
-    
+
     cells, conns = read_data(include_nonconnected_cells=True)
 
     assert(len(cells) == 302)
 
     print_("Lengths are equal if include_nonconnected_cells=True")
-    
-    print_("Found %s cells: %s..."%(len(cells),cells))
-    print_("Found %s connections: %s..."%(len(conns),conns[0]))
+
+    print_("Found %s cells: %s...\n"%(len(cells),cells))
+
+    print_("Found %s connections..."%(len(conns)))
+    for c in conns[:5]: print_("   %s"%c)
+    print_("   ...\n")
 
     neurons, muscles, conns = read_muscle_data()
 
-    print_("Found %i neurons connected to muscles: %s"%(len(neurons), sorted(neurons)))
-    print_("Found %i muscles connected to neurons: %s"%(len(muscles), sorted(muscles)))
-    print_("Found %i connections between neurons and muscles, e.g. %s"%(len(conns), conns[0]))
+    print_("Found %i neurons connected to muscles: %s\n"%(len(neurons), sorted(neurons)))
+    print_("Found %i muscles connected to neurons: %s\n"%(len(muscles), sorted(muscles)))
+    print_("Found %i connections between neurons and muscles, e.g. %s\n"%(len(conns), conns[0]))
 
 
 if __name__ == '__main__':
diff --git a/c302/UpdatedSpreadsheetDataReader2.py b/c302/UpdatedSpreadsheetDataReader2.py
index 1ef61185..373b6efd 100644
--- a/c302/UpdatedSpreadsheetDataReader2.py
+++ b/c302/UpdatedSpreadsheetDataReader2.py
@@ -4,15 +4,16 @@
 
 #    A simple script to read the values in herm_full_edgelist.csv.
 
-#    Note: this file will be replaced with a call to PyOpenWorm
-#    when that package is updated to read all of this data from the 
+#    Note: this file will be replaced with a call to owmeta
+#    when that package is updated to read all of this data from the
 #    spreadseet
 
 ############################################################
 
 import csv
 
-from NeuroMLUtilities import ConnectionInfo
+
+from c302.NeuroMLUtilities import ConnectionInfo
 import os
 
 from c302 import print_
@@ -70,7 +71,7 @@ def get_syntype(syntype):
         return "Send"
     else:
         raise NotImplementedError("Cannot parse syntype '%s'" % syntype)
-    
+
 def get_synclass(cell, syntype):
     #dirty hack
     if syntype == "GapJunction":
@@ -114,7 +115,7 @@ def read_data(include_nonconnected_cells=False):
 
             pre = remove_leading_index_zero(pre)
             post = remove_leading_index_zero(post)
-            
+
             conns.append(ConnectionInfo(pre, post, num, syntype, synclass))
             #print ConnectionInfo(pre, post, num, syntype, synclass)
             if pre not in cells:
@@ -172,21 +173,24 @@ def read_muscle_data():
 
 
 def main():
-    
+
     cells, conns = read_data(include_nonconnected_cells=True)
 
     assert(len(cells) == 302)
 
     print_("Lengths are equal if include_nonconnected_cells=True")
-    
-    print_("Found %s cells: %s..."%(len(cells),cells))
-    print_("Found %s connections: %s..."%(len(conns),conns[0]))
+
+    print_("Found %s cells: %s...\n"%(len(cells),cells))
+
+    print_("Found %s connections..."%(len(conns)))
+    for c in conns[:5]: print_("   %s"%c)
+    print_("   ...\n")
 
     neurons, muscles, conns = read_muscle_data()
 
-    print_("Found %i neurons connected to muscles: %s"%(len(neurons), sorted(neurons)))
-    print_("Found %i muscles connected to neurons: %s"%(len(muscles), sorted(muscles)))
-    print_("Found %i connections between neurons and muscles, e.g. %s"%(len(conns), conns[0]))
+    print_("Found %i neurons connected to muscles: %s\n"%(len(neurons), sorted(neurons)))
+    print_("Found %i muscles connected to neurons: %s\n"%(len(muscles), sorted(muscles)))
+    print_("Found %i connections between neurons and muscles, e.g. %s\n"%(len(conns), conns[0]))
 
 
 if __name__ == '__main__':
diff --git a/c302/__init__.py b/c302/__init__.py
index 2eec3cf7..941adda9 100755
--- a/c302/__init__.py
+++ b/c302/__init__.py
@@ -39,20 +39,20 @@
 
 import collections
 
-import PyOpenWorm
-from PyOpenWorm import connect as pyow_connect, __version__ as pyow_version, ConnectionFailError
-from PyOpenWorm.context import Context
-from PyOpenWorm.neuron import Neuron
-from PyOpenWorm.worm import Worm
+from owmeta_core import __version__ as owc_version
+from owmeta_core.bundle import Bundle
+from owmeta_core.context import Context
+from owmeta import __version__ as owmeta_version
+from owmeta.cell import Cell
+from owmeta.neuron import Neuron
+from owmeta.muscle import Muscle
 
 try:
     from urllib2 import URLError  # Python 2
 except:
     from urllib.error import URLError  # Python 3
 
-import sys
-#sys.path.append("..")
-#import SpreadsheetDataReader
+logging.basicConfig()
 
 here = os.path.abspath(os.path.dirname(__file__))
 about = {}
@@ -62,16 +62,15 @@
 
 LEMS_TEMPLATE_FILE = "LEMS_c302_TEMPLATE.xml"
 
+MUSCLE_RE = re.compile(r'M([VD][LR])(\d+)')
+
+
 def print_(msg, print_it=True): # print_it=False when not verbose
     if print_it:
         pre = "c302      >>> "
         print('%s %s'%(pre,msg.replace('\n','\n'+pre)))
 
 
-def pyopenworm_connect():
-    return pyow_connect('./pyopenworm.conf')
-
-
 def load_data_reader(data_reader="SpreadsheetDataReader"):
     """
     Imports and returns data reader module
@@ -80,8 +79,8 @@ def load_data_reader(data_reader="SpreadsheetDataReader"):
     Returns:
         reader (obj): The data reader object
     """
-    reader = importlib.import_module('c302.%s'%data_reader)
-    return reader
+    return importlib.import_module('c302.%s'%data_reader)
+
 
 def get_str_from_expnotation(num):
     """
@@ -93,29 +92,38 @@ def get_str_from_expnotation(num):
     """
     return '{0:.15f}'.format(num)
 
+
 def get_muscle_position(muscle, data_reader="SpreadsheetDataReader"):
-    """if data_reader == "UpdatedSpreadsheetDataReader":
-        x = 80 * (-1 if muscle[0] == 'v' else 1)
-        z = 80 * (-1 if muscle[4] == 'L' else 1)
-        y = -300 + 30 * int(muscle[5:7])
-        return x, y, z"""
+    if muscle=='MANAL' or muscle=='MVULVA':
+        return 0,0,0
+    # TODO: Pull these positions from openworm/owmeta-data
+    pat1 = r'M([VD])([LR])(\d+)'
+    pat2 = r'([VD])([LR])(\d+)'
+    md = re.fullmatch(pat1, muscle)
+    if not md:
+        md = re.fullmatch(pat2, muscle)
+
+    if md:
+        dv = md.group(1)
+        lr = md.group(2)
+        idx = md.group(3)
+        x = 80 * (1 if lr == 'L' else -1)
+        z = 80 * (-1 if dv == 'V' else 1)
+        y = -300 + 30 * int(idx)
+        return x, y, z
+
+    raise Exception('Unrecognized muscle name format %s' % muscle)
 
-    x = 80 * (1 if muscle[2] == 'L' else -1)
-    z = 80 * (-1 if muscle[1] == 'V' else 1)
-    y = -300 + 30 * int(muscle[3:5])
-    return x, y, z
 
 def is_muscle(cell_name):
-    return cell_name.startswith('MDL') or \
-           cell_name.startswith('MDR') or  \
-           cell_name.startswith('MVL') or  \
-           cell_name.startswith('MVR')
+    return MUSCLE_RE.fullmatch(cell_name)
+
 
 def process_args():
     """
     Parse command-line arguments.
     """
-    parser = argparse.ArgumentParser(description="A script which can generate NeuroML2 compliant networks based on the C elegans connectome, along with LEMS files to run them")
+    parser = argparse.ArgumentParser('c302', description="A script which can generate NeuroML2 compliant networks based on the C elegans connectome, along with LEMS files to run them")
 
     parser.add_argument('reference', type=str, metavar='<reference>',
                         help='Unique reference for new network')
@@ -255,6 +263,7 @@ def get_cell_position(cell):
     #print "%s, %s, %s" %(location.x, location.y, location.z)
     return location
 
+
 def append_input_to_nml_input_list(stim, nml_doc, cell, params):
     target = get_cell_id_string(cell, params, muscle=is_muscle(cell))
 
@@ -387,8 +396,6 @@ def get_cell_names_and_connection(data_reader="SpreadsheetDataReader", test=Fals
     # This could be replaced with a call to "DatabaseReader" or "OpenWormNeuroLexReader" in future...
     # If called from unittest folder ammend path to "../../../../"
 
-    spreadsheet_location = os.path.dirname(os.path.abspath(__file__))+"/data/"
-
     cell_names, conns = load_data_reader(data_reader).read_data(include_nonconnected_cells=True)
 
     cell_names.sort()
@@ -397,14 +404,10 @@ def get_cell_names_and_connection(data_reader="SpreadsheetDataReader", test=Fals
 
 
 def get_cell_muscle_names_and_connection(data_reader="SpreadsheetDataReader", test=False):
-
-    #spreadsheet_location = os.path.dirname(os.path.abspath(__file__))+"/../../../"
-
     mneurons, all_muscles, muscle_conns = load_data_reader(data_reader).read_muscle_data()
-
-    all_muscles = get_muscle_names()
-
-    return mneurons, all_muscles, muscle_conns
+    if 'MANAL' in all_muscles: all_muscles.remove('MANAL')
+    if 'MVULVA' in all_muscles: all_muscles.remove('MVULVA')
+    return mneurons, sorted(all_muscles), muscle_conns
 
 
 def is_cond_based_cell(params):
@@ -442,57 +445,71 @@ def elem_in_coll_matches_conn(coll, conn):
     return False
 
 
-def _get_cell_info(pow_conn, cells):
-
-    if pow_conn is None:
-        return None, None
-
-    ctx = Context(ident="http://openworm.org/data", conf=pow_conn.conf).stored
-    #Go through our list and get the neuron object associated with each name.
-    #Store these in another list.
-    some_neurons = [ctx(Neuron)(name) for name in cells]
+def _get_cell_info(bnd, cells):
+    if bnd is None:
+        return None
     all_neuron_info = collections.OrderedDict()
     all_muscle_info = collections.OrderedDict()
-
-
-    for neuron in some_neurons:
-        #print("=====Checking properties of: %s"%neuron)
-        #print neuron.triples()
-        #print neuron.__class__
-        short = ') %s'%neuron.name()
-
+    ctx = bnd(Context)(ident="http://openworm.org/data").stored
+    # Go through our list and get the neuron object associated with each name.
+    # Store these in another list.
+    fixed_up_names = []
+    for name in cells:
+        match = is_muscle(name)
+        if match:
+            name = match.group(1) + str(int(match.group(2)))
+        fixed_up_names.append(name)
+    #fixed_up_names.remove('MANAL')
+    #fixed_up_names.remove('MVULVA')
+
+    for name in fixed_up_names:
+        cell = next(ctx(Cell).query(name=name).load(), None)
+        if cell is None:
+            print_("No matching cell for %s" % name)
+            continue
+
+        normalized_name = cell.name()
+        short = ') %s' % normalized_name
         color = '.5 0 0'
-        if 'sensory' in neuron.type():
-            short = 'Se%s'%short
-            color = '1 .2 1'
-        if 'interneuron' in neuron.type():
-            short = 'In%s'%short
-            color = '1 0 .4'
-        if 'motor' in neuron.type():
-            short = 'Mo%s'%short
-            color = '.5 .4 1'
-        if is_muscle(neuron.name()):
-            short = 'Mu%s'%short
+        if isinstance(cell, Neuron):
+            neuron_types = cell.type()
+            if 'sensory' in neuron_types:
+                short = 'Se%s' % short
+                color = '1 .2 1'
+            if 'interneuron' in neuron_types:
+                short = 'In%s' % short
+                color = '1 0 .4'
+            if 'motor' in neuron_types:
+                short = 'Mo%s' % short
+                color = '.5 .4 1'
+
+            neurotransmitter = cell.neurotransmitter()
+        elif isinstance(cell, Muscle):
+            neuron_types = ()
+            neurotransmitter = ()
             color = '0 0.6 0'
-
-
-        short = '(%s'%short
-
-
-        if 'GABA' in neuron.neurotransmitter():
-            short = '- %s'%short
-        elif len(neuron.neurotransmitter()) == 0:
-            short = '? %s'%short
+            short = 'Mu%s' % short
+        else:
+            # At this point, we should only have Neurons and Muscles because the reader
+            # filters them out
+            raise Exception('Got an unexpected cell type')
+
+        short = '(%s' % short
+        receptor = cell.receptor()
+        if 'GABA' in neurotransmitter:
+            short = '- %s' % short
+        elif len(neurotransmitter) == 0:
+            short = '? %s' % short
         else:
-            short = '+ %s'%short
+            short = '+ %s' % short
 
-        info = (neuron, neuron.type(), neuron.receptor(), neuron.neurotransmitter(), short, color)
-        #print dir(neuron)
+        info = (cell, neuron_types, receptor, neurotransmitter, short, color)
+
+        if isinstance(cell, Muscle):
+            all_muscle_info[cell.name()] = info
+        elif isinstance(cell, Neuron):
+            all_neuron_info[cell.name()] = info
 
-        if is_muscle(neuron.name()):
-            all_muscle_info[neuron.name()] = info
-        else:
-            all_neuron_info[neuron.name()] = info
     return all_neuron_info, all_muscle_info
 
 
@@ -601,7 +618,8 @@ def generate(net_id,
     info = "\n\nParameters and setting used to generate this network:\n\n"+\
            "    Data reader:                    %s\n" % data_reader+\
            "    c302 version:                   %s\n" % __version__+\
-           "    PyOpenWorm version:             %s\n" % pyow_version+\
+           "    owmeta version:                 %s\n" % owmeta_version+\
+           "    owmeta_core version:            %s\n" % owc_version+\
            "    Cells:                          %s\n" % (cells if cells is not None else "All cells")+\
            "    Cell stimulated:                %s\n" % (cells_to_stimulate if cells_to_stimulate is not None else "All neurons")+\
            "    Connection:                     %s\n" % (conns_to_include if conns_to_include is not None else "All connections") + \
@@ -628,12 +646,10 @@ def generate(net_id,
         nml_doc.cells.append(params.generic_muscle_cell)
         nml_doc.cells.append(params.generic_neuron_cell)
 
-
     net = Network(id=net_id)
 
-
     nml_doc.networks.append(net)
-    
+
     net.properties.append(Property('recommended_duration_ms',duration))
     net.properties.append(Property('recommended_dt_ms',dt))
 
@@ -712,17 +728,15 @@ def generate(net_id,
 
     count = 0
     try:
-        pow_conn = pyopenworm_connect()
+        with Bundle('openworm/owmeta-data', version=6) as bnd:
+            all_neuron_info, all_muscle_info = _get_cell_info(bnd, set(cell_names))
     except Exception as e:
-        print_('Unable to connect to PyOpenWorm database: %s' % e)
-        pow_conn = None
-        
-    all_neuron_info, _ = _get_cell_info(pow_conn, cell_names)
+        print_('Unable to open "openworm/owmeta-data" bundle: %s' % e)
+        all_neuron_info = None
+        all_muscle_info = None
 
     for cell in cell_names:
-
         if cells is None or cell in cells:
-
             inst = Instance(id="0")
 
             if not params.is_level_D():
@@ -740,8 +754,8 @@ def generate(net_id,
                                   size="1")
                 cell_id = cell
 
+            #neuron, neuron.type(), neuron.receptor(), neuron.neurotransmitter(), short, color
             if all_neuron_info is not None:
-                #neuron, neuron.type(), neuron.receptor(), neuron.neurotransmitter(), short, color
                 pop0.properties.append(Property("color", all_neuron_info[cell][5]))
                 types = sorted(all_neuron_info[cell][1])
                 pop0.properties.append(Property("type", str('; '.join(types))))
@@ -854,21 +868,22 @@ def generate(net_id,
     if verbose:
         print_("Finished loading %i cells"%count)
 
-
     mneurons, all_muscles, muscle_conns = get_cell_muscle_names_and_connection(data_reader)
 
+    #print(all_muscles)
     #if data_reader == "SpreadsheetDataReader":
     #    all_muscles = get_muscle_names()
 
-    if muscles_to_include is None or muscles_to_include == True:
+    if muscles_to_include is None or muscles_to_include is True:
         muscles_to_include = all_muscles
-    elif muscles_to_include == False:
+    elif muscles_to_include is False:
         muscles_to_include = []
 
     for m in muscles_to_include:
-        assert m in all_muscles
+        if m not in all_muscles:
+            raise Exception('%s is not among the known muscles' % m)
 
-    if len(muscles_to_include)>0:
+    if len(muscles_to_include) > 0:
 
         muscle_count = 0
         for muscle in muscles_to_include:
@@ -883,7 +898,6 @@ def generate(net_id,
             pop0.properties.append(Property("color", '0 .6 0'))
             pop0.instances.append(inst)
 
-
             # put that Population into the Network data structure from above
             net.populations.append(pop0)
 
@@ -894,7 +908,7 @@ def generate(net_id,
 
             x, y, z = get_muscle_position(muscle, data_reader)
             #print_('Positioning muscle: %s at (%s,%s,%s)'%(muscle,x,y,z))
-            inst.location = Location(x,y,z)
+            inst.location = Location(x, y, z)
 
             #target = "%s/0/%s"%(pop0.id, params.generic_muscle_cell.id) # unused
 
@@ -1183,16 +1197,12 @@ def generate(net_id,
 
                 proj0.connection_wds.append(conn0)
 
-
-
-    if len(muscles_to_include)>0:
+    if len(muscles_to_include) > 0:
         for conn in muscle_conns:
-            if not conn.post_cell in muscles_to_include:#
-                continue#
-            if not conn.pre_cell in lems_info["cells"] and not conn.pre_cell in muscles_to_include:
+            if conn.post_cell not in muscles_to_include:
+                continue
+            if conn.pre_cell not in lems_info["cells"] and conn.pre_cell not in muscles_to_include:
                 continue
-
-
 
             # take information about each connection and package it into a
             # NeuroML Projection data structure
@@ -1215,7 +1225,7 @@ def generate(net_id,
                 conn_pol = "inh"
                 orig_pol = "inh"
 
-            if '_GJ' in conn.synclass :
+            if '_GJ' in conn.synclass:
                 conn_pol = "elec"
                 orig_pol = "elec"
                 elect_conn = params.is_elec_conn(params.neuron_to_neuron_elec_syn)
@@ -1449,10 +1459,7 @@ def parse_dict_arg(dict_arg):
 
 
 def main():
-    # Suppress logs from PyOpenWorm connection failures
-    logger = logging.getLogger('PyOpenWorm.data')
-    logger.addFilter(PyOpenWormConnectionFailFilter())
-
+    print("Starting c302 v%s..."%__version__)
     args = process_args()
 
     exec('from c302.%s import ParameterisedModel' % args.parameters, globals())
@@ -1474,30 +1481,5 @@ def main():
              vmax=args.vmax)
 
 
-class PyOpenWormConnectionFailFilter(logging.Filter):
-    '''
-    Filters out a couple of error messages from PyOpenWorm.data that we don't need to see
-    more than once
-    '''
-    def __init__(self, *args, **kwargs):
-        super(PyOpenWormConnectionFailFilter, self).__init__(*args, **kwargs)
-        self.failures_seen = set()
-
-    def filter(self, record):
-        try:
-            msg = record.getMessage()
-        except Exception:
-            msg = ''
-        try:
-            if ((msg.startswith('Failed to open the data source') or
-                    msg.startswith('Failed to create')) and
-                    msg in self.failures_seen):
-                return False
-        except Exception as e:
-            pass
-        self.failures_seen.add(msg)
-        return True
-
-
 if __name__ == '__main__':
     main()
diff --git a/c302/__version__.py b/c302/__version__.py
index 7a34941c..a62e53d7 100644
--- a/c302/__version__.py
+++ b/c302/__version__.py
@@ -1,2 +1,1 @@
-__version__ = '0.7.7'
-
+__version__ = '0.7.8'
diff --git a/c302/backers.py b/c302/backers.py
index e16b0e25..a416c720 100644
--- a/c302/backers.py
+++ b/c302/backers.py
@@ -1,41 +1,41 @@
 '''
     This method reads a generated list of cells vs. names as assigned by OpenWorm backers
-    
-    This information will eventually be moved to PyOpenWorm
+
+    This information will eventually be moved to owmeta
 '''
 
 import os
 
 def get_adopted_cell_names(root=os.path.dirname(os.path.abspath(__file__))+"/data/"):
-    
+
     file = open(root+"adopters.txt")
     ads = {}
     for line in file:
         cell = line.split(":")[0].strip()
         name = line.split(":")[1].strip()
         ads[cell] = name
-        
+
     return ads
 
-    
+
 if __name__ == '__main__':
-    
+
     ads = get_adopted_cell_names()
-    
+
     file = open('README.md','w')
-    
+
     info = ""
-    
+
     info+="Cells which have been adopted in the OpenWorm project\n"
     info+="=====================================================\n\n"
     info+='<p align="center">\n'
     info+='  <img src="https://raw.githubusercontent.com/openworm/CElegansNeuroML/master/OpenWormBackers/SomeCells.png" alt="Some cells"/>\n'
     info+='</p>\n\n'
-    
+
     url = "https://github.com/openworm/CElegansNeuroML/blob/master/CElegans/pythonScripts/c302/examples/c302_A_Full.nml#L%i"
-    
+
     osb_3d_url = "http://www.opensourcebrain.org/projects/celegans?explorer=https%3A%2F%2Fraw.githubusercontent.com%2Fopenworm%2FCElegansNeuroML%2Fmaster%2FCElegans%2FgeneratedNeuroML2%2F"
-    
+
     for cell in sorted(ads.keys()):
         name = ads[cell]
         info+=cell+"\n"
@@ -47,12 +47,12 @@ def get_adopted_cell_names(root=os.path.dirname(os.path.abspath(__file__))+"/dat
             i+=1
             if 'tag="OpenWormBackerAssignedName" value="%s"'%name in line:
                 info+="Added to c302 network files [here](%s).\n\n"%(url%i)
-                
+
         info+="This cell can be viewed in 3D [here](%s) (requires WebGL).\n\n"%(osb_3d_url+cell+".cell.nml")
-        
+
     print(info)
     file.write(info)
     file.close()
- 
-    
-    
+
+
+
diff --git a/c302/bioparameters.py b/c302/bioparameters.py
index 4263b5c6..9a524c8a 100644
--- a/c302/bioparameters.py
+++ b/c302/bioparameters.py
@@ -3,7 +3,7 @@
 from neuroml import ExpTwoSynapse, GapJunction, GradedSynapse
 
 '''
-    Subject to much change & refactoring once PyOpenWorm is stable...
+    Subject to much change & refactoring once owmeta is stable...
 '''
 
 
@@ -27,20 +27,20 @@ def __init__(self, name, value, source, certainty):
         self.name = name
         self.value = value
         self.source = source
-        self.certainty = certainty 
-    
+        self.certainty = certainty
+
     def __str__(self):
         return "BioParameter: %s = %s (SRC: %s, certainty %s)"%(self.name, self.value, self.source, self.certainty)
-    
+
     def __repr__(self):
         return self.__str__()
-    
+
     def change_magnitude(self, magnitude):
-        
+
         self.value = '%s %s'%(Decimal(magnitude), split_neuroml_quantity(self.value)[1])
-        
+
     def x(self):
-        
+
         return split_neuroml_quantity(self.value)[0]
 
 
@@ -72,7 +72,7 @@ def add_bioparameter_obj(self, bioparameter):
         for bp in self.bioparameters:
             if bp.name == bioparameter.name:
                 self.bioparameters.remove(bp)
-                
+
         self.bioparameters.append(bioparameter)
 
 
@@ -98,8 +98,8 @@ def bioparameter_info(self, indent=""):
         for bp in sorted(self.bioparameters, key=lambda x: x.name):
             info += indent+indent+"%s\n"%bp
         return info
-    
-    
+
+
 class c302ModelPrototype(ParameterisedModelPrototype):
 
     def __init__(self):
@@ -115,28 +115,28 @@ def __init__(self):
         self.offset_current = None
         self.concentration_model = None
         self.found_specific_param = False
-    
+
     def is_level_A(self):
         return self.level.startswith('A')
-    
+
     def is_level_B(self):
         return self.level.startswith('B')
-    
+
     def is_level_C(self):
         return self.level.startswith('C')
-    
+
     def is_level_C0(self):
         return self.level == 'C0'
 
     def is_level_C2(self):
         return self.level == 'C2'
-    
+
     def is_level_D1(self):
         return self.level == 'D1'
-    
+
     def is_level_D(self):
         return self.level.startswith('D')
-    
+
     def is_level_X(self):
         return self.level.startswith('X')
 
diff --git a/c302/c302_Full.py b/c302/c302_Full.py
index c017021d..e23fe8ea 100644
--- a/c302/c302_Full.py
+++ b/c302/c302_Full.py
@@ -1,9 +1,9 @@
 import c302
 import sys
 
-def setup(parameter_set, 
+def setup(parameter_set,
           generate=False,
-          duration=1000, 
+          duration=1000,
           dt=0.05,
           target_directory='examples',
           muscles_to_include = None, # None => All!
@@ -11,50 +11,50 @@ def setup(parameter_set,
           param_overrides={},
           config_param_overrides={},
           verbose=True):
-    
+
     exec('from c302.parameters_%s import ParameterisedModel'%parameter_set, globals())
     params = ParameterisedModel()
-    
+
     # Some random set of neurons
     cells_to_stimulate = ["ADAL", "ADAR", "M1","M2L","M3L","M3R","M4","I1R","I2L","I5","I6","MI","NSMR","MCL","ASEL", "AVEL", "AWAR", "DB1", "DVC", "RIAR", "RMDDL"]
     cells_to_stimulate = ['PVCL','PVCR']
     cells_to_stimulate = ['PLML','PLMR']
     #cells_to_stimulate = ['AVBL','AVBR']
-    
+
     # Plot some directly stimulated & some not stimulated
     cells_to_plot      = ["ADAL", "ADAR", "PVDR", "BDUR","I1R","I2L"]
     cells_to_plot      = ['AVBL','AVBR','PVCL', 'PVCR', 'DB1','DB2','VB1','VB2','DD1','DD2','VD1','VD2']
-    
+
     params.set_bioparameter("unphysiological_offset_current", "5pA", "Testing Full net", "0")
     params.set_bioparameter("unphysiological_offset_current_del", "50 ms", "Testing Full net", "0")
     params.set_bioparameter("unphysiological_offset_current_dur", "900 ms", "Testing Full net", "0")
-    
+
     reference = "c302_%s_Full"%parameter_set
-    
+
     cell_names, conns = c302.get_cell_names_and_connection()
-    
+
     nml_doc = None
-    
+
     if generate:
-        nml_doc = c302.generate(reference, 
-             params, 
-             cells_to_plot=cells_to_plot, 
-             cells_to_stimulate=cells_to_stimulate, 
+        nml_doc = c302.generate(reference,
+             params,
+             cells_to_plot=cells_to_plot,
+             cells_to_stimulate=cells_to_stimulate,
              muscles_to_include = muscles_to_include,
-             duration=duration, 
-             dt=dt, 
-             vmin=-72 if parameter_set=='A' else -52, 
+             duration=duration,
+             dt=dt,
+             vmin=-72 if parameter_set=='A' else -52,
              vmax=-48 if parameter_set=='A' else -28,
              target_directory=target_directory,
              param_overrides=param_overrides,
              verbose=verbose,
              data_reader=data_reader)
-             
+
     return cell_names, cells_to_stimulate, params, muscles_to_include, nml_doc
 
 
 if __name__ == '__main__':
-    
+
     parameter_set = sys.argv[1] if len(sys.argv)==2 else 'A'
-    
+
     setup(parameter_set, generate=True)
diff --git a/c302/c302_IClamp.py b/c302/c302_IClamp.py
index e825a44b..4596dfdf 100644
--- a/c302/c302_IClamp.py
+++ b/c302/c302_IClamp.py
@@ -1,47 +1,47 @@
 import c302
 import sys
 import neuroml.writers as writers
-    
-def setup(parameter_set, 
+
+def setup(parameter_set,
           generate=False,
-          duration=None, 
+          duration=None,
           dt=0.05,
           target_directory='examples',
           data_reader="SpreadsheetDataReader",
           param_overrides={},
           config_param_overrides={},
           verbose=True):
-              
+
     reference = "c302_%s_IClamp"%parameter_set
     c302.print_("Setting up %s"%reference)
-    
+
     exec('from c302.parameters_%s import ParameterisedModel'%parameter_set, globals())
     params = ParameterisedModel()
-    
+
     stim_amplitudes = ["1pA","2pA","3pA","4pA","5pA","6pA"]
     if duration==None:
         duration = (len(stim_amplitudes))*1000
-    
-    
+
+
     my_cells = ["ADAL","PVCL"]
     muscles_to_include = ['MDR01']
-    
-    cells               = my_cells
-    cells_total  = my_cells + muscles_to_include
-    
-    
+
+    cells = my_cells
+    cells_total = my_cells + muscles_to_include
+
+
     nml_doc = None
-    
+
     if generate:
         c302.print_("Generating %s"%reference)
-        
-        nml_doc = c302.generate(reference, 
-                    params, 
-                    cells=cells, 
-                    cells_to_stimulate=[], 
+
+        nml_doc = c302.generate(reference,
+                    params,
+                    cells=cells,
+                    cells_to_stimulate=[],
                     muscles_to_include = muscles_to_include,
-                    duration=duration, 
-                    dt=dt, 
+                    duration=duration,
+                    dt=dt,
                     target_directory=target_directory,
                     param_overrides=param_overrides,
                     verbose=verbose,
@@ -57,11 +57,11 @@ def setup(parameter_set,
         writers.NeuroMLWriter.write(nml_doc, nml_file) # Write over network file written above...
 
         c302.print_("(Re)written network file to: "+nml_file)
-                    
+
     return cells, cells_total, params, muscles_to_include, nml_doc
-             
+
 if __name__ == '__main__':
-    
+
     parameter_set = sys.argv[1] if len(sys.argv)==2 else 'A'
-    
+
     setup(parameter_set, generate=True)
diff --git a/c302/c302_IClampMuscle.py b/c302/c302_IClampMuscle.py
index fe30d5c6..3542ae85 100644
--- a/c302/c302_IClampMuscle.py
+++ b/c302/c302_IClampMuscle.py
@@ -1,10 +1,10 @@
 import c302
 import sys
 import neuroml.writers as writers
-    
-def setup(parameter_set, 
+
+def setup(parameter_set,
           generate=False,
-          duration=2000, 
+          duration=2000,
           dt=0.05,
           target_directory='examples',
           data_reader="SpreadsheetDataReader",
@@ -13,38 +13,38 @@ def setup(parameter_set,
 
     exec('from c302.parameters_%s import ParameterisedModel'%parameter_set, globals())
     params = ParameterisedModel()
-    
-    
-    
+
+
+
     my_cells = []
     muscles_to_include = ['MDR01']
-    
+
     cells               = my_cells
     cells_total  = my_cells + muscles_to_include
-    
+
     reference = "c302_%s_IClampMuscle"%parameter_set
     nml_doc = None
-    
-    
+
+
     if generate:
-        nml_doc = c302.generate(reference, 
-                    params, 
-                    cells=cells, 
-                    cells_to_stimulate=muscles_to_include, 
+        nml_doc = c302.generate(reference,
+                    params,
+                    cells=cells,
+                    cells_to_stimulate=muscles_to_include,
                     muscles_to_include = muscles_to_include,
-                    duration=duration, 
-                    dt=dt, 
+                    duration=duration,
+                    dt=dt,
                     target_directory=target_directory,
                     param_overrides=param_overrides,
                     verbose=verbose,
                     data_reader=data_reader)
-                    
-    
-                    
+
+
+
     return cells, cells_total, params, muscles_to_include, nml_doc
-             
+
 if __name__ == '__main__':
-    
+
     parameter_set = sys.argv[1] if len(sys.argv)==2 else 'A'
-    
+
     setup(parameter_set, generate=True)
diff --git a/c302/c302_MuscleTest.py b/c302/c302_MuscleTest.py
index c0b27327..e8011981 100644
--- a/c302/c302_MuscleTest.py
+++ b/c302/c302_MuscleTest.py
@@ -80,7 +80,7 @@ def setup(parameter_set,
 
     input_list = []
 
-    
+
     #input_list.append(('MDL02', '0ms', '250ms', '3pA'))
     #input_list.append(('MDL03', '0ms', '250ms', '3pA'))
     #input_list.append(('MDR02', '0ms', '250ms', '3pA'))
@@ -92,7 +92,7 @@ def setup(parameter_set,
     input_list.append(('MVR13', '0ms', '250ms', '3pA'))
     input_list.append(('MVR14', '0ms', '250ms', '2pA'))
     input_list.append(('MVR15', '0ms', '250ms', '1pA'))
-    
+
     input_list.append(('MVL10', '0ms', '250ms', '1pA'))
     input_list.append(('MVL11', '0ms', '250ms', '2pA'))
     input_list.append(('MVL12', '0ms', '250ms', '3pA'))
@@ -153,7 +153,7 @@ def setup(parameter_set,
                                 param_overrides=param_overrides,
                                 verbose=verbose)
 
-        if config_param_overrides.has_key('input'):
+        if 'input' in config_param_overrides:
             input_list = config_param_overrides['input']
 
         for stim_input in input_list:
@@ -165,12 +165,13 @@ def setup(parameter_set,
 
         c302.print_("(Re)written network file to: " + nml_file)
 
-
     return cells, cells_to_stimulate, params, muscles_to_include, nml_doc
 
 
 if __name__ == '__main__':
     parameter_set = sys.argv[1] if len(sys.argv) == 2 else 'C2'
-    data_reader = sys.argv[2] if len(sys.argv) == 3 else 'UpdatedSpreadsheetDataReader'
+    setup_kwargs = dict()
+    if len(sys.argv) == 3:
+        setup_kwargs['data_reader'] = sys.argv[2]
 
     setup(parameter_set, generate=True, data_reader=data_reader)
diff --git a/c302/c302_Muscles.py b/c302/c302_Muscles.py
index 9e07746b..96d4d8c3 100644
--- a/c302/c302_Muscles.py
+++ b/c302/c302_Muscles.py
@@ -1,56 +1,56 @@
 import c302
 import sys
 
-def setup(parameter_set, 
+def setup(parameter_set,
           generate=False,
-          duration=1000, 
+          duration=1000,
           dt=0.05,
           target_directory='examples',
           data_reader="SpreadsheetDataReader",
           param_overrides={},
           config_param_overrides={},
           verbose=True):
-    
+
     exec('from c302.parameters_%s import ParameterisedModel'%parameter_set, globals())
     params = ParameterisedModel()
-    
+
     params.set_bioparameter("unphysiological_offset_current", "5pA", "Testing IClamp", "0")
     params.set_bioparameter("unphysiological_offset_current_del", "50 ms", "Testing IClamp", "0")
     params.set_bioparameter("unphysiological_offset_current_dur", "900 ms", "Testing IClamp", "0")
-    
-    #params.set_bioparameter("exc_syn_conductance", ".20 nS", "BlindGuess", "0.1")  
+
+    #params.set_bioparameter("exc_syn_conductance", ".20 nS", "BlindGuess", "0.1")
     params.set_bioparameter("chem_exc_syn_decay", "5 ms", "BlindGuess", "0.1")
-    
+
     #params.set_bioparameter("inh_syn_conductance", ".35 nS", "BlindGuess", "0.1")
     params.set_bioparameter("chem_inh_syn_decay", "200 ms", "BlindGuess", "0.1")
-    
+
     #params.set_bioparameter("elec_syn_gbase", "0.001 nS", "BlindGuess", "0.1")
-    
+
     # Any neurons connected to muscles
-    
-    cells = ['AS1', 'AS10', 'AS11', 'AS2', 'AS3', 'AS4', 'AS5', 'AS6', 'AS7', 'AS8', 'AS9', 
-             'AVFL', 'AVFR', 'AVKR', 'AVL', 
-             'CEPVL', 'CEPVR', 
-             'DA1', 'DA2', 'DA3', 'DA4', 'DA5', 'DA6', 'DA7', 'DA8', 'DA9', 
-             'DB1', 'DB2', 'DB3', 'DB4', 'DB5', 'DB6', 'DB7', 
-             'DD1', 'DD2', 'DD3', 'DD4', 'DD5', 'DD6', 
-             'DVB', 
-             'HSNL', 'HSNR', 
-             'IL1DL', 'IL1DR', 'IL1L', 'IL1R', 'IL1VL', 'IL1VR', 
-             'PDA', 'PDB', 
-             'PVNL', 'PVNR', 
-             'RID', 'RIML', 'RIMR', 'RIVL', 'RIVR', 
-             'RMDDL', 'RMDDR', 'RMDL', 'RMDR', 'RMDVL', 'RMDVR', 'RMED', 'RMEL', 'RMER', 'RMEV', 'RMFL', 'RMGL', 'RMGR', 'RMHL', 'RMHR', 
-             'SMBDL', 'SMBDR', 'SMBVL', 'SMBVR', 'SMDDL', 'SMDDR', 'SMDVL', 'SMDVR', 
-             'URADL', 'URADR', 'URAVL', 'URAVR', 
-             'VA1', 'VA10', 'VA11', 'VA12', 'VA2', 'VA3', 'VA4', 'VA5', 'VA6', 'VA7', 'VA8', 'VA9', 
-             'VB1', 'VB10', 'VB11', 'VB2', 'VB3', 'VB4', 'VB5', 'VB6', 'VB7', 'VB8', 'VB9', 
-             'VC1', 'VC2', 'VC3', 'VC4', 'VC5', 'VC6', 
+
+    cells = ['AS1', 'AS10', 'AS11', 'AS2', 'AS3', 'AS4', 'AS5', 'AS6', 'AS7', 'AS8', 'AS9',
+             'AVFL', 'AVFR', 'AVKR', 'AVL',
+             'CEPVL', 'CEPVR',
+             'DA1', 'DA2', 'DA3', 'DA4', 'DA5', 'DA6', 'DA7', 'DA8', 'DA9',
+             'DB1', 'DB2', 'DB3', 'DB4', 'DB5', 'DB6', 'DB7',
+             'DD1', 'DD2', 'DD3', 'DD4', 'DD5', 'DD6',
+             'DVB',
+             'HSNL', 'HSNR',
+             'IL1DL', 'IL1DR', 'IL1L', 'IL1R', 'IL1VL', 'IL1VR',
+             'PDA', 'PDB',
+             'PVNL', 'PVNR',
+             'RID', 'RIML', 'RIMR', 'RIVL', 'RIVR',
+             'RMDDL', 'RMDDR', 'RMDL', 'RMDR', 'RMDVL', 'RMDVR', 'RMED', 'RMEL', 'RMER', 'RMEV', 'RMFL', 'RMGL', 'RMGR', 'RMHL', 'RMHR',
+             'SMBDL', 'SMBDR', 'SMBVL', 'SMBVR', 'SMDDL', 'SMDDR', 'SMDVL', 'SMDVR',
+             'URADL', 'URADR', 'URAVL', 'URAVR',
+             'VA1', 'VA10', 'VA11', 'VA12', 'VA2', 'VA3', 'VA4', 'VA5', 'VA6', 'VA7', 'VA8', 'VA9',
+             'VB1', 'VB10', 'VB11', 'VB2', 'VB3', 'VB4', 'VB5', 'VB6', 'VB7', 'VB8', 'VB9',
+             'VC1', 'VC2', 'VC3', 'VC4', 'VC5', 'VC6',
              'VD1', 'VD10', 'VD11', 'VD12', 'VD13', 'VD2', 'VD3', 'VD4', 'VD5', 'VD6', 'VD7', 'VD8', 'VD9']
-             
+
     cells+=['AVAL', 'AVAR', 'AVBL', 'AVBR','AVDL', 'AVDR', 'PVCL', 'PVCR']
-    #cells=None  # implies all cells...     
-    
+    #cells=None  # implies all cells...
+
     ## Some random set of neurons
     #probability = 0.1
     cells_to_stimulate = []
@@ -61,40 +61,40 @@ def setup(parameter_set,
         if cell.startswith("xxVB") or cell.startswith("DB"):
             cells_to_stimulate.append(cell)'''
     #cells_to_stimulate = ['DB1', 'VB1']
-    
+
     cells_to_stimulate = ['PVCL', 'AVBL']
     cells_to_stimulate.extend(['DB1', 'VB1'])
     cells_to_stimulate = ['PVCL','PVCR']
     cells_to_stimulate = ['PLML','PLMR']
     cells_to_stimulate = ['AVBL','AVBR']
-    
+
     # Plot some directly stimulated & some not stimulated
     cells_to_plot      = ['AS1', 'AS10', 'AVFL', 'DA1','DB1','DB4','DB7','IL1DL','RID', 'RIML','SMBDL', 'SMBDR', 'VB1', 'VB5', 'VB10','VC1', 'VC2']
     cells_to_plot      = ['AVBL','AVBR','PVCL', 'PVCR', 'DB1','DB2','VB1','VB2','DD1','DD2','VD1','VD2']
-    
+
     reference = "c302_%s_Muscles"%parameter_set
-    
+
     muscles_to_include = None
     nml_doc = None
-    
+
     if generate:
-        nml_doc = c302.generate(reference, 
-                    params, 
+        nml_doc = c302.generate(reference,
+                    params,
                     cells=cells,
-                    cells_to_plot=cells_to_plot, 
-                    cells_to_stimulate=cells_to_stimulate, 
+                    cells_to_plot=cells_to_plot,
+                    cells_to_stimulate=cells_to_stimulate,
                     muscles_to_include = muscles_to_include,
-                    duration=duration, 
-                    dt=dt, 
+                    duration=duration,
+                    dt=dt,
                     target_directory=target_directory,
                     param_overrides=param_overrides,
                     verbose=verbose,
                     data_reader=data_reader)
 
     return cells, cells_to_stimulate, params, muscles_to_include, nml_doc
-             
+
 if __name__ == '__main__':
-    
+
     parameter_set = sys.argv[1] if len(sys.argv)==2 else 'A'
-    
+
     setup(parameter_set, generate=True)
diff --git a/c302/c302_Oscillator.py b/c302/c302_Oscillator.py
index f268bfa5..a0211c96 100644
--- a/c302/c302_Oscillator.py
+++ b/c302/c302_Oscillator.py
@@ -1,86 +1,86 @@
 import c302
 import sys
 
-def setup(parameter_set, 
+def setup(parameter_set,
           generate=False,
-          duration=1000, 
+          duration=1000,
           dt=0.05,
           target_directory='examples',
           data_reader="SpreadsheetDataReader",
           param_overrides={},
           config_param_overrides={},
           verbose=True):
-    
+
     exec('from c302.parameters_%s import ParameterisedModel'%parameter_set, globals())
     params = ParameterisedModel()
-    
+
     params.set_bioparameter("unphysiological_offset_current", "4pA", "Testing Osc", "0")
     params.set_bioparameter("unphysiological_offset_current_del", "100 ms", "Testing Osc", "0")
     params.set_bioparameter("unphysiological_offset_current_dur", "800 ms", "Testing Osc", "0")
-    
+
     #params.set_bioparameter("chem_exc_syn_gbase", ".02 nS", "BlindGuess", "0.1")
     params.set_bioparameter("chem_exc_syn_decay", "5 ms", "BlindGuess", "0.1")
-    
+
     #params.set_bioparameter("chem_inh_syn_gbase", ".02 nS", "BlindGuess", "0.1")
     params.set_bioparameter("chem_inh_syn_decay", "30 ms", "BlindGuess", "0.1")
     params.set_bioparameter("inh_syn_erev", "-90 mV", "BlindGuess", "0.1")
-    
+
     #params.set_bioparameter("elec_syn_gbase", "0.001 nS", "BlindGuess", "0.1")
-    
+
     # Any neurons connected to muscles
-    
-    cells = ['DB1', 'DB2', 'DB3', 'DB4', 'DB5', 'DB6', 'DB7', 
+
+    cells = ['DB1', 'DB2', 'DB3', 'DB4', 'DB5', 'DB6', 'DB7',
              'DD1', 'DD2', 'DD3', 'DD4', 'DD5', 'DD6',
              'VB1', 'VB10', 'VB11', 'VB2', 'VB3', 'VB4', 'VB5', 'VB6', 'VB7', 'VB8', 'VB9',
              'VD1', 'VD10', 'VD11', 'VD2', 'VD3', 'VD4', 'VD5', 'VD6', 'VD7', 'VD8', 'VD9']
-    
+
     cells = ['DB3', 'VB3', 'DD3', 'VD3', 'DB4', 'VB4', 'DD4', 'VD4']
-    
+
     cells = ['DB2', 'VB2', 'DD2', 'VD2', 'DB3', 'VB3', 'DD3', 'VD3']
     cells += ['DA2', 'VA2','DA3','VA3']
     #cells = ['DB3', 'VB3', 'DB4', 'VB4']
-             
+
     #cells+=['AVBL','PVCL','AVBR','PVCR']
     #cells+=[]
     #cells+=['PVCL', 'PVCR','AVBL','AVBR']
     #cells+=['PLML', 'PLMR','AVAL','AVAR']
     cells+=['AVBL','AVBR']
-    #cells=None  # implies all cells...     
-    
-    
+    #cells=None  # implies all cells...
+
+
     #cells_to_stimulate = ['PVCL','PVCR']
     #cells_to_stimulate = ['PLML','PLMR']
     cells_to_stimulate = ['AVBL','AVBR']
     #cells_to_stimulate = ['AVBL']
-    
+
     # Plot some directly stimulated & some not stimulated
     # cells_to_plot      = ['AVBL','PVCL', 'PVCR', 'DB1','DB2','DB3', 'DB4','DD1','DD2','DD3', 'DD4','DB4','VB1','VB2', 'VB3', 'VB4','VD1','VD2', 'VD3', 'VD4']
     cells_to_plot      = cells
-    
+
     reference = "c302_%s_Oscillator"%parameter_set
-    
+
     muscles_to_include = []
-    
+
     nml_doc = None
-    
+
     if generate:
-        nml_doc = c302.generate(reference, 
-                    params, 
+        nml_doc = c302.generate(reference,
+                    params,
                     cells=cells,
-                    cells_to_plot=cells_to_plot, 
-                    cells_to_stimulate=cells_to_stimulate, 
+                    cells_to_plot=cells_to_plot,
+                    cells_to_stimulate=cells_to_stimulate,
                     muscles_to_include = muscles_to_include,
-                    duration=duration, 
-                    dt=dt, 
+                    duration=duration,
+                    dt=dt,
                     target_directory=target_directory,
                     param_overrides=param_overrides,
                     verbose=verbose,
                     data_reader=data_reader)
 
     return cells, cells_to_stimulate, params, muscles_to_include, nml_doc
-             
+
 if __name__ == '__main__':
-    
+
     parameter_set = sys.argv[1] if len(sys.argv)==2 else 'A'
-    
+
     setup(parameter_set, generate=True)
diff --git a/c302/c302_Pharyngeal.py b/c302/c302_Pharyngeal.py
index 941ad3df..941d1538 100644
--- a/c302/c302_Pharyngeal.py
+++ b/c302/c302_Pharyngeal.py
@@ -1,9 +1,9 @@
 import c302
 import sys
 
-def setup(parameter_set, 
+def setup(parameter_set,
           generate=False,
-          duration=500, 
+          duration=500,
           dt=0.01,
           target_directory='examples',
           data_reader="SpreadsheetDataReader",
@@ -13,34 +13,34 @@ def setup(parameter_set,
 
     exec('from c302.parameters_%s import ParameterisedModel'%parameter_set, globals())
     params = ParameterisedModel()
-    
+
     params.set_bioparameter("unphysiological_offset_current", "2.2pA", "Testing Pharyngeal", "0")
     params.set_bioparameter("unphysiological_offset_current_del", "50ms", "Testing Pharyngeal", "0")
     params.set_bioparameter("unphysiological_offset_current_dur", "200ms", "Testing Pharyngeal", "0")
-    
+
     cells = ["M1","M2L","M2R","M3L","M3R","M4","M5","I1L","I1R","I2L","I2R","I3","I4","I5","I6","MI","NSML","NSMR","MCL","MCR"]
     cells_to_stimulate = ["M1","M3R","M4","M5","I1L","I4","I5","I6","MCL","MCR"]
-    
+
     reference = "c302_%s_Pharyngeal"%parameter_set
-    
+
     nml_doc = None
-    
+
     if generate:
-        nml_doc = c302.generate(reference,  
-                      params, 
-                      cells=cells, 
-                      cells_to_stimulate=cells_to_stimulate, 
-                      duration=duration, 
-                      dt=dt, 
+        nml_doc = c302.generate(reference,
+                      params,
+                      cells=cells,
+                      cells_to_stimulate=cells_to_stimulate,
+                      duration=duration,
+                      dt=dt,
                       target_directory=target_directory,
                       param_overrides=param_overrides,
                       verbose=verbose,
                       data_reader=data_reader)
-             
+
     return cells, cells_to_stimulate, params, [], nml_doc
-             
+
 if __name__ == '__main__':
-    
+
     parameter_set = sys.argv[1] if len(sys.argv)==2 else 'A'
-    
-    setup(parameter_set, generate=True)
\ No newline at end of file
+
+    setup(parameter_set, generate=True)
diff --git a/c302/c302_Social.py b/c302/c302_Social.py
index ee37765f..21e3676f 100644
--- a/c302/c302_Social.py
+++ b/c302/c302_Social.py
@@ -6,7 +6,7 @@
 # To run:
 #          python c302_Social.py A   (uses parameters_A, requires jNeuroML to run)
 # or
-#          python c302_Social.py B   (uses parameters_B, requires jNeuroML built from the 
+#          python c302_Social.py B   (uses parameters_B, requires jNeuroML built from the
 #                                     experimental branches to run: 'python getNeuroML experimental'
 #                                     see https://github.com/NeuroML/jNeuroML)
 
@@ -15,39 +15,39 @@
 import neuroml.writers as writers
 
 import sys
-    
-def setup(parameter_set, 
+
+def setup(parameter_set,
           generate=False,
-          duration=2500, 
+          duration=2500,
           dt=0.05,
           target_directory='examples',
           data_reader="SpreadsheetDataReader",
           param_overrides={},
           config_param_overrides={},
           verbose=True):
-    
+
     exec('from c302.parameters_%s import ParameterisedModel'%parameter_set, globals())
     params = ParameterisedModel()
-    
+
     cells = ["RMGR","ASHR","ASKR","AWBR","IL2R","RMHR","URXR"]
     cells_to_stimulate      = []
-    
+
     reference = "c302_%s_Social"%parameter_set
-    
+
     nml_doc = None
-    
+
     if generate:
-        nml_doc = c302.generate(reference, 
-                       params, 
-                       cells=cells, 
-                       cells_to_stimulate=cells_to_stimulate, 
-                       duration=duration, 
-                       dt=dt, 
+        nml_doc = c302.generate(reference,
+                       params,
+                       cells=cells,
+                       cells_to_stimulate=cells_to_stimulate,
+                       duration=duration,
+                       dt=dt,
                        target_directory=target_directory,
                        param_overrides=param_overrides,
                        verbose=verbose,
                        data_reader=data_reader)
-             
+
     stim_amplitude = "5pA"
     c302.add_new_input(nml_doc, "RMGR", "100ms", "200ms", stim_amplitude, params)
     c302.add_new_input(nml_doc, "ASHR", "400ms", "200ms", stim_amplitude, params)
@@ -56,18 +56,18 @@ def setup(parameter_set,
     c302.add_new_input(nml_doc, "IL2R", "1300ms", "200ms", stim_amplitude, params)
     c302.add_new_input(nml_doc, "RMHR", "1600ms", "200ms", stim_amplitude, params)
     c302.add_new_input(nml_doc, "URXR", "1900ms", "200ms", stim_amplitude, params)
-    
-    
+
+
     nml_file = target_directory+'/'+reference+'.net.nml'
     writers.NeuroMLWriter.write(nml_doc, nml_file) # Write over network file written above...
-    
+
     c302.print_("(Re)written network file to: "+nml_file)
-    
+
     return cells, cells_to_stimulate, params, [], nml_doc
-    
-    
+
+
 if __name__ == '__main__':
-    
+
     parameter_set = sys.argv[1] if len(sys.argv)==2 else 'A'
-    
-    setup(parameter_set, generate=True)
\ No newline at end of file
+
+    setup(parameter_set, generate=True)
diff --git a/c302/c302_Syns.py b/c302/c302_Syns.py
index 898710ac..236d3e34 100644
--- a/c302/c302_Syns.py
+++ b/c302/c302_Syns.py
@@ -2,76 +2,76 @@
 import sys
 import neuroml.writers as writers
 
-    
-def setup(parameter_set, 
+
+def setup(parameter_set,
           generate=False,
-          duration=500, 
+          duration=500,
           dt=0.05,
           target_directory='examples',
           data_reader="SpreadsheetDataReader",
           param_overrides={},
           config_param_overrides={},
           verbose=True):
-    
+
     exec('from c302.parameters_%s import ParameterisedModel'%parameter_set, globals())
     params = ParameterisedModel()
-    
+
     stim_amplitudes = ["1pA","5pA"]
     duration = (len(stim_amplitudes))*1800
-    
+
     params.set_bioparameter("unphysiological_offset_current_del", "50 ms", "Testing IClamp", "0")
-    
+
     exc_pre = "URYDL"
     exc_post = "SMDDR"
-    inh_pre = "VD12" 
+    inh_pre = "VD12"
     inh_post = "VB11"
     gap_1 = "AIZL"
     gap_2 = "ASHL"
     moto_pre = "AS2"
     muscle_post = "MDL07"
-    
+
     cells = [exc_pre, exc_post, inh_pre, inh_post, moto_pre]
     cells_to_stimulate_extra      = [exc_pre, inh_pre,moto_pre]
     muscles_to_include = [muscle_post]
-    
+
     if parameter_set!='A':
         cells.append(gap_1)
         cells.append(gap_2)
         cells_to_stimulate_extra.append(gap_1)
-    
+
     reference = "c302_%s_Syns"%parameter_set
-    
+
     nml_doc = None
-    
+
     if generate:
-        nml_doc = c302.generate(reference, 
-                 params, 
-                 cells=cells, 
-                 cells_to_stimulate=[], 
+        nml_doc = c302.generate(reference,
+                 params,
+                 cells=cells,
+                 cells_to_stimulate=[],
                  muscles_to_include = muscles_to_include,
-                 duration=duration, 
-                 dt=dt, 
+                 duration=duration,
+                 dt=dt,
                  target_directory=target_directory,
                  param_overrides=param_overrides,
                  verbose=verbose,
                  data_reader=data_reader)
-                 
-                 
+
+
     for i in range(len(stim_amplitudes)):
         start = "%sms"%(i*1400 + 500)
         for c in cells_to_stimulate_extra:
             c302.add_new_input(nml_doc, c, start, "800ms", stim_amplitudes[i], params)
-    
+
     nml_file = target_directory+'/'+reference+'.net.nml'
     writers.NeuroMLWriter.write(nml_doc, nml_file) # Write over network file written above...
-    
+
     c302.print_("(Re)written network file to: "+nml_file)
-    
-             
+
+
     return cells, cells_to_stimulate_extra, params, [], nml_doc
-             
+
 if __name__ == '__main__':
-    
+
     parameter_set = sys.argv[1] if len(sys.argv)==2 else 'A'
-    
-    setup(parameter_set, generate=True)
\ No newline at end of file
+
+    setup(parameter_set, generate=True)
diff --git a/c302/c302_TargetMuscle.py b/c302/c302_TargetMuscle.py
index b22d96ec..41057ce0 100644
--- a/c302/c302_TargetMuscle.py
+++ b/c302/c302_TargetMuscle.py
@@ -1,10 +1,10 @@
 import c302
 import sys
 import neuroml.writers as writers
-    
-def setup(parameter_set, 
+
+def setup(parameter_set,
           generate=False,
-          duration=3000, 
+          duration=3000,
           dt=0.05,
           target_directory='examples',
           data_reader="SpreadsheetDataReader",
@@ -14,43 +14,43 @@ def setup(parameter_set,
 
     exec('from c302.parameters_%s import ParameterisedModel'%parameter_set, globals())
     params = ParameterisedModel()
-    
+
     params.set_bioparameter("unphysiological_offset_current", "15pA", "Testing IClamp", "0")
     params.set_bioparameter("unphysiological_offset_current_del", "1 ms", "Testing IClamp", "0")
     params.set_bioparameter("unphysiological_offset_current_dur", "20 ms", "Testing IClamp", "0")
-    
+
     duration = 300
-    
-    
+
+
     my_cells = ["AVKR"]
     my_cells = ["RMHR"]
-    muscles_to_include = None 
-    
+    muscles_to_include = None
+
     cells               = my_cells
-    
+
     reference = "c302_%s_TargetMuscle"%parameter_set
-    
+
     nml_doc = None
-    
+
     if generate:
-        nml_doc = c302.generate(reference, 
-                    params, 
-                    cells=cells, 
-                    cells_to_stimulate=cells, 
+        nml_doc = c302.generate(reference,
+                    params,
+                    cells=cells,
+                    cells_to_stimulate=cells,
                     muscles_to_include = muscles_to_include,
-                    duration=duration, 
-                    dt=dt, 
+                    duration=duration,
+                    dt=dt,
                     target_directory=target_directory,
                     param_overrides=param_overrides,
                     verbose=verbose,
                     data_reader=data_reader,
                     print_connections=True)
-                    
-                    
+
+
     return cells, cells, params, muscles_to_include, nml_doc
-             
+
 if __name__ == '__main__':
-    
+
     parameter_set = sys.argv[1] if len(sys.argv)==2 else 'A'
-    
+
     setup(parameter_set, generate=True)
diff --git a/c302/c302_info.py b/c302/c302_info.py
new file mode 100644
index 00000000..584ac851
--- /dev/null
+++ b/c302/c302_info.py
@@ -0,0 +1,120 @@
+import sys
+import os
+from pyneuroml import pynml
+import matplotlib.pyplot as plt
+import numpy as np
+
+import c302
+
+
+
+def generate_c302_info(nml_doc, verbose=False):
+
+    net = nml_doc.networks[0]
+
+    cc_exc_conns = {}
+    cc_inh_conns = {}
+    all_cells = []
+
+    for cp in net.continuous_projections:
+        if not cp.presynaptic_population in cc_exc_conns.keys():
+            cc_exc_conns[cp.presynaptic_population] = {}
+        if not cp.presynaptic_population in cc_inh_conns.keys():
+            cc_inh_conns[cp.presynaptic_population] = {}
+
+        if not cp.presynaptic_population in all_cells:
+            all_cells.append(cp.presynaptic_population)
+        if not cp.postsynaptic_population in all_cells:
+            all_cells.append(cp.postsynaptic_population)
+
+        for c in cp.continuous_connection_instance_ws:
+            if 'inh' in c.post_component:
+                cc_inh_conns[cp.presynaptic_population][cp.postsynaptic_population] = float(c.weight)
+            else:
+                cc_exc_conns[cp.presynaptic_population][cp.postsynaptic_population] = float(c.weight)
+
+
+    gj_conns = {}
+    for ep in net.electrical_projections:
+        if not ep.presynaptic_population in gj_conns.keys():
+            gj_conns[ep.presynaptic_population] = {}
+
+        if not ep.presynaptic_population in all_cells:
+            all_cells.append(ep.presynaptic_population)
+        if not ep.postsynaptic_population in all_cells:
+            all_cells.append(ep.postsynaptic_population)
+
+        for e in ep.electrical_connection_instance_ws:
+            gj_conns[ep.presynaptic_population][ep.postsynaptic_population] = float(e.weight)
+
+
+    all_cells = sorted(all_cells)
+
+    try:
+        from PyOpenWorm import connect as pyow_connect, __version__ as pyow_version, ConnectionFailError
+        pow_conn = pyow_connect('./pyopenworm.conf')
+        all_neuron_info, all_muscle_info = c302._get_cell_info(pow_conn, all_cells)
+        ver_info = 'PyOpenWorm v%s'%pyow_version
+    except Exception as e:
+        c302.print_('Unable to connect to PyOpenWorm database: %s' % e)
+        from owmeta_core.bundle import Bundle
+
+        from owmeta_core import __version__ as owc_version
+        from owmeta import __version__ as owmeta_version
+
+        ver_info = 'owmeta v%s (owmeta core v%s)'%(owmeta_version,owc_version)
+
+        with Bundle('openworm/owmeta-data', version=6) as bnd:
+            all_neuron_info, all_muscle_info = c302._get_cell_info(bnd, all_cells)
+
+
+    all_neurons = []
+    all_muscles = []
+    for c in all_cells:
+        if c302.is_muscle(c):
+            all_muscles.append(c)
+        else:
+            all_neurons.append(c)
+
+    info = '# Information on neuron and muscles\n'
+    info+='## Generated using %s\n'%ver_info
+
+    info+='### Neurons (%i)\n'%(len(all_neuron_info))
+    info+='<table>\n'
+    for n in all_neuron_info:
+        info+='<tr>\n'
+        ni =all_neuron_info[n]
+        #print(ni)
+        info+=('<td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>Colour: %s</td>'%(n,_info_set(ni[1]),_info_set(ni[2]),_info_set(ni[3]),ni[4],ni[5]))
+        info+='</tr>\n'
+    info+='</table>\n'
+
+
+    info+='### Muscles (%i)\n'%(len(all_muscle_info))
+    info+='<table>\n'
+    for n in all_muscle_info:
+        info+='<tr>\n'
+        ni =all_muscle_info[n]
+        info+=('<td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>Colour: %s</td>'%(n,_info_set(ni[1]),_info_set(ni[2]),_info_set(ni[3]),ni[4],ni[5]))
+        info+='</tr>\n'
+    info+='</table>\n'
+
+    with open('examples/summary/summary.md','w') as f2:
+        #f2.write('<html><body>%s</body></html>'%info)
+        f2.write('%s'%info)
+
+def _info_set(s):
+    s = sorted(s)
+    return ', '.join(['%s'%i for i in s])
+
+if __name__ == '__main__':
+
+    from neuroml.loaders import read_neuroml2_file
+
+    config = 'c302_C0_Full.net.nml'
+
+
+
+    nml_doc = read_neuroml2_file('examples/%s'%config)
+
+    generate_c302_info(nml_doc)
diff --git a/c302/c302_utils.py b/c302/c302_utils.py
index 566e2ddd..5aed70b6 100644
--- a/c302/c302_utils.py
+++ b/c302/c302_utils.py
@@ -1,20 +1,23 @@
 import sys
 import os
-from pyneuroml import pynml
+import re
+import collections
+import traceback
+
 import matplotlib.pyplot as plt
 import numpy as np
+from pyneuroml import pynml
+from owmeta_core.bundle import Bundle
 
 import c302
 
-import re
-import collections
 
 
-natsort = lambda s: [int(t) if t.isdigit() else t for t in re.split('(\d+)', s)]
+natsort = lambda s: [int(t) if t.isdigit() else t for t in re.split(r'(\d+)', s)]
 
 
 def plots(a_n, info, cells, dt):
-    
+
 
     c302.print_('Generating plots for: %s'%info)
 
@@ -49,7 +52,7 @@ def plots(a_n, info, cells, dt):
     #fig = plt.figure()
     #ax = fig.gca()
     downscale = 10
-    
+
     a_n_ = a_n[:,::downscale]
 
     plot0 = ax.pcolormesh(a_n_)
@@ -58,13 +61,13 @@ def plots(a_n, info, cells, dt):
     ax.tick_params(axis='y', labelsize=6)
     #plt.setp(ax.get_yticklabels(), rotation=45)
 
-    
+
     fig.colorbar(plot0)
-    
+
     fig.canvas.set_window_title(info)
     plt.title(info)
     plt.xlabel('Time (ms)')
- 
+
     fig.canvas.draw()
 
     labels = [] #issue is with unicode
@@ -73,7 +76,7 @@ def plots(a_n, info, cells, dt):
             labels.append(float( str((label.get_text())) )*dt*downscale*1000)
         # except:
         #     print "Error value on forming axis values, value: ", label.get_text(), ", length: ",len(label.get_text())
-    
+
     #labels = [float(label.get_text())*dt*downscale*1000 for item in ax.get_xticklabels()]
     ax.set_xticklabels(labels)
     #print labels
@@ -81,14 +84,14 @@ def plots(a_n, info, cells, dt):
     plt.xlim(0,a_n_.shape[1])
     #print plt.xlim()
 
-    
+
 def plots_prof(a_n, info, cells, dt):
     cProfile.run('real_plots(a_n, info, cells, dt)')
-    
+
 def generate_traces_plot(config,parameter_set,xvals,yvals,info,labels,save,save_fig_path,voltage,muscles):
-                         
+
     file_name = 'traces_%s%s_%s_%s.png'%(('muscles' if muscles else 'neuron'),('' if voltage else '_activity'),config,parameter_set)
-    
+
     pynml.generate_plot(xvals,
                         yvals,
                         info,
@@ -99,18 +102,18 @@ def generate_traces_plot(config,parameter_set,xvals,yvals,info,labels,save,save_
                         save_figure_to=(None if not save else save_fig_path%(file_name)),
                         cols_in_legend_box=8,
                         title_above_plot=True)
-    
-    
-def plot_c302_results(lems_results, 
-                      config, 
-                      parameter_set, 
+
+
+def plot_c302_results(lems_results,
+                      config,
+                      parameter_set,
                       directory='./',
                       save=True,
-                      show_plot_already=True, 
+                      show_plot_already=True,
                       data_reader="SpreadsheetDataReader",
                       plot_ca=True):
-    
-    
+
+
     params = {'legend.fontsize': 8,
               'font.size': 10}
     plt.rcParams.update(params)
@@ -125,46 +128,47 @@ def plot_c302_results(lems_results,
     times = [t*1000 for t in lems_results['t']]
     for cm in lems_results.keys():
         if not cm=='t' and cm.endswith('/v'):
-            if c302.is_muscle(cm):
-                muscles.append(cm.split('/')[0])
+            cell_name_part = cm.split('/')[0]
+            if c302.is_muscle(cell_name_part):
+                muscles.append(cell_name_part)
             else:
-                cells.append(cm.split('/')[0])
-    
+                cells.append(cell_name_part)
+
     cells.sort(key=natsort)
     cells.reverse()
-            
+
     c302.print_("All cells: %s"%cells)
     dt = lems_results['t'][1]
-    
+
     ################################################
     ## Plot voltages cells
-    
+
     if len(cells) > 0:
         c302.print_("Plotting neuron voltages")
-        
+
         template = '{0}/0/GenericNeuronCell/{1}'
         if parameter_set.startswith('A') or parameter_set.startswith('B'):
             template = '{0}/0/generic_neuron_iaf_cell/{1}'
         if parameter_set.startswith('D'):
             template = '{0}/0/{0}/{1}'
-    
-        
+
+
         xvals = []
         yvals = []
         labels = []
-        
+
         for cell in cells:
             v = lems_results[template.format(cell,'v')]
-            
+
             xvals.append(times)
             labels.append(cell)
-            
+
             if cell==cells[0]:
                 volts_n = np.array([[vv*1000 for vv in v]])
             else:
                 volts_n = np.append(volts_n,[[vv*1000 for vv in v]],axis=0)
             yvals.append(volts_n[-1])
-            
+
         info = 'Membrane potentials of %i neuron(s) (%s %s)'%(len(cells),config,parameter_set)
 
         #tasks.append((volts_n, info, cells, dt))
@@ -185,19 +189,19 @@ def plot_c302_results(lems_results,
                              save_fig_path=save_fig_path,
                              voltage=True,
                              muscles=False)
-            
-        
+
+
     ################################################
     ## Plot voltages muscles
 
- 
+
     muscles.sort(key=natsort)
     muscles.reverse()
 
     xvals = []
     yvals = []
     labels = []
-    
+
     if len(muscles)>0:
 
         c302.print_("Plotting muscle voltages")
@@ -211,7 +215,7 @@ def plot_c302_results(lems_results,
 
             xvals.append(times)
             labels.append(muscle)
-        
+
             if muscle==muscles[0]:
                 mvolts_n = np.array([[vv*1000 for vv in mv]])
             else:
@@ -221,7 +225,7 @@ def plot_c302_results(lems_results,
         info = 'Membrane potentials of %i muscle(s) (%s %s)'%(len(muscles),config,parameter_set)
 
         plots(mvolts_n, info, muscles, dt)
-        
+
         if save:
             f = save_fig_path%('muscles_%s_%s.png'%(parameter_set,config))
             c302.print_("Saving figure to: %s"%os.path.abspath(f))
@@ -237,16 +241,16 @@ def plot_c302_results(lems_results,
                              save_fig_path=save_fig_path,
                              voltage=True,
                              muscles=True)
-    
+
     ################################################
     ## Plot activity/[Ca2+] in cells
-    
+
     if plot_ca and parameter_set!='A' and len(cells) > 0:
-        
+
         c302.print_("Plotting neuron activities ([Ca2+])")
         variable = 'activity'
         description = 'Activity'
-            
+
         if parameter_set.startswith('C') or parameter_set.startswith('D'):
             variable = 'caConc'
             description = '[Ca2+]'
@@ -258,11 +262,11 @@ def plot_c302_results(lems_results,
         info = '%s of %i neurons (%s %s)'%(description, len(cells),config,parameter_set)
         for cell in cells:
             a = lems_results[template.format(cell,variable)]
-            
+
             xvals.append(times)
             yvals.append(a)
             labels.append(cell)
-            
+
             if cell==cells[0]:
                 activities_n = np.array([a])
             else:
@@ -285,20 +289,20 @@ def plot_c302_results(lems_results,
                              save_fig_path=save_fig_path,
                              voltage=False,
                              muscles=False)
-    
+
     ################################################
     ## Plot activity/[Ca2+] in muscles
-    
+
     if plot_ca and parameter_set!='A' and len(muscles)>0:
-        
+
         c302.print_("Plotting muscle activities ([Ca2+])")
         variable = 'activity'
         description = 'Activity'
-            
+
         if parameter_set.startswith('C') or parameter_set.startswith('D'):
             variable = 'caConc'
             description = '[Ca2+]'
-            
+
         xvals = []
         yvals = []
         labels = []
@@ -306,18 +310,18 @@ def plot_c302_results(lems_results,
         info = '%s of %i muscles (%s %s)'%(description, len(muscles),config,parameter_set)
         for m in muscles:
             a = lems_results[template_m.format(m,variable)]
-            
+
             xvals.append(times)
             yvals.append(a)
             labels.append(m)
-            
+
             if m==muscles[0]:
                 activities_n = np.array([a])
             else:
                 activities_n = np.append(activities_n,[a],axis=0)
 
         plots(activities_n, info, muscles, dt)
-    
+
         if save:
             f = save_fig_path%('muscle_activity_%s_%s.png'%(parameter_set,config))
             c302.print_("Saving figure to: %s"%os.path.abspath(f))
@@ -333,7 +337,7 @@ def plot_c302_results(lems_results,
                              save_fig_path=save_fig_path,
                              voltage=False,
                              muscles=True)
-    
+
 
     if show_plot_already:
         try:
@@ -342,46 +346,46 @@ def plot_c302_results(lems_results,
             c302.print_("Interrupt received, stopping...")
     else:
         plt.close("all")
-        
-        
+
+
 def _show_conn_matrix(data, t, all_info_pre,all_info_post, type, save_figure_to=False):
-    
-    
+
+
     if data.shape[0]>0 and data.shape[1]>0 and np.amax(data)>0:
         ##norm = matplotlib.colors.LogNorm(vmin=1, vmax=np.amax(data))
         maxn = int(np.amax(data))
     else:
         ##norm = None
         maxn = 0
-        
+
     c302.print_("Plotting data of size %s, max %s: %s"%(str(data.shape),maxn, t))
-    
+
     if maxn==0:
         c302.print_("No connections!!")
         return
-    
+
     fig, ax = plt.subplots()
     title = '%s: %s'%(type,t)
     plt.title(title)
     fig.canvas.set_window_title(title)
     import matplotlib
     cm = matplotlib.cm.get_cmap('gist_stern_r')
-    
-    
+
+
     im = plt.imshow(data, cmap=cm, interpolation='nearest',norm=None)
-    
+
     ax = plt.gca();
     # Gridlines based on minor ticks
     if data.shape[0]<40:
         ax.grid(which='minor', color='grey', linestyle='-', linewidth=.3)
-    
+
     xt = np.arange(data.shape[1]) + 0
     ax.set_xticks(xt)
     ax.set_xticks(xt[:-1]+0.5,minor=True)
     ax.set_yticks(np.arange(data.shape[0]) + 0)
     ax.set_yticks(np.arange(data.shape[0]) + 0.5,minor=True)
-    
-    
+
+
     ax.set_yticklabels([all_info_pre[k][4] for k in all_info_pre])
     ax.set_xticklabels([all_info_post[k][4] for k in all_info_post])
     ax.set_ylabel('presynaptic')
@@ -390,80 +394,81 @@ def _show_conn_matrix(data, t, all_info_pre,all_info_post, type, save_figure_to=
     ax.set_xlabel('postsynaptic')
     ax.tick_params(axis='x', labelsize=tick_size)
     fig.autofmt_xdate()
-    
-    
+
+
     #heatmap = ax.pcolor(data, cmap='gist_stern')
     cbar = plt.colorbar(im, ticks=range(maxn+1))
     cbar.set_ticklabels(range(maxn+1))
     if save_figure_to:
         c302.print_("Saving connectivity figure to: %s"%save_figure_to)
         plt.savefig(save_figure_to,bbox_inches='tight')
+    else:
+        c302.print_("Not saving figure")
 
 def generate_conn_matrix(nml_doc, save_fig_dir=None, verbose=False):
-    
+
     net = nml_doc.networks[0]
-    
+
     cc_exc_conns = {}
     cc_inh_conns = {}
     all_cells = []
-    
+
     for cp in net.continuous_projections:
         if not cp.presynaptic_population in cc_exc_conns.keys():
             cc_exc_conns[cp.presynaptic_population] = {}
         if not cp.presynaptic_population in cc_inh_conns.keys():
             cc_inh_conns[cp.presynaptic_population] = {}
-            
+
         if not cp.presynaptic_population in all_cells:
             all_cells.append(cp.presynaptic_population)
         if not cp.postsynaptic_population in all_cells:
             all_cells.append(cp.postsynaptic_population)
-        
+
         for c in cp.continuous_connection_instance_ws:
             if 'inh' in c.post_component:
                 cc_inh_conns[cp.presynaptic_population][cp.postsynaptic_population] = float(c.weight)
             else:
                 cc_exc_conns[cp.presynaptic_population][cp.postsynaptic_population] = float(c.weight)
-                
-    
+
+
     gj_conns = {}
     for ep in net.electrical_projections:
         if not ep.presynaptic_population in gj_conns.keys():
             gj_conns[ep.presynaptic_population] = {}
-            
+
         if not ep.presynaptic_population in all_cells:
             all_cells.append(ep.presynaptic_population)
         if not ep.postsynaptic_population in all_cells:
             all_cells.append(ep.postsynaptic_population)
-        
+
         for e in ep.electrical_connection_instance_ws:
             gj_conns[ep.presynaptic_population][ep.postsynaptic_population] = float(e.weight)
-            
-            
+
+
     all_cells = sorted(all_cells)
-    
+
     try:
-        from PyOpenWorm import connect as pyow_connect
-        pow_conn = pyow_connect('./pyopenworm.conf')
+        with Bundle('openworm/owmeta-data', version=6) as bnd:
+            all_neuron_info, all_muscle_info = c302._get_cell_info(bnd, all_cells)
     except Exception as e:
-        c302.print_('Unable to connect to PyOpenWorm database: %s' % e)
-        pow_conn = None
-    
-    all_neuron_info, all_muscle_info = c302._get_cell_info(pow_conn, all_cells)
-    all_neurons = [] 
+        c302.print_('Unable to connect to owmeta bundle: %s' % e)
+        traceback.print_exc()
+
+    all_neurons = []
     all_muscles = []
     for c in all_cells:
         if c302.is_muscle(c):
             all_muscles.append(c)
         else:
             all_neurons.append(c)
-        
-    
+
+
     data_exc_n = np.zeros((len(all_neurons),len(all_neurons)))
     data_exc_m = np.zeros((len(all_neurons),len(all_muscles)))
-    
+
     data_inh_n = np.zeros((len(all_neurons),len(all_neurons)))
     data_inh_m = np.zeros((len(all_neurons),len(all_muscles)))
-    
+
     for pre in cc_exc_conns.keys():
         for post in cc_exc_conns[pre].keys():
             c302.print_("Exc Conn %s -> %s: %s"%(pre,post,cc_exc_conns[pre][post]), verbose)
@@ -473,7 +478,7 @@ def generate_conn_matrix(nml_doc, save_fig_dir=None, verbose=False):
                 data_exc_m[all_neurons.index(pre),all_muscles.index(post)] = cc_exc_conns[pre][post]
             if pre in all_muscles:
                 raise Exception("Unexpected...")
-                
+
     for pre in cc_inh_conns.keys():
         for post in cc_inh_conns[pre].keys():
             c302.print_("Inh Conn %s -> %s: %s"%(pre,post,cc_inh_conns[pre][post]), verbose)
@@ -483,20 +488,20 @@ def generate_conn_matrix(nml_doc, save_fig_dir=None, verbose=False):
                 data_inh_m[all_neurons.index(pre),all_muscles.index(post)] = cc_inh_conns[pre][post]
             if pre in all_muscles:
                 raise Exception("Unexpected...")
-                
-    
-    _show_conn_matrix(data_exc_n, 'Excitatory (non GABA) conns to neurons',all_neuron_info,all_neuron_info, 
+
+
+    _show_conn_matrix(data_exc_n, 'Excitatory (non GABA) conns to neurons',all_neuron_info,all_neuron_info,
                       net.id, save_figure_to='%s/%s_exc_to_neurons.png'%(save_fig_dir,net.id) if save_fig_dir else None)
-                      
-    _show_conn_matrix(data_exc_m, 'Excitatory (non GABA) conns to muscles',all_neuron_info,all_muscle_info, 
+
+    _show_conn_matrix(data_exc_m, 'Excitatory (non GABA) conns to muscles',all_neuron_info,all_muscle_info,
                       net.id, save_figure_to='%s/%s_exc_to_muscles.png'%(save_fig_dir,net.id) if save_fig_dir else None)
-    
-    _show_conn_matrix(data_inh_n, 'Inhibitory (GABA) conns to neurons',all_neuron_info,all_neuron_info, 
+
+    _show_conn_matrix(data_inh_n, 'Inhibitory (GABA) conns to neurons',all_neuron_info,all_neuron_info,
                       net.id, save_figure_to='%s/%s_inh_to_neurons.png'%(save_fig_dir,net.id) if save_fig_dir else None)
-    _show_conn_matrix(data_inh_m, 'Inhibitory (GABA) conns to muscles',all_neuron_info,all_muscle_info, 
+    _show_conn_matrix(data_inh_m, 'Inhibitory (GABA) conns to muscles',all_neuron_info,all_muscle_info,
                       net.id, save_figure_to='%s/%s_inh_to_muscles.png'%(save_fig_dir,net.id) if save_fig_dir else None)
-    
-    
+
+
     data_n = np.zeros((len(all_neurons),len(all_neurons)))
     data_n_m = np.zeros((len(all_neurons),len(all_muscles)))
     data_m_m = np.zeros((len(all_muscles), len(all_muscles)))
@@ -507,7 +512,7 @@ def generate_conn_matrix(nml_doc, save_fig_dir=None, verbose=False):
     for pre in gj_conns.keys():
         for post in gj_conns[pre].keys():
             c302.print_("Elect Conn %s -> %s: %s"%(pre,post,gj_conns[pre][post]), verbose)
-            
+
             if pre in all_neurons and post in all_neurons:
                 data_n[all_neurons.index(pre),all_neurons.index(post)] = gj_conns[pre][post]
             elif pre in all_neurons and post in all_muscles or pre in all_muscles and post in all_neurons:
@@ -521,9 +526,9 @@ def generate_conn_matrix(nml_doc, save_fig_dir=None, verbose=False):
                 data_m_m[all_muscles.index(pre), all_muscles.index(post)] = gj_conns[pre][post]
             else:
                 raise Exception("Unexpected...")
-        
-    
-    _show_conn_matrix(data_n, 'Electrical (gap junction) conns to neurons',all_neuron_info,all_neuron_info, 
+
+
+    _show_conn_matrix(data_n, 'Electrical (gap junction) conns to neurons',all_neuron_info,all_neuron_info,
                       net.id, save_figure_to='%s/%s_elec_neurons_neurons.png'%(save_fig_dir,net.id) if save_fig_dir else None)
 
     if neuron_muscle:
@@ -538,28 +543,29 @@ def generate_conn_matrix(nml_doc, save_fig_dir=None, verbose=False):
                           save_figure_to='%s/%s_elec_muscles_muscles.png' % (
                           save_fig_dir, net.id) if save_fig_dir else None)
     #_show_conn_matrix(data_m, 'Electrical (gap junction) conns to muscles',all_neuron_info,all_muscle_info, net.id)
-        
 
-            
+
+
 if __name__ == '__main__':
 
     from neuroml.loaders import read_neuroml2_file
-    
+
     configs = ['c302_C0_Syns.net.nml', 'c302_C0_Social.net.nml','c302_C0_Muscles.net.nml','c302_C0_Pharyngeal.net.nml','c302_C0_Oscillator.net.nml','c302_C0_Full.net.nml']
     configs = ['c302_C0_Syns.net.nml', 'c302_C0_Social.net.nml']
-    #configs = ['c302_C0_Syns.net.nml']
+    #
+    configs = ['c302_C0_Syns.net.nml']
+    configs = ['c302_C0_Oscillator.net.nml']
     configs = ['c302_C0_Muscles.net.nml']
-    #configs = ['c302_C0_Oscillator.net.nml']
     
     if '-phar' in sys.argv:
-        
+
         configs = ['c302_C0_Pharyngeal.net.nml']
-    
+
     for c in configs:
 
         nml_doc = read_neuroml2_file('examples/%s'%c)
 
         generate_conn_matrix(nml_doc, save_fig_dir='./examples/summary/')
-    
+
     if not '-nogui' in sys.argv:
-        plt.show()
\ No newline at end of file
+        plt.show()
diff --git a/c302/runAndPlot.py b/c302/runAndPlot.py
index ef9e6d26..e9747c9b 100644
--- a/c302/runAndPlot.py
+++ b/c302/runAndPlot.py
@@ -1,26 +1,28 @@
 import errno
 import sys
 import os
-from pyneuroml import pynml
-import c302_utils
-import c302
 import time
-
+import importlib as IM
 from collections import OrderedDict
 
+from pyneuroml import pynml
+
+import c302
+from c302 import c302_utils
+
 save_fig_dir = 'summary/'
 save_image_dir = 'images'
 save_image_full_dir = '%s/%s'%(save_fig_dir,save_image_dir)
 
 
-def run_c302(config, 
-             parameter_set, 
-             prefix, 
-             duration, 
-             dt, 
-             simulator, 
-             save=False, 
-             show_plot_already=True, 
+def run_c302(config,
+             parameter_set,
+             prefix,
+             duration,
+             dt,
+             simulator,
+             save=False,
+             show_plot_already=True,
              data_reader="SpreadsheetDataReader",
              verbose=False,
              plot_ca=True,
@@ -36,10 +38,11 @@ def run_c302(config,
         save_fig_dir = save_fig_to
 
     c302.print_("********************\n\n   Going to generate c302_%s_%s and run for %sms (dt: %sms) on %s\n\n********************"%(parameter_set,config,duration, dt, simulator))
-    if config_package:
-        exec ('from %s.c302_%s import setup' % (config_package, config), globals())
-    else:
-        exec ('from c302_%s import setup' % config, globals())
+
+    if not config_package:
+        config_package = 'c302'
+
+    setup = IM.import_module('%s.c302_%s' % (config_package, config)).setup
 
     try:
         os.makedirs(target_directory)
@@ -50,7 +53,7 @@ def run_c302(config,
     cells, cells_to_stimulate, params, muscles, nml_doc = setup(parameter_set,
                                                        data_reader=data_reader,
                                                        generate=True,
-                                                       duration = duration, 
+                                                       duration = duration,
                                                        dt = dt,
                                                        target_directory=target_directory,
                                                        verbose=verbose,
@@ -68,20 +71,20 @@ def run_c302(config,
             raise
 
     lems_file = 'LEMS_c302_%s_%s.xml'%(parameter_set,config)
-    
+
     if simulator == 'jNeuroML':
         results = pynml.run_lems_with_jneuroml(lems_file, nogui=True, load_saved_data=True, verbose=verbose)
     elif simulator == 'jNeuroML_NEURON':
         results = pynml.run_lems_with_jneuroml_neuron(lems_file, nogui=True, load_saved_data=True, verbose=verbose)
-        
+
     c302.print_("Finished simulation of %s and have reloaded results"%lems_file)
-        
-    c302_utils.plot_c302_results(results, 
-                                 config, 
-                                 parameter_set, 
+
+    c302_utils.plot_c302_results(results,
+                                 config,
+                                 parameter_set,
                                  directory=save_image_full_dir,
                                  save=save,
-                                 show_plot_already=show_plot_already, 
+                                 show_plot_already=show_plot_already,
                                  data_reader=data_reader,
                                  plot_ca=plot_ca)
 
@@ -91,32 +94,32 @@ def run_c302(config,
     os.chdir(orig_dir)
 
     return cells, cells_to_stimulate, params, muscles
-    
-    
+
+
 if __name__ == '__main__':
 
 
     if '-full' in sys.argv:
         run_c302('Full','C','',300,0.05,'jNeuroML_NEURON')
-        
+
     elif '-fullA' in sys.argv:
         run_c302('Full','A','',1000,0.05,'jNeuroML_NEURON')
-        
+
     elif '-fullB' in sys.argv:
         run_c302('Full','B','',1000,0.05,'jNeuroML_NEURON')
-        
+
     elif '-fullC0' in sys.argv:
         run_c302('Full','C0','',1000,0.05,'jNeuroML_NEURON')
-        
+
     elif '-fullC' in sys.argv:
         run_c302('Full','C','',1000,0.05,'jNeuroML_NEURON')
-        
+
     elif '-fullC1' in sys.argv:
         run_c302('Full','C1','',1000,0.05,'jNeuroML_NEURON')
-        
+
     elif '-fullD' in sys.argv:
         run_c302('Full','D','',1000,0.05,'jNeuroML_NEURON')
-        
+
     elif '-fullD1' in sys.argv:
         run_c302('Full','D1','',1000,0.05,'jNeuroML_NEURON')
 
@@ -126,13 +129,13 @@ def run_c302(config,
     elif '-fw1' in sys.argv:
         #run_c302('FW','C2','',1000,0.05,'jNeuroML_NEURON', data_reader='UpdatedSpreadsheetDataReader2', save=True)
         run_c302('FW','C2','',5000,0.005,'jNeuroML_NEURON', data_reader='UpdatedSpreadsheetDataReader2', save=True, show_plot_already=False)
-        
+
     elif '-fwTest' in sys.argv:
         run_c302('FW','C2','',5000,0.05,'jNeuroML_NEURON', data_reader='UpdatedSpreadsheetDataReader2', save=True, show_plot_already=True)
-        
+
     elif '-fullC2' in sys.argv:
         run_c302('Full','C2','',1000,0.05,'jNeuroML_NEURON')
-        
+
     elif '-muscle1' in sys.argv:
         run_c302('MuscleTest','C2','',2000,0.05,'jNeuroML_NEURON', data_reader='UpdatedSpreadsheetDataReader', save=True)
 
@@ -141,118 +144,118 @@ def run_c302(config,
 
     elif '-muscle' in sys.argv or '-muscles' in sys.argv:
         run_c302('Muscles','C','',500,0.05,'jNeuroML_NEURON')
-        
+
     elif '-musclesA' in sys.argv or  '-muscA' in sys.argv:
         run_c302('Muscles','A','',1000,0.05,'jNeuroML_NEURON')
-        
+
     elif '-musclesB' in sys.argv or  '-muscB' in sys.argv:
         run_c302('Muscles','B','',1000,0.05,'jNeuroML_NEURON')
-        
+
     elif '-musclesC0' in sys.argv or  '-muscC0' in sys.argv:
         run_c302('Muscles','C0','',1000,0.05,'jNeuroML_NEURON')
-        
+
     elif '-musclesC' in sys.argv or  '-muscC' in sys.argv:
         run_c302('Muscles','C','',2000,0.05,'jNeuroML_NEURON')
-        
+
     elif '-musclesC1' in sys.argv or  '-muscC1' in sys.argv:
         run_c302('Muscles','C1','',2000,0.05,'jNeuroML_NEURON')
-        
+
     elif '-musclesD' in sys.argv or  '-muscD' in sys.argv:
         run_c302('Muscles','D','',2000,0.05,'jNeuroML_NEURON')
-        
+
     elif '-musclesD1' in sys.argv or  '-muscD1' in sys.argv:
         run_c302('Muscles','D1','',2000,0.05,'jNeuroML_NEURON')
-        
+
     elif '-pharA' in sys.argv or '-pharyngealA' in sys.argv:
         run_c302('Pharyngeal','A','',500,0.01,'jNeuroML_NEURON')
-        
+
     elif '-pharB' in sys.argv or '-pharyngealB' in sys.argv:
         run_c302('Pharyngeal','B','',500,0.01,'jNeuroML_NEURON')
-        
+
     elif '-pharC0' in sys.argv or '-pharyngealC0' in sys.argv:
         run_c302('Pharyngeal','C0','',500,0.01,'jNeuroML_NEURON')
-        
+
     elif '-pharC1' in sys.argv or '-pharyngealC1' in sys.argv:
         run_c302('Pharyngeal','C1','',500,0.01,'jNeuroML_NEURON')
-        
+
     elif '-pharD' in sys.argv or '-pharyngealD' in sys.argv:
         run_c302('Pharyngeal','D','',500,0.05,'jNeuroML_NEURON')
-        
+
     elif '-pharD1' in sys.argv or '-pharyngealD1' in sys.argv:
         run_c302('Pharyngeal','D1','',500,0.05,'jNeuroML_NEURON')
-        
+
     elif '-phar' in sys.argv or '-pharyngeal' in sys.argv:
         run_c302('Pharyngeal','C','',500,0.01,'jNeuroML_NEURON')
-        
+
     elif '-synsA' in sys.argv:
         run_c302('Syns','A','',500,0.05,'jNeuroML_NEURON')
-        
+
     elif '-synsB' in sys.argv:
         run_c302('Syns','B','',500,0.05,'jNeuroML_NEURON')
-        
+
     elif '-synsC0' in sys.argv:
         run_c302('Syns','C0','',500,0.05,'jNeuroML_NEURON')
-        
+
     elif '-synsC' in sys.argv:
         run_c302('Syns','C','',500,0.05,'jNeuroML_NEURON')
-        
+
     elif '-synsC1' in sys.argv:
         run_c302('Syns','C1','',500,0.05,'jNeuroML_NEURON')
-        
+
     elif '-synsD' in sys.argv:
         run_c302('Syns','D','',500,0.05,'jNeuroML_NEURON')
-        
+
     elif '-synsD1' in sys.argv:
         run_c302('Syns','D1','',500,0.05,'jNeuroML_NEURON')
-        
+
     elif '-socialA' in sys.argv:
         run_c302('Social','A','',2500,0.05,'jNeuroML_NEURON')
-        
+
     elif '-socialB' in sys.argv:
         run_c302('Social','B','',2500,0.05,'jNeuroML_NEURON')
-        
+
     elif '-socialC0' in sys.argv:
         run_c302('Social','C0','',2500,0.05,'jNeuroML_NEURON')
-        
+
     elif '-socialC' in sys.argv:
         run_c302('Social','C','',2500,0.05,'jNeuroML_NEURON')
-        
+
     elif '-socialC1' in sys.argv:
         run_c302('Social','C1','',2500,0.05,'jNeuroML_NEURON')
-        
+
     elif '-oscA' in sys.argv:
         run_c302('Oscillator','A','',600,0.05,'jNeuroML_NEURON')
-        
+
     elif '-oscB' in sys.argv:
         run_c302('Oscillator','B','',600,0.05,'jNeuroML_NEURON')
-        
+
     elif '-oscC0' in sys.argv:
         run_c302('Oscillator','C0','',2000,0.025,'jNeuroML_NEURON')
-        
+
     elif '-oscmC0' in sys.argv:
         run_c302('OscillatorM','C0','',2000,0.025,'jNeuroML_NEURON')
-        
+
     elif '-test' in sys.argv:
         run_c302('Oscillator','C0','',2000,0.025,'jNeuroML',show_plot_already=False)
-        
+
     elif '-oscC' in sys.argv:
         run_c302('Oscillator','C','',2000,0.05,'jNeuroML_NEURON')
-        
+
     elif '-oscC1' in sys.argv:
         run_c302('Oscillator','C1','',2000,0.05,'jNeuroML_NEURON')
-        
+
     elif '-KatoC1' in sys.argv:
         run_c302('Kato','C1','',1080,0.05,'jNeuroML_NEURON')
-        
+
     elif '-targetC0' in sys.argv:
         run_c302('TargetMuscle','C0','',300,0.05,'jNeuroML')
-        
+
     elif '-twC2' in sys.argv:
         run_c302('TapWithdrawal', 'C2', '', 500, 0.05, 'jNeuroML_NEURON', data_reader="UpdatedSpreadsheetDataReader")
-        
+
     elif '-sinusC2' in sys.argv:
         run_c302('SinusoidalInputTest', 'C2', '', 1000, 0.05, 'jNeuroML_NEURON', data_reader="UpdatedSpreadsheetDataReader")
-        
+
     elif '-iA' in sys.argv:
         run_c302('IClamp','A','',6000,0.05,'jNeuroML')
     elif '-iB' in sys.argv:
@@ -267,7 +270,7 @@ def run_c302(config,
         run_c302('IClamp','D','',6000,0.05,'jNeuroML_NEURON',save=True)
     elif '-iD1' in sys.argv:
         run_c302('IClamp','D1','',6000,0.05,'jNeuroML_NEURON',save=True)
-        
+
     elif '-all' in sys.argv:
         print('Generating all plots')
         html = '<table>\n'
@@ -277,7 +280,7 @@ def run_c302(config,
         #levels = ['C2']
         #levels = ['C0']
 
-        
+
         durations = OrderedDict([('IClamp',6000),
                                 ('Syns',500),
                                 ('Pharyngeal',500),
@@ -285,16 +288,16 @@ def run_c302(config,
                                 ('Oscillator',1000),
                                 ('Muscles',1000),
                                 ('Full',1000)])
-        
+
         '''durations = OrderedDict([('IClamp',1000),
                                 ('Syns',500),
                                 ('Oscillator',1000),
                                 ('OscillatorM',1000)])
-                                
+
         durations = OrderedDict([('IClamp',1000),
                                 ('Syns',500),
                                 ('Social',2500)])'''
-            
+
         html+='<tr>\n'
         html+='  <td>&nbsp;</td>\n'
         for p in durations.keys():
@@ -303,9 +306,9 @@ def run_c302(config,
         html+='</tr>\n'
         for c in levels:
             print('Generating for: %s'%c)
-            
+
             img_loc = save_image_dir
-            
+
             html+='\n<tr>\n'
             html+='  <td><b><a href="https://github.com/openworm/c302/blob/master/c302/parameters_%s.py">Params %s</a></b></td>\n'%(c,c)
             for p in durations.keys():
@@ -316,27 +319,27 @@ def run_c302(config,
                 html2 += '<table>\n'
                 html+='  <td><a href="summary_%s_%s.html">\n'%(c,p)
                 html+='    <img alt="?" src="%s/neurons_%s_%s.png" height="80"/></a>\n'%(img_loc,c,p)
-                
+
                 html+='    <br/><a href="https://github.com/openworm/c302/blob/master/examples/c302_%s_%s.net.nml">NML</a>\n'%(c,p)
                 html+='    &nbsp;<a href="http://opensourcebrain.org/projects/celegans?explorer=https://raw.githubusercontent.com/openworm/c302/master/examples/c302_%s_%s.net.nml">OSB</a>\n'%(c,p)
-                
+
                 pres = ['neurons_','neuron_activity_','muscles_','muscle_activity_']
                 for pre in pres:
-                    
+
                     html2+='\n<tr>\n  <td><a href="%s/%s%s_%s.png"><img alt=" " src="%s/%s%s_%s.png" height="320"/></a></td>\n'%(img_loc,pre,c,p,img_loc,pre,c,p)
                     if pre == 'neurons_':
                         pre = 'neuron_'
                     if pre == 'muscle_activity_':
                         pre = 'muscles_activity_'
                     html2+='  <td><a href="%s/traces_%s%s_%s.png"><img alt=" " src="%s/traces_%s%s_%s.png" height="320"/></a></td>\n</tr>\n'%(img_loc,pre,p,c,img_loc,pre,p,c)
-                    
+
                 html2+='</table>\n'
                 html2+='<table>\n'
-                
+
                 html2 += '\n<tr><td><a href="%s/c302_%s_%s_exc_to_neurons.png"><img alt=" " src="%s/c302_%s_%s_exc_to_neurons.png" height="320"/></a></td>\n' % (img_loc,c,p,img_loc,c,p)
                 html2 += '\n  <td><a href="%s/c302_%s_%s_inh_to_neurons.png"><img alt=" " src="%s/c302_%s_%s_inh_to_neurons.png" height="320"/></a></td>\n' % (img_loc,c,p,img_loc,c,p)
                 html2 += '\n  <td><a href="%s/c302_%s_%s_elec_neurons_neurons.png"><img alt=" " src="%s/c302_%s_%s_elec_neurons_neurons.png" height="320"/></a></td></tr>\n' % (img_loc,c,p,img_loc,c,p)
-                
+
                 html2 += '\n<tr><td><a href="%s/c302_%s_%s_exc_to_muscles.png"><img alt=" " src="%s/c302_%s_%s_exc_to_muscles.png" height="320"/></a></td>\n' % (img_loc,c,p,img_loc,c,p)
                 html2 += '\n  <td><a href="%s/c302_%s_%s_inh_to_muscles.png"><img alt=" " src="%s/c302_%s_%s_inh_to_muscles.png" height="320"/></a></td>' % (img_loc,c,p,img_loc,c,p)
                 if os.path.isfile('%s/%s/%s/c302_%s_%s_elec_neurons_muscles.png' % ('examples', save_fig_dir, img_loc, c, p)):
@@ -346,16 +349,16 @@ def run_c302(config,
                 if os.path.isfile('%s/%s/%s/c302_%s_%s_elec_muscles_muscles.png' % ('examples', save_fig_dir, img_loc, c, p)):
                     html2 += '\n<tr><td><a href="%s/c302_%s_%s_elec_muscles_muscles.png"><img alt=" " src="%s/c302_%s_%s_elec_muscles_muscles.png" height="320"/></a></td></tr>\n' % (img_loc,c,p,img_loc,c,p)
 
-                    
+
                 html2+='</table>\n'
-                
+
                 with open('examples/%s/summary_%s_%s.html'%(save_fig_dir, c,p),'w') as f2:
                     f2.write('<html><body>%s</body></html>'%html2)
                 with open('examples/%s/summary_%s_%s.md'%(save_fig_dir,c,p),'w') as f3:
                     f3.write('### Parameter config summary \n%s'%html2)
 
                 dt = 0.05 if p!='Pharyngeal' else 0.01
-                
+
                 run_c302(p,
                          c,
                          '',
@@ -366,21 +369,17 @@ def run_c302(config,
                          show_plot_already=False,
                          plot_connectivity=True,
                          data_reader='SpreadsheetDataReader')
-                
+
                 html+='  </td>\n'
-                
+
             html+='</tr>\n'
-        
+
         html+='</table>\n'
-                
+
         with open('examples/'+save_fig_dir+'info.html','w') as f:
             f.write('<html><body>\n%s\n</body></html>'%html)
         with open('examples/'+save_fig_dir+'README.md','w') as f2:
             f2.write('### c302 activity summary \n%s'%(html.replace('.html','.md')))
-        
+
     else:
         run_c302('Syns','C','',500,0.05,'jNeuroML')
-        
-        
-    
-        
diff --git a/examples/summary/summary.md b/examples/summary/summary.md
new file mode 100644
index 00000000..a9799d8a
--- /dev/null
+++ b/examples/summary/summary.md
@@ -0,0 +1,796 @@
+# Information on neuron and muscles
+## Generated using owmeta v0.12.3.dev0 (owmeta core v0.12.2)
+### Neurons (299)
+<table>
+<tr>
+<td>ADAL</td><td>interneuron</td><td></td><td>Glutamate</td><td>+ (In) ADAL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>ADAR</td><td>interneuron</td><td></td><td>Glutamate</td><td>+ (In) ADAR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>ADEL</td><td>sensory</td><td>ACR-16, DOP-2, EXP-1, OCTR-1, TRP-4, TYRA-3</td><td>Dopamine</td><td>+ (Se) ADEL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>ADER</td><td>sensory</td><td>ACR-16, DOP-2, EXP-1, OCTR-1, TRP-4, TYRA-3</td><td>Dopamine</td><td>+ (Se) ADER</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>ADFL</td><td>sensory</td><td>MGL-3, NPR-2, NPR-5, NTR-1, NTR-2, OCR-2, OSM-9, SRB-6, SRD-1, TMC-1</td><td>Serotonin</td><td>+ (Se) ADFL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>ADFR</td><td>sensory</td><td>MGL-3, NPR-2, NPR-5, NTR-1, NTR-2, OCR-2, OSM-9, SRB-6, SRD-1, TMC-1</td><td>Serotonin</td><td>+ (Se) ADFR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>ADLL</td><td>sensory</td><td>GCY-21, NTR-1, NTR-2, OCR-1, OCR-2, OSM-9, SER-6, SRB-6, SRE-1, SRH-132, SRH-220, SRI-51, SRO-1, TMC-1, TYRA-3</td><td></td><td>? (Se) ADLL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>ADLR</td><td>sensory</td><td>GCY-21, NTR-1, NTR-2, OCR-1, OCR-2, OSM-9, SER-6, SRB-6, SRE-1, SRH-132, SRH-220, SRI-51, SRO-1, TMC-1, TYRA-3</td><td></td><td>? (Se) ADLR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>AFDL</td><td>sensory</td><td>GCY-18, GCY-23, GCY-29, GCY-8, TMC-1, TYRA-3</td><td>Glutamate</td><td>+ (Se) AFDL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>AFDR</td><td>sensory</td><td>GCY-18, GCY-23, GCY-29, GCY-8, TMC-1, TYRA-3</td><td>Glutamate</td><td>+ (Se) AFDR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>AIAL</td><td>interneuron</td><td>GCY-28, GLC-3, GLR-2, MGL-1, MOD-1, NPR-11, NPR-5, NTR-2, SCD-2, SRA-11</td><td>Acetylcholine</td><td>+ (In) AIAL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AIAR</td><td>interneuron</td><td>GCY-28, GLC-3, GLR-2, MGL-1, MOD-1, NPR-11, NPR-5, NTR-2, SCD-2, SRA-11</td><td>Acetylcholine</td><td>+ (In) AIAR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AIBL</td><td>interneuron</td><td>GGR-1, GLR-1, GLR-2, GLR-5, MGL-2, MOD-1, SER-4</td><td>Glutamate</td><td>+ (In) AIBL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AIBR</td><td>interneuron</td><td>GGR-1, GLR-1, GLR-2, GLR-5, MGL-2, MOD-1, SER-1, SER-4</td><td></td><td>? (In) AIBR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AIML</td><td>interneuron</td><td>GCY-18, LGC-53, TYRA-3</td><td>Glutamate, Serotonin</td><td>+ (In) AIML</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AIMR</td><td>interneuron</td><td>GCY-18, LGC-53, TYRA-3</td><td>Glutamate, Serotonin</td><td>+ (In) AIMR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AINL</td><td>interneuron</td><td></td><td>Acetylcholine</td><td>+ (In) AINL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AINR</td><td>interneuron</td><td></td><td>Acetylcholine</td><td>+ (In) AINR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AIYL</td><td>interneuron</td><td>ACR-14, C50F7.1, CKR-2, GAR-2, GCY-1, GLC-3, LGC-38, MGL-1, MOD-1, NPR-11, NPR-14, OCTR-1, SER-2, SRA-11</td><td>Acetylcholine</td><td>+ (In) AIYL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AIYR</td><td>interneuron</td><td>ACR-14, C50F7.1, CKR-2, GAR-2, GCY-1, GLC-3, LGC-38, MGL-1, MOD-1, NPR-11, NPR-14, OCTR-1, SER-2, SRA-11</td><td>Acetylcholine</td><td>+ (In) AIYR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AIZL</td><td>interneuron</td><td>MOD-1, NPR-2, SER-2</td><td>Glutamate</td><td>+ (In) AIZL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AIZR</td><td>interneuron</td><td>MOD-1, NPR-2, SER-2</td><td>Glutamate</td><td>+ (In) AIZR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>ALA</td><td>interneuron</td><td>ACR-13, ACR-4, SRA-10</td><td></td><td>? (In) ALA</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>ALML</td><td>sensory</td><td>ASIC-1, DEG-3, DEGT-1, DEL-1, DES-2, DOP-1, GAB-1, GLR-8, LGC-37, LGC-55, MEC-10, MEC-2, MEC-4, MEC-6, MEC-9, PDFR-1, STR-33, TYRA-2</td><td>Glutamate</td><td>+ (Se) ALML</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>ALMR</td><td>sensory</td><td>ASIC-1, DEG-3, DEGT-1, DEL-1, DES-2, DOP-1, GAB-1, GLR-8, LGC-37, LGC-55, MEC-10, MEC-2, MEC-4, MEC-6, MEC-9, PDFR-1, STR-33, TYRA-2</td><td>Glutamate</td><td>+ (Se) ALMR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>ALNL</td><td>sensory</td><td>DOP-1, LGC-55, SER-2</td><td>Acetylcholine</td><td>+ (Se) ALNL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>ALNR</td><td>sensory</td><td>DOP-1, LGC-55, SER-2</td><td>Acetylcholine</td><td>+ (Se) ALNR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>AQR</td><td>sensory</td><td>GCY-25, GCY-32, GCY-34, GCY-35, GCY-36, GCY-37, NLP-37, NPR-1</td><td>Glutamate</td><td>+ (Se) AQR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>AS1</td><td>motor</td><td>ACR-14, ACR-15, CKR-2, DOP-1, DOP-3, LGC-46, NPR-3, UNC-63</td><td>Acetylcholine</td><td>+ (Mo) AS1</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>AS10</td><td>motor</td><td>ACR-14, ACR-15, CKR-2, DOP-1, DOP-3, LGC-46, NPR-3, UNC-63</td><td>Acetylcholine</td><td>+ (Mo) AS10</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>AS11</td><td>motor</td><td>ACR-14, ACR-15, CKR-2, DOP-1, DOP-3, LGC-46, NPR-3, UNC-63</td><td>Acetylcholine</td><td>+ (Mo) AS11</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>AS2</td><td>motor</td><td>ACR-14, ACR-15, CKR-2, DOP-1, DOP-3, LGC-46, NPR-3, UNC-63</td><td>Acetylcholine</td><td>+ (Mo) AS2</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>AS3</td><td>motor</td><td>ACR-14, ACR-15, CKR-2, DOP-1, DOP-3, LGC-46, NPR-3, UNC-63</td><td>Acetylcholine</td><td>+ (Mo) AS3</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>AS4</td><td>motor</td><td>ACR-14, ACR-15, CKR-2, DOP-1, DOP-3, LGC-46, NPR-3, UNC-63</td><td>Acetylcholine</td><td>+ (Mo) AS4</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>AS5</td><td>motor</td><td>ACR-14, ACR-15, CKR-2, DOP-1, DOP-3, LGC-46, NPR-3, UNC-63</td><td>Acetylcholine</td><td>+ (Mo) AS5</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>AS6</td><td>motor</td><td>ACR-14, ACR-15, CKR-2, DOP-1, DOP-3, LGC-46, NPR-3, UNC-63</td><td>Acetylcholine</td><td>+ (Mo) AS6</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>AS7</td><td>motor</td><td>ACR-14, ACR-15, CKR-2, DOP-1, DOP-3, LGC-46, NPR-3, UNC-63</td><td>Acetylcholine</td><td>+ (Mo) AS7</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>AS8</td><td>motor</td><td>ACR-14, ACR-15, CKR-2, DOP-1, DOP-3, LGC-46, NPR-3, UNC-63</td><td>Acetylcholine</td><td>+ (Mo) AS8</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>AS9</td><td>motor</td><td>ACR-14, ACR-15, CKR-2, DOP-1, DOP-3, LGC-46, NPR-3, UNC-63</td><td>Acetylcholine</td><td>+ (Mo) AS9</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>ASEL</td><td>sensory</td><td>DEL-3, DEL-4, DOP-3, DOP-5, GCY-14, GCY-19, GCY-20, GCY-29, GCY-6, GCY-7, MGL-3, NPR-1, NPR-15, NPR-5, NTR-1, OSM-9, SRAB-14, SRD-33, SRG-30, SRX-76, TMC-1, TRPA-2, TYRA-2</td><td>Glutamate</td><td>+ (Se) ASEL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>ASER</td><td>sensory</td><td>DAF-2, DEL-3, DEL-4, DOP-3, DOP-5, GCY-1, GCY-19, GCY-22, GCY-29, GCY-3, GCY-4, GCY-5, MGL-3, NPR-1, NPR-15, NPR-5, NTR-1, OSM-9, SRAB-14, SRD-33, SRG-30, SRX-76, TMC-1, TRP-2, TRPA-2, TYRA-2</td><td>Glutamate</td><td>+ (Se) ASER</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>ASGL</td><td>sensory</td><td>DOP-4, GCY-15, GCY-21, NPR-1, NPR-15, NPR-5, OSM-9, TYRA-2</td><td>Glutamate, Serotonin</td><td>+ (Se) ASGL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>ASGR</td><td>sensory</td><td>DOP-4, GCY-15, GCY-21, NPR-1, NPR-15, NPR-5, OSM-9, TYRA-2</td><td>Glutamate, Serotonin</td><td>+ (Se) ASGR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>ASHL</td><td>sensory</td><td>DCAR-1, DOP-4, NPR-1, NPR-2, NTR-1, NTR-2, OCR-2, OCTR-1, OSM-9, SER-3, SER-5, SRA-6, SRB-6, TMC-1, TRPA-1, TYRA-2, UNC-8</td><td>Glutamate</td><td>+ (Se) ASHL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>ASHR</td><td>sensory</td><td>DCAR-1, DOP-4, NPR-1, NPR-2, NTR-1, NTR-2, OCR-2, OCTR-1, OSM-9, SER-3, SER-5, SRA-6, SRB-6, TMC-1, TRPA-1, TYRA-2, UNC-8</td><td>Glutamate</td><td>+ (Se) ASHR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>ASIL</td><td>sensory</td><td>DAF-11, DAF-37, DAF-38, DCAR-1, GCY-1, GCY-2, GCY-27, GCY-3, NPR-15, NPR-17, NPR-5, OCTR-1, SER-6, SRD-1, STR-2, STR-3, TYRA-2</td><td></td><td>? (Se) ASIL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>ASIR</td><td>sensory</td><td>DAF-11, DAF-37, DAF-38, DCAR-1, GCY-1, GCY-2, GCY-27, GCY-3, NPR-15, NPR-17, NPR-5, OCTR-1, SER-6, SRD-1, STR-2, STR-3, TYRA-2</td><td></td><td>? (Se) ASIR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>ASJL</td><td>sensory</td><td>DAF-11, NPR-5, OSM-9, SRE-1</td><td></td><td>? (Se) ASJL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>ASJR</td><td>sensory</td><td>DAF-11, NPR-5, OSM-9, SRE-1</td><td></td><td>? (Se) ASJR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>ASKL</td><td>sensory</td><td>DAF-11, DOP-3, NPR-5, OSM-9, SRA-7, SRA-9, SRG-2, SRG-8, TYRA-3</td><td>Glutamate</td><td>+ (Se) ASKL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>ASKR</td><td>sensory</td><td>DAF-11, DOP-3, NPR-5, OSM-9, SRA-7, SRA-9, SRG-2, SRG-8, TYRA-3</td><td>Glutamate</td><td>+ (Se) ASKR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>AUAL</td><td>interneuron</td><td>DOP-1, GLR-4, NPR-1, NPR-5, SER-2, TYRA-3</td><td>Glutamate</td><td>+ (In) AUAL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AUAR</td><td>interneuron</td><td>DOP-1, GLR-4, NPR-1, NPR-5, SER-2, TYRA-3</td><td>Glutamate</td><td>+ (In) AUAR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AVAL</td><td>interneuron</td><td>GGR-3, GLR-1, GLR-2, GLR-4, GLR-5, NMR-1, NMR-2, NPR-4, UNC-8</td><td></td><td>? (In) AVAL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AVAR</td><td>interneuron</td><td>GGR-3, GLR-1, GLR-2, GLR-4, GLR-5, NMR-1, NMR-2, NPR-4, UNC-8</td><td></td><td>? (In) AVAR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AVBL</td><td>interneuron</td><td>GGR-3, GLR-1, GLR-5, LGC-55, SRA-11, UNC-8</td><td></td><td>? (In) AVBL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AVBR</td><td>interneuron</td><td>GGR-3, GLR-1, GLR-5, LGC-55, SRA-11, UNC-8</td><td></td><td>? (In) AVBR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AVDL</td><td>interneuron</td><td>GLR-1, GLR-2, GLR-5, NMR-1, NMR-2, PDFR-1, UNC-8</td><td></td><td>? (In) AVDL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AVDR</td><td>interneuron</td><td>GLR-1, GLR-2, GLR-5, NMR-1, NMR-2, PDFR-1, UNC-8</td><td></td><td>? (In) AVDR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AVEL</td><td>interneuron</td><td>FRPR-4, GLR-1, GLR-2, GLR-5, NMR-1, NMR-2</td><td></td><td>? (In) AVEL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AVER</td><td>interneuron</td><td>FRPR-4, GLR-1, GLR-2, GLR-5, NMR-1, NMR-2</td><td></td><td>? (In) AVER</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AVFL</td><td>interneuron</td><td>LGC-53, PDFR-1</td><td></td><td>? (In) AVFL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AVFR</td><td>interneuron</td><td>LGC-53, PDFR-1</td><td></td><td>? (In) AVFR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AVG</td><td>interneuron</td><td>DEG-3, GLR-1, GLR-2, NMR-1, NMR-2, NPR-17, NTR-2</td><td></td><td>? (In) AVG</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AVHL</td><td>interneuron</td><td>GGR-1, GLR-4, SER-2</td><td></td><td>? (In) AVHL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AVHR</td><td>interneuron</td><td>GGR-1, GLR-4, SER-2</td><td></td><td>? (In) AVHR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AVJL</td><td>interneuron</td><td>GLR-1, SER-5</td><td></td><td>? (In) AVJL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AVJR</td><td>interneuron</td><td>GLR-1, SER-5</td><td></td><td>? (In) AVJR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AVKL</td><td>interneuron</td><td>GLR-5</td><td></td><td>? (In) AVKL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AVKR</td><td>interneuron</td><td>GLR-5</td><td></td><td>? (In) AVKR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>AVL</td><td>interneuron, motor</td><td>DOP-4</td><td>GABA</td><td>- (MoIn) AVL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>AVM</td><td>sensory</td><td>DOP-1, LGC-55, PDFR-1</td><td>Glutamate</td><td>+ (Se) AVM</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>AWAL</td><td>sensory</td><td>NPR-5, OCR-1, OCR-2, ODR-10, OSM-9</td><td></td><td>? (Se) AWAL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>AWAR</td><td>sensory</td><td>NPR-5, OCR-1, OCR-2, ODR-10, OSM-9</td><td></td><td>? (Se) AWAR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>AWBL</td><td>sensory</td><td>AEX-2, DAF-11, NPR-5, SER-5, SER-6, STR-1</td><td></td><td>? (Se) AWBL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>AWBR</td><td>sensory</td><td>AEX-2, DAF-11, NPR-5, SER-5, SER-6, STR-1</td><td></td><td>? (Se) AWBR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>AWCL</td><td>sensory</td><td>DAF-11, OSM-9, STR-2, TYRA-3</td><td>Glutamate</td><td>+ (Se) AWCL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>AWCR</td><td>sensory</td><td>DAF-11, OSM-9, STR-2, TYRA-3</td><td>Glutamate</td><td>+ (Se) AWCR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>BAGL</td><td>sensory</td><td>GCY-33, NPR-4, TYRA-3</td><td>Glutamate</td><td>+ (Se) BAGL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>BAGR</td><td>sensory</td><td>GCY-33, NPR-4, TYRA-3</td><td>Glutamate</td><td>+ (Se) BAGR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>BDUL</td><td>interneuron</td><td>GLR-8, NPR-4, NTR-1, SER-2</td><td></td><td>? (In) BDUL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>BDUR</td><td>interneuron</td><td>GLR-8, NPR-4, NTR-1, SER-2</td><td></td><td>? (In) BDUR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>CEPDL</td><td>sensory</td><td>DOP-2, OCTR-1, TYRA-3</td><td>Dopamine</td><td>+ (Se) CEPDL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>CEPDR</td><td>sensory</td><td>DOP-2, OCTR-1, TYRA-3</td><td>Dopamine</td><td>+ (Se) CEPDR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>CEPVL</td><td>sensory</td><td>DOP-2, OCTR-1, TYRA-3</td><td>Dopamine</td><td>+ (Se) CEPVL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>CEPVR</td><td>sensory</td><td>DOP-2, OCTR-1, TYRA-3</td><td>Dopamine</td><td>+ (Se) CEPVR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>DA1</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, NPR-3, SER-2, UNC-8</td><td>Acetylcholine</td><td>+ (Mo) DA1</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DA2</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, NPR-3, SER-2, UNC-8</td><td>Acetylcholine</td><td>+ (Mo) DA2</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DA3</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, NPR-3, SER-2, UNC-8</td><td>Acetylcholine</td><td>+ (Mo) DA3</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DA4</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, NPR-3, SER-2, UNC-8</td><td>Acetylcholine</td><td>+ (Mo) DA4</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DA5</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, NPR-3, SER-2, UNC-8</td><td>Acetylcholine</td><td>+ (Mo) DA5</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DA6</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, NPR-3, SER-2, UNC-8</td><td>Acetylcholine</td><td>+ (Mo) DA6</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DA7</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, NPR-3, SER-2, UNC-8</td><td>Acetylcholine</td><td>+ (Mo) DA7</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DA8</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, NPR-3, SER-2, UNC-8</td><td>Acetylcholine</td><td>+ (Mo) DA8</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DA9</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, NPR-3, SER-2, UNC-8</td><td>Acetylcholine</td><td>+ (Mo) DA9</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DB1</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, NPR-3</td><td>Acetylcholine</td><td>+ (Mo) DB1</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DB2</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, NPR-3, PDFR-1</td><td>Acetylcholine</td><td>+ (Mo) DB2</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DB3</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, NPR-3</td><td>Acetylcholine</td><td>+ (Mo) DB3</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DB4</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, NPR-3</td><td>Acetylcholine</td><td>+ (Mo) DB4</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DB5</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, NPR-3</td><td>Acetylcholine</td><td>+ (Mo) DB5</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DB6</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, NPR-3</td><td>Acetylcholine</td><td>+ (Mo) DB6</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DB7</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, NPR-3</td><td>Acetylcholine</td><td>+ (Mo) DB7</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DD1</td><td>motor</td><td>DOP-3, MOD-1, NPR-1</td><td>GABA</td><td>- (Mo) DD1</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DD2</td><td>motor</td><td>DOP-3, MOD-1, NPR-1</td><td>GABA</td><td>- (Mo) DD2</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DD3</td><td>motor</td><td>DOP-3, MOD-1, NPR-1</td><td>GABA</td><td>- (Mo) DD3</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DD4</td><td>motor</td><td>DOP-3, MOD-1, NPR-1</td><td>GABA</td><td>- (Mo) DD4</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DD5</td><td>motor</td><td>DOP-3, MOD-1, NPR-1</td><td>GABA</td><td>- (Mo) DD5</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DD6</td><td>motor</td><td>DOP-3, MOD-1, NPR-1</td><td>GABA</td><td>- (Mo) DD6</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DVA</td><td>interneuron, sensory</td><td>EGL-6, FRPR-4, GGR-3, GLR-4, GLR-5, NMR-1, SER-2, SER-4, TRP-4</td><td>Acetylcholine</td><td>+ (InSe) DVA</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>DVB</td><td>interneuron, motor</td><td></td><td>GABA</td><td>- (MoIn) DVB</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>DVC</td><td>interneuron</td><td>GLR-1, SER-1, SER-4, TRP-4</td><td>Glutamate</td><td>+ (In) DVC</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>FLPL</td><td>sensory</td><td>DEG-3, DEL-1, DES-2, GLR-4, LGC-53, MEC-10, NPR-2, OSM-9, PDFR-1, UNC-8</td><td>Glutamate</td><td>+ (Se) FLPL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>FLPR</td><td>sensory</td><td>DEG-3, DEL-1, DES-2, GLR-4, LGC-53, MEC-10, NPR-2, OSM-9, PDFR-1, UNC-8</td><td>Glutamate</td><td>+ (Se) FLPR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>HSNL</td><td>motor</td><td>EGL-6, GAR-2, GGR-2, GLR-5, LGC-53, LGC-55, MEC-6</td><td>Serotonin</td><td>+ (Mo) HSNL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>HSNR</td><td>motor</td><td>EGL-6, GAR-2, GGR-2, GLR-5, LGC-53, LGC-55, MEC-6</td><td>Serotonin</td><td>+ (Mo) HSNR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>I1L</td><td>interneuron, sensory</td><td>DOP-4, FRPR-4, GLR-7, GLR-8, PDFR-1</td><td>Acetylcholine</td><td>+ (InSe) I1L</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>I1R</td><td>interneuron, sensory</td><td>DOP-4, FRPR-4, GLR-7, GLR-8, PDFR-1</td><td>Acetylcholine</td><td>+ (InSe) I1R</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>I2L</td><td>interneuron, sensory</td><td>DOP-4, GLR-7, GLR-8, NTR-1, SER-7</td><td>Glutamate</td><td>+ (InSe) I2L</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>I2R</td><td>interneuron, sensory</td><td>DOP-4, GLR-7, GLR-8, NTR-1, SER-7</td><td></td><td>? (InSe) I2R</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>I3</td><td>interneuron, sensory</td><td>GLR-7, GLR-8, SER-7</td><td></td><td>? (InSe) I3</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>I4</td><td>interneuron</td><td>SER-7</td><td></td><td>? (In) I4</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>I5</td><td>interneuron, sensory</td><td></td><td>Glutamate, Serotonin</td><td>+ (InSe) I5</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>I6</td><td>interneuron, sensory</td><td>GLR-7, GLR-8, SER-7</td><td>Acetylcholine</td><td>+ (InSe) I6</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>IL1DL</td><td>interneuron, motor, sensory</td><td>DEG-3, LGC-55, MEC-6, TRPA-1</td><td>Glutamate</td><td>+ (MoInSe) IL1DL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>IL1DR</td><td>interneuron, motor, sensory</td><td>DEG-3, LGC-55, MEC-6, TRPA-1</td><td>Glutamate</td><td>+ (MoInSe) IL1DR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>IL1L</td><td>interneuron, motor, sensory</td><td>DEG-3, LGC-55, MEC-6, TRPA-1</td><td>Glutamate</td><td>+ (MoInSe) IL1L</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>IL1R</td><td>interneuron, motor, sensory</td><td>DEG-3, LGC-55, MEC-6, TRPA-1</td><td>Glutamate</td><td>+ (MoInSe) IL1R</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>IL1VL</td><td>interneuron, motor, sensory</td><td>DEG-3, LGC-55, MEC-6, TRPA-1</td><td>Glutamate</td><td>+ (MoInSe) IL1VL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>IL1VR</td><td>interneuron, motor, sensory</td><td>DEG-3, LGC-55, MEC-6, TRPA-1</td><td>Glutamate</td><td>+ (MoInSe) IL1VR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>IL2DL</td><td>sensory</td><td>DES-2, LGC-53, NPR-1, NPR-5</td><td>Acetylcholine</td><td>+ (Se) IL2DL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>IL2DR</td><td>sensory</td><td>DES-2, LGC-53, NPR-1, NPR-5</td><td>Acetylcholine</td><td>+ (Se) IL2DR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>IL2L</td><td>sensory</td><td>DES-2, LGC-53, NPR-1, NPR-5</td><td>Acetylcholine</td><td>+ (Se) IL2L</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>IL2R</td><td>sensory</td><td>DES-2, LGC-53, NPR-1, NPR-5</td><td>Acetylcholine</td><td>+ (Se) IL2R</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>IL2VL</td><td>sensory</td><td>DES-2, LGC-53, NPR-1, NPR-5</td><td>Acetylcholine</td><td>+ (Se) IL2VL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>IL2VR</td><td>sensory</td><td>DES-2, LGC-53, NPR-1, NPR-5</td><td>Acetylcholine</td><td>+ (Se) IL2VR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>LUAL</td><td>interneuron</td><td>GLR-5, SER-2</td><td>Glutamate</td><td>+ (In) LUAL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>LUAR</td><td>interneuron</td><td>GLR-5, SER-2</td><td>Glutamate</td><td>+ (In) LUAR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>M1</td><td>motor</td><td>AVR-14, GLR-2, SER-4</td><td>Acetylcholine</td><td>+ (Mo) M1</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>M2L</td><td>motor</td><td>SER-7</td><td>Acetylcholine</td><td>+ (Mo) M2L</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>M2R</td><td>motor</td><td>SER-7</td><td>Acetylcholine</td><td>+ (Mo) M2R</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>M3L</td><td>motor, sensory</td><td>GLR-8, NPR-1, SER-7</td><td>Glutamate</td><td>+ (MoSe) M3L</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>M3R</td><td>motor, sensory</td><td>GLR-8, NPR-1, SER-7</td><td>Glutamate</td><td>+ (MoSe) M3R</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>M4</td><td>motor</td><td>GLR-8, SER-7, SER7b</td><td>Acetylcholine</td><td>+ (Mo) M4</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>M5</td><td>motor</td><td>GLR-8, SER-7</td><td>Acetylcholine</td><td>+ (Mo) M5</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>MCL</td><td>motor, sensory</td><td>GLR-8, SER-7, TYRA-2</td><td>Acetylcholine</td><td>+ (MoSe) MCL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>MCR</td><td>motor, sensory</td><td>GLR-8, SER-7, TYRA-2</td><td>Acetylcholine</td><td>+ (MoSe) MCR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>MI</td><td>interneuron, motor</td><td></td><td>Glutamate</td><td>+ (MoIn) MI</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>NSML</td><td>motor, sensory</td><td>AEX-2, DOP-3, GLR-7, GLR-8, SER-2, SER-4, TYRA-2</td><td>Serotonin</td><td>+ (MoSe) NSML</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>NSMR</td><td>motor, sensory</td><td>AEX-2, DOP-3, GLR-7, GLR-8, SER-2, SER-4, TYRA-2</td><td>Serotonin</td><td>+ (MoSe) NSMR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>OLLL</td><td>sensory</td><td>PDFR-1, SER-2</td><td>Glutamate</td><td>+ (Se) OLLL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>OLLR</td><td>sensory</td><td>PDFR-1, SER-2</td><td>Glutamate</td><td>+ (Se) OLLR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>OLQDL</td><td>interneuron, sensory</td><td>NPR-1, NPR-2, OCR-4, OSM-9, PDFR-1, TRPA-1, TYRA-3</td><td>Glutamate</td><td>+ (InSe) OLQDL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>OLQDR</td><td>interneuron, sensory</td><td>NPR-1, NPR-2, OCR-4, OSM-9, PDFR-1, TRPA-1, TYRA-3</td><td>Glutamate</td><td>+ (InSe) OLQDR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>OLQVL</td><td>interneuron, sensory</td><td>NPR-1, NPR-2, OCR-4, OSM-9, PDFR-1, TRPA-1, TYRA-3</td><td>Glutamate</td><td>+ (InSe) OLQVL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>OLQVR</td><td>interneuron, sensory</td><td>NPR-1, NPR-2, OCR-4, OSM-9, PDFR-1, TRPA-1, TYRA-3</td><td>Glutamate</td><td>+ (InSe) OLQVR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>PDA</td><td>motor</td><td>DOP-2, EXP-1, SER-2, UNC-8</td><td>Acetylcholine</td><td>+ (Mo) PDA</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>PDB</td><td>interneuron, motor</td><td>UNC-8</td><td></td><td>? (MoIn) PDB</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>PDEL</td><td>sensory</td><td>DOP-2</td><td>Dopamine</td><td>+ (Se) PDEL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>PDER</td><td>sensory</td><td>DOP-2</td><td>Dopamine</td><td>+ (Se) PDER</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>PHAL</td><td>sensory</td><td>GCY-12, NPR-1, NPR-5, OCR-2, OSM-9, PDFR-1, SER-3, SRB-6, SRG-13</td><td>Glutamate</td><td>+ (Se) PHAL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>PHAR</td><td>sensory</td><td>GCY-12, NPR-1, NPR-5, OCR-2, OSM-9, PDFR-1, SER-3, SRB-6, SRG-13</td><td>Glutamate</td><td>+ (Se) PHAR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>PHBL</td><td>sensory</td><td>NPR-1, NPR-5, OCR-2, OSM-9, PDFR-1, SER-3, SRB-6</td><td>Glutamate, Serotonin</td><td>+ (Se) PHBL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>PHBR</td><td>sensory</td><td>NPR-1, NPR-5, OCR-2, OSM-9, PDFR-1, SER-3, SRB-6</td><td>Glutamate, Serotonin</td><td>+ (Se) PHBR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>PHCL</td><td>sensory</td><td>DOP-1</td><td>Glutamate</td><td>+ (Se) PHCL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>PHCR</td><td>sensory</td><td>DOP-1</td><td>Glutamate</td><td>+ (Se) PHCR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>PLML</td><td>sensory</td><td>DEG-3, DES-2, DOP-1, GLR-8, MEC-2, MEC-4, MEC-6, MEC-9, PDFR-1</td><td>Glutamate</td><td>+ (Se) PLML</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>PLMR</td><td>sensory</td><td>DEG-3, DES-2, DOP-1, GLR-8, MEC-2, MEC-4, MEC-6, MEC-9, PDFR-1</td><td>Glutamate</td><td>+ (Se) PLMR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>PLNL</td><td>interneuron, sensory</td><td>DOP-1</td><td>Acetylcholine</td><td>+ (InSe) PLNL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>PLNR</td><td>interneuron, sensory</td><td>DOP-1</td><td>Acetylcholine</td><td>+ (InSe) PLNR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>PQR</td><td>sensory</td><td>DOP-4, GCY-32, GCY-35, NPR-1, NPR-17, NPR-4, NTR-1, NTR-2, PDFR-1</td><td>Glutamate</td><td>+ (Se) PQR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>PVCL</td><td>interneuron</td><td>PDFR-1, SER-2</td><td>Acetylcholine</td><td>+ (In) PVCL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>PVCR</td><td>interneuron</td><td>PDFR-1, SER-2</td><td>Acetylcholine</td><td>+ (In) PVCR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>PVDL</td><td>sensory</td><td>DEG-3, DES-2, DOP-1, DOP-3, GLR-4, LGC-53, MEC-10, MEC-6, MEC-9, NPR-2, OSM-9, SER-2, TRPA-1, TYRA-2</td><td>Glutamate</td><td>+ (Se) PVDL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>PVDR</td><td>sensory</td><td>DEG-3, DES-2, DOP-1, DOP-3, GLR-4, LGC-53, MEC-10, MEC-6, MEC-9, NPR-2, OSM-9, SER-2, TRPA-1, TYRA-2</td><td>Glutamate</td><td>+ (Se) PVDR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>PVM</td><td>sensory</td><td>FRPR-4, GAR-1, MEC-10, MEC-2, MEC-4, MEC-6, MEC-9, PDFR-1, UNC-8</td><td></td><td>? (Se) PVM</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>PVNL</td><td>interneuron, motor</td><td></td><td></td><td>? (MoIn) PVNL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>PVNR</td><td>interneuron, motor</td><td></td><td></td><td>? (MoIn) PVNR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>PVPL</td><td>interneuron</td><td>NPR-17, NTR-2</td><td>Acetylcholine</td><td>+ (In) PVPL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>PVPR</td><td>interneuron</td><td>NPR-17, NTR-2</td><td>Acetylcholine</td><td>+ (In) PVPR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>PVQL</td><td>interneuron</td><td>DOP-1, GGR-1, GLR-1, GLR-5, NPR-17, NPR-2, NTR-1, NTR-2, PDFR-1, SER-1, SER-3, SRA-6</td><td>Glutamate</td><td>+ (In) PVQL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>PVQR</td><td>interneuron</td><td>DOP-1, GGR-1, GLR-1, GLR-5, NPR-17, NPR-2, NTR-1, NTR-2, PDFR-1, SER-1, SER-3, SRA-6</td><td>Glutamate</td><td>+ (In) PVQR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>PVR</td><td>interneuron</td><td>NTR-1, NTR-2</td><td>Glutamate</td><td>+ (In) PVR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>PVT</td><td>interneuron</td><td>SER-1, SER-2, SER-4, TYRA-3</td><td></td><td>? (In) PVT</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>PVWL</td><td>interneuron</td><td>NTR-1, NTR-2, PDFR-1</td><td>Acetylcholine</td><td>+ (In) PVWL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>PVWR</td><td>interneuron</td><td>NTR-1, NTR-2, PDFR-1</td><td>Acetylcholine</td><td>+ (In) PVWR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>RIAL</td><td>interneuron</td><td>DOP-2, FRPR-4, SER-1, SER-2</td><td>Glutamate</td><td>+ (In) RIAL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>RIAR</td><td>interneuron</td><td>DOP-2, FRPR-4, SER-1, SER-2</td><td>Glutamate</td><td>+ (In) RIAR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>RIBL</td><td>interneuron</td><td>DOP-1, SER-4</td><td></td><td>? (In) RIBL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>RIBR</td><td>interneuron</td><td>DOP-1, SER-4</td><td></td><td>? (In) RIBR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>RICL</td><td>interneuron</td><td>DOP-3, MOD-1, NTR-1, SER-1, SER-2, SER-6</td><td>Octopamine</td><td>+ (In) RICL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>RICR</td><td>interneuron</td><td>DOP-3, MOD-1, NTR-1, SER-1, SER-2, SER-6</td><td>Octopamine</td><td>+ (In) RICR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>RID</td><td>interneuron, motor</td><td>DOP-2, MOD-1, SER-2</td><td></td><td>? (MoIn) RID</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>RIFL</td><td>interneuron</td><td>NTR-2, PDFR-1</td><td></td><td>? (In) RIFL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>RIFR</td><td>interneuron</td><td>NTR-2, PDFR-1</td><td></td><td>? (In) RIFR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>RIGL</td><td>interneuron</td><td>NPR-1</td><td>Glutamate</td><td>+ (In) RIGL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>RIGR</td><td>interneuron</td><td>NPR-1</td><td>Glutamate</td><td>+ (In) RIGR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>RIH</td><td>interneuron</td><td></td><td>Serotonin</td><td>+ (In) RIH</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>RIML</td><td>interneuron, motor</td><td>DOP-1, MOD-1, SER-4</td><td>Acetylcholine, Glutamate, Tyramine</td><td>+ (MoIn) RIML</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>RIMR</td><td>interneuron, motor</td><td>DOP-1, MOD-1, SER-4</td><td>Acetylcholine, Glutamate, Tyramine</td><td>+ (MoIn) RIMR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>RIPL</td><td>interneuron</td><td></td><td></td><td>? (In) RIPL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>RIPR</td><td>interneuron</td><td></td><td></td><td>? (In) RIPR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>RIR</td><td>interneuron</td><td></td><td></td><td>? (In) RIR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>RIS</td><td>interneuron</td><td>DOP-1, GLR-1, SER-4</td><td>GABA</td><td>- (In) RIS</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>RIVL</td><td>interneuron, motor</td><td>NPR-1, NPR-4</td><td></td><td>? (MoIn) RIVL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>RIVR</td><td>interneuron, motor</td><td>NPR-1, NPR-4</td><td></td><td>? (MoIn) RIVR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>RMDDL</td><td>motor</td><td>GLR-1, LGC-55, SER-1</td><td>Acetylcholine</td><td>+ (Mo) RMDDL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>RMDDR</td><td>motor</td><td>GLR-1, LGC-55, SER-1</td><td>Acetylcholine</td><td>+ (Mo) RMDDR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>RMDL</td><td>motor</td><td>GLR-1, LGC-55, SER-1</td><td>Acetylcholine</td><td>+ (Mo) RMDL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>RMDR</td><td>motor</td><td>GLR-1, LGC-55, SER-1</td><td>Acetylcholine</td><td>+ (Mo) RMDR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>RMDVL</td><td>motor</td><td>GLR-1, LGC-55, SER-1</td><td>Acetylcholine</td><td>+ (Mo) RMDVL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>RMDVR</td><td>motor</td><td>GLR-1, LGC-55, SER-1</td><td>Acetylcholine</td><td>+ (Mo) RMDVR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>RMED</td><td>motor</td><td>AVR-15, GLR-1, MOD-1, NTR-2, PDFR-1, SER-2</td><td>GABA</td><td>- (Mo) RMED</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>RMEL</td><td>motor</td><td>AVR-15, GLR-1, MOD-1, NTR-2, PDFR-1, SER-2</td><td>GABA</td><td>- (Mo) RMEL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>RMER</td><td>motor</td><td>AVR-15, GLR-1, MOD-1, NTR-2, PDFR-1, SER-2</td><td>GABA</td><td>- (Mo) RMER</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>RMEV</td><td>motor</td><td>AVR-15, GLR-1, MOD-1, NTR-2, PDFR-1, SER-2</td><td>GABA</td><td>- (Mo) RMEV</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>RMFL</td><td>motor</td><td>SER-1</td><td></td><td>? (Mo) RMFL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>RMFR</td><td>motor</td><td>SER-1</td><td></td><td>? (Mo) RMFR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>RMGL</td><td>interneuron</td><td>NPR-1</td><td></td><td>? (In) RMGL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>RMGR</td><td>interneuron</td><td>NPR-1</td><td></td><td>? (In) RMGR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>RMHL</td><td>motor</td><td>SER-1</td><td></td><td>? (Mo) RMHL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>RMHR</td><td>motor</td><td>SER-1</td><td></td><td>? (Mo) RMHR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SAADL</td><td>interneuron, motor</td><td>NPR-1</td><td>Acetylcholine</td><td>+ (MoIn) SAADL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SAADR</td><td>interneuron, motor</td><td>NPR-1</td><td>Acetylcholine</td><td>+ (MoIn) SAADR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SAAVL</td><td>interneuron, motor</td><td></td><td>Acetylcholine</td><td>+ (MoIn) SAAVL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SAAVR</td><td>interneuron, motor</td><td></td><td>Acetylcholine</td><td>+ (MoIn) SAAVR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SABD</td><td>interneuron, motor</td><td>NPR-2, SER-2</td><td>Acetylcholine</td><td>+ (MoIn) SABD</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SABVL</td><td>interneuron, motor</td><td>NPR-2, SER-2</td><td>Acetylcholine</td><td>+ (MoIn) SABVL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SABVR</td><td>interneuron, motor</td><td>NPR-2, SER-2</td><td>Acetylcholine</td><td>+ (MoIn) SABVR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SDQL</td><td>interneuron, sensory</td><td>EGL-6, LGC-55, NPR-1, SER-2, TYRA-3</td><td>Acetylcholine</td><td>+ (InSe) SDQL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>SDQR</td><td>interneuron, sensory</td><td>EGL-6, LGC-55, NPR-1, SER-2, TYRA-3</td><td>Acetylcholine</td><td>+ (InSe) SDQR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>SIADL</td><td>interneuron, motor</td><td>DOP-2, DOP-3, SER-2, SER-3, SER-6</td><td>Acetylcholine</td><td>+ (MoIn) SIADL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SIADR</td><td>interneuron, motor</td><td>DOP-2, DOP-3, SER-2, SER-3, SER-6</td><td>Acetylcholine</td><td>+ (MoIn) SIADR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SIAVL</td><td>interneuron, motor</td><td>DOP-2, DOP-3, SER-2, SER-3, SER-6</td><td>Acetylcholine</td><td>+ (MoIn) SIAVL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SIAVR</td><td>interneuron, motor</td><td>DOP-2, DOP-3, SER-2, SER-3, SER-6</td><td>Acetylcholine</td><td>+ (MoIn) SIAVR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SIBDL</td><td>interneuron, motor</td><td>DOP-2</td><td>Acetylcholine</td><td>+ (MoIn) SIBDL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SIBDR</td><td>interneuron, motor</td><td>DOP-2</td><td>Acetylcholine</td><td>+ (MoIn) SIBDR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SIBVL</td><td>interneuron, motor</td><td>DOP-2</td><td>Acetylcholine</td><td>+ (MoIn) SIBVL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SIBVR</td><td>interneuron, motor</td><td>DOP-2</td><td>Acetylcholine</td><td>+ (MoIn) SIBVR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SMBDL</td><td>motor</td><td>NPR-1</td><td>Acetylcholine</td><td>+ (Mo) SMBDL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SMBDR</td><td>motor</td><td>NPR-1</td><td>Acetylcholine</td><td>+ (Mo) SMBDR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SMBVL</td><td>motor</td><td></td><td>Acetylcholine</td><td>+ (Mo) SMBVL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SMBVR</td><td>motor</td><td></td><td>Acetylcholine</td><td>+ (Mo) SMBVR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SMDDL</td><td>motor</td><td>LGC-55, NTR-2</td><td>Acetylcholine</td><td>+ (Mo) SMDDL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SMDDR</td><td>motor</td><td>LGC-55, NTR-2</td><td>Acetylcholine</td><td>+ (Mo) SMDDR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SMDVL</td><td>motor</td><td>LGC-55, NTR-2</td><td>Acetylcholine</td><td>+ (Mo) SMDVL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>SMDVR</td><td>motor</td><td>LGC-55, NTR-2</td><td>Acetylcholine</td><td>+ (Mo) SMDVR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>URADL</td><td>motor, sensory</td><td></td><td>Acetylcholine</td><td>+ (MoSe) URADL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>URADR</td><td>motor, sensory</td><td></td><td>Acetylcholine</td><td>+ (MoSe) URADR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>URAVL</td><td>motor, sensory</td><td></td><td>Acetylcholine</td><td>+ (MoSe) URAVL</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>URAVR</td><td>motor, sensory</td><td></td><td>Acetylcholine</td><td>+ (MoSe) URAVR</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>URBL</td><td>interneuron</td><td></td><td>Acetylcholine</td><td>+ (In) URBL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>URBR</td><td>interneuron</td><td></td><td>Acetylcholine</td><td>+ (In) URBR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>URXL</td><td>interneuron, sensory</td><td>GCY-1, GCY-25, GCY-32, GCY-34, GCY-35, GCY-36, GCY-37, NPR-1, PDFR-1, SRA-10</td><td></td><td>? (InSe) URXL</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>URXR</td><td>interneuron, sensory</td><td>GCY-1, GCY-25, GCY-32, GCY-34, GCY-35, GCY-36, GCY-37, NPR-1, PDFR-1, SRA-10</td><td></td><td>? (InSe) URXR</td><td>Colour: 1 0 .4</td></tr>
+<tr>
+<td>URYDL</td><td>sensory</td><td>LGC-53, PDFR-1, SER-1</td><td>Glutamate</td><td>+ (Se) URYDL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>URYDR</td><td>sensory</td><td>LGC-53, PDFR-1, SER-1</td><td>Glutamate</td><td>+ (Se) URYDR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>URYVL</td><td>sensory</td><td>LGC-53, PDFR-1, SER-1</td><td>Glutamate</td><td>+ (Se) URYVL</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>URYVR</td><td>sensory</td><td>LGC-53, PDFR-1, SER-1</td><td>Glutamate</td><td>+ (Se) URYVR</td><td>Colour: 1 .2 1</td></tr>
+<tr>
+<td>VA1</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, LGC-53, NPR-3</td><td>Acetylcholine</td><td>+ (Mo) VA1</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VA10</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, LGC-53, NPR-3</td><td>Acetylcholine</td><td>+ (Mo) VA10</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VA11</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, LGC-53, NPR-3</td><td>Acetylcholine</td><td>+ (Mo) VA11</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VA12</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, LGC-53, NPR-3</td><td>Acetylcholine</td><td>+ (Mo) VA12</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VA2</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, LGC-53, NPR-3</td><td>Acetylcholine</td><td>+ (Mo) VA2</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VA3</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, LGC-53, NPR-3</td><td>Acetylcholine</td><td>+ (Mo) VA3</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VA4</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, LGC-53, NPR-3</td><td>Acetylcholine</td><td>+ (Mo) VA4</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VA5</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, LGC-53, NPR-3</td><td>Acetylcholine</td><td>+ (Mo) VA5</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VA6</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, LGC-53, NPR-3</td><td>Acetylcholine</td><td>+ (Mo) VA6</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VA7</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, LGC-53, NPR-3</td><td>Acetylcholine</td><td>+ (Mo) VA7</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VA8</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, LGC-53, NPR-3</td><td>Acetylcholine</td><td>+ (Mo) VA8</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VA9</td><td>motor</td><td>CKR-2, DOP-1, DOP-3, LGC-53, NPR-3</td><td>Acetylcholine</td><td>+ (Mo) VA9</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VB1</td><td>motor, sensory</td><td>CKR-2, DOP-1, DOP-3, NPR-3</td><td>Acetylcholine</td><td>+ (MoSe) VB1</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VB10</td><td>motor, sensory</td><td>CKR-2, DOP-1, DOP-3, NPR-3</td><td>Acetylcholine</td><td>+ (MoSe) VB10</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VB11</td><td>motor, sensory</td><td>CKR-2, DOP-1, DOP-3, NPR-3</td><td>Acetylcholine</td><td>+ (MoSe) VB11</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VB2</td><td>motor, sensory</td><td>CKR-2, DOP-1, DOP-3, NPR-3</td><td>Acetylcholine</td><td>+ (MoSe) VB2</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VB3</td><td>motor, sensory</td><td>CKR-2, DOP-1, DOP-3, NPR-3</td><td>Acetylcholine</td><td>+ (MoSe) VB3</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VB4</td><td>motor, sensory</td><td>CKR-2, DOP-1, DOP-3, NPR-3</td><td>Acetylcholine</td><td>+ (MoSe) VB4</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VB5</td><td>motor, sensory</td><td>CKR-2, DOP-1, DOP-3, NPR-3</td><td>Acetylcholine</td><td>+ (MoSe) VB5</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VB6</td><td>motor, sensory</td><td>CKR-2, DOP-1, DOP-3, NPR-3</td><td>Acetylcholine</td><td>+ (MoSe) VB6</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VB7</td><td>motor, sensory</td><td>CKR-2, DOP-1, DOP-3, NPR-3</td><td>Acetylcholine</td><td>+ (MoSe) VB7</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VB8</td><td>motor, sensory</td><td>CKR-2, DOP-1, DOP-3, NPR-3</td><td>Acetylcholine</td><td>+ (MoSe) VB8</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VB9</td><td>motor, sensory</td><td>CKR-2, DOP-1, DOP-3, NPR-3</td><td>Acetylcholine</td><td>+ (MoSe) VB9</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VC1</td><td>motor</td><td>GLR-5</td><td>Acetylcholine</td><td>+ (Mo) VC1</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VC2</td><td>motor</td><td>GLR-5</td><td>Acetylcholine</td><td>+ (Mo) VC2</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VC3</td><td>motor</td><td>GLR-5</td><td>Acetylcholine</td><td>+ (Mo) VC3</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VC4</td><td>motor</td><td>GLR-5</td><td>Acetylcholine, Serotonin</td><td>+ (Mo) VC4</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VC5</td><td>motor</td><td>GLR-5</td><td>Acetylcholine, Serotonin</td><td>+ (Mo) VC5</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VD1</td><td>motor</td><td>DOP-3, MOD-1, NPR-1, SER-2</td><td>GABA</td><td>- (Mo) VD1</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VD10</td><td>motor</td><td>DOP-3, MOD-1, NPR-1, SER-2</td><td>GABA</td><td>- (Mo) VD10</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VD11</td><td>motor</td><td>DOP-3, MOD-1, NPR-1, SER-2</td><td>GABA</td><td>- (Mo) VD11</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VD12</td><td>motor</td><td>DOP-3, MOD-1, NPR-1, SER-2</td><td>GABA</td><td>- (Mo) VD12</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VD13</td><td>motor</td><td>DOP-3, MOD-1, NPR-1, SER-2</td><td>GABA</td><td>- (Mo) VD13</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VD2</td><td>motor</td><td>DOP-3, MOD-1, NPR-1, SER-2</td><td>GABA</td><td>- (Mo) VD2</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VD3</td><td>motor</td><td>DOP-3, MOD-1, NPR-1, SER-2</td><td>GABA</td><td>- (Mo) VD3</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VD4</td><td>motor</td><td>DOP-3, MOD-1, NPR-1, SER-2</td><td>GABA</td><td>- (Mo) VD4</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VD5</td><td>motor</td><td>DOP-3, MOD-1, NPR-1, SER-2</td><td>GABA</td><td>- (Mo) VD5</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VD6</td><td>motor</td><td>DOP-3, MOD-1, NPR-1, SER-2</td><td>GABA</td><td>- (Mo) VD6</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VD7</td><td>motor</td><td>DOP-3, MOD-1, NPR-1, SER-2</td><td>GABA</td><td>- (Mo) VD7</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VD8</td><td>motor</td><td>DOP-3, MOD-1, NPR-1, SER-2</td><td>GABA</td><td>- (Mo) VD8</td><td>Colour: .5 .4 1</td></tr>
+<tr>
+<td>VD9</td><td>motor</td><td>DOP-3, MOD-1, NPR-1, SER-2</td><td>GABA</td><td>- (Mo) VD9</td><td>Colour: .5 .4 1</td></tr>
+</table>
+### Muscles (95)
+<table>
+<tr>
+<td>DL1</td><td></td><td></td><td></td><td>? (Mu) DL1</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL2</td><td></td><td></td><td></td><td>? (Mu) DL2</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL3</td><td></td><td></td><td></td><td>? (Mu) DL3</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL4</td><td></td><td></td><td></td><td>? (Mu) DL4</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL5</td><td></td><td></td><td></td><td>? (Mu) DL5</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL6</td><td></td><td></td><td></td><td>? (Mu) DL6</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL7</td><td></td><td></td><td></td><td>? (Mu) DL7</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL8</td><td></td><td></td><td></td><td>? (Mu) DL8</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL9</td><td></td><td></td><td></td><td>? (Mu) DL9</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL10</td><td></td><td></td><td></td><td>? (Mu) DL10</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL11</td><td></td><td></td><td></td><td>? (Mu) DL11</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL12</td><td></td><td></td><td></td><td>? (Mu) DL12</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL13</td><td></td><td></td><td></td><td>? (Mu) DL13</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL14</td><td></td><td></td><td></td><td>? (Mu) DL14</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL15</td><td></td><td></td><td></td><td>? (Mu) DL15</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL16</td><td></td><td></td><td></td><td>? (Mu) DL16</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL17</td><td></td><td></td><td></td><td>? (Mu) DL17</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL18</td><td></td><td></td><td></td><td>? (Mu) DL18</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL19</td><td></td><td></td><td></td><td>? (Mu) DL19</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL20</td><td></td><td></td><td></td><td>? (Mu) DL20</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL21</td><td></td><td></td><td></td><td>? (Mu) DL21</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL22</td><td></td><td></td><td></td><td>? (Mu) DL22</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL23</td><td></td><td></td><td></td><td>? (Mu) DL23</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DL24</td><td></td><td></td><td></td><td>? (Mu) DL24</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR1</td><td></td><td></td><td></td><td>? (Mu) DR1</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR2</td><td></td><td></td><td></td><td>? (Mu) DR2</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR3</td><td></td><td></td><td></td><td>? (Mu) DR3</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR4</td><td></td><td></td><td></td><td>? (Mu) DR4</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR5</td><td></td><td></td><td></td><td>? (Mu) DR5</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR6</td><td></td><td></td><td></td><td>? (Mu) DR6</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR7</td><td></td><td></td><td></td><td>? (Mu) DR7</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR8</td><td></td><td></td><td></td><td>? (Mu) DR8</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR9</td><td></td><td></td><td></td><td>? (Mu) DR9</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR10</td><td></td><td></td><td></td><td>? (Mu) DR10</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR11</td><td></td><td></td><td></td><td>? (Mu) DR11</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR12</td><td></td><td></td><td></td><td>? (Mu) DR12</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR13</td><td></td><td></td><td></td><td>? (Mu) DR13</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR14</td><td></td><td></td><td></td><td>? (Mu) DR14</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR15</td><td></td><td></td><td></td><td>? (Mu) DR15</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR16</td><td></td><td></td><td></td><td>? (Mu) DR16</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR17</td><td></td><td></td><td></td><td>? (Mu) DR17</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR18</td><td></td><td></td><td></td><td>? (Mu) DR18</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR19</td><td></td><td></td><td></td><td>? (Mu) DR19</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR20</td><td></td><td></td><td></td><td>? (Mu) DR20</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR21</td><td></td><td></td><td></td><td>? (Mu) DR21</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR22</td><td></td><td></td><td></td><td>? (Mu) DR22</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR23</td><td></td><td></td><td></td><td>? (Mu) DR23</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>DR24</td><td></td><td></td><td></td><td>? (Mu) DR24</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL1</td><td></td><td></td><td></td><td>? (Mu) VL1</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL2</td><td></td><td></td><td></td><td>? (Mu) VL2</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL3</td><td></td><td></td><td></td><td>? (Mu) VL3</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL4</td><td></td><td></td><td></td><td>? (Mu) VL4</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL5</td><td></td><td></td><td></td><td>? (Mu) VL5</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL6</td><td></td><td></td><td></td><td>? (Mu) VL6</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL7</td><td></td><td></td><td></td><td>? (Mu) VL7</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL8</td><td></td><td></td><td></td><td>? (Mu) VL8</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL9</td><td></td><td></td><td></td><td>? (Mu) VL9</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL10</td><td></td><td></td><td></td><td>? (Mu) VL10</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL11</td><td></td><td></td><td></td><td>? (Mu) VL11</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL12</td><td></td><td></td><td></td><td>? (Mu) VL12</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL13</td><td></td><td></td><td></td><td>? (Mu) VL13</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL14</td><td></td><td></td><td></td><td>? (Mu) VL14</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL15</td><td></td><td></td><td></td><td>? (Mu) VL15</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL16</td><td></td><td></td><td></td><td>? (Mu) VL16</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL17</td><td></td><td></td><td></td><td>? (Mu) VL17</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL18</td><td></td><td></td><td></td><td>? (Mu) VL18</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL19</td><td></td><td></td><td></td><td>? (Mu) VL19</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL20</td><td></td><td></td><td></td><td>? (Mu) VL20</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL21</td><td></td><td></td><td></td><td>? (Mu) VL21</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL22</td><td></td><td></td><td></td><td>? (Mu) VL22</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VL23</td><td></td><td></td><td></td><td>? (Mu) VL23</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR1</td><td></td><td></td><td></td><td>? (Mu) VR1</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR2</td><td></td><td></td><td></td><td>? (Mu) VR2</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR3</td><td></td><td></td><td></td><td>? (Mu) VR3</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR4</td><td></td><td></td><td></td><td>? (Mu) VR4</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR5</td><td></td><td></td><td></td><td>? (Mu) VR5</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR6</td><td></td><td></td><td></td><td>? (Mu) VR6</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR7</td><td></td><td></td><td></td><td>? (Mu) VR7</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR8</td><td></td><td></td><td></td><td>? (Mu) VR8</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR9</td><td></td><td></td><td></td><td>? (Mu) VR9</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR10</td><td></td><td></td><td></td><td>? (Mu) VR10</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR11</td><td></td><td></td><td></td><td>? (Mu) VR11</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR12</td><td></td><td></td><td></td><td>? (Mu) VR12</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR13</td><td></td><td></td><td></td><td>? (Mu) VR13</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR14</td><td></td><td></td><td></td><td>? (Mu) VR14</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR15</td><td></td><td></td><td></td><td>? (Mu) VR15</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR16</td><td></td><td></td><td></td><td>? (Mu) VR16</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR17</td><td></td><td></td><td></td><td>? (Mu) VR17</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR18</td><td></td><td></td><td></td><td>? (Mu) VR18</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR19</td><td></td><td></td><td></td><td>? (Mu) VR19</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR20</td><td></td><td></td><td></td><td>? (Mu) VR20</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR21</td><td></td><td></td><td></td><td>? (Mu) VR21</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR22</td><td></td><td></td><td></td><td>? (Mu) VR22</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR23</td><td></td><td></td><td></td><td>? (Mu) VR23</td><td>Colour: 0 0.6 0</td></tr>
+<tr>
+<td>VR24</td><td></td><td></td><td></td><td>? (Mu) VR24</td><td>Colour: 0 0.6 0</td></tr>
+</table>
diff --git a/setup.py b/setup.py
index d62fa0f6..e0a8bb75 100644
--- a/setup.py
+++ b/setup.py
@@ -26,7 +26,8 @@
         'xlwt',
         'libNeuroML>=0.2.39',
         'pyNeuroML>=0.3.11',
-        'pyopenworm>=0.10.0'
+        'owmeta_core>=0.13.0',
+        'owmeta'
     ],
     entry_points={
         'console_scripts': ['c302 = c302.__init__:main']},
@@ -45,7 +46,7 @@
         'License :: OSI Approved :: MIT License',
         'Natural Language :: English',
         'Operating System :: OS Independent',
-        'Programming Language :: Python :: 2.7',
+        'Programming Language :: Python :: 3',
         'Topic :: Scientific/Engineering'
     ]
 )


Test patch:
diff --git a/test.sh b/test.sh
index b46abcab..3079e643 100755
--- a/test.sh
+++ b/test.sh
@@ -1,4 +1,4 @@
-set -e
+set -ex
 
 ##   Install
 
@@ -6,80 +6,80 @@ python setup.py install
 
 ##   Test readers
 
-python c302/SpreadsheetDataReader.py 
-python c302/UpdatedSpreadsheetDataReader.py                                                                                                                                                                      
-python c302/UpdatedSpreadsheetDataReader2.py                                                                                                                                                                  
-python c302/OpenWormReader.py 
+python -m c302.SpreadsheetDataReader 
+python -m c302.UpdatedSpreadsheetDataReader                                                                                                                                                                      
+python -m c302.UpdatedSpreadsheetDataReader2                                                                                                                                                                  
+python -m c302.OpenWormReader 
 
 
 ##   (Re)generate NeuroML 2 & LEMS files from the python scripts
 
-python c302/c302_IClamp.py A
-python c302/c302_Syns.py A
-python c302/c302_Social.py A
-python c302/c302_Pharyngeal.py A
-python c302/c302_Full.py A
-python c302/c302_Muscles.py A
-python c302/c302_Oscillator.py A
-
-
-python c302/c302_IClamp.py B
-python c302/c302_Syns.py B
-python c302/c302_Social.py B
-python c302/c302_Pharyngeal.py B
-python c302/c302_Full.py B
-python c302/c302_Muscles.py B
-python c302/c302_Oscillator.py B
-
-
-python c302/c302_IClamp.py C
-python c302/c302_Syns.py C
-python c302/c302_Social.py C
-python c302/c302_Pharyngeal.py C
-python c302/c302_Full.py C
-python c302/c302_Muscles.py C
-python c302/c302_Oscillator.py C
-
-python c302/c302_IClamp.py C0
-python c302/c302_Syns.py C0
-python c302/c302_Social.py C0
-python c302/c302_Pharyngeal.py C0
-python c302/c302_Full.py C0
-python c302/c302_Muscles.py C0
-python c302/c302_Oscillator.py C0
-
-python c302/c302_IClamp.py C1
-python c302/c302_Syns.py C1
-python c302/c302_Social.py C1
-python c302/c302_Pharyngeal.py C1
-python c302/c302_Full.py C1
-python c302/c302_Muscles.py C1
-python c302/c302_Oscillator.py C1
-
-python c302/c302_IClamp.py C2
-python c302/c302_Syns.py C2
-python c302/c302_Social.py C2
-python c302/c302_Pharyngeal.py C2
-python c302/c302_Full.py C2
-python c302/c302_Muscles.py C2
-python c302/c302_Oscillator.py C2
-python c302/c302_FW.py C2
-
-python c302/c302_IClamp.py D
-python c302/c302_Syns.py D
-python c302/c302_Social.py D
-python c302/c302_Pharyngeal.py D
-python c302/c302_Full.py D
-python c302/c302_Muscles.py D
-python c302/c302_Oscillator.py D
-
-python c302/c302_IClamp.py D1
-python c302/c302_Syns.py D1
-python c302/c302_Social.py D1
-python c302/c302_Pharyngeal.py D1
-python c302/c302_Full.py D1
-python c302/c302_Muscles.py D1
-python c302/c302_Oscillator.py D1
+python -m c302.c302_IClamp A
+python -m c302.c302_Syns A
+python -m c302.c302_Social A
+python -m c302.c302_Pharyngeal A
+python -m c302.c302_Full A
+python -m c302.c302_Muscles A
+python -m c302.c302_Oscillator A
+
+
+python -m c302.c302_IClamp B
+python -m c302.c302_Syns B
+python -m c302.c302_Social B
+python -m c302.c302_Pharyngeal B
+python -m c302.c302_Full B
+python -m c302.c302_Muscles B
+python -m c302.c302_Oscillator B
+
+
+python -m c302.c302_IClamp C
+python -m c302.c302_Syns C
+python -m c302.c302_Social C
+python -m c302.c302_Pharyngeal C
+python -m c302.c302_Full C
+python -m c302.c302_Muscles C
+python -m c302.c302_Oscillator C
+
+python -m c302.c302_IClamp C0
+python -m c302.c302_Syns C0
+python -m c302.c302_Social C0
+python -m c302.c302_Pharyngeal C0
+python -m c302.c302_Full C0
+python -m c302.c302_Muscles C0
+python -m c302.c302_Oscillator C0
+
+python -m c302.c302_IClamp C1
+python -m c302.c302_Syns C1
+python -m c302.c302_Social C1
+python -m c302.c302_Pharyngeal C1
+python -m c302.c302_Full C1
+python -m c302.c302_Muscles C1
+python -m c302.c302_Oscillator C1
+
+python -m c302.c302_IClamp C2
+python -m c302.c302_Syns C2
+python -m c302.c302_Social C2
+python -m c302.c302_Pharyngeal C2
+python -m c302.c302_Full C2
+python -m c302.c302_Muscles C2
+python -m c302.c302_Oscillator C2
+python -m c302.c302_FW C2
+
+python -m c302.c302_IClamp D
+python -m c302.c302_Syns D
+python -m c302.c302_Social D
+python -m c302.c302_Pharyngeal D
+python -m c302.c302_Full D
+python -m c302.c302_Muscles D
+python -m c302.c302_Oscillator D
+
+python -m c302.c302_IClamp D1
+python -m c302.c302_Syns D1
+python -m c302.c302_Social D1
+python -m c302.c302_Pharyngeal D1
+python -m c302.c302_Full D1
+python -m c302.c302_Muscles D1
+python -m c302.c302_Oscillator D1
 
 cd examples
 
@@ -124,15 +124,15 @@ cd ..
 
 c302 MyNetwork parameters_C -cells ["AVBR","VD3"] -cellstostimulate ["AVBR"] -paramoverride {"unphysiological_offset_current":"2.9pA"} -duration 300
 
-python  c302/__init__.py c302_A_Syns2 parameters_A -cells ["ADAL","AIBL","RIVR","RMEV"] -cellstostimulate ["ADAL","RIVR"] -duration 500 -dt 0.1 -vmin -72 -vmax -48
+c302 c302_A_Syns2 parameters_A -cells ["ADAL","AIBL","RIVR","RMEV"] -cellstostimulate ["ADAL","RIVR"] -duration 500 -dt 0.1 -vmin -72 -vmax -48
 
-python  c302/__init__.py c302_A_Weights parameters_A -cells ["ADAL","AIBL","I1L","I3","DB5","PVCR"] -cellstostimulate ["ADAL","I1L","PVCR"] -connnumberoverride=["I1L-I3":2.5] -connnumberscaling=["PVCR-DB5":5] -duration 500 -dt 0.1 -vmin -72 -vmax -48
+c302 c302_A_Weights parameters_A -cells ["ADAL","AIBL","I1L","I3","DB5","PVCR"] -cellstostimulate ["ADAL","I1L","PVCR"] -connnumberoverride=["I1L-I3":2.5] -connnumberscaling=["PVCR-DB5":5] -duration 500 -dt 0.1 -vmin -72 -vmax -48
 
-python  c302/__init__.py c302_C1_Test parameters_C1 -cellstostimulate AFDL -connnumberscaling {"I1L-I3":2}
+c302 c302_C1_Test parameters_C1 -cellstostimulate AFDL -connnumberscaling {"I1L-I3":2}
 
 mkdir -p cells
 
-python  c302/__init__.py c302_D1_Weights parameters_D1 -cells ["ADAL","AIBL","I1L","I3","DB5","PVCR"] -cellstostimulate ["ADAL","I1L","PVCR"] -connnumberoverride=["I1L-I3":2.5] -connnumberscaling=["PVCR-DB5":5] -duration 500 -dt 0.1
+c302 c302_D1_Weights parameters_D1 -cells ["ADAL","AIBL","I1L","I3","DB5","PVCR"] -cellstostimulate ["ADAL","I1L","PVCR"] -connnumberoverride=["I1L-I3":2.5] -connnumberscaling=["PVCR-DB5":5] -duration 500 -dt 0.1
 
 cd examples
 
@@ -147,9 +147,9 @@ cd -
 
 ## Try helper scripts
 
-python c302/runAndPlot.py -test
+python -m c302.runAndPlot -test
 
-python c302/c302_utils.py -nogui
+python -m c302.c302_utils -nogui
 
 echo
 echo "  Successfully completed all c302 tests!"