diff --git a/.github/workflows/non_omv.yml b/.github/workflows/non_omv.yml index 918d6f36..af430558 100644 --- a/.github/workflows/non_omv.yml +++ b/.github/workflows/non_omv.yml @@ -14,7 +14,7 @@ jobs: fail-fast: false matrix: runs-on: [ubuntu-latest, macos-12, macos-latest ] - python-version: [ 3.8, 3.9, "3.10" ] + python-version: [ 3.8, 3.9, "3.10", "3.11" ] exclude: - runs-on: macos-latest python-version: "3.8" @@ -43,7 +43,9 @@ jobs: pip list - name: Test OpenWormReader with owmeta + if: ${{ matrix.python-version != '3.11' }} run: | + pip install owmeta>=0.12.3 owm bundle remote --user add ow 'https://raw.githubusercontent.com/openworm/owmeta-bundles/master/index.json' python -m c302.OpenWormReader diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml new file mode 100644 index 00000000..85cc411b --- /dev/null +++ b/.github/workflows/python-publish.yml @@ -0,0 +1,36 @@ +# This workflow will upload a Python Package using Twine when a release is created +# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Upload Python Package + +on: + release: + types: [published] + +jobs: + deploy: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build + - name: Build package + run: python -m build + - name: Publish package + uses: pypa/gh-action-pypi-publish@release/v1 + with: + user: __token__ + password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/.gitignore b/.gitignore index 8ed29ac6..50673366 100644 --- a/.gitignore +++ b/.gitignore @@ -105,3 +105,4 @@ arm64 /examples/test/images/c302_C1_Pharyngeal.net.nml /examples/test/images/c302_C1_Social.net.nml /examples/test/images/c302_C1_Syns.net.nml +*ken.sh diff --git a/README.md b/README.md index ed4f13ad..ee0e7750 100644 --- a/README.md +++ b/README.md @@ -9,27 +9,33 @@ c302 is a framework for generating network models in NeuroML 2 based on *C. eleg ![c302 structure](https://raw.githubusercontent.com/openworm/CElegansNeuroML/master/CElegans/pythonScripts/c302/images/c302.png) -It uses information on the synaptic connectivity of the network (from [here](https://github.com/openworm/c302/blob/master/c302/data/CElegansNeuronTables.xls)) and uses [libNeuroML](https://github.com/NeuralEnsemble/libNeuroML) to generate a network in valid NeuroML, which can be run in [jNeuroML](https://github.com/NeuroML/jNeuroML) or [pyNeuroML](https://github.com/NeuroML/pyNeuroML). +It uses information on the synaptic connectivity of the network (from [here](https://github.com/openworm/c302/blob/master/c302/data)) and uses [libNeuroML](https://github.com/NeuralEnsemble/libNeuroML) to generate a network in valid NeuroML, which can be run in [jNeuroML](https://github.com/NeuroML/jNeuroML) or [pyNeuroML](https://github.com/NeuroML/pyNeuroML). -**The c302 paper has recently been published!** +**The c302 paper is out!** *c302: a multiscale framework for modelling the nervous system of Caenorhabditis elegans* Padraig Gleeson, David Lung, Radu Grosu, Ramin Hasani, Stephen D. Larson, [Phil. Trans. R. Soc. B 2018 373 20170379](http://rstb.royalsocietypublishing.org/content/373/1758/20170379); DOI: 10.1098/rstb.2017.0379. ### To install & test -The full set of dependencies for c302 can be installed with the following (see also the [Travis-CI script](https://github.com/openworm/c302/blob/master/.travis.yml)): +The full set of dependencies for c302 can be installed with the following (see also the [ci.yml](https://github.com/openworm/c302/blob/master/.github/workflows/ci.yml) and [non_omv.yml](https://github.com/openworm/c302/blob/master/.github/workflows/non_omv.yml) workflow files): - git clone https://github.com/openworm/c302.git - cd c302 - pip install . - owm bundle remote --user add ow 'https://raw.githubusercontent.com/openworm/owmeta-bundles/master/index.json' +```console +git clone https://github.com/openworm/c302.git +cd c302 +pip install . + +# The following can only be run on Mac and Linux. Note: c302 can be run without ownmeta fully installed +owm bundle remote --user add ow 'https://raw.githubusercontent.com/openworm/owmeta-bundles/master/index.json' +``` This will install c302 as well as [pyNeuroML](https://github.com/NeuroML/pyNeuroML) and [owmeta](https://github.com/openworm/owmeta). -To run the test.sh script, the Neuron simulator is also required, and should be installed as described [here](https://www.neuron.yale.edu/neuron/download). +For Windows users a virtual environment must be generated with Python 3.10 as any newer versions do not currently support owmeta. + +To run the test.sh script, the Neuron simulator is also required, and should be installed as described [here](https://www.neuron.yale.edu/neuron/download) (On Mac and Linux it can be installed with `pip install neuron`). -For Linux users, additional dependencies (OpenJDK 19 and Graphviz) are required to run the Usage Examples: +For Linux users, additional dependencies (OpenJDK 19 and Graphviz) are required to run the usage examples: sudo apt-get install openjdk-19-jdk graphviz @@ -81,7 +87,7 @@ Screenshots of a simulation with pyNeuroML of c302_B_Pharyngeal are shown below #### 1b) Run standard examples with Neuron -The models can also be run using the Neuron simulator. This should be installed as outlined [here](https://www.neuron.yale.edu/neuron/download). +The models can also be run using the Neuron simulator. This should be installed as outlined [here](https://www.neuron.yale.edu/neuron/download). Note: running c302 with Neuron is not currently supported on Windows. cd examples pynml LEMS_c302_A_IClamp.xml -neuron # Generate the Neuron files (Python/hoc/mod) diff --git a/c302/CompareMain.py b/c302/CompareMain.py index d4843b6f..bac3fce9 100644 --- a/c302/CompareMain.py +++ b/c302/CompareMain.py @@ -1,11 +1,11 @@ -__author__ = 'Ari' +__author__ = "Ari" from operator import itemgetter import xlrd import os -def comparitor(fName1, fName2): +def comparitor(fName1, fName2): path1 = fName1 path2 = fName2 dir = os.path.dirname(__file__) @@ -28,17 +28,54 @@ def comparitor(fName1, fName2): # Print results. Give number of pairs that are matched, remained from unmatched files, and associated pairs. print("Number of matching pairs: " + str(len(matches[indexName2[0]]))) for p in range(len(matches[indexName2[0]])): - print(str(matches[indexName2[0]][p])+" -> "+str(matches[indexName2[1]][p])+" ("+str(matches[indexName2[2]][p])+", "+str(matches[indexName2[3]][p])+")") - print("\nNumber of pairs unmatched in " + fName1 + " is: " + str(len(col1[indexName2[0]]))) + print( + str(matches[indexName2[0]][p]) + + " -> " + + str(matches[indexName2[1]][p]) + + " (" + + str(matches[indexName2[2]][p]) + + ", " + + str(matches[indexName2[3]][p]) + + ")" + ) + print( + "\nNumber of pairs unmatched in " + + fName1 + + " is: " + + str(len(col1[indexName2[0]])) + ) for p in range(len(col1[indexName2[0]])): - print(str(col1[indexName2[0]][p])+" -> "+str(col1[indexName2[1]][p])+" ("+str(col1[indexName2[2]][p])+", "+str(col1[indexName2[3]][p])+")") - print("\nNumber of pairs unmatched in " + fName2 + " is: " + str(len(col2[indexName1[0]]))) + print( + str(col1[indexName2[0]][p]) + + " -> " + + str(col1[indexName2[1]][p]) + + " (" + + str(col1[indexName2[2]][p]) + + ", " + + str(col1[indexName2[3]][p]) + + ")" + ) + print( + "\nNumber of pairs unmatched in " + + fName2 + + " is: " + + str(len(col2[indexName1[0]])) + ) for p in range(len(col2[indexName1[0]])): - print(str(col2[indexName1[0]][p])+" -> "+str(col2[indexName1[1]][p])+" ("+str(col2[indexName1[2]][p])+", "+str(col2[indexName1[3]][p])+")") + print( + str(col2[indexName1[0]][p]) + + " -> " + + str(col2[indexName1[1]][p]) + + " (" + + str(col2[indexName1[2]][p]) + + ", " + + str(col2[indexName1[3]][p]) + + ")" + ) # Get columns from .txt files -def getColumns(fileIn, delim = "\t", header = True): +def getColumns(fileIn, delim="\t", header=True): cols = {} indexName = {} for lineNum, line in enumerate(fileIn): @@ -63,6 +100,7 @@ def getColumns(fileIn, delim = "\t", header = True): i += 1 return cols, indexName + # Get columns from .xls files def getColumnsXls(fileIn): cols = {} @@ -92,16 +130,19 @@ def getColumnsXls(fileIn): cols[indexName[curr_cell]] += [cell_value] return cols, indexName + # Sort dictionaries by first two column (From/To Neurons), first by one, then the other. def sortTwoColumns(cols): - cols = sorted(cols, key = itemgetter(0,1)) + cols = sorted(cols, key=itemgetter(0, 1)) + # Formatting involved removing any filler zeros from the middle of strings. def formatNames(cols, indexName): for i in range(2): for char in cols[indexName[i]]: - if char[-1] != '0': - char = "".join(char.split("0",1)) + if char[-1] != "0": + char = "".join(char.split("0", 1)) + # Compare two lists, create new list of matching pairs, remove pairs from respective original lists. def matchLists(cols1, cols2, indexName1, indexName2): @@ -134,7 +175,9 @@ def matchLists(cols1, cols2, indexName1, indexName2): if x2 == pair: index2 = p2 # If matches array does not contain current pair from long array, add it - if not zip(matches[indexNames1[0]], matches[indexNames1[1]]).__contains__(([pair[0]],[pair[1]])): + if not zip(matches[indexNames1[0]], matches[indexNames1[1]]).__contains__( + ([pair[0]], [pair[1]]) + ): # print(matches[indexNames1[0]], matches[indexNames1[1]]) for i in range(len(indexNames1)): if col1[indexNames1[i]][index1] == col2[indexNames2[i]][index2]: @@ -144,17 +187,23 @@ def matchLists(cols1, cols2, indexName1, indexName2): del col2[indexNames2[i]][index2] del col1[indexNames1[i]][index1] else: - matches[indexNames1[i]] += [[col1[indexNames1[i]][index1], col2[indexNames2[i]][index2]]] + matches[indexNames1[i]] += [ + [col1[indexNames1[i]][index1], col2[indexNames2[i]][index2]] + ] del col2[indexNames2[i]][index2] del col1[indexNames1[i]][index1] # If pair is already in array, add value from last two columns to array else: - for p3, x3 in enumerate(zip(matches[indexNames1[0]], matches[indexNames1[1]])): + for p3, x3 in enumerate( + zip(matches[indexNames1[0]], matches[indexNames1[1]]) + ): if x3 == ([pair[0]], [pair[1]]): index3 = p3 for i in range(len(indexNames1)): if i > 1: - matches[indexNames1[i]][index3] += [col1[indexNames1[i]][index1]] + matches[indexNames1[i]][index3] += [ + col1[indexNames1[i]][index1] + ] del col1[indexNames1[i]][index1] del col2[indexNames2[i]][index2] @@ -164,8 +213,12 @@ def matchLists(cols1, cols2, indexName1, indexName2): if x1 == pair: index1 = p1 # If matches array does contain current pair from long array, add its conn. type and number - if zip(matches[indexNames1[0]], matches[indexNames1[1]]).__contains__(([pair[0]],[pair[1]])): - for p3, x3 in enumerate(zip(matches[indexNames1[0]], matches[indexNames1[1]])): + if zip(matches[indexNames1[0]], matches[indexNames1[1]]).__contains__( + ([pair[0]], [pair[1]]) + ): + for p3, x3 in enumerate( + zip(matches[indexNames1[0]], matches[indexNames1[1]]) + ): if x3 == ([pair[0]], [pair[1]]): index3 = p3 for i in range(len(indexNames1)): @@ -183,7 +236,9 @@ def matchLists(cols1, cols2, indexName1, indexName2): for p4, x4 in enumerate(zip(matches[indexNames1[0]], matches[indexNames1[1]])): if x4 == ([pair[1]], [pair[0]]): index4 = p4 - if zip(matches[indexNames1[0]], matches[indexNames1[1]]).__contains__(([pair[1]], [pair[0]])): + if zip(matches[indexNames1[0]], matches[indexNames1[1]]).__contains__( + ([pair[1]], [pair[0]]) + ): # print(zip(matches[indexNames1[0]], matches[indexNames1[1]])) # print(([pair[1]], [pair[0]])) for i in range(len(indexNames1)): @@ -193,21 +248,21 @@ def matchLists(cols1, cols2, indexName1, indexName2): matches[indexNames1[i]][index4] += [col1[indexNames1[i]][index1]] del col1[indexNames1[i]][index1] - return matches, col1, col2 + # Option of additional formatting to shorten lists. Not used. Not complete. # 'EJ' maps to 'GapJunction'. # 'R', 'Rp', 'S', 'Sp' map to 'Send'. # 'NMJ' does not map. def typeMapping(cols1, cols2, indexName1, indexName2): - list1 = ['GapJunction','Send'] - list2 = ['EJ','NMJ','R','Rp','S','Sp'] + list1 = ["GapJunction", "Send"] + list2 = ["EJ", "NMJ", "R", "Rp", "S", "Sp"] type1 = cols1[indexName1[2]] type2 = cols2[indexName2[2]] -if __name__ == '__main__': +if __name__ == "__main__": fName1 = "CElegansNeuronTables.xls" fName2 = "NeuronConnectFormatted.xlsx" @@ -215,4 +270,4 @@ def typeMapping(cols1, cols2, indexName1, indexName2): # file2 = "C:\\Users\\Ari\\Documents\\Projects\\OpenWorm\\book2.txt" # xfile1 = "C:\\Users\\Ari\\Documents\\Projects\\OpenWorm\\CElegansNeuroML\\CElegansNeuronTables.xls" # xfile2 = "C:\\Users\\Ari\\Documents\\Projects\\OpenWorm\\CElegansNeuroML\\NeuronConnectFormatted.xlsx" - comparitor(fName1,fName2) \ No newline at end of file + comparitor(fName1, fName2) diff --git a/c302/ConnectomeReader.py b/c302/ConnectomeReader.py index fad60549..9f059329 100644 --- a/c302/ConnectomeReader.py +++ b/c302/ConnectomeReader.py @@ -8,25 +8,426 @@ from c302 import print_ -PREFERRED_NEURON_NAMES = ['ADAL', 'ADAR', 'ADEL', 'ADER', 'ADFL', 'ADFR', 'ADLL', 'ADLR', 'AFDL', 'AFDR', 'AIAL', 'AIAR', 'AIBL', 'AIBR', 'AIML', 'AIMR', 'AINL', 'AINR', 'AIYL', 'AIYR', 'AIZL', 'AIZR', 'ALA', 'ALML', 'ALMR', 'ALNL', 'ALNR', 'AQR', 'AS1', 'AS10', 'AS11', 'AS2', 'AS3', 'AS4', 'AS5', 'AS6', 'AS7', 'AS8', 'AS9', 'ASEL', 'ASER', 'ASGL', 'ASGR', 'ASHL', 'ASHR', 'ASIL', 'ASIR', 'ASJL', 'ASJR', 'ASKL', 'ASKR', 'AUAL', 'AUAR', 'AVAL', 'AVAR', 'AVBL', 'AVBR', 'AVDL', 'AVDR', 'AVEL', 'AVER', 'AVFL', 'AVFR', 'AVG', 'AVHL', 'AVHR', 'AVJL', 'AVJR', 'AVKL', 'AVKR', 'AVL', 'AVM', 'AWAL', 'AWAR', 'AWBL', 'AWBR', 'AWCL', 'AWCR', 'BAGL', 'BAGR', 'BDUL', 'BDUR', 'CANL', 'CANR', 'CEPDL', 'CEPDR', 'CEPVL', 'CEPVR', 'DA1', 'DA2', 'DA3', 'DA4', 'DA5', 'DA6', 'DA7', 'DA8', 'DA9', 'DB1', 'DB2', 'DB3', 'DB4', 'DB5', 'DB6', 'DB7', 'DD1', 'DD2', 'DD3', 'DD4', 'DD5', 'DD6', 'DVA', 'DVB', 'DVC', 'FLPL', 'FLPR', 'HSNL', 'HSNR', 'I1L', 'I1R', 'I2L', 'I2R', 'I3', 'I4', 'I5', 'I6', 'IL1DL', 'IL1DR', 'IL1L', 'IL1R', 'IL1VL', 'IL1VR', 'IL2DL', 'IL2DR', 'IL2L', 'IL2R', 'IL2VL', 'IL2VR', 'LUAL', 'LUAR', 'M1', 'M2L', 'M2R', 'M3L', 'M3R', 'M4', 'M5', 'MCL', 'MCR', 'MI', 'NSML', 'NSMR', 'OLLL', 'OLLR', 'OLQDL', 'OLQDR', 'OLQVL', 'OLQVR', 'PDA', 'PDB', 'PDEL', 'PDER', 'PHAL', 'PHAR', 'PHBL', 'PHBR', 'PHCL', 'PHCR', 'PLML', 'PLMR', 'PLNL', 'PLNR', 'PQR', 'PVCL', 'PVCR', 'PVDL', 'PVDR', 'PVM', 'PVNL', 'PVNR', 'PVPL', 'PVPR', 'PVQL', 'PVQR', 'PVR', 'PVT', 'PVWL', 'PVWR', 'RIAL', 'RIAR', 'RIBL', 'RIBR', 'RICL', 'RICR', 'RID', 'RIFL', 'RIFR', 'RIGL', 'RIGR', 'RIH', 'RIML', 'RIMR', 'RIPL', 'RIPR', 'RIR', 'RIS', 'RIVL', 'RIVR', 'RMDDL', 'RMDDR', 'RMDL', 'RMDR', 'RMDVL', 'RMDVR', 'RMED', 'RMEL', 'RMER', 'RMEV', 'RMFL', 'RMFR', 'RMGL', 'RMGR', 'RMHL', 'RMHR', 'SAADL', 'SAADR', 'SAAVL', 'SAAVR', 'SABD', 'SABVL', 'SABVR', 'SDQL', 'SDQR', 'SIADL', 'SIADR', 'SIAVL', 'SIAVR', 'SIBDL', 'SIBDR', 'SIBVL', 'SIBVR', 'SMBDL', 'SMBDR', 'SMBVL', 'SMBVR', 'SMDDL', 'SMDDR', 'SMDVL', 'SMDVR', 'URADL', 'URADR', 'URAVL', 'URAVR', 'URBL', 'URBR', 'URXL', 'URXR', 'URYDL', 'URYDR', 'URYVL', 'URYVR', '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'] -PREFERRED_MUSCLE_NAMES = ['MANAL', 'MDL01', 'MDL02', 'MDL03', 'MDL04', 'MDL05', 'MDL06', 'MDL07', 'MDL08', 'MDL09', 'MDL10', 'MDL11', 'MDL12', 'MDL13', 'MDL14', 'MDL15', 'MDL16', 'MDL17', 'MDL18', 'MDL19', 'MDL20', 'MDL21', 'MDL22', 'MDL23', 'MDL24', 'MDR01', 'MDR02', 'MDR03', 'MDR04', 'MDR05', 'MDR06', 'MDR07', 'MDR08', 'MDR09', 'MDR10', 'MDR11', 'MDR12', 'MDR13', 'MDR14', 'MDR15', 'MDR16', 'MDR17', 'MDR18', 'MDR19', 'MDR20', 'MDR21', 'MDR22', 'MDR23', 'MDR24', 'MVL01', 'MVL02', 'MVL03', 'MVL04', 'MVL05', 'MVL06', 'MVL07', 'MVL08', 'MVL09', 'MVL10', 'MVL11', 'MVL12', 'MVL13', 'MVL14', 'MVL15', 'MVL16', 'MVL17', 'MVL18', 'MVL19', 'MVL20', 'MVL21', 'MVL22', 'MVL23', 'MVR01', 'MVR02', 'MVR03', 'MVR04', 'MVR05', 'MVR06', 'MVR07', 'MVR08', 'MVR09', 'MVR10', 'MVR11', 'MVR12', 'MVR13', 'MVR14', 'MVR15', 'MVR16', 'MVR17', 'MVR18', 'MVR19', 'MVR20', 'MVR21', 'MVR22', 'MVR23', 'MVR24', 'MVULVA'] +PREFERRED_NEURON_NAMES = [ + "ADAL", + "ADAR", + "ADEL", + "ADER", + "ADFL", + "ADFR", + "ADLL", + "ADLR", + "AFDL", + "AFDR", + "AIAL", + "AIAR", + "AIBL", + "AIBR", + "AIML", + "AIMR", + "AINL", + "AINR", + "AIYL", + "AIYR", + "AIZL", + "AIZR", + "ALA", + "ALML", + "ALMR", + "ALNL", + "ALNR", + "AQR", + "AS1", + "AS10", + "AS11", + "AS2", + "AS3", + "AS4", + "AS5", + "AS6", + "AS7", + "AS8", + "AS9", + "ASEL", + "ASER", + "ASGL", + "ASGR", + "ASHL", + "ASHR", + "ASIL", + "ASIR", + "ASJL", + "ASJR", + "ASKL", + "ASKR", + "AUAL", + "AUAR", + "AVAL", + "AVAR", + "AVBL", + "AVBR", + "AVDL", + "AVDR", + "AVEL", + "AVER", + "AVFL", + "AVFR", + "AVG", + "AVHL", + "AVHR", + "AVJL", + "AVJR", + "AVKL", + "AVKR", + "AVL", + "AVM", + "AWAL", + "AWAR", + "AWBL", + "AWBR", + "AWCL", + "AWCR", + "BAGL", + "BAGR", + "BDUL", + "BDUR", + "CANL", + "CANR", + "CEPDL", + "CEPDR", + "CEPVL", + "CEPVR", + "DA1", + "DA2", + "DA3", + "DA4", + "DA5", + "DA6", + "DA7", + "DA8", + "DA9", + "DB1", + "DB2", + "DB3", + "DB4", + "DB5", + "DB6", + "DB7", + "DD1", + "DD2", + "DD3", + "DD4", + "DD5", + "DD6", + "DVA", + "DVB", + "DVC", + "FLPL", + "FLPR", + "HSNL", + "HSNR", + "I1L", + "I1R", + "I2L", + "I2R", + "I3", + "I4", + "I5", + "I6", + "IL1DL", + "IL1DR", + "IL1L", + "IL1R", + "IL1VL", + "IL1VR", + "IL2DL", + "IL2DR", + "IL2L", + "IL2R", + "IL2VL", + "IL2VR", + "LUAL", + "LUAR", + "M1", + "M2L", + "M2R", + "M3L", + "M3R", + "M4", + "M5", + "MCL", + "MCR", + "MI", + "NSML", + "NSMR", + "OLLL", + "OLLR", + "OLQDL", + "OLQDR", + "OLQVL", + "OLQVR", + "PDA", + "PDB", + "PDEL", + "PDER", + "PHAL", + "PHAR", + "PHBL", + "PHBR", + "PHCL", + "PHCR", + "PLML", + "PLMR", + "PLNL", + "PLNR", + "PQR", + "PVCL", + "PVCR", + "PVDL", + "PVDR", + "PVM", + "PVNL", + "PVNR", + "PVPL", + "PVPR", + "PVQL", + "PVQR", + "PVR", + "PVT", + "PVWL", + "PVWR", + "RIAL", + "RIAR", + "RIBL", + "RIBR", + "RICL", + "RICR", + "RID", + "RIFL", + "RIFR", + "RIGL", + "RIGR", + "RIH", + "RIML", + "RIMR", + "RIPL", + "RIPR", + "RIR", + "RIS", + "RIVL", + "RIVR", + "RMDDL", + "RMDDR", + "RMDL", + "RMDR", + "RMDVL", + "RMDVR", + "RMED", + "RMEL", + "RMER", + "RMEV", + "RMFL", + "RMFR", + "RMGL", + "RMGR", + "RMHL", + "RMHR", + "SAADL", + "SAADR", + "SAAVL", + "SAAVR", + "SABD", + "SABVL", + "SABVR", + "SDQL", + "SDQR", + "SIADL", + "SIADR", + "SIAVL", + "SIAVR", + "SIBDL", + "SIBDR", + "SIBVL", + "SIBVR", + "SMBDL", + "SMBDR", + "SMBVL", + "SMBVR", + "SMDDL", + "SMDDR", + "SMDVL", + "SMDVR", + "URADL", + "URADR", + "URAVL", + "URAVR", + "URBL", + "URBR", + "URXL", + "URXR", + "URYDL", + "URYDR", + "URYVL", + "URYVR", + "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", +] +PREFERRED_MUSCLE_NAMES = [ + "MANAL", + "MDL01", + "MDL02", + "MDL03", + "MDL04", + "MDL05", + "MDL06", + "MDL07", + "MDL08", + "MDL09", + "MDL10", + "MDL11", + "MDL12", + "MDL13", + "MDL14", + "MDL15", + "MDL16", + "MDL17", + "MDL18", + "MDL19", + "MDL20", + "MDL21", + "MDL22", + "MDL23", + "MDL24", + "MDR01", + "MDR02", + "MDR03", + "MDR04", + "MDR05", + "MDR06", + "MDR07", + "MDR08", + "MDR09", + "MDR10", + "MDR11", + "MDR12", + "MDR13", + "MDR14", + "MDR15", + "MDR16", + "MDR17", + "MDR18", + "MDR19", + "MDR20", + "MDR21", + "MDR22", + "MDR23", + "MDR24", + "MVL01", + "MVL02", + "MVL03", + "MVL04", + "MVL05", + "MVL06", + "MVL07", + "MVL08", + "MVL09", + "MVL10", + "MVL11", + "MVL12", + "MVL13", + "MVL14", + "MVL15", + "MVL16", + "MVL17", + "MVL18", + "MVL19", + "MVL20", + "MVL21", + "MVL22", + "MVL23", + "MVR01", + "MVR02", + "MVR03", + "MVR04", + "MVR05", + "MVR06", + "MVR07", + "MVR08", + "MVR09", + "MVR10", + "MVR11", + "MVR12", + "MVR13", + "MVR14", + "MVR15", + "MVR16", + "MVR17", + "MVR18", + "MVR19", + "MVR20", + "MVR21", + "MVR22", + "MVR23", + "MVR24", + "MVULVA", +] def convert_to_preferred_muscle_name(muscle): - if muscle.startswith("BWM-VL"): - return "MVL%s" %muscle[6:] + return "MVL%s" % muscle[6:] elif muscle.startswith("BWM-VR"): - return "MVR%s" %muscle[6:] + return "MVR%s" % muscle[6:] elif muscle.startswith("BWM-DL"): - return "MDL%s" %muscle[6:] + return "MDL%s" % muscle[6:] elif muscle.startswith("BWM-DR"): - return "MDR%s" %muscle[6:] - elif muscle=='LegacyBodyWallMuscles': - return 'BWM' + return "MDR%s" % muscle[6:] + elif muscle == "LegacyBodyWallMuscles": + return "BWM" else: return muscle + "???" + def get_all_muscle_prefixes(): return ["pm", "vm", "um", "BWM-D", "BWM-V", "LegacyBodyWallMuscles", "vBWM", "dBWM"] @@ -57,43 +458,51 @@ def remove_leading_index_zero(cell): return "%s%s" % (cell[:-2], cell[-1:]) return cell -class ConnectionInfo: - - def __init__(self, - pre_cell, - post_cell, - number, - syntype, - synclass): +class ConnectionInfo: + def __init__(self, pre_cell, post_cell, number, syntype, synclass): self.pre_cell = pre_cell self.post_cell = post_cell self.number = number self.syntype = syntype self.synclass = synclass - def __str__(self): - return "Connection from %s to %s (%i times, type: %s, neurotransmitter: %s)"%(self.pre_cell, self.post_cell, self.number, self.syntype, self.synclass) + return "Connection from %s to %s (%i times, type: %s, neurotransmitter: %s)" % ( + self.pre_cell, + self.post_cell, + self.number, + self.syntype, + self.synclass, + ) def short(self): - return "Connection from %s to %s (%s)"%(self.pre_cell, self.post_cell, self.syntype) - + 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 - + 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: + if other.pre_cell + other.post_cell > self.pre_cell + self.post_cell: return True - else: + else: return False - + def __repr__(self): return self.__str__() def check_neurons(cells): - preferred = [] not_in_preferred = [] missing_preferred = [n for n in PREFERRED_NEURON_NAMES] @@ -107,19 +516,23 @@ def check_neurons(cells): return preferred, not_in_preferred, missing_preferred + def analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_conns): + print_("Found %s cells: %s\n" % (len(cells), sorted(cells))) + # assert(len(cells) == 302) + # print_("Expected number of cells correct if include_nonconnected_cells=True") - print_("Found %s cells: %s\n"%(len(cells),sorted(cells))) - #assert(len(cells) == 302) - #print_("Expected number of cells correct if include_nonconnected_cells=True") - preferred, not_in_preferred, missing_preferred = check_neurons(cells) - print_("Found %s non-neuron(s) here: %s\n"%(len(not_in_preferred),sorted(not_in_preferred))) - print_("Known neurons not present: %s\n"%(sorted(missing_preferred))) + print_( + "Found %s non-neuron(s) here: %s\n" + % (len(not_in_preferred), sorted(not_in_preferred)) + ) + print_("Known neurons not present: %s\n" % (sorted(missing_preferred))) - print_("Found %s connections..."%(len(neuron_conns))) - for c in neuron_conns[:5]: print_(" %s"%c) + print_("Found %s connections..." % (len(neuron_conns))) + for c in neuron_conns[:5]: + print_(" %s" % c) print_(" ...\n") nts = {} @@ -129,28 +542,45 @@ def analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_co if not nt in nts: nts[nt] = 0 nts_tot[nt] = 0 - nts[nt]+=1 - nts_tot[nt]+=c.number - + nts[nt] += 1 + nts_tot[nt] += c.number + for nt in sorted(nts.keys()): - print_(" %s present in %s connections, %s synapses total (avg %.3f syns per conn)"%(nt, nts[nt], nts_tot[nt], nts_tot[nt]/nts[nt])) + print_( + " %s present in %s connections, %s synapses total (avg %.3f syns per conn)" + % (nt, nts[nt], nts_tot[nt], nts_tot[nt] / nts[nt]) + ) print_("") print_(" --- Muscles ---") print_("") - print_("Found %s muscles: %s\n"%(len(muscles),sorted(muscles))) + print_("Found %s muscles: %s\n" % (len(muscles), sorted(muscles))) not_in_preferred = [] for m in muscles: if not m in PREFERRED_MUSCLE_NAMES: not_in_preferred.append(m) - - print_("Found %s unidentified muscles: %s\n"%(len(not_in_preferred),sorted(not_in_preferred))) - print_("Found %i neurons connected to muscles: %s\n"%(len(neurons2muscles), sorted(neurons2muscles))) - print_("Found %i muscles connected to neurons: %s\n"%(len(muscles), sorted(muscles))) - - print_("Found %i connections between neurons and muscles%s\n"%(len(muscle_conns), (', e.g. %s'%muscle_conns[0]) if len(muscle_conns)>0 else '')) + print_( + "Found %s unidentified muscles: %s\n" + % (len(not_in_preferred), sorted(not_in_preferred)) + ) + + print_( + "Found %i neurons connected to muscles: %s\n" + % (len(neurons2muscles), sorted(neurons2muscles)) + ) + print_( + "Found %i muscles connected to neurons: %s\n" % (len(muscles), sorted(muscles)) + ) + + print_( + "Found %i connections between neurons and muscles%s\n" + % ( + len(muscle_conns), + (", e.g. %s" % muscle_conns[0]) if len(muscle_conns) > 0 else "", + ) + ) nts = {} nts_tot = {} @@ -159,41 +589,41 @@ def analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_co if not nt in nts: nts[nt] = 0 nts_tot[nt] = 0 - nts[nt]+=1 - nts_tot[nt]+=c.number - + nts[nt] += 1 + nts_tot[nt] += c.number + for nt in nts: - print_(" %s present in %s connections, %s synapses total (avg %.3f syns per conn)"%(nt, nts[nt], nts_tot[nt], nts_tot[nt]/nts[nt])) - - - core_set = ['AVBL','PVCL','VA6', 'VB6', 'VD6', 'DB4', 'DD4'] - #core_set = ['VA6', 'VD6'] - print_("\n\nConnections between cells in the subset %s:\n"%(core_set)) + print_( + " %s present in %s connections, %s synapses total (avg %.3f syns per conn)" + % (nt, nts[nt], nts_tot[nt], nts_tot[nt] / nts[nt]) + ) + + core_set = ["AVBL", "PVCL", "VA6", "VB6", "VD6", "DB4", "DD4"] + # core_set = ['VA6', 'VD6'] + print_("\n\nConnections between cells in the subset %s:\n" % (core_set)) for c in neuron_conns: if c.pre_cell in core_set and c.post_cell in core_set: print_(str(c)) - print_details_on =['AVBR','NSMR'] + print_details_on = ["AVBR", "NSMR"] for cd in print_details_on: - print_("\n\nAll outgoing connections of %s:\n"%(cd)) + print_("\n\nAll outgoing connections of %s:\n" % (cd)) for c in neuron_conns: if c.pre_cell == cd: print_(str(c)) - print_("\n\nAll incoming connections of %s:\n"%(cd)) + print_("\n\nAll incoming connections of %s:\n" % (cd)) for c in neuron_conns: if c.post_cell == cd: print_(str(c)) - print_("") if __name__ == "__main__": - from SpreadsheetDataReader import read_data, read_muscle_data - + cells, neuron_conns = read_data(include_nonconnected_cells=True) neurons2muscles, muscles, muscle_conns = read_muscle_data() - analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_conns) \ No newline at end of file + analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_conns) diff --git a/c302/Cook2019DataReader.py b/c302/Cook2019DataReader.py index dc7cf361..d04878cc 100644 --- a/c302/Cook2019DataReader.py +++ b/c302/Cook2019DataReader.py @@ -4,7 +4,7 @@ # A simple script to read the values in herm_full_edgelist.csv. -# This is on of a number of interchangeable "Readers" which can +# This is on of a number of interchangeable "Readers" which can # be used to get connection data for c302 ############################################################ @@ -25,21 +25,19 @@ from c302 import print_ -spreadsheet_location = os.path.dirname(os.path.abspath(__file__))+"/data/" +spreadsheet_location = os.path.dirname(os.path.abspath(__file__)) + "/data/" filename = "%sSI 5 Connectome adjacency matrices.xlsx" % spreadsheet_location -HERM_CHEM = 'hermaphrodite chemical' -HERM_GAP_SYMM = 'herm gap jn symmetric' +HERM_CHEM = "hermaphrodite chemical" +HERM_GAP_SYMM = "herm gap jn symmetric" -pre_range = {HERM_CHEM:range(4,304), - HERM_GAP_SYMM:range(4,472)} - -post_range = {HERM_CHEM:range(4,457), - HERM_GAP_SYMM:range(4,472)} +pre_range = {HERM_CHEM: range(4, 304), HERM_GAP_SYMM: range(4, 472)} + +post_range = {HERM_CHEM: range(4, 457), HERM_GAP_SYMM: range(4, 472)} def get_synclass(cell, syntype): - #TODO: fix this dirty hack + # TODO: fix this dirty hack if syntype == "GapJunction": return "Generic_GJ" else: @@ -47,51 +45,74 @@ def get_synclass(cell, syntype): return "GABA" return "Acetylcholine" -class Cook2019DataReader(): +class Cook2019DataReader: verbose = False def __init__(self): - wb = load_workbook(filename) - print_("Opened the Excel file: " + filename) + print_("Opened the Excel file: " + filename) self.pre_cells = {} self.post_cells = {} self.conn_nums = {} for conn_type in [HERM_CHEM, HERM_GAP_SYMM]: - sheet = wb.get_sheet_by_name(conn_type) - print('Looking at sheet: %s'%conn_type) + print("Looking at sheet: %s" % conn_type) self.pre_cells[conn_type] = [] self.post_cells[conn_type] = [] for i in pre_range[conn_type]: - self.pre_cells[conn_type].append(sheet['C%i'%i].value) - - if self.verbose: print(' - Pre cells for %s (%i):\n%s'%(conn_type, len(self.pre_cells[conn_type]), self.pre_cells[conn_type])) + self.pre_cells[conn_type].append(sheet["C%i" % i].value) + + if self.verbose: + print( + " - Pre cells for %s (%i):\n%s" + % ( + conn_type, + len(self.pre_cells[conn_type]), + self.pre_cells[conn_type], + ) + ) for i in post_range[conn_type]: self.post_cells[conn_type].append(sheet.cell(row=3, column=i).value) - if self.verbose: print(' - Post cells for %s (%i):\n%s'%(conn_type, len(self.post_cells[conn_type]), self.post_cells[conn_type])) - - self.conn_nums[conn_type] = np.zeros([len(self.pre_cells[conn_type]),len(self.post_cells[conn_type])], dtype=int) + if self.verbose: + print( + " - Post cells for %s (%i):\n%s" + % ( + conn_type, + len(self.post_cells[conn_type]), + self.post_cells[conn_type], + ) + ) + + self.conn_nums[conn_type] = np.zeros( + [len(self.pre_cells[conn_type]), len(self.post_cells[conn_type])], + dtype=int, + ) for i in range(len(self.pre_cells[conn_type])): for j in range(len(self.post_cells[conn_type])): - row =4+i - col = 4+j + row = 4 + i + col = 4 + j val = sheet.cell(row=row, column=col).value - #print('Cell (%i,%i) [row %i, col %i] = %s'%(i,j,row, col, val)) + # print('Cell (%i,%i) [row %i, col %i] = %s'%(i,j,row, col, val)) if val is not None: - self.conn_nums[conn_type][i,j] = int(val) - - if self.verbose: print(' - Conns for %s (%s):\n%s'%(conn_type, self.conn_nums[conn_type].shape, self.conn_nums[conn_type])) - - + self.conn_nums[conn_type][i, j] = int(val) + + if self.verbose: + print( + " - Conns for %s (%s):\n%s" + % ( + conn_type, + self.conn_nums[conn_type].shape, + self.conn_nums[conn_type], + ) + ) def read_data(self, include_nonconnected_cells=False): """ @@ -103,28 +124,30 @@ def read_data(self, include_nonconnected_cells=False): """ if not include_nonconnected_cells: - raise Exception('Option include_nonconnected_cells=False not supported') + raise Exception("Option include_nonconnected_cells=False not supported") conns = [] cells = [] for conn_type in [HERM_CHEM, HERM_GAP_SYMM]: - for pre_index in range(len(self.pre_cells[conn_type])): for post_index in range(len(self.post_cells[conn_type])): - - pre = remove_leading_index_zero(self.pre_cells[conn_type][pre_index]) - post = remove_leading_index_zero(self.post_cells[conn_type][post_index]) + pre = remove_leading_index_zero( + self.pre_cells[conn_type][pre_index] + ) + post = remove_leading_index_zero( + self.post_cells[conn_type][post_index] + ) if is_body_wall_muscle(post): continue # post is a BWM so ignore - num = self.conn_nums[conn_type][pre_index,post_index] - if num>0: - syntype = 'Send' if conn_type == HERM_CHEM else "GapJunction" + num = self.conn_nums[conn_type][pre_index, post_index] + if num > 0: + syntype = "Send" if conn_type == HERM_CHEM else "GapJunction" synclass = get_synclass(pre, syntype) conns.append(ConnectionInfo(pre, post, num, syntype, synclass)) - #print ConnectionInfo(pre, post, num, syntype, synclass) + # print ConnectionInfo(pre, post, num, syntype, synclass) if pre not in cells: cells.append(pre) if post not in cells: @@ -132,7 +155,6 @@ def read_data(self, include_nonconnected_cells=False): return cells, conns - def read_muscle_data(self): """ Returns: @@ -145,7 +167,7 @@ def read_muscle_data(self): muscles = [] conns = [] - ''' + """ with open(filename, 'r') as f: reader = csv.DictReader(f) print_("Opened file: " + filename) @@ -168,21 +190,21 @@ def read_muscle_data(self): elif is_body_wall_muscle(pre) and pre not in muscles: muscles.append(pre) if post not in muscles: - muscles.append(post)''' + muscles.append(post)""" return neurons, muscles, conns def main(): - cdr = Cook2019DataReader() read_data = cdr.read_data read_muscle_data = cdr.read_muscle_data - + cells, neuron_conns = read_data(include_nonconnected_cells=True) neurons2muscles, muscles, muscle_conns = read_muscle_data() analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_conns) -if __name__ == '__main__': + +if __name__ == "__main__": main() diff --git a/c302/Cook2019HermReader.py b/c302/Cook2019HermReader.py index 9ccd96dd..3b8a50c6 100644 --- a/c302/Cook2019HermReader.py +++ b/c302/Cook2019HermReader.py @@ -1,4 +1,4 @@ -# Temporary class to allow this to be used in comparison notebook. +# Temporary class to allow this to be used in comparison notebook. # Should be tidied up. from c302.Cook2019DataReader import Cook2019DataReader @@ -9,11 +9,12 @@ read_data = cdr.read_data read_muscle_data = cdr.read_muscle_data + def main1(): cells, neuron_conns = read_data(include_nonconnected_cells=True) neurons2muscles, muscles, muscle_conns = read_muscle_data() analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_conns) -if __name__ == '__main__': - main1() \ No newline at end of file +if __name__ == "__main__": + main1() diff --git a/c302/NeuroML2/printNML2Info.py b/c302/NeuroML2/printNML2Info.py index e256f810..ba6e99f2 100644 --- a/c302/NeuroML2/printNML2Info.py +++ b/c302/NeuroML2/printNML2Info.py @@ -7,49 +7,53 @@ nml2_files = [] -if len(sys.argv) >=2: - for i in range(1,len(sys.argv)): +if len(sys.argv) >= 2: + for i in range(1, len(sys.argv)): nml2_files.append(sys.argv[i]) print("") for nml2_file in nml2_files: nml2_doc = loaders.NeuroMLLoader.load(nml2_file) - print("-------- File: %s ----------"%nml2_file) + print("-------- File: %s ----------" % nml2_file) for cell in nml2_doc.cells: - print(" Cell: %s; %i segments"%(cell.id, len(cell.morphology.segments))) + print(" Cell: %s; %i segments" % (cell.id, len(cell.morphology.segments))) for exp_two_synapse in nml2_doc.exp_two_synapses: - print(" Synapse: %s"%(exp_two_synapse.id)) + print(" Synapse: %s" % (exp_two_synapse.id)) for gap_junction in nml2_doc.gap_junctions: - print(" Electrical Synapse: %s"%(gap_junction.id)) + print(" Electrical Synapse: %s" % (gap_junction.id)) for network in nml2_doc.networks: - print(" Network: %s"%(network.id)) + print(" Network: %s" % (network.id)) pops = [] for pop in network.populations: pops.append(pop.id) - print(" Populations (%i): %s"%(len(pops),pops)) - + print(" Populations (%i): %s" % (len(pops), pops)) + projs = [] connections = 0 for proj in network.projections: projs.append(proj.id) - connections+=len(proj.connections) - - print(" Projections: %i with %i connections in total"%(len(projs),connections)) - + connections += len(proj.connections) + + print( + " Projections: %i with %i connections in total" + % (len(projs), connections) + ) + elec_projs = [] elec_connections = 0 for elec_proj in network.electrical_projections: elec_projs.append(elec_proj.id) - elec_connections+=len(elec_proj.electrical_connections) - - print(" Electrical Projections: %i with %i connections in total"%(len(elec_projs),elec_connections)) + elec_connections += len(elec_proj.electrical_connections) + print( + " Electrical Projections: %i with %i connections in total" + % (len(elec_projs), elec_connections) + ) print("") - diff --git a/c302/NeuroMLUtilities.py b/c302/NeuroMLUtilities.py index 9c5d9eee..cc399d9d 100644 --- a/c302/NeuroMLUtilities.py +++ b/c302/NeuroMLUtilities.py @@ -22,9 +22,10 @@ def getSegmentIds(cell): return seg_ids + def get3DPosition(cell, segment_index, fraction_along): seg = cell.morphology.segments[segment_index] - + end = seg.distal start = seg.proximal @@ -37,20 +38,20 @@ def get3DPosition(cell, segment_index, fraction_along): fy = fract(start.y, end.y, fraction_along) fz = fract(start.z, end.z, fraction_along) - #print "(%f, %f, %f) is %f between (%f, %f, %f) and (%f, %f, %f)"%(fx,fy,fz,fraction_along,start.x,start.y,start.z,end.x,end.y,end.z) + # print "(%f, %f, %f) is %f between (%f, %f, %f) and (%f, %f, %f)"%(fx,fy,fz,fraction_along,start.x,start.y,start.z,end.x,end.y,end.z) return fx, fy, fz + def fract(a, b, f): - return a+(b-a)*f + return a + (b - a) * f if __name__ == "__main__": - from SpreadsheetDataReader import read_data, read_muscle_data from WormNeuroAtlasReader import read_data, read_muscle_data - + cells, neuron_conns = read_data(include_nonconnected_cells=True) neurons2muscles, muscles, muscle_conns = read_muscle_data() - analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_conns) \ No newline at end of file + analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_conns) diff --git a/c302/OpenWormReader.py b/c302/OpenWormReader.py index b88f45ca..02e9feed 100644 --- a/c302/OpenWormReader.py +++ b/c302/OpenWormReader.py @@ -5,11 +5,15 @@ from c302.NeuroMLUtilities import analyse_connections from c302 import print_, MUSCLE_RE -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 +try: + 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 +except: + print("owmeta not installed! Cannot run OpenWormReader") + exit() ############################################################ @@ -26,7 +30,6 @@ def __init__(self): self.cached = False def get_cells_in_model(self, net): - cell_names = set() for n in net.neurons(): cell_names.add(str(n.name())) @@ -37,11 +40,13 @@ def read_data(self, include_nonconnected_cells=False): print_("Initialising OpenWormReader") try: - cell_names, pre, post, conns = self._read_connections('neuron') + cell_names, pre, post, conns = self._read_connections("neuron") except: - print('\nProblem loading connections via owmeta! The package is installed however. You may need to try running:'+ - "\n\n owm bundle remote --user add ow 'https://raw.githubusercontent.com/openworm/owmeta-bundles/master/index.json'\n") - + print( + "\nProblem loading connections via owmeta! The package is installed however. You may need to try running:" + + "\n\n owm bundle remote --user add ow 'https://raw.githubusercontent.com/openworm/owmeta-bundles/master/index.json'\n" + ) + exit() if include_nonconnected_cells: @@ -50,12 +55,12 @@ def read_data(self, include_nonconnected_cells=False): return pre + post, conns def read_muscle_data(self): - cell_names, neurons, muscles, conns = self._read_connections('muscle') + 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: + 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() @@ -77,9 +82,9 @@ def _read_connections(self, termination=None): self.cell_names = self.get_cells_in_model(net) self.cached = True - if termination == 'neuron': + if termination == "neuron": term_type = set([Neuron.rdf_type]) - elif termination == 'muscle': + elif termination == "muscle": term_type = set([BodyWallMuscle.rdf_type]) else: term_type = set([Neuron.rdf_type, BodyWallMuscle.rdf_type]) @@ -88,11 +93,12 @@ def _read_connections(self, termination=None): 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)): + 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 '' + 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: @@ -106,14 +112,20 @@ def _read_connections(self, termination=None): if pre_name.startswith("DD") or pre_name.startswith("VD"): synclass = "GABA" synclass = "Acetylcholine" - conns.append(ConnectionInfo(pre_name, post_name, num, syntype, synclass)) + 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 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 @@ -124,11 +136,11 @@ def format_muscle_name(muscle_name): if md: return muscle_name else: - md = re.fullmatch(r'([VD][LR])(\d+)', muscle_name) + md = re.fullmatch(r"([VD][LR])(\d+)", muscle_name) if md: - return 'M{0}{1:02d}'.format(md.group(1), int(md.group(2))) + return "M{0}{1:02d}".format(md.group(1), int(md.group(2))) else: - LOGGER.debug('Unrecognized muscle name format in %s', muscle_name) + LOGGER.debug("Unrecognized muscle name format in %s", muscle_name) return muscle_name @@ -138,8 +150,6 @@ def format_muscle_name(muscle_name): read_muscle_data = READER.read_muscle_data if __name__ == "__main__": - - cells, neuron_conns = read_data(include_nonconnected_cells=True) neurons2muscles, muscles, muscle_conns = read_muscle_data() @@ -147,20 +157,26 @@ def format_muscle_name(muscle_name): exit() - conn_map_OWR = {} for c in conns: conn_map_OWR[c.short().lower()] = c from c302.UpdatedSpreadsheetDataReader import read_data as read_data_usr - #from c302.SpreadsheetDataReader 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 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) + 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: @@ -180,16 +196,18 @@ def format_muscle_name(muscle_name): else: 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 refs_USR = list(conn_map_USR.keys()) for i in range(min(maxn, len(refs_USR))): - #print("\n----- Connection in USR: %s"%refs[i]) + # print("\n----- Connection in USR: %s"%refs[i]) # print cm2[refs[i]] ref = refs_USR[i] if ref in conn_map_OWR: @@ -200,4 +218,4 @@ def format_muscle_name(muscle_name): else: 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 66dc0fda..e8ac18c8 100644 --- a/c302/SpreadsheetDataReader.py +++ b/c302/SpreadsheetDataReader.py @@ -4,7 +4,7 @@ # A simple script to read the values in CElegansNeuronTables.xls. -# This is one of a number of interchangeable "Readers" which can +# This is one of a number of interchangeable "Readers" which can # be used to get connection data for c302 ############################################################ @@ -16,30 +16,30 @@ from xlrd import open_workbook import os -spreadsheet_location = os.path.dirname(os.path.abspath(__file__))+"/data/" +spreadsheet_location = os.path.dirname(os.path.abspath(__file__)) + "/data/" from c302 import print_ -READER_DESCRIPTION = """Data extracted from CElegansNeuronTables.xls for neuronal connectivity""" - -def read_data(include_nonconnected_cells=False, neuron_connect=False): - +READER_DESCRIPTION = ( + """Data extracted from CElegansNeuronTables.xls for neuronal connectivity""" +) -# reading the NeuronConnectFormatted.xls file if neuron_connect = True +def read_data(include_nonconnected_cells=False, neuron_connect=False): + # reading the NeuronConnectFormatted.xls file if neuron_connect = True if neuron_connect: conns = [] cells = [] - filename = "%sNeuronConnectFormatted.xlsx"%spreadsheet_location + filename = "%sNeuronConnectFormatted.xlsx" % spreadsheet_location rb = open_workbook(filename) print_("Opened the Excel file: " + filename) - for row in range(1,rb.sheet_by_index(0).nrows): - pre = str(rb.sheet_by_index(0).cell(row,0).value) - post = str(rb.sheet_by_index(0).cell(row,1).value) - syntype = rb.sheet_by_index(0).cell(row,2).value - num = int(rb.sheet_by_index(0).cell(row,3).value) - synclass = 'Generic_GJ' if 'EJ' in syntype else 'Chemical_Synapse' + for row in range(1, rb.sheet_by_index(0).nrows): + pre = str(rb.sheet_by_index(0).cell(row, 0).value) + post = str(rb.sheet_by_index(0).cell(row, 1).value) + syntype = rb.sheet_by_index(0).cell(row, 2).value + num = int(rb.sheet_by_index(0).cell(row, 3).value) + synclass = "Generic_GJ" if "EJ" in syntype else "Chemical_Synapse" conns.append(ConnectionInfo(pre, post, num, syntype, synclass)) if pre not in cells: @@ -52,20 +52,19 @@ def read_data(include_nonconnected_cells=False, neuron_connect=False): else: conns = [] cells = [] - filename = "%sCElegansNeuronTables.xls"%spreadsheet_location + filename = "%sCElegansNeuronTables.xls" % spreadsheet_location rb = open_workbook(filename) print_("Opened Excel file: " + filename) - known_nonconnected_cells = ['CANL', 'CANR', 'VC6'] - + known_nonconnected_cells = ["CANL", "CANR", "VC6"] - for row in range(1,rb.sheet_by_index(0).nrows): - pre = str(rb.sheet_by_index(0).cell(row,0).value) - post = str(rb.sheet_by_index(0).cell(row,1).value) - syntype = rb.sheet_by_index(0).cell(row,2).value - num = int(rb.sheet_by_index(0).cell(row,3).value) - synclass = rb.sheet_by_index(0).cell(row,4).value + for row in range(1, rb.sheet_by_index(0).nrows): + pre = str(rb.sheet_by_index(0).cell(row, 0).value) + post = str(rb.sheet_by_index(0).cell(row, 1).value) + syntype = rb.sheet_by_index(0).cell(row, 2).value + num = int(rb.sheet_by_index(0).cell(row, 3).value) + synclass = rb.sheet_by_index(0).cell(row, 4).value conns.append(ConnectionInfo(pre, post, num, syntype, synclass)) if pre not in cells: @@ -74,29 +73,30 @@ def read_data(include_nonconnected_cells=False, neuron_connect=False): cells.append(post) if include_nonconnected_cells: - for c in known_nonconnected_cells: cells.append(c) + for c in known_nonconnected_cells: + cells.append(c) return cells, conns -def read_muscle_data(): +def read_muscle_data(): conns = [] neurons = [] muscles = [] - filename = "%sCElegansNeuronTables.xls"%spreadsheet_location + filename = "%sCElegansNeuronTables.xls" % spreadsheet_location rb = open_workbook(filename) - print_("Opened Excel file: "+ filename) + print_("Opened Excel file: " + filename) sheet = rb.sheet_by_index(1) - for row in range(1,sheet.nrows): - pre = str(sheet.cell(row,0).value) - post = str(sheet.cell(row,1).value) - syntype = 'Send' - num = int(sheet.cell(row,2).value) - synclass = sheet.cell(row,3).value.replace(',', 'plus').replace(' ', '_') + for row in range(1, sheet.nrows): + pre = str(sheet.cell(row, 0).value) + post = str(sheet.cell(row, 1).value) + syntype = "Send" + num = int(sheet.cell(row, 2).value) + synclass = sheet.cell(row, 3).value.replace(",", "plus").replace(" ", "_") conns.append(ConnectionInfo(pre, post, num, syntype, synclass)) if pre not in neurons: @@ -104,18 +104,15 @@ def read_muscle_data(): if post not in muscles: muscles.append(post) - return neurons, muscles, conns - def main(): - cells, neuron_conns = read_data(include_nonconnected_cells=True) neurons2muscles, muscles, muscle_conns = read_muscle_data() analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_conns) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/c302/UpdatedSpreadsheetDataReader.py b/c302/UpdatedSpreadsheetDataReader.py index 25e0f303..97f66086 100644 --- a/c302/UpdatedSpreadsheetDataReader.py +++ b/c302/UpdatedSpreadsheetDataReader.py @@ -4,7 +4,7 @@ # A simple script to read the values in herm_full_edgelist.csv. -# This is on of a number of interchangeable "Readers" which can +# This is on of a number of interchangeable "Readers" which can # be used to get connection data for c302 ############################################################ @@ -17,9 +17,10 @@ from c302 import print_ -spreadsheet_location = os.path.dirname(os.path.abspath(__file__))+"/data/" +spreadsheet_location = os.path.dirname(os.path.abspath(__file__)) + "/data/" filename = "%sherm_full_edgelist.csv" % spreadsheet_location + def get_all_muscle_prefixes(): return ["pm", "vm", "um", "dBWM", "vBWM"] @@ -50,6 +51,7 @@ def remove_leading_index_zero(cell): return "%s%s" % (cell[:-2], cell[-1:]) return cell + def get_old_muscle_name(muscle): index = int(muscle[5:]) if index < 10: @@ -63,6 +65,7 @@ def get_old_muscle_name(muscle): elif muscle.startswith("dBWMR"): return "MDR%s" % index + def get_syntype(syntype): if syntype == "electrical": return "GapJunction" @@ -71,8 +74,9 @@ def get_syntype(syntype): else: raise NotImplementedError("Cannot parse syntype '%s'" % syntype) + def get_synclass(cell, syntype): - #dirty hack + # dirty hack if syntype == "GapJunction": return "Generic_GJ" else: @@ -80,6 +84,7 @@ def get_synclass(cell, syntype): return "GABA" return "Acetylcholine" + def parse_row(row): pre = str.strip(row["Source"]) post = str.strip(row["Target"]) @@ -88,6 +93,7 @@ def parse_row(row): synclass = get_synclass(pre, syntype) return pre, post, num, syntype, synclass + def read_data(include_nonconnected_cells=False): """ Args: @@ -100,11 +106,11 @@ def read_data(include_nonconnected_cells=False): conns = [] cells = [] - with open(filename, 'r') as f: + with open(filename, "r") as f: reader = csv.DictReader(f) print_("Opened file: " + filename) - known_nonconnected_cells = ['CANL', 'CANR'] + known_nonconnected_cells = ["CANL", "CANR"] for row in reader: pre, post, num, syntype, synclass = parse_row(row) @@ -116,7 +122,7 @@ def read_data(include_nonconnected_cells=False): post = remove_leading_index_zero(post) conns.append(ConnectionInfo(pre, post, num, syntype, synclass)) - #print ConnectionInfo(pre, post, num, syntype, synclass) + # print ConnectionInfo(pre, post, num, syntype, synclass) if pre not in cells: cells.append(pre) if post not in cells: @@ -142,14 +148,16 @@ def read_muscle_data(): muscles = [] conns = [] - with open(filename, 'r') as f: + with open(filename, "r") as f: reader = csv.DictReader(f) print_("Opened file: " + filename) for row in reader: pre, post, num, syntype, synclass = parse_row(row) - if not (is_neuron(pre) or is_body_wall_muscle(pre)) or not is_body_wall_muscle(post): + if not ( + is_neuron(pre) or is_body_wall_muscle(pre) + ) or not is_body_wall_muscle(post): continue if is_neuron(pre): @@ -170,11 +178,11 @@ def read_muscle_data(): def main(): - cells, neuron_conns = read_data(include_nonconnected_cells=True) neurons2muscles, muscles, muscle_conns = read_muscle_data() analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_conns) -if __name__ == '__main__': + +if __name__ == "__main__": main() diff --git a/c302/UpdatedSpreadsheetDataReader2.py b/c302/UpdatedSpreadsheetDataReader2.py index 8f909eb9..234e283c 100644 --- a/c302/UpdatedSpreadsheetDataReader2.py +++ b/c302/UpdatedSpreadsheetDataReader2.py @@ -4,7 +4,7 @@ # A simple script to read the values in herm_full_edgelist.csv. -# This is on of a number of interchangeable "Readers" which can +# This is on of a number of interchangeable "Readers" which can # be used to get connection data for c302 ############################################################ @@ -18,9 +18,10 @@ from c302 import print_ -spreadsheet_location = os.path.dirname(os.path.abspath(__file__))+"/data/" +spreadsheet_location = os.path.dirname(os.path.abspath(__file__)) + "/data/" filename = "%sherm_full_edgelist_MODIFIED.csv" % spreadsheet_location + def get_all_muscle_prefixes(): return ["pm", "vm", "um", "dBWM", "vBWM"] @@ -51,6 +52,7 @@ def remove_leading_index_zero(cell): return "%s%s" % (cell[:-2], cell[-1:]) return cell + def get_old_muscle_name(muscle): index = int(muscle[5:]) if index < 10: @@ -64,6 +66,7 @@ def get_old_muscle_name(muscle): elif muscle.startswith("dBWMR"): return "MDR%s" % index + def get_syntype(syntype): if syntype == "electrical": return "GapJunction" @@ -72,8 +75,9 @@ def get_syntype(syntype): else: raise NotImplementedError("Cannot parse syntype '%s'" % syntype) + def get_synclass(cell, syntype): - #dirty hack + # dirty hack if syntype == "GapJunction": return "Generic_GJ" else: @@ -81,6 +85,7 @@ def get_synclass(cell, syntype): return "GABA" return "Acetylcholine" + def parse_row(row): pre = str.strip(row["Source"]) post = str.strip(row["Target"]) @@ -89,6 +94,7 @@ def parse_row(row): synclass = get_synclass(pre, syntype) return pre, post, num, syntype, synclass + def read_data(include_nonconnected_cells=False): """ Args: @@ -101,11 +107,11 @@ def read_data(include_nonconnected_cells=False): conns = [] cells = [] - with open(filename, 'r') as f: + with open(filename, "r") as f: reader = csv.DictReader(f) print_("Opened file: " + filename) - known_nonconnected_cells = ['CANL', 'CANR'] + known_nonconnected_cells = ["CANL", "CANR"] for row in reader: pre, post, num, syntype, synclass = parse_row(row) @@ -117,7 +123,7 @@ def read_data(include_nonconnected_cells=False): post = remove_leading_index_zero(post) conns.append(ConnectionInfo(pre, post, num, syntype, synclass)) - #print ConnectionInfo(pre, post, num, syntype, synclass) + # print ConnectionInfo(pre, post, num, syntype, synclass) if pre not in cells: cells.append(pre) if post not in cells: @@ -143,14 +149,16 @@ def read_muscle_data(): muscles = [] conns = [] - with open(filename, 'r') as f: + with open(filename, "r") as f: reader = csv.DictReader(f) print_("Opened file: " + filename) 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): + 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 continue @@ -161,7 +169,7 @@ 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) + # 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: @@ -173,11 +181,11 @@ def read_muscle_data(): def main(): - cells, neuron_conns = read_data(include_nonconnected_cells=True) neurons2muscles, muscles, muscle_conns = read_muscle_data() analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_conns) -if __name__ == '__main__': + +if __name__ == "__main__": main() diff --git a/c302/VarshneyDataReader.py b/c302/VarshneyDataReader.py index 69ce15df..d01fe88e 100644 --- a/c302/VarshneyDataReader.py +++ b/c302/VarshneyDataReader.py @@ -5,36 +5,40 @@ import os from c302 import print_ -spreadsheet_location = os.path.dirname(os.path.abspath(__file__))+"/data/" -spreadsheet_name = "NeuronConnect.xlsx" # has old name... +spreadsheet_location = os.path.dirname(os.path.abspath(__file__)) + "/data/" +spreadsheet_name = "NeuronConnect.xlsx" # has old name... spreadsheet_name = "NeuronConnectFormatted.xlsx" -READER_DESCRIPTION = """Data extracted from %s for neuronal connectivity"""%spreadsheet_name +READER_DESCRIPTION = ( + """Data extracted from %s for neuronal connectivity""" % spreadsheet_name +) -NMJ_ENDPOINT = 'NMJ' +NMJ_ENDPOINT = "NMJ" -def read_data(include_nonconnected_cells=False, neuron_connect=True): +def read_data(include_nonconnected_cells=False, neuron_connect=True): if neuron_connect: conns = [] cells = [] - filename = "%s%s"%(spreadsheet_location,spreadsheet_name) + filename = "%s%s" % (spreadsheet_location, spreadsheet_name) wb = load_workbook(filename) sheet = wb.worksheets[0] - print_("Opened the Excel file: " + filename) + print_("Opened the Excel file: " + filename) - for row in sheet.iter_rows(min_row=2, values_only=True): # Assuming data starts from the second row + for row in sheet.iter_rows( + min_row=2, values_only=True + ): # Assuming data starts from the second row pre = str(row[0]) - post = str(row[1]) + post = str(row[1]) - if not post==NMJ_ENDPOINT: + if not post == NMJ_ENDPOINT: syntype = str(row[2]) num = int(row[3]) - synclass = 'Generic_GJ' if 'EJ' in syntype else 'Generic_CS' + synclass = "Generic_GJ" if "EJ" in syntype else "Generic_CS" conns.append(ConnectionInfo(pre, post, num, syntype, synclass)) if pre not in cells: - cells.append(pre) + cells.append(pre) if post not in cells: cells.append(post) @@ -42,25 +46,26 @@ def read_data(include_nonconnected_cells=False, neuron_connect=True): def read_muscle_data(): - conns = [] neurons = [] muscles = [] - filename = "%s%s"%(spreadsheet_location,spreadsheet_name) + filename = "%s%s" % (spreadsheet_location, spreadsheet_name) wb = load_workbook(filename) sheet = wb.worksheets[0] - print_("Opened Excel file: "+ filename) + print_("Opened Excel file: " + filename) - for row in sheet.iter_rows(min_row=2, values_only=True): # Assuming data starts from the second row + for row in sheet.iter_rows( + min_row=2, values_only=True + ): # Assuming data starts from the second row pre = str(row[0]) post = str(row[1]) - if post==NMJ_ENDPOINT: + if post == NMJ_ENDPOINT: syntype = str(row[2]) num = int(row[3]) - synclass = 'Generic_GJ' if 'EJ' in syntype else 'Generic_CS' + synclass = "Generic_GJ" if "EJ" in syntype else "Generic_CS" conns.append(ConnectionInfo(pre, post, num, syntype, synclass)) if pre not in neurons: @@ -68,18 +73,15 @@ def read_muscle_data(): if not post in muscles: muscles.append(post) - return neurons, muscles, conns - def main(): - cells, neuron_conns = read_data(include_nonconnected_cells=True) neurons2muscles, muscles, muscle_conns = read_muscle_data() analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_conns) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/c302/W_SpreadsheetDataReader.py b/c302/W_SpreadsheetDataReader.py index c152aa91..dbd1dfb4 100644 --- a/c302/W_SpreadsheetDataReader.py +++ b/c302/W_SpreadsheetDataReader.py @@ -9,29 +9,28 @@ from c302 import print_ -spreadsheet_location = os.path.dirname(os.path.abspath(__file__))+"/data/" +spreadsheet_location = os.path.dirname(os.path.abspath(__file__)) + "/data/" -class WitvlietDataReader: - +class WitvlietDataReader: def __init__(self, spreadsheet): + self.filename = "%s%s" % (spreadsheet_location, spreadsheet) - self.filename = "%s%s"%(spreadsheet_location,spreadsheet) - - def read_data(self,include_nonconnected_cells=True): - + def read_data(self, include_nonconnected_cells=True): if not include_nonconnected_cells: - raise Exception('Option include_nonconnected_cells=False not supported') - + raise Exception("Option include_nonconnected_cells=False not supported") + conns = [] cells = [] wb = load_workbook(self.filename) sheet = wb.worksheets[0] print_("Opened the Excel file: " + self.filename) - - for row in sheet.iter_rows(min_row=2, values_only=True): # Assuming data starts from the second row - #print(row) + + for row in sheet.iter_rows( + min_row=2, values_only=True + ): # Assuming data starts from the second row + # print(row) pre = str(row[0]) post = str(row[1]) @@ -40,8 +39,8 @@ def read_data(self,include_nonconnected_cells=True): syntype = str(row[2]) num = int(row[3]) - synclass = 'Generic_GJ' if 'electrical' in syntype else 'Generic_CS' - + synclass = "Generic_GJ" if "electrical" in syntype else "Generic_CS" + conns.append(ConnectionInfo(pre, post, num, syntype, synclass)) if pre not in cells: @@ -51,9 +50,7 @@ def read_data(self,include_nonconnected_cells=True): return cells, conns - def read_muscle_data(self): - conns = [] neurons = [] muscles = [] @@ -61,32 +58,31 @@ def read_muscle_data(self): wb = load_workbook(self.filename) sheet = wb.worksheets[0] - print_("Opened Excel file: "+ self.filename) + print_("Opened Excel file: " + self.filename) for row in sheet.iter_rows(min_row=2, values_only=True): pre = str(row[0]) post = str(row[1]) syntype = str(row[2]) num = int(row[3]) - synclass = 'Generic_GJ' if 'EJ' in syntype else 'Generic_CS' + synclass = "Generic_GJ" if "EJ" in syntype else "Generic_CS" if post.startswith("BWM-"): post = convert_to_preferred_muscle_name(post) else: - continue - + continue + conns.append(ConnectionInfo(pre, post, num, syntype, synclass)) if pre not in neurons: - neurons.append(pre) + neurons.append(pre) if post not in muscles: - muscles.append(post) - + muscles.append(post) return neurons, muscles, conns - -def main1(): - wdr = WitvlietDataReader('witvliet_2020_7.xlsx') + +def main1(): + wdr = WitvlietDataReader("witvliet_2020_7.xlsx") cells, neuron_conns = wdr.read_data() neurons2muscles, muscles, muscle_conns = wdr.read_muscle_data() @@ -95,14 +91,14 @@ def main1(): def main2(): - - wdr = WitvlietDataReader('witvliet_2020_8.xlsx') + wdr = WitvlietDataReader("witvliet_2020_8.xlsx") cells, neuron_conns = wdr.read_data() neurons2muscles, muscles, muscle_conns = wdr.read_muscle_data() analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_conns) -if __name__ == '__main__': + +if __name__ == "__main__": main1() - main2() \ No newline at end of file + main2() diff --git a/c302/WhiteDataReader.py b/c302/WhiteDataReader.py index b84931b1..a4111d93 100644 --- a/c302/WhiteDataReader.py +++ b/c302/WhiteDataReader.py @@ -4,7 +4,7 @@ # A simple script to read the values in herm_full_edgelist.csv. -# This is on of a number of interchangeable "Readers" which can +# This is on of a number of interchangeable "Readers" which can # be used to get connection data for c302 ############################################################ @@ -40,8 +40,9 @@ def get_syntype(syntype): else: raise NotImplementedError("Cannot parse syntype '%s'" % syntype) + def get_synclass(cell, syntype): - #dirty hack + # dirty hack if syntype == "GapJunction": return "Generic_GJ" else: @@ -49,6 +50,7 @@ def get_synclass(cell, syntype): return "GABA" return "Acetylcholine" + def parse_line(line): elements = line.split() pre = str.strip(elements[0]) @@ -58,21 +60,20 @@ def parse_line(line): synclass = get_synclass(pre, syntype) return pre, post, num, syntype, synclass + class White_A: - - spreadsheet_location = os.path.dirname(os.path.abspath(__file__))+"/data/" + spreadsheet_location = os.path.dirname(os.path.abspath(__file__)) + "/data/" filename = "%saconnectome_white_1986_A.csv" % spreadsheet_location - def read_data(include_nonconnected_cells=False): conns = [] cells = [] - - with open(White_A.filename, 'r') as f: + + with open(White_A.filename, "r") as f: print_("Opened file: " + White_A.filename) f.readline() - known_nonconnected_cells = ['CANL', 'CANR'] + known_nonconnected_cells = ["CANL", "CANR"] for line in f: pre, post, num, syntype, synclass = parse_line(line) @@ -84,7 +85,7 @@ def read_data(include_nonconnected_cells=False): post = remove_leading_index_zero(post) conns.append(ConnectionInfo(pre, post, num, syntype, synclass)) - #print ConnectionInfo(pre, post, num, syntype, synclass) + # print ConnectionInfo(pre, post, num, syntype, synclass) if pre not in cells: cells.append(pre) if post not in cells: @@ -97,13 +98,12 @@ def read_data(include_nonconnected_cells=False): return cells, conns - def read_muscle_data(): neurons = [] muscles = [] conns = [] - with open(White_A.filename, 'r') as f: + with open(White_A.filename, "r") as f: print_("Opened file: " + White_A.filename) f.readline() @@ -112,13 +112,13 @@ def read_muscle_data(): if not is_body_wall_muscle(post): continue - + if is_neuron(pre): pre = remove_leading_index_zero(pre) post = convert_to_preferred_muscle_name(post) conns.append(ConnectionInfo(pre, post, num, syntype, synclass)) - + if is_neuron(pre) and pre not in neurons: neurons.append(pre) if post not in muscles: @@ -126,25 +126,27 @@ def read_muscle_data(): return neurons, muscles, conns + def main1(): cells, neuron_conns = White_A.read_data(include_nonconnected_cells=True) neurons2muscles, muscles, muscle_conns = White_A.read_muscle_data() analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_conns) + class White_L4: - spreadsheet_location = os.path.dirname(os.path.abspath(__file__))+"/data/" - filename = "%saconnectome_white_1986_L4.csv" % spreadsheet_location - + spreadsheet_location = os.path.dirname(os.path.abspath(__file__)) + "/data/" + filename = "%saconnectome_white_1986_L4.csv" % spreadsheet_location + def read_data(include_nonconnected_cells=False): conns = [] cells = [] - - with open(White_L4.filename, 'r') as f: + + with open(White_L4.filename, "r") as f: print_("Opened file: " + White_L4.filename) f.readline() - known_nonconnected_cells = ['CANL', 'CANR'] + known_nonconnected_cells = ["CANL", "CANR"] for line in f: pre, post, num, syntype, synclass = parse_line(line) @@ -156,7 +158,7 @@ def read_data(include_nonconnected_cells=False): post = remove_leading_index_zero(post) conns.append(ConnectionInfo(pre, post, num, syntype, synclass)) - #print ConnectionInfo(pre, post, num, syntype, synclass) + # print ConnectionInfo(pre, post, num, syntype, synclass) if pre not in cells: cells.append(pre) if post not in cells: @@ -168,13 +170,13 @@ def read_data(include_nonconnected_cells=False): cells.append(c) return cells, conns - + def read_muscle_data(): neurons = [] muscles = [] conns = [] - with open(White_L4.filename, 'r') as f: + with open(White_L4.filename, "r") as f: print_("Opened file: " + White_L4.filename) f.readline() @@ -183,13 +185,13 @@ def read_muscle_data(): if not is_body_wall_muscle(post): continue - + if is_neuron(pre): pre = remove_leading_index_zero(pre) post = convert_to_preferred_muscle_name(post) conns.append(ConnectionInfo(pre, post, num, syntype, synclass)) - + if is_neuron(pre) and pre not in neurons: neurons.append(pre) if post not in muscles: @@ -197,29 +199,29 @@ def read_muscle_data(): return neurons, muscles, conns + def main2(): cells, neuron_conns = White_L4.read_data(include_nonconnected_cells=True) neurons2muscles, muscles, muscle_conns = White_L4.read_muscle_data() analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_conns) + class White_whole: - spreadsheet_location = os.path.dirname(os.path.abspath(__file__))+"/data/" + spreadsheet_location = os.path.dirname(os.path.abspath(__file__)) + "/data/" filename = "%saconnectome_white_1986_whole.csv" % spreadsheet_location BODYWALLMUSCLE_ENDPOINT = "LegacyBodyWallMuscles" - def read_data(include_nonconnected_cells=False): - conns = [] cells = [] - with open(White_whole.filename, 'r') as f: + with open(White_whole.filename, "r") as f: print_("Opened file: " + White_whole.filename) f.readline() - known_nonconnected_cells = ['CANL', 'CANR'] + known_nonconnected_cells = ["CANL", "CANR"] for line in f: pre, post, num, syntype, synclass = parse_line(line) @@ -230,7 +232,7 @@ def read_data(include_nonconnected_cells=False): post = remove_leading_index_zero(post) conns.append(ConnectionInfo(pre, post, num, syntype, synclass)) - #print ConnectionInfo(pre, post, num, syntype, synclass) + # print ConnectionInfo(pre, post, num, syntype, synclass) if pre not in cells: cells.append(pre) if post not in cells: @@ -242,30 +244,28 @@ def read_data(include_nonconnected_cells=False): cells.append(c) return cells, conns - - def read_muscle_data(): + def read_muscle_data(): neurons = [] muscles = [] conns = [] - with open(White_whole.filename, 'r') as f: + with open(White_whole.filename, "r") as f: print_("Opened file: " + White_whole.filename) f.readline() - for line in f: pre, post, num, syntype, synclass = parse_line(line) - + if not is_body_wall_muscle(post): continue - + if is_neuron(pre): pre = remove_leading_index_zero(pre) post = convert_to_preferred_muscle_name(post) conns.append(ConnectionInfo(pre, post, num, syntype, synclass)) - + if is_neuron(pre) and pre not in neurons: neurons.append(pre) if post not in muscles: @@ -273,6 +273,7 @@ def read_muscle_data(): return neurons, muscles, conns + def main3(): cells, neuron_conns = White_whole.read_data(include_nonconnected_cells=True) neurons2muscles, muscles, muscle_conns = White_whole.read_muscle_data() @@ -280,7 +281,7 @@ def main3(): analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_conns) -if __name__ == '__main__': +if __name__ == "__main__": main1() main2() - main3() \ No newline at end of file + main3() diff --git a/c302/White_A.py b/c302/White_A.py index cdc1f389..a43bb00c 100644 --- a/c302/White_A.py +++ b/c302/White_A.py @@ -1,4 +1,4 @@ -# Temporary class to allow this to be used in comparison notebook. +# Temporary class to allow this to be used in comparison notebook. # Should be tidied up. from c302.WhiteDataReader import White_A @@ -8,11 +8,12 @@ read_data = White_A.read_data read_muscle_data = White_A.read_muscle_data + def main1(): cells, neuron_conns = read_data(include_nonconnected_cells=True) neurons2muscles, muscles, muscle_conns = read_muscle_data() analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_conns) -if __name__ == '__main__': - main1() \ No newline at end of file +if __name__ == "__main__": + main1() diff --git a/c302/White_L4.py b/c302/White_L4.py index 8728af97..b8208de0 100644 --- a/c302/White_L4.py +++ b/c302/White_L4.py @@ -1,4 +1,4 @@ -# Temporary class to allow this to be used in comparison notebook. +# Temporary class to allow this to be used in comparison notebook. # Should be tidied up. from c302.WhiteDataReader import White_L4 @@ -15,5 +15,5 @@ def main1(): analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_conns) -if __name__ == '__main__': - main1() \ No newline at end of file +if __name__ == "__main__": + main1() diff --git a/c302/White_whole.py b/c302/White_whole.py index f688c5fe..35b4dd28 100644 --- a/c302/White_whole.py +++ b/c302/White_whole.py @@ -1,4 +1,4 @@ -# Temporary class to allow this to be used in comparison notebook. +# Temporary class to allow this to be used in comparison notebook. # Should be tidied up. from c302.WhiteDataReader import White_whole @@ -8,11 +8,12 @@ read_data = White_whole.read_data read_muscle_data = White_whole.read_muscle_data + def main1(): cells, neuron_conns = read_data(include_nonconnected_cells=True) neurons2muscles, muscles, muscle_conns = read_muscle_data() analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_conns) -if __name__ == '__main__': - main1() \ No newline at end of file +if __name__ == "__main__": + main1() diff --git a/c302/WitvlietDataReader1.py b/c302/WitvlietDataReader1.py index dd1ff29b..34f6b846 100644 --- a/c302/WitvlietDataReader1.py +++ b/c302/WitvlietDataReader1.py @@ -1,21 +1,21 @@ -# Temporary class to allow this to be used in comparison notebook. +# Temporary class to allow this to be used in comparison notebook. # Should be tidied up. from c302.W_SpreadsheetDataReader import WitvlietDataReader from c302.NeuroMLUtilities import analyse_connections -wdr = WitvlietDataReader('witvliet_2020_7.xlsx') +wdr = WitvlietDataReader("witvliet_2020_7.xlsx") read_data = wdr.read_data read_muscle_data = wdr.read_muscle_data -def main1(): +def main1(): cells, neuron_conns = read_data() neurons2muscles, muscles, muscle_conns = read_muscle_data() analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_conns) -if __name__ == '__main__': - main1() \ No newline at end of file +if __name__ == "__main__": + main1() diff --git a/c302/WitvlietDataReader2.py b/c302/WitvlietDataReader2.py index fd0e70d5..e5ea61e8 100644 --- a/c302/WitvlietDataReader2.py +++ b/c302/WitvlietDataReader2.py @@ -1,22 +1,21 @@ -# Temporary class to allow this to be used in comparison notebook. +# Temporary class to allow this to be used in comparison notebook. # Should be tidied up. from c302.W_SpreadsheetDataReader import WitvlietDataReader from c302.NeuroMLUtilities import analyse_connections -wdr = WitvlietDataReader('witvliet_2020_8.xlsx') +wdr = WitvlietDataReader("witvliet_2020_8.xlsx") read_data = wdr.read_data read_muscle_data = wdr.read_muscle_data def main2(): - cells, neuron_conns = read_data() neurons2muscles, muscles, muscle_conns = read_muscle_data() analyse_connections(cells, neuron_conns, neurons2muscles, muscles, muscle_conns) -if __name__ == '__main__': - main2() \ No newline at end of file +if __name__ == "__main__": + main2() diff --git a/c302/WormNeuroAtlasReader.py b/c302/WormNeuroAtlasReader.py index dad7ee69..a37c71a3 100644 --- a/c302/WormNeuroAtlasReader.py +++ b/c302/WormNeuroAtlasReader.py @@ -12,7 +12,7 @@ # A simple script to read the values in WormNeuroAtlas -# This is on of a number of interchangeable "Readers" which can +# This is on of a number of interchangeable "Readers" which can # be used to get connection data for c302 ############################################################ @@ -21,42 +21,40 @@ class WormNeuroAtlasReader(object): - def __init__(self): self.atlas = wa.NeuroAtlas() syn_sign = wa.SynapseSign() - self.dom_glu = syn_sign.get_neurons_producing("Glu", mode='dominant') - self.dom_ach = syn_sign.get_neurons_producing("ACh", mode='dominant') - self.dom_gaba = syn_sign.get_neurons_producing("GABA", mode='dominant') + self.dom_glu = syn_sign.get_neurons_producing("Glu", mode="dominant") + self.dom_ach = syn_sign.get_neurons_producing("ACh", mode="dominant") + self.dom_gaba = syn_sign.get_neurons_producing("GABA", mode="dominant") - self.alt_glu = syn_sign.get_neurons_producing("Glu", mode='alternative') - self.alt_ach = syn_sign.get_neurons_producing("ACh", mode='alternative') - self.alt_gaba = syn_sign.get_neurons_producing("GABA", mode='alternative') + self.alt_glu = syn_sign.get_neurons_producing("Glu", mode="alternative") + self.alt_ach = syn_sign.get_neurons_producing("ACh", mode="alternative") + self.alt_gaba = syn_sign.get_neurons_producing("GABA", mode="alternative") self.all_cells = self.atlas.neuron_ids for i in range(len(self.all_cells)): - if self.all_cells[i] == 'AWCOFF': - self.all_cells[i] = 'AWCL' - if self.all_cells[i] == 'AWCON': - self.all_cells[i] = 'AWCR' + if self.all_cells[i] == "AWCOFF": + self.all_cells[i] = "AWCL" + if self.all_cells[i] == "AWCON": + self.all_cells[i] = "AWCR" def determine_nt(self, neuron): if neuron in self.dom_glu: - return 'Glutamate' + return "Glutamate" elif neuron in self.dom_ach: - return 'Acetylcholine' + return "Acetylcholine" elif neuron in self.dom_gaba: - return 'GABA' + return "GABA" else: - - nt = 'Generic_CS' + nt = "Generic_CS" if neuron in self.alt_glu: - nt += '_Glutamate' + nt += "_Glutamate" if neuron in self.alt_ach: - nt += '_Acetylcholine' + nt += "_Acetylcholine" if neuron in self.dom_gaba: - nt += '_GABA' + nt += "_GABA" return nt @@ -72,23 +70,23 @@ def read_data(self, include_nonconnected_cells=False): for pre in self.all_cells: apre = self.atlas.ids_to_ai([pre]) for post in self.all_cells: - apost = self.atlas.ids_to_ai([post]) + apost = self.atlas.ids_to_ai([post]) connection = False gji = gj[apost, apre] num = gji[0] - if num>0: - #print("Gap junc (%s (%i) -> %s (%i): %s"%(pre, apre, post, apost, gji)) - synclass = 'Generic_GJ' + if num > 0: + # print("Gap junc (%s (%i) -> %s (%i): %s"%(pre, apre, post, apost, gji)) + synclass = "Generic_GJ" syntype = "GapJunction" conns.append(ConnectionInfo(pre, post, num, syntype, synclass)) connection = True csi = cs[apost, apre] num = csi[0] - if num>0: - #print("Chem syn (%s (%i) -> %s (%i): %s"%(pre, apre, post, apost, gji)) + if num > 0: + # print("Chem syn (%s (%i) -> %s (%i): %s"%(pre, apre, post, apost, gji)) synclass = self.determine_nt(pre) syntype = "Chemical" conns.append(ConnectionInfo(pre, post, num, syntype, synclass)) @@ -99,7 +97,7 @@ def read_data(self, include_nonconnected_cells=False): connected_cells.append(pre) if not post in connected_cells: connected_cells.append(post) - + if include_nonconnected_cells: return self.all_cells, conns else: @@ -111,13 +109,13 @@ def read_muscle_data(self): conns = [] return neurons, muscles, conns + READER = WormNeuroAtlasReader() read_data = READER.read_data read_muscle_data = READER.read_muscle_data if __name__ == "__main__": - cells, neuron_conns = read_data(include_nonconnected_cells=True) neurons2muscles, muscles, muscle_conns = read_muscle_data() diff --git a/c302/__init__.py b/c302/__init__.py index 581c08b8..4ab74976 100755 --- a/c302/__init__.py +++ b/c302/__init__.py @@ -37,15 +37,23 @@ from lxml import etree import re +import json + import collections -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 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 + + owmeta_installed = True +except: + print("owmeta not installed! Proceeding anyway...") + owmeta_installed = False try: from urllib2 import URLError # Python 2 @@ -56,19 +64,23 @@ here = os.path.abspath(os.path.dirname(__file__)) about = {} -with open(os.path.join(here, '__version__.py')) as version_file: - exec (version_file.read(), about) -__version__ = about['__version__'] +with open(os.path.join(here, "__version__.py")) as version_file: + exec(version_file.read(), about) +__version__ = about["__version__"] LEMS_TEMPLATE_FILE = "LEMS_c302_TEMPLATE.xml" -MUSCLE_RE = re.compile(r'M([VD][LR])(\d+)') +MUSCLE_RE = re.compile(r"M([VD][LR])(\d+)") +OWMETA_CACHED_DATA_FILE = ( + os.path.dirname(os.path.abspath(__file__)) + "/data/owmeta_cache.json" +) -def print_(msg, print_it=True): # print_it=False when not verbose + +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))) + print("%s %s" % (pre, msg.replace("\n", "\n" + pre))) def load_data_reader(data_reader="SpreadsheetDataReader"): @@ -79,7 +91,7 @@ def load_data_reader(data_reader="SpreadsheetDataReader"): Returns: reader (obj): The data reader object """ - return importlib.import_module('c302.%s'%data_reader) + return importlib.import_module("c302.%s" % data_reader) def get_str_from_expnotation(num): @@ -90,15 +102,15 @@ def get_str_from_expnotation(num): Returns: (str): A string representing a float with 15 fractional digits. """ - return '{0:.15f}'.format(num) + return "{0:.15f}".format(num) def get_muscle_position(muscle, data_reader="SpreadsheetDataReader"): - if muscle=='MANAL' or muscle=='MVULVA': - return 0,0,0 + 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+)' + pat1 = r"M([VD])([LR])(\d+)" + pat2 = r"([VD])([LR])(\d+)" md = re.fullmatch(pat1, muscle) if not md: md = re.fullmatch(pat2, muscle) @@ -107,12 +119,12 @@ def get_muscle_position(muscle, data_reader="SpreadsheetDataReader"): 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) + 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) + raise Exception("Unrecognized muscle name format %s" % muscle) def is_muscle(cell_name): @@ -123,128 +135,163 @@ def process_args(): """ Parse command-line arguments. """ - 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='', - help='Unique reference for new network') - - parser.add_argument('parameters', type=str, metavar='', - help='Set of biophysical parametes to use, e.g. parameters_A') - - parser.add_argument('-datareader', - type=str, - metavar='', - default="SpreadsheetDataReader", - help='Use a specific data reader. Possible values are: "SpreadsheetDataReader". (default: SpreadsheetDataReader)') - - parser.add_argument('-cells', - type=str, - metavar='', - default=None, - help='List of cells to include in network (default: all)') - - parser.add_argument('-cellstoplot', - type=str, - metavar='', - default=None, - help='List of cells to plot (default: all)') - - parser.add_argument('-cellstostimulate', - type=str, - metavar='', - default=None, - help='List of cells to stimulate (default: all)') - - parser.add_argument('-connpolarityoverride', - type=str, - metavar='', - default=None, - help='Map of connection polarities to override, e.g. {"AVAL-AVBR":"inh", ...} => use inhibitory connection for AVAL-AVBR') - - parser.add_argument('-connnumberoverride', - type=str, - metavar='', - default=None, - help='Map of connection numbers to override, e.g. {"I1L-I3":2.5, "AVAR-AVBL_GJ":2} => use 2.5 connections from I1L to I3, use 2 connections for GJ AVAR-AVBL') - - - parser.add_argument('-paramoverride', - type=str, - metavar='', - default=None, - help='Map of parameters to override, e.g. {"unphysiological_offset_current":"2pA", ...} => use 2pA for additional offset currnet') - - parser.add_argument('-connnumberscaling', - type=str, - metavar='', - default=None, - help='Map of scaling factors for connection numbers, e.g. {"I1L-I3":2, "AVAR-AVBL_GJ":2} => use 2 times as many connections from I1L to I3, use 2 times as many connections for GJ AVAR-AVBL') - - parser.add_argument('-musclestoinclude', - type=str, - metavar='', - default=[], - help='List of muscles to include (default: empty list, i.e. none)') - - parser.add_argument('-duration', - type=float, - metavar='', - default=100, - help='Duration of simulation in ms') - - parser.add_argument('-dt', - type=float, - metavar='