From 160bf5503d3ed07a3c13fa32c83c5aeb2bef92f1 Mon Sep 17 00:00:00 2001 From: Mark Watts Date: Wed, 6 Feb 2019 20:37:03 -0600 Subject: [PATCH] Updating PyOpenWorm-related code (openworm/c302#10) --- c302/__init__.py | 272 +++++++++++++++++++++++------------------------ 1 file changed, 134 insertions(+), 138 deletions(-) diff --git a/c302/__init__.py b/c302/__init__.py index 850f4e64..57dfec54 100755 --- a/c302/__init__.py +++ b/c302/__init__.py @@ -1,4 +1,5 @@ #! /usr/bin/env python +from __future__ import print_function from neuroml import NeuroMLDocument from neuroml import Network @@ -23,7 +24,12 @@ import neuroml.writers as writers import neuroml.loaders as loaders -import bioparameters +from . import bioparameters +from PyOpenWorm import connect as pow_connect +from PyOpenWorm.neuron import Neuron +from PyOpenWorm.cell import Cell +from PyOpenWorm.muscle import Muscle +from PyOpenWorm.worm import Worm import airspeed @@ -33,6 +39,7 @@ import os import importlib import math +import traceback from lxml import etree import re @@ -62,15 +69,6 @@ def print_(msg, print_it=True): # print_it=False when not verbose pre = "c302 >>> " print('%s %s'%(pre,msg.replace('\n','\n'+pre))) -try: - import PyOpenWorm as P - print_("Connecting to the PyOpenWorm database...") - P.connect() -except Exception as e: - P = None - print_("Can't connect to PyOpenWorm: ...") - print(e) - def load_data_reader(data_reader="SpreadsheetDataReader"): """ @@ -99,7 +97,7 @@ def get_muscle_position(muscle, data_reader="SpreadsheetDataReader"): z = 80 * (-1 if muscle[4] == 'L' else 1) y = -300 + 30 * int(muscle[5:7]) return x, y, z""" - + 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]) @@ -213,7 +211,7 @@ def process_args(): # soma positions from http://www.wormatlas.org/neuronalwiring.html - 2.2 Neuron Description (Neuron Types) VB_soma_pos = { 'VB1':0.21, - 'VB2':0.19, + 'VB2':0.19, 'VB3':0.28, 'VB4':0.32, 'VB5':0.38, @@ -227,7 +225,7 @@ def process_args(): DB_soma_pos = { 'DB1':0.24, - 'DB2':0.21, + 'DB2':0.21, 'DB3':0.3, 'DB4':0.39, 'DB5':0.51, @@ -248,7 +246,7 @@ def get_next_stim_id(nml_doc, cell): def get_cell_position(cell): root_dir = os.path.dirname(os.path.abspath(__file__)) #cell_file_path = root_dir + "/../../../" if test else root_dir + "/../../" # if running test - cell_file_path = root_dir + "/" + cell_file_path = root_dir + "/" cell_file = cell_file_path + 'NeuroML2/%s.cell.nml' % cell doc = loaders.NeuroMLLoader.load(cell_file) location = doc.cells[0].morphology.segments[0].proximal @@ -267,7 +265,7 @@ def append_input_to_nml_input_list(stim, nml_doc, cell, params): def add_new_sinusoidal_input(nml_doc, cell, delay, duration, amplitude, period, params): id = get_next_stim_id(nml_doc, cell) - + if cell.startswith("VB"): phase = VB_soma_pos[cell] else: @@ -275,21 +273,21 @@ def add_new_sinusoidal_input(nml_doc, cell, delay, duration, amplitude, period, #phase = get_cell_position(cell).x phase = phase * -0.886 print_("### CELL %s PHASE: %s" % (cell, phase)) - + if cell.startswith("VB"): if amplitude.startswith("-"): amplitude = amplitude[1:] else: amplitude = "-" + amplitude - - - + + + input = SineGenerator(id=id, delay=delay, phase=phase, duration=duration, amplitude=amplitude, period=period) nml_doc.sine_generators.append(input) append_input_to_nml_input_list(input, nml_doc, cell, params) - - + + def add_new_input(nml_doc, cell, delay, duration, amplitude, params): id = get_next_stim_id(nml_doc, cell) @@ -320,11 +318,11 @@ def merge_with_template(model, templfile): -def write_to_file(nml_doc, - lems_info, - reference, - template_path='', - validate=True, +def write_to_file(nml_doc, + lems_info, + reference, + template_path='', + validate=True, verbose=True, target_directory='.'): @@ -334,7 +332,7 @@ def write_to_file(nml_doc, print_("Writing generated network to: %s"%os.path.realpath(nml_file)) writers.NeuroMLWriter.write(nml_doc, nml_file) - if verbose: + if verbose: print_("Written network file to: "+nml_file) lems_file_name = target_directory+'/'+'LEMS_%s.xml'%reference @@ -343,7 +341,7 @@ def write_to_file(nml_doc, merged = merge_with_template(lems_info, template_path+LEMS_TEMPLATE_FILE) lems.write(merged) - if verbose: + if verbose: print_("Written LEMS file to: "+lems_file_name) if validate: @@ -376,34 +374,34 @@ def get_random_colour_hex(): def get_file_name_relative_to_c302(file_name): - + if 'C302_HOME' in os.environ: return os.path.relpath(os.environ['C302_HOME'],file_name) - - + + def get_cell_names_and_connection(data_reader="SpreadsheetDataReader", test=False): - + # Use the spreadsheet reader to give a list of all cells and a list of all connections # 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).readDataFromSpreadsheet(include_nonconnected_cells=True) cell_names.sort() - + return cell_names, conns 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).readMuscleDataFromSpreadsheet() all_muscles = get_muscle_names() - + return mneurons, all_muscles, muscle_conns @@ -419,7 +417,7 @@ def get_cell_id_string(cell, params, muscle=False): return "../%s/0/%s"%(cell, params.generic_neuron_cell.id) else: return "../%s/0/%s"%(cell, params.generic_muscle_cell.id) - + else: if not muscle: return "../%s/0/%s"%(cell, cell) @@ -443,64 +441,59 @@ def elem_in_coll_matches_conn(coll, conn): def _get_cell_info(cells): - - if P==None: - #print_("Couldn't connect to PyOpenWorm...") - return None, None #Get the worm object. - worm = P.Worm() + worm = Worm() #Extract the network object from the worm object. - net = worm.neuron_network() + qcell = Cell() + worm.cell(qcell) #Go through our list and get the neuron object associated with each name. #Store these in another list. - some_neurons = [P.Neuron(name) for name in cells] 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() - + + for cell in qcell.load(): + short = ') %s' % cell.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()): + if isinstance(cell, Neuron): + types = cell.type() + if 'sensory' in types: + short = 'Se%s'%short + color = '1 .2 1' + if 'interneuron' in types: + short = 'In%s'%short + color = '1 0 .4' + if 'motor' in types: + short = 'Mo%s'%short + color = '.5 .4 1' + elif isinstance(cell, Muscle): short = 'Mu%s'%short color = '0 0.6 0' - - + + short = '(%s'%short - - - if 'GABA' in neuron.neurotransmitter(): - short = '- %s'%short - elif len(neuron.neurotransmitter())==0: - short = '? %s'%short - else: - short = '+ %s'%short - - info = (neuron, neuron.type(), neuron.receptor(), neuron.neurotransmitter(), short, color) - #print dir(neuron) - - if is_muscle(neuron.name()): - all_muscle_info[neuron.name()] = info + + + if isinstance(cell, Neuron): + if 'GABA' in cell.neurotransmitter(): + short = '- %s'%short + elif len(cell.neurotransmitter()) == 0: + short = '? %s'%short + else: + short = '+ %s'%short else: - all_neuron_info[neuron.name()] = info - + short = '? %s'%short + + if isinstance(cell, Neuron): + all_neuron_info[cell.name()] = (cell, cell.type(), cell.receptor(), cell.neurotransmitter(), short, color) + elif isinstance(cell, Muscle): + all_muscle_info[cell.name()] = (cell, [], cell.receptors(), cell.neurotransmitter(), short, color) + + return all_neuron_info, all_muscle_info - + def set_param(params, param, value): v = params.get_bioparameter(param,warn_if_missing=False) @@ -529,7 +522,7 @@ def mirror_param(params, k, v): set_param(params, override_key1, v) set_param(params, override_key2, v) - + def generate(net_id, params, data_reader = "SpreadsheetDataReader", @@ -552,9 +545,11 @@ def generate(net_id, print_connections=False, param_overrides={}, target_directory='./'): - + + pow_connect(configFile='.pow/pow.conf') + validate = not (params.is_level_B() or params.is_level_C0() or params.is_level_C2 or params.is_level_D1()) - + root_dir = os.path.dirname(os.path.abspath(__file__)) regex_param_overrides = {'mirrored_elec_conn_params':{}} @@ -580,18 +575,18 @@ def generate(net_id, params.create_models() - + if vmin==None: if params.is_level_A() or params.is_level_B(): - vmin=-52 + vmin=-52 elif params.is_level_C(): vmin=-60 elif params.is_level_D(): vmin=-60 else: - vmin=-52 - - + vmin=-52 + + if vmax==None: if params.is_level_A() or params.is_level_B(): vmax=-28 @@ -601,7 +596,7 @@ def generate(net_id, vmax=25 else: vmax=-28 - + random.seed(seed) info = "\n\nParameters and setting used to generate this network:\n\n"+\ @@ -622,14 +617,14 @@ def generate(net_id, nml_doc = NeuroMLDocument(id=net_id, notes=info) if params.is_level_A() or params.is_level_B() or params.level == "BC1": - nml_doc.iaf_cells.append(params.generic_muscle_cell) - nml_doc.iaf_cells.append(params.generic_neuron_cell) + nml_doc.iaf_cells.append(params.generic_muscle_cell) + nml_doc.iaf_cells.append(params.generic_neuron_cell) elif params.is_level_C(): nml_doc.cells.append(params.generic_muscle_cell) nml_doc.cells.append(params.generic_neuron_cell) elif params.is_level_D(): nml_doc.cells.append(params.generic_muscle_cell) - + net = Network(id=net_id) @@ -699,14 +694,14 @@ def generate(net_id, etree.ElementTree(root).write(os.path.join(target_directory, ctd), pretty_print=True) else: shutil.copy(def_file, target_directory) - + if target_directory == './' and not os.path.isfile(ctd): ctd = '%s/%s'%(os.path.dirname(__file__),ctd) lems_info["includes"].append(ctd) nml_doc.includes.append(IncludeType(href=ctd)) - - + + import backers cells_vs_name = backers.get_adopted_cell_names() @@ -733,27 +728,28 @@ def generate(net_id, type="populationList", size="1") cell_id = cell - + try: all_neuron_info, all_muscle_info = _get_cell_info([cell]) #neuron, neuron.type(), neuron.receptor(), neuron.neurotransmitter(), short, color - pop0.properties.append(Property("color", all_neuron_info[cell][5])) + 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)))) + pop0.properties.append(Property("type", str('; '.join(types)))) recps = sorted(all_neuron_info[cell][2]) pop0.properties.append(Property("receptor", str('; '.join(recps)))) - pop0.properties.append(Property("neurotransmitter", str('; '.join(all_neuron_info[cell][3])))) - except: - # It's only metadata... + pop0.properties.append(Property("neurotransmitter", str('; '.join(all_neuron_info[cell][3])))) + except Exception as e: + print("Skipping PyOpenWorm metadata", file=sys.stderr) + traceback.print_exc() pass - + pop0.instances.append(inst) # put that Population into the Network data structure from above net.populations.append(pop0) - + if cell in cells_vs_name: p = Property(tag="OpenWormBackerAssignedName", value=cells_vs_name[cell]) pop0.properties.append(p) @@ -764,44 +760,44 @@ def generate(net_id, cell_file = cell_file_path+'NeuroML2/%s.cell.nml'%cell doc = loaders.NeuroMLLoader.load(cell_file) all_cells[cell] = doc.cells[0] - - + + if params.is_level_D(): new_cell = params.create_neuron_cell(cell, doc.cells[0].morphology) - + nml_cell_doc = NeuroMLDocument(id=cell) nml_cell_doc.cells.append(new_cell) new_cell_file = 'cells/'+cell+'_D.cell.nml' nml_file = target_directory+'/'+new_cell_file print_("Writing new cell to: %s"%os.path.realpath(nml_file)) writers.NeuroMLWriter.write(nml_cell_doc, nml_file) - + nml_doc.includes.append(IncludeType(href=new_cell_file)) lems_info["includes"].append(new_cell_file) - + inst.location = Location(0,0,0) else: location = doc.cells[0].morphology.segments[0].proximal - + inst.location = Location(float(location.x), float(location.y), float(location.z)) - - if verbose: + + if verbose: print_("Loaded morphology: %s; id: %s; placing at location: (%s, %s, %s)"%(os.path.realpath(cell_file), all_cells[cell].id, inst.location.x, inst.location.y, inst.location.z)) - + if cells_to_stimulate is None or cell in cells_to_stimulate: target = "../%s/0/%s"%(pop0.id, cell_id) if params.is_level_D(): target+="/0" - + input_list = InputList(id="Input_%s_%s"%(cell,params.offset_current.id), component=params.offset_current.id, populations='%s'%cell) - input_list.input.append(Input(id=0, - target=target, + input_list.input.append(Input(id=0, + target=target, destination="synapses")) net.input_lists.append(input_list) @@ -851,20 +847,20 @@ def generate(net_id, count+=1 - if verbose: + if verbose: print_("Finished loading %i cells"%count) - + mneurons, all_muscles, muscle_conns = get_cell_muscle_names_and_connection(data_reader) #if data_reader == "SpreadsheetDataReader": # all_muscles = get_muscle_names() - + if muscles_to_include == None or muscles_to_include == True: muscles_to_include = all_muscles elif muscles_to_include == False: muscles_to_include = [] - + for m in muscles_to_include: assert m in all_muscles @@ -912,7 +908,7 @@ def generate(net_id, plot["colour"] = get_random_colour_hex() plot["quantity"] = "%s/0/%s/activity" % (muscle, params.generic_muscle_cell.id) lems_info["muscle_activity_plots"].append(plot) - + if params.generic_muscle_cell.__class__.__name__ == 'Cell': plot = {} @@ -940,27 +936,27 @@ def generate(net_id, lems_info["muscles"].append(muscle) muscle_count+=1 - + if cells_to_stimulate!=None and muscle in cells_to_stimulate: target = "../%s/0/%s"%(pop0.id, params.generic_muscle_cell.id) if params.is_level_D(): target+="/0" - + input_list = InputList(id="Input_%s_%s"%(muscle,params.offset_current.id), component=params.offset_current.id, populations='%s'%pop0.id) - input_list.input.append(Input(id=0, - target=target, + input_list.input.append(Input(id=0, + target=target, destination="synapses")) net.input_lists.append(input_list) - if verbose: + if verbose: print_("Finished creating %i muscles"%muscle_count) - - + + existing_synapses = {} for conn in conns: @@ -978,7 +974,7 @@ def generate(net_id, conn_pol = "exc" orig_pol = "exc" - + if 'GABA' in conn.synclass: conn_pol = "inh" orig_pol = "inh" @@ -1100,7 +1096,7 @@ def generate(net_id, print "%s num:%s" % (conn_shorthand, number_syns) else: print "%s %s num:%s" % (conn_shorthand, orig_pol, number_syns)""" - + if number_syns != conn.number: if analog_conn or elect_conn: magnitude, unit = bioparameters.split_neuroml_quantity(syn0.conductance) @@ -1109,7 +1105,7 @@ def generate(net_id, cond0 = "%s%s"%(magnitude*conn.number, unit) cond1 = "%s%s" % (get_str_from_expnotation(magnitude * number_syns), unit) gj = "" if not elect_conn else " GapJunction" - if verbose: + if verbose: print_(">> Changing number of effective synapses connection %s -> %s%s: was: %s (total cond: %s), becomes %s (total cond: %s)" % \ (conn.pre_cell, conn.post_cell, gj, conn.number, cond0, number_syns, cond1)) @@ -1141,9 +1137,9 @@ def generate(net_id, weight=number_syns) proj0.electrical_connection_instance_ws.append(conn0) - + elif analog_conn: - + proj0 = ContinuousProjection(id=proj_id, \ presynaptic_population=conn.pre_cell, postsynaptic_population=conn.post_cell) @@ -1161,8 +1157,8 @@ def generate(net_id, weight=number_syns) proj0.continuous_connection_instance_ws.append(conn0) - - + + else: proj0 = Projection(id=proj_id, \ @@ -1299,7 +1295,7 @@ def generate(net_id, scale = params.get_bioparameter('global_connectivity_power_scaling').x() #print("Scaling by %s"%scale) number_syns = math.pow(number_syns,scale) - + if conn_number_override: for conn_num_override in conn_number_override.keys(): if conn_num_override == conn_shorthand: @@ -1365,7 +1361,7 @@ def generate(net_id, weight=number_syns) proj0.electrical_connection_instance_ws.append(conn0) - + elif analog_conn: proj0 = ContinuousProjection(id=proj_id, \ @@ -1450,7 +1446,7 @@ def parse_dict_arg(dict_arg): def main(): args = process_args() - + exec('from %s import ParameterisedModel'%args.parameters, globals()) params = ParameterisedModel()