def save_to_file(self, file_name=None): if file_name is None: file_name = "LEMS_%s.xml" % self.lems_info['sim_id'] lems_file = open(file_name, 'w') lems_file.write(self.to_xml()) lems_file.close() print_comment("Written LEMS Simulation %s to file: %s" % (self.lems_info['sim_id'], file_name), True) return file_name
def save_to_file(self, file_name=None): if file_name==None: file_name = "LEMS_%s.xml"%self.lems_info['sim_id'] lems_file = open(file_name, 'w') lems_file.write(self.to_xml()) lems_file.close() print_comment("Written LEMS Simulation %s to file: %s"%(self.lems_info['sim_id'], file_name), True) return file_name
def generate_lems_channel_analyser(channel_file, channel, min_target_voltage, step_target_voltage, max_target_voltage, clamp_delay, clamp_duration, clamp_base_voltage, duration, erev, gates, temperature, ca_conc, iv_curve, scale_dt=1, dat_suffix='',verbose=True): print_comment(("Generating LEMS file to investigate %s in %s, %smV->%smV, " "%sdegC") % (channel,channel_file, min_target_voltage, max_target_voltage, temperature), verbose) target_voltages = [] v = min_target_voltage while v <= max_target_voltage: target_voltages.append(v) v+=step_target_voltage target_voltages_map = [] for t in target_voltages: fract = float(target_voltages.index(t)) / (len(target_voltages)-1) info = {} info["v"] = t info["v_str"] = str(t).replace("-", "min") info["col"] = get_colour_hex(fract) target_voltages_map.append(info) includes = get_includes_from_channel_file(channel_file) includes_relative = [] base_path = os.path.dirname(channel_file) for inc in includes: includes_relative.append(os.path.abspath(base_path+'/'+inc)) model = {"channel_file": channel_file, "includes": includes_relative, "channel": channel, "target_voltages" : target_voltages_map, "clamp_delay": clamp_delay, "clamp_duration": clamp_duration, "clamp_base_voltage": clamp_base_voltage, "min_target_voltage": min_target_voltage, "max_target_voltage": max_target_voltage, "duration": duration, "scale_dt": scale_dt, "erev": erev, "gates": gates, "temperature": temperature, "ca_conc": ca_conc, "iv_curve": iv_curve, "dat_suffix": dat_suffix} #pp.pprint(model) merged = merge_with_template(model, TEMPLATE_FILE) return merged
def save_to_file(self, file_name=None): if file_name == None: file_name = "LEMS_%s.xml" % self.lems_info['sim_id'] lems_file = open(file_name, 'w') lems_file.write(self.to_xml()) lems_file.close() print_comment( "Written LEMS Simulation %s to file: %s" % (self.lems_info['sim_id'], file_name), True) return file_name # main method example moved to examples/create_new_lems_file.py
def show(self): """ Plot the result of the simulation once it's been intialized """ from matplotlib import pyplot as plt if self.already_run: for ref in self.volts.keys(): plt.plot(self.t, self.volts[ref], label=ref) plt.title("Simulation voltage vs time") plt.legend() plt.xlabel("Time [ms]") plt.ylabel("Voltage [mV]") else: pynml.print_comment("First you have to 'go()' the simulation.", True) plt.show()
def generate_current_vs_frequency_curve(nml2_file, cell_id, start_amp_nA=-0.1, end_amp_nA=0.1, step_nA=0.01, custom_amps_nA=[], analysis_duration=1000, analysis_delay=0, pre_zero_pulse=0, post_zero_pulse=0, dt=0.05, temperature="32degC", spike_threshold_mV=0., plot_voltage_traces=False, plot_if=True, plot_iv=False, xlim_if=None, ylim_if=None, xlim_iv=None, ylim_iv=None, label_xaxis=True, label_yaxis=True, show_volts_label=True, grid=True, font_size=12, if_iv_color='k', linewidth=1, bottom_left_spines_only=False, show_plot_already=True, save_voltage_traces_to=None, save_if_figure_to=None, save_iv_figure_to=None, save_if_data_to=None, save_iv_data_to=None, simulator="jNeuroML", num_processors=1, include_included=True, title_above_plot=False, return_axes=False, verbose=False): print_comment( "Running generate_current_vs_frequency_curve() on %s (%s)" % (nml2_file, os.path.abspath(nml2_file)), verbose) from pyelectro.analysis import max_min from pyelectro.analysis import mean_spike_frequency import numpy as np traces_ax = None if_ax = None iv_ax = None sim_id = 'iv_%s' % cell_id total_duration = pre_zero_pulse + analysis_duration + analysis_delay + post_zero_pulse pulse_duration = analysis_duration + analysis_delay end_stim = pre_zero_pulse + analysis_duration + analysis_delay ls = LEMSSimulation(sim_id, total_duration, dt) ls.include_neuroml2_file(nml2_file, include_included=include_included) stims = [] if len(custom_amps_nA) > 0: stims = [float(a) for a in custom_amps_nA] stim_info = ['%snA' % float(a) for a in custom_amps_nA] else: amp = start_amp_nA while amp <= end_amp_nA: stims.append(amp) amp += step_nA stim_info = '(%snA->%snA; %s steps of %snA; %sms)' % ( start_amp_nA, end_amp_nA, len(stims), step_nA, total_duration) print_comment_v("Generating an IF curve for cell %s in %s using %s %s" % (cell_id, nml2_file, simulator, stim_info)) number_cells = len(stims) pop = nml.Population(id="population_of_%s" % cell_id, component=cell_id, size=number_cells) # create network and add populations net_id = "network_of_%s" % cell_id net = nml.Network(id=net_id, type="networkWithTemperature", temperature=temperature) ls.assign_simulation_target(net_id) net_doc = nml.NeuroMLDocument(id=net.id) net_doc.networks.append(net) net_doc.includes.append(nml.IncludeType(nml2_file)) net.populations.append(pop) for i in range(number_cells): stim_amp = "%snA" % stims[i] input_id = ("input_%s" % stim_amp).replace('.', '_').replace('-', 'min') pg = nml.PulseGenerator(id=input_id, delay="%sms" % pre_zero_pulse, duration="%sms" % pulse_duration, amplitude=stim_amp) net_doc.pulse_generators.append(pg) # Add these to cells input_list = nml.InputList(id=input_id, component=pg.id, populations=pop.id) input = nml.Input(id='0', target="../%s[%i]" % (pop.id, i), destination="synapses") input_list.input.append(input) net.input_lists.append(input_list) net_file_name = '%s.net.nml' % sim_id pynml.write_neuroml2_file(net_doc, net_file_name) ls.include_neuroml2_file(net_file_name) disp0 = 'Voltage_display' ls.create_display(disp0, "Voltages", "-90", "50") of0 = 'Volts_file' ls.create_output_file(of0, "%s.v.dat" % sim_id) for i in range(number_cells): ref = "v_cell%i" % i quantity = "%s[%i]/v" % (pop.id, i) ls.add_line_to_display(disp0, ref, quantity, "1mV", pynml.get_next_hex_color()) ls.add_column_to_output_file(of0, ref, quantity) lems_file_name = ls.save_to_file() print_comment( "Written LEMS file %s (%s)" % (lems_file_name, os.path.abspath(lems_file_name)), verbose) if simulator == "jNeuroML": results = pynml.run_lems_with_jneuroml(lems_file_name, nogui=True, load_saved_data=True, plot=False, show_plot_already=False, verbose=verbose) elif simulator == "jNeuroML_NEURON": results = pynml.run_lems_with_jneuroml_neuron(lems_file_name, nogui=True, load_saved_data=True, plot=False, show_plot_already=False, verbose=verbose) elif simulator == "jNeuroML_NetPyNE": results = pynml.run_lems_with_jneuroml_netpyne( lems_file_name, nogui=True, load_saved_data=True, plot=False, show_plot_already=False, num_processors=num_processors, verbose=verbose) else: raise Exception( "Sorry, cannot yet run current vs frequency analysis using simulator %s" % simulator) print_comment( "Completed run in simulator %s (results: %s)" % (simulator, results.keys()), verbose) #print(results.keys()) times_results = [] volts_results = [] volts_labels = [] if_results = {} iv_results = {} for i in range(number_cells): t = np.array(results['t']) * 1000 v = np.array(results["%s[%i]/v" % (pop.id, i)]) * 1000 if plot_voltage_traces: times_results.append(t) volts_results.append(v) volts_labels.append("%s nA" % stims[i]) mm = max_min(v, t, delta=0, peak_threshold=spike_threshold_mV) spike_times = mm['maxima_times'] freq = 0 if len(spike_times) > 2: count = 0 for s in spike_times: if s >= pre_zero_pulse + analysis_delay and s < ( pre_zero_pulse + analysis_duration + analysis_delay): count += 1 freq = 1000 * count / float(analysis_duration) mean_freq = mean_spike_frequency(spike_times) #print("--- %s nA, spike times: %s, mean_spike_frequency: %f, freq (%fms -> %fms): %f"%(stims[i],spike_times, mean_freq, analysis_delay, analysis_duration+analysis_delay, freq)) if_results[stims[i]] = freq if freq == 0: if post_zero_pulse == 0: iv_results[stims[i]] = v[-1] else: v_end = None for j in range(len(t)): if v_end == None and t[j] >= end_stim: v_end = v[j] iv_results[stims[i]] = v_end if plot_voltage_traces: traces_ax = pynml.generate_plot( times_results, volts_results, "Membrane potential traces for: %s" % nml2_file, xaxis='Time (ms)' if label_xaxis else ' ', yaxis='Membrane potential (mV)' if label_yaxis else '', xlim=[total_duration * -0.05, total_duration * 1.05], show_xticklabels=label_xaxis, font_size=font_size, bottom_left_spines_only=bottom_left_spines_only, grid=False, labels=volts_labels if show_volts_label else [], show_plot_already=False, save_figure_to=save_voltage_traces_to, title_above_plot=title_above_plot, verbose=verbose) if plot_if: stims = sorted(if_results.keys()) stims_pA = [ii * 1000 for ii in stims] freqs = [if_results[s] for s in stims] if_ax = pynml.generate_plot( [stims_pA], [freqs], "Firing frequency versus injected current for: %s" % nml2_file, colors=[if_iv_color], linestyles=['-'], markers=['o'], linewidths=[linewidth], xaxis='Input current (pA)' if label_xaxis else ' ', yaxis='Firing frequency (Hz)' if label_yaxis else '', xlim=xlim_if, ylim=ylim_if, show_xticklabels=label_xaxis, show_yticklabels=label_yaxis, font_size=font_size, bottom_left_spines_only=bottom_left_spines_only, grid=grid, show_plot_already=False, save_figure_to=save_if_figure_to, title_above_plot=title_above_plot, verbose=verbose) if save_if_data_to: with open(save_if_data_to, 'w') as if_file: for i in range(len(stims_pA)): if_file.write("%s\t%s\n" % (stims_pA[i], freqs[i])) if plot_iv: stims = sorted(iv_results.keys()) stims_pA = [ii * 1000 for ii in sorted(iv_results.keys())] vs = [iv_results[s] for s in stims] xs = [] ys = [] xs.append([]) ys.append([]) for si in range(len(stims)): stim = stims[si] if len(custom_amps_nA) == 0 and si > 1 and ( stims[si] - stims[si - 1]) > step_nA * 1.01: xs.append([]) ys.append([]) xs[-1].append(stim * 1000) ys[-1].append(iv_results[stim]) iv_ax = pynml.generate_plot( xs, ys, "V at %sms versus I below threshold for: %s" % (end_stim, nml2_file), colors=[if_iv_color for s in xs], linestyles=['-' for s in xs], markers=['o' for s in xs], xaxis='Input current (pA)' if label_xaxis else '', yaxis='Membrane potential (mV)' if label_yaxis else '', xlim=xlim_iv, ylim=ylim_iv, show_xticklabels=label_xaxis, show_yticklabels=label_yaxis, font_size=font_size, linewidths=[linewidth for s in xs], bottom_left_spines_only=bottom_left_spines_only, grid=grid, show_plot_already=False, save_figure_to=save_iv_figure_to, title_above_plot=title_above_plot, verbose=verbose) if save_iv_data_to: with open(save_iv_data_to, 'w') as iv_file: for i in range(len(stims_pA)): iv_file.write("%s\t%s\n" % (stims_pA[i], vs[i])) if show_plot_already: from matplotlib import pyplot as plt plt.show() if return_axes: return traces_ax, if_ax, iv_ax return if_results
def generate_lems_file_for_neuroml( sim_id, neuroml_file, target, duration, dt, lems_file_name, target_dir, nml_doc=None, # Use this if the nml doc has already been loaded (to avoid delay in reload) include_extra_files=[], gen_plots_for_all_v=True, plot_all_segments=False, gen_plots_for_quantities={}, # Dict with displays vs lists of quantity paths gen_plots_for_only_populations=[], # List of populations, all pops if=[] gen_saves_for_all_v=True, save_all_segments=False, gen_saves_for_only_populations=[], # List of populations, all pops if=[] gen_saves_for_quantities={}, # Dict with file names vs lists of quantity paths gen_spike_saves_for_all_somas=False, gen_spike_saves_for_only_populations=[], # List of populations, all pops if=[] gen_spike_saves_for_cells={}, # Dict with file names vs lists of quantity paths spike_time_format='ID_TIME', copy_neuroml=True, report_file_name=None, lems_file_generate_seed=None, verbose=False, simulation_seed=12345): my_random = random.Random() if lems_file_generate_seed: my_random.seed( lems_file_generate_seed ) # To ensure same LEMS file (e.g. colours of plots) are generated every time for the same input else: my_random.seed( 12345 ) # To ensure same LEMS file (e.g. colours of plots) are generated every time for the same input file_name_full = '%s/%s' % (target_dir, lems_file_name) print_comment_v( 'Creating LEMS file at: %s for NeuroML 2 file: %s (copy: %s)' % (file_name_full, neuroml_file, copy_neuroml)) ls = LEMSSimulation(sim_id, duration, dt, target, simulation_seed=simulation_seed) if nml_doc is None: nml_doc = read_neuroml2_file(neuroml_file, include_includes=True, verbose=verbose) nml_doc_inc_not_included = read_neuroml2_file(neuroml_file, include_includes=False, verbose=False) else: nml_doc_inc_not_included = nml_doc ls.set_report_file(report_file_name) quantities_saved = [] for f in include_extra_files: ls.include_neuroml2_file(f, include_included=False) if not copy_neuroml: rel_nml_file = os.path.relpath(os.path.abspath(neuroml_file), os.path.abspath(target_dir)) print_comment_v("Including existing NeuroML file (%s) as: %s" % (neuroml_file, rel_nml_file)) ls.include_neuroml2_file(rel_nml_file, include_included=True, relative_to_dir=os.path.abspath(target_dir)) else: print_comment_v( "Copying a NeuroML file (%s) to: %s (abs path: %s)" % (neuroml_file, target_dir, os.path.abspath(target_dir))) if not os.path.isdir(target_dir): raise Exception("Target directory %s does not exist!" % target_dir) if os.path.realpath( os.path.dirname(neuroml_file)) != os.path.realpath(target_dir): shutil.copy(neuroml_file, target_dir) else: print_comment_v("No need, same file...") neuroml_file_name = os.path.basename(neuroml_file) ls.include_neuroml2_file(neuroml_file_name, include_included=False) nml_dir = os.path.dirname(neuroml_file) if len( os.path.dirname(neuroml_file)) > 0 else '.' for include in nml_doc_inc_not_included.includes: if nml_dir == '.' and os.path.isfile(include.href): incl_curr = include.href else: incl_curr = '%s/%s' % (nml_dir, include.href) if os.path.isfile(include.href): incl_curr = include.href print_comment_v( ' - Including %s (located at %s; nml dir: %s), copying to %s' % (include.href, incl_curr, nml_dir, target_dir)) ''' if not os.path.isfile("%s/%s" % (target_dir, os.path.basename(incl_curr))) and \ not os.path.isfile("%s/%s" % (target_dir, incl_curr)) and \ not os.path.isfile(incl_curr): shutil.copy(incl_curr, target_dir) else: print_comment_v("No need to copy...")''' f1 = "%s/%s" % (target_dir, os.path.basename(incl_curr)) f2 = "%s/%s" % (target_dir, incl_curr) if os.path.isfile(f1): print_comment_v("No need to copy, file exists: %s..." % f1) elif os.path.isfile(f2): print_comment_v("No need to copy, file exists: %s..." % f2) else: shutil.copy(incl_curr, target_dir) ls.include_neuroml2_file(include.href, include_included=False) sub_doc = read_neuroml2_file(incl_curr) sub_dir = os.path.dirname(incl_curr) if len( os.path.dirname(incl_curr)) > 0 else '.' if sub_doc.__class__ == neuroml.nml.nml.NeuroMLDocument: for include in sub_doc.includes: incl_curr = '%s/%s' % (sub_dir, include.href) print_comment_v(' -- Including %s located at %s' % (include.href, incl_curr)) if not os.path.isfile("%s/%s" % (target_dir, os.path.basename(incl_curr))) and \ not os.path.isfile("%s/%s" % (target_dir, incl_curr)): shutil.copy(incl_curr, target_dir) ls.include_neuroml2_file(include.href, include_included=False) if gen_plots_for_all_v \ or gen_saves_for_all_v \ or len(gen_plots_for_only_populations) > 0 \ or len(gen_saves_for_only_populations) > 0 \ or gen_spike_saves_for_all_somas \ or len(gen_spike_saves_for_only_populations) > 0: for network in nml_doc.networks: for population in network.populations: variable = "v" quantity_template_e = "%s[%i]" component = population.component size = population.size cell = None segment_ids = [] for c in nml_doc.spike_generator_poissons: if c.id == component: variable = "tsince" for c in nml_doc.SpikeSourcePoisson: if c.id == component: variable = "tsince" quantity_template = "%s[%i]/" + variable if plot_all_segments or gen_spike_saves_for_all_somas: for c in nml_doc.cells: if c.id == component: cell = c for segment in cell.morphology.segments: segment_ids.append(segment.id) segment_ids.sort() if population.type and population.type == 'populationList': quantity_template = "%s/%i/" + component + "/" + variable quantity_template_e = "%s/%i/" + component + "" # Multicompartmental cell # Needs to be supported in NeuronWriter # if len(segment_ids)>1: # quantity_template_e = "%s/%i/"+component+"/0" size = len(population.instances) if gen_plots_for_all_v or population.id in gen_plots_for_only_populations: print_comment( 'Generating %i plots for %s in population %s' % (size, component, population.id)) disp0 = 'DispPop__%s' % population.id ls.create_display( disp0, "Membrane potentials of cells in %s" % population.id, "-90", "50") for i in range(size): if cell is not None and plot_all_segments: quantity_template_seg = "%s/%i/" + component + "/%i/v" for segment_id in segment_ids: quantity = quantity_template_seg % ( population.id, i, segment_id) ls.add_line_to_display( disp0, "%s[%i] seg %i: v" % (population.id, i, segment_id), quantity, "1mV", get_next_hex_color(my_random)) else: quantity = quantity_template % (population.id, i) ls.add_line_to_display( disp0, "%s[%i]: v" % (population.id, i), quantity, "1mV", get_next_hex_color(my_random)) if gen_saves_for_all_v or population.id in gen_saves_for_only_populations: print_comment( 'Saving %i values of %s for %s in population %s' % (size, variable, component, population.id)) of0 = 'Volts_file__%s' % population.id ls.create_output_file( of0, "%s.%s.%s.dat" % (sim_id, population.id, variable)) for i in range(size): if cell is not None and save_all_segments: quantity_template_seg = "%s/%i/" + component + "/%i/v" for segment_id in segment_ids: quantity = quantity_template_seg % ( population.id, i, segment_id) ls.add_column_to_output_file( of0, 'v_%s' % safe_variable(quantity), quantity) quantities_saved.append(quantity) else: quantity = quantity_template % (population.id, i) ls.add_column_to_output_file( of0, 'v_%s' % safe_variable(quantity), quantity) quantities_saved.append(quantity) if gen_spike_saves_for_all_somas or population.id in gen_spike_saves_for_only_populations: print_comment( 'Saving spikes in %i somas for %s in population %s' % (size, component, population.id)) eof0 = 'Spikes_file__%s' % population.id ls.create_event_output_file(eof0, "%s.%s.spikes" % (sim_id, population.id), format=spike_time_format) for i in range(size): quantity = quantity_template_e % (population.id, i) ls.add_selection_to_event_output_file( eof0, i, quantity, "spike") quantities_saved.append(quantity) for display in sorted(gen_plots_for_quantities.keys()): quantities = gen_plots_for_quantities[display] max_ = "1" min_ = "-1" scale = "1" # Check for v ... if quantities and len(quantities) > 0 and quantities[0].endswith('/v'): max_ = "40" min_ = "-80" scale = "1mV" ls.create_display(display, "Plots of %s" % display, min_, max_) for q in quantities: ls.add_line_to_display(display, safe_variable(q), q, scale, get_next_hex_color(my_random)) for file_name in sorted(gen_saves_for_quantities.keys()): quantities = gen_saves_for_quantities[file_name] of_id = safe_variable(file_name) ls.create_output_file(of_id, file_name) for q in quantities: ls.add_column_to_output_file(of_id, safe_variable(q), q) quantities_saved.append(q) for file_name in sorted(gen_spike_saves_for_cells.keys()): quantities = gen_spike_saves_for_cells[file_name] of_id = safe_variable(file_name) ls.create_event_output_file(of_id, file_name) pop_here = None for i, quantity in enumerate(quantities): pop, index = get_pop_index(quantity) if pop_here: if pop_here != pop: raise Exception('Problem with generating LEMS for saving spikes for file %s.\n' % file_name + \ 'Multiple cells from different populations in one file will cause issues with index/spike id.') pop_here = pop # print('===== Adding to %s (%s) event %i for %s, pop: %s, i: %s' % (file_name, of_id, i, quantity, pop, index)) ls.add_selection_to_event_output_file(of_id, index, quantity, "spike") quantities_saved.append(quantity) ls.save_to_file(file_name=file_name_full) return quantities_saved, ls
def generate_lems_file_for_neuroml(sim_id, neuroml_file, target, duration, dt, lems_file_name, target_dir, nml_doc = None, # Use this if the nml doc has already been loaded (to avoid delay in reload) include_extra_files = [], gen_plots_for_all_v = True, plot_all_segments = False, gen_plots_for_quantities = {}, # Dict with displays vs lists of quantity paths gen_plots_for_only_populations = [], # List of populations, all pops if = [] gen_saves_for_all_v = True, save_all_segments = False, gen_saves_for_only_populations = [], # List of populations, all pops if = [] gen_saves_for_quantities = {}, # Dict with file names vs lists of quantity paths gen_spike_saves_for_all_somas = False, gen_spike_saves_for_only_populations = [], # List of populations, all pops if = [] gen_spike_saves_for_cells = {}, # Dict with file names vs lists of quantity paths spike_time_format='ID_TIME', copy_neuroml = True, report_file_name = None, lems_file_generate_seed=None, verbose=False, simulation_seed=12345): my_random = random.Random() if lems_file_generate_seed: my_random.seed(lems_file_generate_seed) # To ensure same LEMS file (e.g. colours of plots) are generated every time for the same input else: my_random.seed(12345) # To ensure same LEMS file (e.g. colours of plots) are generated every time for the same input file_name_full = '%s/%s'%(target_dir,lems_file_name) print_comment_v('Creating LEMS file at: %s for NeuroML 2 file: %s (copy: %s)'%(file_name_full,neuroml_file,copy_neuroml)) ls = LEMSSimulation(sim_id, duration, dt, target,simulation_seed=simulation_seed) if nml_doc == None: nml_doc = read_neuroml2_file(neuroml_file, include_includes=True, verbose=verbose) nml_doc_inc_not_included = read_neuroml2_file(neuroml_file, include_includes=False, verbose=False) else: nml_doc_inc_not_included = nml_doc ls.set_report_file(report_file_name) quantities_saved = [] for f in include_extra_files: ls.include_neuroml2_file(f, include_included=False) if not copy_neuroml: rel_nml_file = os.path.relpath(os.path.abspath(neuroml_file), os.path.abspath(target_dir)) print_comment_v("Including existing NeuroML file (%s) as: %s"%(neuroml_file, rel_nml_file)) ls.include_neuroml2_file(rel_nml_file, include_included=True, relative_to_dir=os.path.abspath(target_dir)) else: print_comment_v("Copying a NeuroML file (%s) to: %s (abs path: %s)"%(neuroml_file, target_dir, os.path.abspath(target_dir))) if not os.path.isdir(target_dir): raise Exception("Target directory %s does not exist!"%target_dir) if os.path.realpath(os.path.dirname(neuroml_file))!=os.path.realpath(target_dir): shutil.copy(neuroml_file, target_dir) else: print_comment_v("No need, same file...") neuroml_file_name = os.path.basename(neuroml_file) ls.include_neuroml2_file(neuroml_file_name, include_included=False) nml_dir = os.path.dirname(neuroml_file) if len(os.path.dirname(neuroml_file))>0 else '.' for include in nml_doc_inc_not_included.includes: if nml_dir=='.' and os.path.isfile(include.href): incl_curr = include.href else: incl_curr = '%s/%s'%(nml_dir,include.href) if os.path.isfile(include.href): incl_curr = include.href print_comment_v(' - Including %s (located at %s; nml dir: %s), copying to %s'%(include.href, incl_curr, nml_dir, target_dir)) ''' if not os.path.isfile("%s/%s"%(target_dir, os.path.basename(incl_curr))) and \ not os.path.isfile("%s/%s"%(target_dir, incl_curr)) and \ not os.path.isfile(incl_curr): shutil.copy(incl_curr, target_dir) else: print_comment_v("No need to copy...")''' f1 = "%s/%s"%(target_dir, os.path.basename(incl_curr)) f2 = "%s/%s"%(target_dir, incl_curr) if os.path.isfile(f1): print_comment_v("No need to copy, file exists: %s..."%f1) elif os.path.isfile(f2): print_comment_v("No need to copy, file exists: %s..."%f2) else: shutil.copy(incl_curr, target_dir) ls.include_neuroml2_file(include.href, include_included=False) sub_doc = read_neuroml2_file(incl_curr) sub_dir = os.path.dirname(incl_curr) if len(os.path.dirname(incl_curr))>0 else '.' for include in sub_doc.includes: incl_curr = '%s/%s'%(sub_dir,include.href) print_comment_v(' -- Including %s located at %s'%(include.href, incl_curr)) if not os.path.isfile("%s/%s"%(target_dir, os.path.basename(incl_curr))) and \ not os.path.isfile("%s/%s"%(target_dir, incl_curr)): shutil.copy(incl_curr, target_dir) ls.include_neuroml2_file(include.href, include_included=False) if gen_plots_for_all_v \ or gen_saves_for_all_v \ or len(gen_plots_for_only_populations)>0 \ or len(gen_saves_for_only_populations)>0 \ or gen_spike_saves_for_all_somas \ or len(gen_spike_saves_for_only_populations)>0 : for network in nml_doc.networks: for population in network.populations: variable = "v" # quantity_template_e = "%s[%i]" component = population.component size = population.size cell = None segment_ids = [] for c in nml_doc.spike_generator_poissons: if c.id == component: variable = "tsince" for c in nml_doc.SpikeSourcePoisson: if c.id == component: variable = "tsince" quantity_template = "%s[%i]/"+variable if plot_all_segments or gen_spike_saves_for_all_somas: for c in nml_doc.cells: if c.id == component: cell = c for segment in cell.morphology.segments: segment_ids.append(segment.id) segment_ids.sort() if population.type and population.type == 'populationList': quantity_template = "%s/%i/"+component+"/"+variable quantity_template_e = "%s/%i/"+component+"" # Multicompartmental cell ### Needs to be supported in NeuronWriter ###if len(segment_ids)>1: ### quantity_template_e = "%s/%i/"+component+"/0" size = len(population.instances) if gen_plots_for_all_v or population.id in gen_plots_for_only_populations: print_comment('Generating %i plots for %s in population %s'%(size, component, population.id)) disp0 = 'DispPop__%s'%population.id ls.create_display(disp0, "Membrane potentials of cells in %s"%population.id, "-90", "50") for i in range(size): if cell!=None and plot_all_segments: quantity_template_seg = "%s/%i/"+component+"/%i/v" for segment_id in segment_ids: quantity = quantity_template_seg%(population.id, i, segment_id) ls.add_line_to_display(disp0, "%s[%i] seg %i: v"%(population.id, i, segment_id), quantity, "1mV", get_next_hex_color(my_random)) else: quantity = quantity_template%(population.id, i) ls.add_line_to_display(disp0, "%s[%i]: v"%(population.id, i), quantity, "1mV", get_next_hex_color(my_random)) if gen_saves_for_all_v or population.id in gen_saves_for_only_populations: print_comment('Saving %i values of %s for %s in population %s'%(size, variable, component, population.id)) of0 = 'Volts_file__%s'%population.id ls.create_output_file(of0, "%s.%s.%s.dat"%(sim_id,population.id,variable)) for i in range(size): if cell!=None and save_all_segments: quantity_template_seg = "%s/%i/"+component+"/%i/v" for segment_id in segment_ids: quantity = quantity_template_seg%(population.id, i, segment_id) ls.add_column_to_output_file(of0, 'v_%s'%safe_variable(quantity), quantity) quantities_saved.append(quantity) else: quantity = quantity_template%(population.id, i) ls.add_column_to_output_file(of0, 'v_%s'%safe_variable(quantity), quantity) quantities_saved.append(quantity) if gen_spike_saves_for_all_somas or population.id in gen_spike_saves_for_only_populations: print_comment('Saving spikes in %i somas for %s in population %s'%(size, component, population.id)) eof0 = 'Spikes_file__%s'%population.id ls.create_event_output_file(eof0, "%s.%s.spikes"%(sim_id,population.id), format=spike_time_format) for i in range(size): quantity = quantity_template_e%(population.id, i) ls.add_selection_to_event_output_file(eof0, i, quantity, "spike") quantities_saved.append(quantity) for display in gen_plots_for_quantities.keys(): quantities = gen_plots_for_quantities[display] max_ = "1" min_ = "-1" scale = "1" # Check for v ... if quantities and len(quantities)>0 and quantities[0].endswith('/v'): max_ = "40" min_ = "-80" scale = "1mV" ls.create_display(display, "Plots of %s"%display, min_, max_) for q in quantities: ls.add_line_to_display(display, safe_variable(q), q, scale, get_next_hex_color(my_random)) for file_name in gen_saves_for_quantities.keys(): quantities = gen_saves_for_quantities[file_name] of_id = safe_variable(file_name) ls.create_output_file(of_id, file_name) for q in quantities: ls.add_column_to_output_file(of_id, safe_variable(q), q) quantities_saved.append(q) for file_name in gen_spike_saves_for_cells.keys(): cells = gen_spike_saves_for_cells[file_name] of_id = safe_variable(file_name) ls.create_event_output_file(of_id, file_name) for i, c in enumerate(cells): ls.add_selection_to_event_output_file(of_id, i, c, "spike") quantities_saved.append(c) ls.save_to_file(file_name=file_name_full) return quantities_saved, ls
def generate_lems_file_for_neuroml(sim_id, neuroml_file, target, duration, dt, lems_file_name, target_dir, include_extra_files = [], gen_plots_for_all_v = True, plot_all_segments = False, gen_plots_for_quantities = {}, # Dict with displays vs lists of quantity paths gen_plots_for_only_populations = [], # List of populations, all pops if = [] gen_saves_for_all_v = True, save_all_segments = False, gen_saves_for_only_populations = [], # List of populations, all pops if = [] gen_saves_for_quantities = {}, # Dict with file names vs lists of quantity paths copy_neuroml = True, seed=None): if seed: random.seed(seed) # To ensure same LEMS file (e.g. colours of plots) are generated every time for the same input file_name_full = '%s/%s'%(target_dir,lems_file_name) print_comment_v('Creating LEMS file at: %s for NeuroML 2 file: %s'%(file_name_full,neuroml_file)) ls = LEMSSimulation(sim_id, duration, dt, target) nml_doc = read_neuroml2_file(neuroml_file, include_includes=True, verbose=True) quantities_saved = [] for f in include_extra_files: ls.include_neuroml2_file(f, include_included=False) if not copy_neuroml: rel_nml_file = os.path.relpath(os.path.abspath(neuroml_file), os.path.abspath(target_dir)) print_comment_v("Including existing NeuroML file (%s) as: %s"%(neuroml_file, rel_nml_file)) ls.include_neuroml2_file(rel_nml_file, include_included=True, relative_to_dir=os.path.abspath(target_dir)) else: print_comment_v("Copying NeuroML file (%s) to: %s (%s)"%(neuroml_file, target_dir, os.path.abspath(target_dir))) if os.path.abspath(os.path.dirname(neuroml_file))!=os.path.abspath(target_dir): shutil.copy(neuroml_file, target_dir) neuroml_file_name = os.path.basename(neuroml_file) ls.include_neuroml2_file(neuroml_file_name, include_included=False) for include in nml_doc.includes: incl_curr = '%s/%s'%(os.path.dirname(neuroml_file),include.href) print_comment_v(' - Including %s located at %s'%(include.href, incl_curr)) shutil.copy(incl_curr, target_dir) ls.include_neuroml2_file(include.href, include_included=False) sub_doc = read_neuroml2_file(incl_curr) for include in sub_doc.includes: incl_curr = '%s/%s'%(os.path.dirname(neuroml_file),include.href) print_comment_v(' -- Including %s located at %s'%(include.href, incl_curr)) shutil.copy(incl_curr, target_dir) ls.include_neuroml2_file(include.href, include_included=False) if gen_plots_for_all_v or gen_saves_for_all_v or len(gen_plots_for_only_populations)>0 or len(gen_saves_for_only_populations)>0 : for network in nml_doc.networks: for population in network.populations: quantity_template = "%s[%i]/v" component = population.component size = population.size cell = None segment_ids = [] if plot_all_segments: for c in nml_doc.cells: if c.id == component: cell = c for segment in cell.morphology.segments: segment_ids.append(segment.id) segment_ids.sort() if population.type and population.type == 'populationList': quantity_template = "%s/%i/"+component+"/v" size = len(population.instances) if gen_plots_for_all_v or population.id in gen_plots_for_only_populations: print_comment('Generating %i plots for %s in population %s'%(size, component, population.id)) disp0 = 'DispPop__%s'%population.id ls.create_display(disp0, "Membrane potentials of cells in %s"%population.id, "-90", "50") for i in range(size): if cell!=None and plot_all_segments: quantity_template_seg = "%s/%i/"+component+"/%i/v" for segment_id in segment_ids: quantity = quantity_template_seg%(population.id, i, segment_id) ls.add_line_to_display(disp0, "%s[%i] seg %i: v"%(population.id, i, segment_id), quantity, "1mV", get_next_hex_color()) else: quantity = quantity_template%(population.id, i) ls.add_line_to_display(disp0, "%s[%i]: v"%(population.id, i), quantity, "1mV", get_next_hex_color()) if gen_saves_for_all_v or population.id in gen_saves_for_only_populations: print_comment('Saving %i values of v for %s in population %s'%(size, component, population.id)) of0 = 'Volts_file__%s'%population.id ls.create_output_file(of0, "%s.%s.v.dat"%(sim_id,population.id)) for i in range(size): if cell!=None and save_all_segments: quantity_template_seg = "%s/%i/"+component+"/%i/v" for segment_id in segment_ids: quantity = quantity_template_seg%(population.id, i, segment_id) ls.add_column_to_output_file(of0, 'v_%s'%safe_variable(quantity), quantity) quantities_saved.append(quantity) else: quantity = quantity_template%(population.id, i) ls.add_column_to_output_file(of0, 'v_%s'%safe_variable(quantity), quantity) quantities_saved.append(quantity) for display in gen_plots_for_quantities.keys(): quantities = gen_plots_for_quantities[display] ls.create_display(display, "Plots of %s"%display, "-90", "50") for q in quantities: ls.add_line_to_display(display, safe_variable(q), q, "1", get_next_hex_color()) for file_name in gen_saves_for_quantities.keys(): quantities = gen_saves_for_quantities[file_name] ls.create_output_file(file_name, file_name) for q in quantities: ls.add_column_to_output_file(file_name, safe_variable(q), q) ls.save_to_file(file_name=file_name_full) return quantities_saved
def generate_lems_channel_analyser(channel_file, channel, min_target_voltage, step_target_voltage, max_target_voltage, clamp_delay, clamp_duration, clamp_base_voltage, duration, erev, gates, temperature, ca_conc, iv_curve, scale_dt=1, dat_suffix='', verbose=True): print_comment(("Generating LEMS file to investigate %s in %s, %smV->%smV, " "%sdegC") % (channel, channel_file, min_target_voltage, max_target_voltage, temperature), verbose) target_voltages = [] v = min_target_voltage while v <= max_target_voltage: target_voltages.append(v) v += step_target_voltage target_voltages_map = [] for t in target_voltages: fract = float(target_voltages.index(t)) / (len(target_voltages) - 1) info = {} info["v"] = t info["v_str"] = str(t).replace("-", "min") info["col"] = get_colour_hex(fract) target_voltages_map.append(info) includes = get_includes_from_channel_file(channel_file) includes_relative = [] base_path = os.path.dirname(channel_file) for inc in includes: includes_relative.append(os.path.abspath(base_path + '/' + inc)) model = { "channel_file": channel_file, "includes": includes_relative, "channel": channel, "target_voltages": target_voltages_map, "clamp_delay": clamp_delay, "clamp_duration": clamp_duration, "clamp_base_voltage": clamp_base_voltage, "min_target_voltage": min_target_voltage, "max_target_voltage": max_target_voltage, "duration": duration, "scale_dt": scale_dt, "erev": erev, "gates": gates, "temperature": temperature, "ca_conc": ca_conc, "iv_curve": iv_curve, "dat_suffix": dat_suffix } # pp.pprint(model) merged = merge_with_template(model, TEMPLATE_FILE) return merged
def generate_lems_file_for_neuroml(sim_id, neuroml_file, target, duration, dt, lems_file_name, target_dir, gen_plots_for_all_v = True, gen_saves_for_all_v = True, copy_neuroml = True, seed=None): if seed: random.seed(seed) # To ensure same LEMS file (e.g. colours of plots) are generated every time for the same input file_name_full = '%s/%s'%(target_dir,lems_file_name) print_comment_v('Creating LEMS file at: %s for NeuroML 2 file: %s'%(file_name_full,neuroml_file)) ls = LEMSSimulation(sim_id, duration, dt, target) nml_doc = read_neuroml2_file(neuroml_file) quantities_saved = [] if not copy_neuroml: rel_nml_file = os.path.relpath(os.path.abspath(neuroml_file), os.path.abspath(target_dir)) print_comment_v("Including existing NeuroML file (%s) as: %s"%(neuroml_file, rel_nml_file)) ls.include_neuroml2_file(rel_nml_file, include_included=True, relative_to_dir=os.path.abspath(target_dir)) else: if os.path.abspath(os.path.dirname(neuroml_file))!=os.path.abspath(target_dir): shutil.copy(neuroml_file, target_dir) neuroml_file_name = os.path.basename(neuroml_file) ls.include_neuroml2_file(neuroml_file_name, include_included=False) for include in nml_doc.includes: incl_curr = '%s/%s'%(os.path.dirname(neuroml_file),include.href) print_comment_v(' - Including %s located at %s'%(include.href, incl_curr)) shutil.copy(incl_curr, target_dir) ls.include_neuroml2_file(include.href, include_included=False) sub_doc = read_neuroml2_file(incl_curr) for include in sub_doc.includes: incl_curr = '%s/%s'%(os.path.dirname(neuroml_file),include.href) print_comment_v(' -- Including %s located at %s'%(include.href, incl_curr)) shutil.copy(incl_curr, target_dir) ls.include_neuroml2_file(include.href, include_included=False) if gen_plots_for_all_v or gen_saves_for_all_v: for network in nml_doc.networks: for population in network.populations: size = population.size component = population.component quantity_template = "%s[%i]/v" if population.type and population.type == 'populationList': quantity_template = "%s/%i/"+component+"/v" if gen_plots_for_all_v: print_comment('Generating %i plots for %s in population %s'%(size, component, population.id)) disp0 = 'DispPop__%s'%population.id ls.create_display(disp0, "Voltages of %s"%disp0, "-90", "50") for i in range(size): quantity = quantity_template%(population.id, i) ls.add_line_to_display(disp0, "v %s"%safe_variable(quantity), quantity, "1mV", get_next_hex_color()) if gen_saves_for_all_v: print_comment('Saving %i values of v for %s in population %s'%(size, component, population.id)) of0 = 'Volts_file__%s'%population.id ls.create_output_file(of0, "%s.%s.v.dat"%(sim_id,population.id)) for i in range(size): quantity = quantity_template%(population.id, i) ls.add_column_to_output_file(of0, 'v_%s'%safe_variable(quantity), quantity) quantities_saved.append(quantity) ls.save_to_file(file_name=file_name_full) return quantities_saved
def main(): args = process_args() xmlfile = args.neuroml_file pov_file_name = ( xmlfile.replace(".xml", ".pov").replace(".nml1", ".pov").replace(".nml.h5", ".pov").replace(".nml", ".pov") ) pov_file = open(pov_file_name, "w") header = """ /* POV-Ray file generated from NeuroML network */ #version 3.6; #include "colors.inc" background {rgbt %s} \n""" ### end of header pov_file.write(header % (args.background)) cells_file = pov_file net_file = pov_file splitOut = False cf = pov_file_name.replace(".pov", "_cells.inc") nf = pov_file_name.replace(".pov", "_net.inc") if args.split: splitOut = True cells_file = open(cf, "w") net_file = open(nf, "w") print_comment_v("Saving into %s and %s and %s" % (pov_file_name, cf, nf)) print_comment_v("Converting XML file: %s to %s" % (xmlfile, pov_file_name)) nml_doc = pynml.read_neuroml2_file(xmlfile, include_includes=True, verbose=args.v) cell_elements = [] cell_elements.extend(nml_doc.cells) cell_elements.extend(nml_doc.cell2_ca_poolses) minXc = 1e9 minYc = 1e9 minZc = 1e9 maxXc = -1e9 maxYc = -1e9 maxZc = -1e9 minX = 1e9 minY = 1e9 minZ = 1e9 maxX = -1e9 maxY = -1e9 maxZ = -1e9 declaredcells = {} print_comment_v("There are %i cells in the file" % len(cell_elements)) cell_id_vs_seg_id_vs_proximal = {} cell_id_vs_seg_id_vs_distal = {} cell_id_vs_cell = {} for cell in cell_elements: cellName = cell.id cell_id_vs_cell[cell.id] = cell print_comment_v("Handling cell: %s" % cellName) cell_id_vs_seg_id_vs_proximal[cell.id] = {} cell_id_vs_seg_id_vs_distal[cell.id] = {} declaredcell = "cell_" + cellName declaredcells[cellName] = declaredcell cells_file.write("#declare %s = \n" % declaredcell) cells_file.write("union {\n") prefix = "" segments = cell.morphology.segments distpoints = {} proxpoints = {} for segment in segments: id = int(segment.id) distal = segment.distal x = float(distal.x) y = float(distal.y) z = float(distal.z) r = max(float(distal.diameter) / 2.0, args.mindiam) if x - r < minXc: minXc = x - r if y - r < minYc: minYc = y - r if z - r < minZc: minZc = z - r if x + r > maxXc: maxXc = x + r if y + r > maxYc: maxYc = y + r if z + r > maxZc: maxZc = z + r distalpoint = "<%f, %f, %f>, %f " % (x, y, z, r) distpoints[id] = distalpoint cell_id_vs_seg_id_vs_distal[cell.id][id] = (x, y, z) proximalpoint = "" if segment.proximal is not None: proximal = segment.proximal proximalpoint = "<%f, %f, %f>, %f " % ( float(proximal.x), float(proximal.y), float(proximal.z), max(float(proximal.diameter) / 2.0, args.mindiam), ) cell_id_vs_seg_id_vs_proximal[cell.id][id] = (float(proximal.x), float(proximal.y), float(proximal.z)) else: parent = int(segment.parent.segments) proximalpoint = distpoints[parent] cell_id_vs_seg_id_vs_proximal[cell.id][id] = cell_id_vs_seg_id_vs_distal[cell.id][parent] proxpoints[id] = proximalpoint shape = "cone" if proximalpoint == distalpoint: shape = "sphere" proximalpoint = "" if shape == "cone" and (proximalpoint.split(">")[0] == distalpoint.split(">")[0]): comment = "Ignoring zero length segment (id = %i): %s -> %s\n" % (id, proximalpoint, distalpoint) print_comment_v(comment) cells_file.write(" // " + comment) else: cells_file.write(" %s {\n" % shape) cells_file.write(" %s\n" % distalpoint) if len(proximalpoint): cells_file.write(" %s\n" % proximalpoint) cells_file.write(" //%s_%s.%s\n" % ("CELL_GROUP_NAME", "0", id)) cells_file.write(" }\n") cells_file.write(" pigment { color rgb <%f,%f,%f> }\n" % (random.random(), random.random(), random.random())) cells_file.write("}\n\n") if splitOut: pov_file.write('#include "' + cf + '"\n\n') pov_file.write('#include "' + nf + '"\n\n') pov_file.write( """\n/*\n Defining a dummy cell to use when cell in population is not found in NeuroML file...\n*/\n#declare %s = union { sphere { <0.000000, 0.000000, 0.000000>, 5.000000 } pigment { color rgb <1,0,0> } }\n""" % _DUMMY_CELL ) pov_file.write( """\n/*\n Defining the spheres to use for end points of connections...\n*/\n#declare conn_start_point = union { sphere { <0.000000, 0.000000, 0.000000>, 3.000000 } pigment { color rgb <0,1,0> } }\n\n#declare conn_end_point = union { sphere { <0.000000, 0.000000, 0.000000>, 3.000000 } pigment { color rgb <1,0,0> } }\n""" ) positions = {} popElements = nml_doc.networks[0].populations pop_id_vs_cell = {} print_comment_v("There are %i populations in the file" % len(popElements)) for pop in popElements: name = pop.id celltype = pop.component instances = pop.instances if cell_id_vs_cell.has_key(pop.component): pop_id_vs_cell[pop.id] = cell_id_vs_cell[pop.component] info = "Population: %s has %i positioned cells of type: %s" % (name, len(instances), celltype) print_comment_v(info) colour = "1" for prop in pop.properties: if prop.tag == "color": colour = prop.value colour = colour.replace(" ", ",") # print "Colour determined to be: "+colour net_file.write("\n\n/* " + info + " */\n\n") pop_positions = {} if not celltype in declaredcells: cell_definition = _DUMMY_CELL minXc = 0 minYc = 0 minZc = 0 maxXc = 0 maxYc = 0 maxZc = 0 else: cell_definition = declaredcells[celltype] for instance in instances: location = instance.location id = int(instance.id) net_file.write("object {\n") net_file.write(" %s\n" % cell_definition) x = float(location.x) y = float(location.y) z = float(location.z) pop_positions[id] = (x, y, z) if x + minXc < minX: minX = x + minXc if y + minYc < minY: minY = y + minYc if z + minZc < minZ: minZ = z + minZc if x + maxXc > maxX: maxX = x + maxXc if y + maxYc > maxY: maxY = y + maxYc if z + maxZc > maxZ: maxZ = z + maxZc net_file.write(" translate <%s, %s, %s>\n" % (x, y, z)) if colour == "1": colour = "%f,%f,%f" % (random.random(), random.random(), random.random()) if colour is not None: net_file.write(" pigment { color rgb <%s> }" % (colour)) net_file.write("\n //%s_%s\n" % (name, id)) net_file.write("}\n") positions[name] = pop_positions if len(instances) == 0 and int(pop.size > 0): info = "Population: %s has %i unpositioned cells of type: %s" % (name, pop.size, celltype) print_comment_v(info) colour = "1" """ if pop.annotation: print dir(pop.annotation) print pop.annotation.anytypeobjs_ print pop.annotation.member_data_items_[0].name print dir(pop.annotation.member_data_items_[0]) for prop in pop.annotation.anytypeobjs_: print prop if len(prop.getElementsByTagName('meta:tag'))>0 and prop.getElementsByTagName('meta:tag')[0].childNodes[0].data == 'color': #print prop.getElementsByTagName('meta:tag')[0].childNodes colour = prop.getElementsByTagName('meta:value')[0].childNodes[0].data colour = colour.replace(" ", ",") elif prop.hasAttribute('tag') and prop.getAttribute('tag') == 'color': colour = prop.getAttribute('value') colour = colour.replace(" ", ",") print "Colour determined to be: "+colour """ net_file.write("\n\n/* " + info + " */\n\n") net_file.write("object {\n") net_file.write(" %s\n" % cell_definition) x = 0 y = 0 z = 0 if x + minXc < minX: minX = x + minXc if y + minYc < minY: minY = y + minYc if z + minZc < minZ: minZ = z + minZc if x + maxXc > maxX: maxX = x + maxXc if y + maxYc > maxY: maxY = y + maxYc if z + maxZc > maxZ: maxZ = z + maxZc net_file.write(" translate <%s, %s, %s>\n" % (x, y, z)) if colour == "1": colour = "%f,%f,%f" % (random.random(), random.random(), random.random()) if colour is not None: net_file.write(" pigment { color rgb <%s> }" % (colour)) net_file.write("\n //%s_%s\n" % (name, id)) net_file.write("}\n") # print positions if ( args.conns or args.conn_points ): # Note: segment specific connections not implemented yet... i.e. connections from dends to axons... # print_comment_v("************************\n*\n* Note: connection lines in 3D do not yet target dendritic locations!\n*\n************************") for projection in nml_doc.networks[0].projections: pre = projection.presynaptic_population post = projection.postsynaptic_population connections = projection.connections + projection.connection_wds print_comment_v("Adding %i connections %s -> %s " % (len(connections), pre, post)) # print cell_id_vs_seg_id_vs_distal # print cell_id_vs_seg_id_vs_proximal for connection in connections: pre_cell_id = connection.get_pre_cell_id() post_cell_id = connection.get_post_cell_id() pre_loc = (0, 0, 0) if positions.has_key(pre): if len(positions[pre]) > 0: pre_loc = positions[pre][pre_cell_id] post_loc = (0, 0, 0) if positions.has_key(post): post_loc = positions[post][post_cell_id] if pop_id_vs_cell.has_key(projection.presynaptic_population): pre_cell = pop_id_vs_cell[projection.presynaptic_population] d = cell_id_vs_seg_id_vs_distal[pre_cell.id][int(connection.pre_segment_id)] p = cell_id_vs_seg_id_vs_proximal[pre_cell.id][int(connection.pre_segment_id)] m = [p[i] + float(connection.pre_fraction_along) * (d[i] - p[i]) for i in [0, 1, 2]] print_comment("Pre point is %s, %s between %s and %s" % (m, connection.pre_fraction_along, p, d)) pre_loc = [pre_loc[i] + m[i] for i in [0, 1, 2]] if pop_id_vs_cell.has_key(projection.postsynaptic_population): post_cell = pop_id_vs_cell[projection.postsynaptic_population] d = cell_id_vs_seg_id_vs_distal[post_cell.id][int(connection.post_segment_id)] p = cell_id_vs_seg_id_vs_proximal[post_cell.id][int(connection.post_segment_id)] m = [p[i] + float(connection.post_fraction_along) * (d[i] - p[i]) for i in [0, 1, 2]] print_comment("Post point is %s, %s between %s and %s" % (m, connection.post_fraction_along, p, d)) post_loc = [post_loc[i] + m[i] for i in [0, 1, 2]] if post_loc != pre_loc: info = "// Connection from %s:%s %s -> %s:%s %s\n" % ( pre, pre_cell_id, pre_loc, post, post_cell_id, post_loc, ) print_comment(info) net_file.write("// %s" % info) if args.conns: net_file.write( "cylinder { <%s,%s,%s>, <%s,%s,%s>, .5 pigment{color Grey}}\n" % (pre_loc[0], pre_loc[1], pre_loc[2], post_loc[0], post_loc[1], post_loc[2]) ) if args.conn_points: net_file.write( "object { conn_start_point translate <%s,%s,%s> }\n" % (pre_loc[0], pre_loc[1], pre_loc[2]) ) net_file.write( "object { conn_end_point translate <%s,%s,%s> }\n" % (post_loc[0], post_loc[1], post_loc[2]) ) plane = """ plane { y, vv(-1) pigment {checker color rgb 1.0, color rgb 0.8 scale 20} } """ footer = """ #declare minX = %f; #declare minY = %f; #declare minZ = %f; #declare maxX = %f; #declare maxY = %f; #declare maxZ = %f; #macro uu(xx) 0.5 * (maxX *(1+xx) + minX*(1-xx)) #end #macro vv(xx) 0.5 * (maxY *(1+xx) + minY*(1-xx)) #end #macro ww(xx) 0.5 * (maxZ *(1+xx) + minZ*(1-xx)) #end light_source { <uu(5),uu(2),uu(5)> color rgb <1,1,1> } light_source { <uu(-5),uu(2),uu(-5)> color rgb <1,1,1> } light_source { <uu(5),uu(-2),uu(-5)> color rgb <1,1,1> } light_source { <uu(-5),uu(-2),uu(5)> color rgb <1,1,1> } // Trying to view box camera { location < uu(%s + %s * sin (clock * 2 * 3.141)) , vv(%s + %s * sin (clock * 2 * 3.141)) , ww(%s + %s * cos (clock * 2 * 3.141)) > look_at < uu(%s + 0) , vv(%s + 0.05+0.3*sin (clock * 2 * 3.141)) , ww(%s + 0)> } %s \n""" % ( minX, minY, minZ, maxX, maxY, maxZ, args.posx, args.scalex, args.posy, args.scaley, args.posz, args.scalez, args.viewx, args.viewy, args.viewz, (plane if args.plane else ""), ) ### end of footer pov_file.write(footer) pov_file.close() if args.movie: ini_file_name = pov_file_name.replace(".pov", "_movie.ini") ini_movie = """ Antialias=On +W800 +H600 Antialias_Threshold=0.3 Antialias_Depth=4 Input_File_Name=%s Initial_Frame=1 Final_Frame=%i Initial_Clock=0 Final_Clock=1 Cyclic_Animation=on Pause_when_Done=off """ ini_file = open(ini_file_name, "w") ini_file.write(ini_movie % (pov_file_name, args.frames)) ini_file.close() print_comment_v( "Created file for generating %i movie frames at: %s. To run this type:\n\n povray %s\n" % (args.frames, ini_file_name, ini_file_name) ) else: print_comment_v( "Created file for generating image of network. To run this type:\n\n povray %s\n" % (pov_file_name) ) print_comment_v( "Or for higher resolution:\n\n povray Antialias=On Antialias_Depth=10 Antialias_Threshold=0.1 +W1200 +H900 %s\n" % (pov_file_name) )
def generate_current_vs_frequency_curve(nml2_file, cell_id, start_amp_nA = -0.1, end_amp_nA = 0.1, step_nA = 0.01, custom_amps_nA = [], analysis_duration = 1000, analysis_delay = 0, pre_zero_pulse = 0, post_zero_pulse = 0, dt = 0.05, temperature = "32degC", spike_threshold_mV = 0., plot_voltage_traces = False, plot_if = True, plot_iv = False, xlim_if = None, ylim_if = None, xlim_iv = None, ylim_iv = None, label_xaxis = True, label_yaxis = True, show_volts_label = True, grid = True, font_size = 12, if_iv_color = 'k', linewidth = 1, bottom_left_spines_only = False, show_plot_already = True, save_voltage_traces_to = None, save_if_figure_to = None, save_iv_figure_to = None, save_if_data_to = None, save_iv_data_to = None, simulator = "jNeuroML", num_processors = 1, include_included = True, title_above_plot = False, return_axes = False, verbose = False): print_comment("Running generate_current_vs_frequency_curve() on %s (%s)"%(nml2_file,os.path.abspath(nml2_file)), verbose) from pyelectro.analysis import max_min from pyelectro.analysis import mean_spike_frequency import numpy as np traces_ax = None if_ax = None iv_ax = None sim_id = 'iv_%s'%cell_id total_duration = pre_zero_pulse+analysis_duration+analysis_delay+post_zero_pulse pulse_duration = analysis_duration+analysis_delay end_stim = pre_zero_pulse+analysis_duration+analysis_delay ls = LEMSSimulation(sim_id, total_duration, dt) ls.include_neuroml2_file(nml2_file, include_included=include_included) stims = [] if len(custom_amps_nA)>0: stims = [float(a) for a in custom_amps_nA] stim_info = ['%snA'%float(a) for a in custom_amps_nA] else: amp = start_amp_nA while amp<=end_amp_nA : stims.append(amp) amp+=step_nA stim_info = '(%snA->%snA; %s steps of %snA; %sms)'%(start_amp_nA, end_amp_nA, len(stims), step_nA, total_duration) print_comment_v("Generating an IF curve for cell %s in %s using %s %s"% (cell_id, nml2_file, simulator, stim_info)) number_cells = len(stims) pop = nml.Population(id="population_of_%s"%cell_id, component=cell_id, size=number_cells) # create network and add populations net_id = "network_of_%s"%cell_id net = nml.Network(id=net_id, type="networkWithTemperature", temperature=temperature) ls.assign_simulation_target(net_id) net_doc = nml.NeuroMLDocument(id=net.id) net_doc.networks.append(net) net_doc.includes.append(nml.IncludeType(nml2_file)) net.populations.append(pop) for i in range(number_cells): stim_amp = "%snA"%stims[i] input_id = ("input_%s"%stim_amp).replace('.','_').replace('-','min') pg = nml.PulseGenerator(id=input_id, delay="%sms"%pre_zero_pulse, duration="%sms"%pulse_duration, amplitude=stim_amp) net_doc.pulse_generators.append(pg) # Add these to cells input_list = nml.InputList(id=input_id, component=pg.id, populations=pop.id) input = nml.Input(id='0', target="../%s[%i]"%(pop.id, i), destination="synapses") input_list.input.append(input) net.input_lists.append(input_list) net_file_name = '%s.net.nml'%sim_id pynml.write_neuroml2_file(net_doc, net_file_name) ls.include_neuroml2_file(net_file_name) disp0 = 'Voltage_display' ls.create_display(disp0,"Voltages", "-90", "50") of0 = 'Volts_file' ls.create_output_file(of0, "%s.v.dat"%sim_id) for i in range(number_cells): ref = "v_cell%i"%i quantity = "%s[%i]/v"%(pop.id, i) ls.add_line_to_display(disp0, ref, quantity, "1mV", pynml.get_next_hex_color()) ls.add_column_to_output_file(of0, ref, quantity) lems_file_name = ls.save_to_file() print_comment("Written LEMS file %s (%s)"%(lems_file_name,os.path.abspath(lems_file_name)), verbose) if simulator == "jNeuroML": results = pynml.run_lems_with_jneuroml(lems_file_name, nogui=True, load_saved_data=True, plot=False, show_plot_already=False, verbose=verbose) elif simulator == "jNeuroML_NEURON": results = pynml.run_lems_with_jneuroml_neuron(lems_file_name, nogui=True, load_saved_data=True, plot=False, show_plot_already=False, verbose=verbose) elif simulator == "jNeuroML_NetPyNE": results = pynml.run_lems_with_jneuroml_netpyne(lems_file_name, nogui=True, load_saved_data=True, plot=False, show_plot_already=False, num_processors = num_processors, verbose=verbose) else: raise Exception("Sorry, cannot yet run current vs frequency analysis using simulator %s"%simulator) print_comment("Completed run in simulator %s (results: %s)"%(simulator,results.keys()), verbose) #print(results.keys()) times_results = [] volts_results = [] volts_labels = [] if_results = {} iv_results = {} for i in range(number_cells): t = np.array(results['t'])*1000 v = np.array(results["%s[%i]/v"%(pop.id, i)])*1000 if plot_voltage_traces: times_results.append(t) volts_results.append(v) volts_labels.append("%s nA"%stims[i]) mm = max_min(v, t, delta=0, peak_threshold=spike_threshold_mV) spike_times = mm['maxima_times'] freq = 0 if len(spike_times) > 2: count = 0 for s in spike_times: if s >= pre_zero_pulse + analysis_delay and s < (pre_zero_pulse + analysis_duration+analysis_delay): count+=1 freq = 1000 * count/float(analysis_duration) mean_freq = mean_spike_frequency(spike_times) #print("--- %s nA, spike times: %s, mean_spike_frequency: %f, freq (%fms -> %fms): %f"%(stims[i],spike_times, mean_freq, analysis_delay, analysis_duration+analysis_delay, freq)) if_results[stims[i]] = freq if freq == 0: if post_zero_pulse==0: iv_results[stims[i]] = v[-1] else: v_end = None for j in range(len(t)): if v_end==None and t[j]>=end_stim: v_end = v[j] iv_results[stims[i]] = v_end if plot_voltage_traces: traces_ax = pynml.generate_plot(times_results, volts_results, "Membrane potential traces for: %s"%nml2_file, xaxis = 'Time (ms)' if label_xaxis else ' ', yaxis = 'Membrane potential (mV)' if label_yaxis else '', xlim = [total_duration*-0.05,total_duration*1.05], show_xticklabels = label_xaxis, font_size = font_size, bottom_left_spines_only = bottom_left_spines_only, grid = False, labels = volts_labels if show_volts_label else [], show_plot_already=False, save_figure_to = save_voltage_traces_to, title_above_plot = title_above_plot, verbose=verbose) if plot_if: stims = sorted(if_results.keys()) stims_pA = [ii*1000 for ii in stims] freqs = [if_results[s] for s in stims] if_ax = pynml.generate_plot([stims_pA], [freqs], "Firing frequency versus injected current for: %s"%nml2_file, colors = [if_iv_color], linestyles=['-'], markers=['o'], linewidths = [linewidth], xaxis = 'Input current (pA)' if label_xaxis else ' ', yaxis = 'Firing frequency (Hz)' if label_yaxis else '', xlim = xlim_if, ylim = ylim_if, show_xticklabels = label_xaxis, show_yticklabels = label_yaxis, font_size = font_size, bottom_left_spines_only = bottom_left_spines_only, grid = grid, show_plot_already=False, save_figure_to = save_if_figure_to, title_above_plot = title_above_plot, verbose=verbose) if save_if_data_to: with open(save_if_data_to,'w') as if_file: for i in range(len(stims_pA)): if_file.write("%s\t%s\n"%(stims_pA[i],freqs[i])) if plot_iv: stims = sorted(iv_results.keys()) stims_pA = [ii*1000 for ii in sorted(iv_results.keys())] vs = [iv_results[s] for s in stims] xs = [] ys = [] xs.append([]) ys.append([]) for si in range(len(stims)): stim = stims[si] if len(custom_amps_nA)==0 and si>1 and (stims[si]-stims[si-1])>step_nA*1.01: xs.append([]) ys.append([]) xs[-1].append(stim*1000) ys[-1].append(iv_results[stim]) iv_ax = pynml.generate_plot(xs, ys, "V at %sms versus I below threshold for: %s"%(end_stim,nml2_file), colors = [if_iv_color for s in xs], linestyles=['-' for s in xs], markers=['o' for s in xs], xaxis = 'Input current (pA)' if label_xaxis else '', yaxis = 'Membrane potential (mV)' if label_yaxis else '', xlim = xlim_iv, ylim = ylim_iv, show_xticklabels = label_xaxis, show_yticklabels = label_yaxis, font_size = font_size, linewidths = [linewidth for s in xs], bottom_left_spines_only = bottom_left_spines_only, grid = grid, show_plot_already=False, save_figure_to = save_iv_figure_to, title_above_plot = title_above_plot, verbose=verbose) if save_iv_data_to: with open(save_iv_data_to,'w') as iv_file: for i in range(len(stims_pA)): iv_file.write("%s\t%s\n"%(stims_pA[i],vs[i])) if show_plot_already: from matplotlib import pyplot as plt plt.show() if return_axes: return traces_ax, if_ax, iv_ax return if_results
def main (): args = process_args() xmlfile = args.neuroml_file pov_file_name = xmlfile endings = [".xml",".h5",".nml"] for e in endings: if pov_file_name.endswith(e): pov_file_name.replace(e, ".pov") if pov_file_name == xmlfile: pov_file_name+='.pov' pov_file = open(pov_file_name, "w") header=''' /* POV-Ray file generated from NeuroML network */ #version 3.6; #include "colors.inc" background {rgbt %s} \n''' ### end of header pov_file.write(header%(args.background)) cells_file = pov_file net_file = pov_file splitOut = False cf = pov_file_name.replace(".pov", "_cells.inc") nf = pov_file_name.replace(".pov", "_net.inc") if args.split: splitOut = True cells_file = open(cf, "w") net_file = open(nf, "w") print_comment_v("Saving into %s and %s and %s"%(pov_file_name, cf, nf)) print_comment_v("Converting XML file: %s to %s"%(xmlfile, pov_file_name)) nml_doc = pynml.read_neuroml2_file(xmlfile, include_includes=True, verbose=args.v, optimized=True) cell_elements = [] cell_elements.extend(nml_doc.cells) cell_elements.extend(nml_doc.cell2_ca_poolses) minXc = 1e9 minYc = 1e9 minZc = 1e9 maxXc = -1e9 maxYc = -1e9 maxZc = -1e9 minX = 1e9 minY = 1e9 minZ = 1e9 maxX = -1e9 maxY = -1e9 maxZ = -1e9 declaredcells = {} print_comment_v("There are %i cells in the file"%len(cell_elements)) cell_id_vs_seg_id_vs_proximal = {} cell_id_vs_seg_id_vs_distal = {} cell_id_vs_cell = {} for cell in cell_elements: cellName = cell.id cell_id_vs_cell[cell.id] = cell print_comment_v("Handling cell: %s"%cellName) cell_id_vs_seg_id_vs_proximal[cell.id] = {} cell_id_vs_seg_id_vs_distal[cell.id] = {} declaredcell = "cell_"+cellName declaredcells[cellName] = declaredcell cells_file.write("#declare %s = \n"%declaredcell) cells_file.write("union {\n") prefix = "" segments = cell.morphology.segments distpoints = {} proxpoints = {} for segment in segments: id = int(segment.id) distal = segment.distal x = float(distal.x) y = float(distal.y) z = float(distal.z) r = max(float(distal.diameter)/2.0, args.mindiam) if x-r<minXc: minXc=x-r if y-r<minYc: minYc=y-r if z-r<minZc: minZc=z-r if x+r>maxXc: maxXc=x+r if y+r>maxYc: maxYc=y+r if z+r>maxZc: maxZc=z+r distalpoint = "<%f, %f, %f>, %f "%(x,y,z,r) distpoints[id] = distalpoint cell_id_vs_seg_id_vs_distal[cell.id][id] = (x,y,z) proximalpoint = "" if segment.proximal is not None: proximal = segment.proximal proximalpoint = "<%f, %f, %f>, %f "%(float(proximal.x),float(proximal.y),float(proximal.z),max(float(proximal.diameter)/2.0, args.mindiam)) cell_id_vs_seg_id_vs_proximal[cell.id][id] = (float(proximal.x),float(proximal.y),float(proximal.z)) else: parent = int(segment.parent.segments) proximalpoint = distpoints[parent] cell_id_vs_seg_id_vs_proximal[cell.id][id] = cell_id_vs_seg_id_vs_distal[cell.id][parent] proxpoints[id] = proximalpoint shape = "cone" if proximalpoint == distalpoint: shape = "sphere" proximalpoint = "" if ( shape == "cone" and (proximalpoint.split('>')[0] == distalpoint.split('>')[0])): comment = "Ignoring zero length segment (id = %i): %s -> %s\n"%(id, proximalpoint, distalpoint) print_comment_v(comment) cells_file.write(" // "+comment) else: cells_file.write(" %s {\n"%shape) cells_file.write(" %s\n"%distalpoint) if len(proximalpoint): cells_file.write(" %s\n"%proximalpoint) cells_file.write(" //%s_%s.%s\n"%('CELL_GROUP_NAME','0', id)) cells_file.write(" }\n") if args.segids: cells_file.write(' text {\n') cells_file.write(' ttf "timrom.ttf" "------- Segment: %s" .1, 0.01\n'%(segment.id)) cells_file.write(' pigment { Red }\n') cells_file.write(' rotate <0,180,0>\n') cells_file.write(' scale <10,10,10>') cells_file.write(' translate %s>\n'%distalpoint.split('>')[0]) cells_file.write(' }\n') cells_file.write(" pigment { color rgb <%f,%f,%f> }\n"%(random.random(),random.random(),random.random())) cells_file.write("}\n\n") if splitOut: pov_file.write("#include \""+cf+"\"\n\n") pov_file.write("#include \""+nf+"\"\n\n") pov_file.write('''\n/*\n Defining a dummy cell to use when cell in population is not found in NeuroML file...\n*/\n#declare %s = union { sphere { <0.000000, 0.000000, 0.000000>, 5.000000 } pigment { color rgb <1,0,0> } }\n'''%_DUMMY_CELL) pov_file.write('''\n/*\n Defining the spheres to use for end points of connections...\n*/ \n#declare conn_start_point = union { sphere { <0.000000, 0.000000, 0.000000>, 3.000000 } pigment { color rgb <0,1,0> } }\n \n#declare conn_end_point = union { sphere { <0.000000, 0.000000, 0.000000>, 3.000000 } pigment { color rgb <1,0,0> } }\n \n#declare input_object = union { cone { <0, 0, 0>, 0.1 // Center and radius of one end <0, -40, 0>, 2.5 // Center and radius of other end } pigment { color rgb <0.2,0.2,0.8> } }\n''') positions = {} popElements = nml_doc.networks[0].populations pop_id_vs_cell = {} print_comment_v("There are %i populations in the file"%len(popElements)) for pop in popElements: name = pop.id celltype = pop.component instances = pop.instances if pop.component in cell_id_vs_cell.keys(): pop_id_vs_cell[pop.id] = cell_id_vs_cell[pop.component] info = "Population: %s has %i positioned cells of type: %s"%(name,len(instances),celltype) print_comment_v(info) colour = "1" substitute_radius = None for prop in pop.properties: if prop.tag == 'color': colour = prop.value colour = colour.replace(" ", ",") #print "Colour determined to be: "+colour if prop.tag == 'radius': substitute_radius = float(prop.value) net_file.write("\n\n/* "+info+" */\n\n") pop_positions = {} if not celltype in declaredcells: minXc = 0 minYc = 0 minZc = 0 maxXc = 0 maxYc = 0 maxZc = 0 if substitute_radius: dummy_cell_name = define_dummy_cell(name, substitute_radius, pov_file) cell_definition = dummy_cell_name else: cell_definition = _DUMMY_CELL else: cell_definition = declaredcells[celltype] for instance in instances: location = instance.location id = int(instance.id) net_file.write("object {\n") net_file.write(" %s\n"%cell_definition) x = float(location.x) y = float(location.y) z = float(location.z) pop_positions[id] = (x,y,z) if x+minXc<minX: minX=x+minXc if y+minYc<minY: minY=y+minYc if z+minZc<minZ: minZ=z+minZc if x+maxXc>maxX: maxX=x+maxXc if y+maxYc>maxY: maxY=y+maxYc if z+maxZc>maxZ: maxZ=z+maxZc net_file.write(" translate <%s, %s, %s>\n"%(x,y,z)) if colour == '1': colour = "%f,%f,%f"%(random.random(),random.random(),random.random()) if colour is not None: net_file.write(" pigment { color rgb <%s> }"%(colour)) net_file.write("\n //%s_%s\n"%(name, id)) net_file.write("}\n") positions[name] = pop_positions if len(instances) == 0 and int(pop.size>0): info = "Population: %s has %i unpositioned cells of type: %s"%(name,pop.size,celltype) print_comment_v(info) colour = "1" ''' if pop.annotation: print dir(pop.annotation) print pop.annotation.anytypeobjs_ print pop.annotation.member_data_items_[0].name print dir(pop.annotation.member_data_items_[0]) for prop in pop.annotation.anytypeobjs_: print prop if len(prop.getElementsByTagName('meta:tag'))>0 and prop.getElementsByTagName('meta:tag')[0].childNodes[0].data == 'color': #print prop.getElementsByTagName('meta:tag')[0].childNodes colour = prop.getElementsByTagName('meta:value')[0].childNodes[0].data colour = colour.replace(" ", ",") elif prop.hasAttribute('tag') and prop.getAttribute('tag') == 'color': colour = prop.getAttribute('value') colour = colour.replace(" ", ",") print "Colour determined to be: "+colour ''' net_file.write("\n\n/* "+info+" */\n\n") net_file.write("object {\n") net_file.write(" %s\n"%cell_definition) x = 0 y = 0 z = 0 if x+minXc<minX: minX=x+minXc if y+minYc<minY: minY=y+minYc if z+minZc<minZ: minZ=z+minZc if x+maxXc>maxX: maxX=x+maxXc if y+maxYc>maxY: maxY=y+maxYc if z+maxZc>maxZ: maxZ=z+maxZc net_file.write(" translate <%s, %s, %s>\n"%(x,y,z)) if colour == '1': colour = "%f,%f,%f"%(random.random(),random.random(),random.random()) if colour is not None: net_file.write(" pigment { color rgb <%s> }"%(colour)) net_file.write("\n //%s_%s\n"%(name, id)) net_file.write("}\n") if args.conns or args.conn_points: projections = nml_doc.networks[0].projections + nml_doc.networks[0].electrical_projections + nml_doc.networks[0].continuous_projections for projection in projections: pre = projection.presynaptic_population post = projection.postsynaptic_population if isinstance(projection, neuroml.Projection): connections = [] for c in projection.connection_wds: connections.append(c) for c in projection.connections: connections.append(c) color='Grey' elif isinstance(projection, neuroml.ElectricalProjection): connections = projection.electrical_connections + projection.electrical_connection_instances + projection.electrical_connection_instance_ws color='Yellow' elif isinstance(projection, neuroml.ContinuousProjection): connections = projection.continuous_connections + projection.continuous_connection_instances + projection.continuous_connection_instance_ws color='Blue' print_comment_v("Adding %i connections for %s: %s -> %s "%(len(connections),projection.id,pre,post)) #print cell_id_vs_seg_id_vs_distal #print cell_id_vs_seg_id_vs_proximal for connection in connections: pre_cell_id = connection.get_pre_cell_id() post_cell_id = connection.get_post_cell_id() pre_loc = (0,0,0) if pre in positions.keys(): if len(positions[pre])>0: pre_loc = positions[pre][pre_cell_id] post_loc = (0,0,0) if post in positions.keys(): post_loc = positions[post][post_cell_id] if projection.presynaptic_population in pop_id_vs_cell.keys(): pre_cell = pop_id_vs_cell[projection.presynaptic_population] d = cell_id_vs_seg_id_vs_distal[pre_cell.id][connection.get_pre_segment_id()] p = cell_id_vs_seg_id_vs_proximal[pre_cell.id][connection.get_pre_segment_id()] m = [ p[i]+connection.get_pre_fraction_along()*(d[i]-p[i]) for i in [0,1,2] ] print_comment("Pre point is %s, %s between %s and %s"%(m,connection.get_pre_fraction_along(),p,d)) pre_loc = [ pre_loc[i]+m[i] for i in [0,1,2] ] if projection.postsynaptic_population in pop_id_vs_cell.keys(): post_cell = pop_id_vs_cell[projection.postsynaptic_population] d = cell_id_vs_seg_id_vs_distal[post_cell.id][connection.get_post_segment_id()] p = cell_id_vs_seg_id_vs_proximal[post_cell.id][connection.get_post_segment_id()] m = [ p[i]+connection.get_post_fraction_along()*(d[i]-p[i]) for i in [0,1,2] ] print_comment("Post point is %s, %s between %s and %s"%(m,connection.get_post_fraction_along(),p,d)) post_loc = [ post_loc[i]+m[i] for i in [0,1,2] ] if post_loc != pre_loc: info = "// Connection from %s:%s %s -> %s:%s %s\n"%(pre, pre_cell_id, pre_loc, post, post_cell_id, post_loc) print_comment(info) net_file.write("// %s"%info) if args.conns: net_file.write("cylinder { <%s,%s,%s>, <%s,%s,%s>, .5 pigment{color %s}}\n"%(pre_loc[0],pre_loc[1],pre_loc[2], post_loc[0],post_loc[1],post_loc[2],color)) if args.conn_points: net_file.write("object { conn_start_point translate <%s,%s,%s> }\n"%(pre_loc[0],pre_loc[1],pre_loc[2])) net_file.write("object { conn_end_point translate <%s,%s,%s> }\n"%(post_loc[0],post_loc[1],post_loc[2])) if args.inputs: for il in nml_doc.networks[0].input_lists: for input in il.input: popi = il.populations cell_id = input.get_target_cell_id() cell = pop_id_vs_cell[popi] loc = (0,0,0) if popi in positions.keys(): if len(positions[popi])>0: loc = positions[popi][cell_id] d = cell_id_vs_seg_id_vs_distal[cell.id][input.get_segment_id()] p = cell_id_vs_seg_id_vs_proximal[cell.id][input.get_segment_id()] m = [ p[i]+input.get_fraction_along()*(d[i]-p[i]) for i in [0,1,2] ] input_info = "Input on cell %s:%s at %s; point %s along (%s -> %s): %s"%(popi,cell_id, loc,input.get_fraction_along(),d,p,m) loc = [ loc[i]+m[i] for i in [0,1,2] ] net_file.write("/* %s */\n"%input_info) net_file.write("object { input_object translate <%s,%s,%s> }\n\n"%(loc[0],loc[1],loc[2])) plane = ''' plane { y, vv(-1) pigment {checker color rgb 1.0, color rgb 0.8 scale 20} } ''' footer=''' #declare minX = %f; #declare minY = %f; #declare minZ = %f; #declare maxX = %f; #declare maxY = %f; #declare maxZ = %f; #macro uu(xx) 0.5 * (maxX *(1+xx) + minX*(1-xx)) #end #macro vv(xx) 0.5 * (maxY *(1+xx) + minY*(1-xx)) #end #macro ww(xx) 0.5 * (maxZ *(1+xx) + minZ*(1-xx)) #end light_source { <uu(5),uu(2),uu(5)> color rgb <1,1,1> } light_source { <uu(-5),uu(2),uu(-5)> color rgb <1,1,1> } light_source { <uu(5),uu(-2),uu(-5)> color rgb <1,1,1> } light_source { <uu(-5),uu(-2),uu(5)> color rgb <1,1,1> } // Trying to view box camera { location < uu(%s + %s * sin (clock * 2 * 3.141)) , vv(%s + %s * sin (clock * 2 * 3.141)) , ww(%s + %s * cos (clock * 2 * 3.141)) > look_at < uu(%s + 0) , vv(%s + 0.05+0.3*sin (clock * 2 * 3.141)) , ww(%s + 0)> } %s \n'''%(minX,minY,minZ,maxX,maxY,maxZ, args.posx, args.scalex, args.posy, args.scaley, args.posz, args.scalez, args.viewx, args.viewy, args.viewz, (plane if args.plane else "")) ### end of footer pov_file.write(footer) pov_file.close() if args.movie: ini_file_name = pov_file_name.replace(".pov", "_movie.ini") ini_movie = ''' Antialias=On +W800 +H600 Antialias_Threshold=0.3 Antialias_Depth=4 Input_File_Name=%s Initial_Frame=1 Final_Frame=%i Initial_Clock=0 Final_Clock=1 Cyclic_Animation=on Pause_when_Done=off ''' ini_file = open(ini_file_name, 'w') ini_file.write(ini_movie%(pov_file_name, args.frames)) ini_file.close() print_comment_v("Created file for generating %i movie frames at: %s. To run this type:\n\n povray %s\n"%(args.frames,ini_file_name,ini_file_name)) else: print_comment_v("Created file for generating image of network. To run this type:\n\n povray %s\n"%(pov_file_name)) print_comment_v("Or for higher resolution:\n\n povray Antialias=On Antialias_Depth=10 Antialias_Threshold=0.1 +W1200 +H900 %s\n"%(pov_file_name))
def main (): args = process_args() xmlfile = args.neuroml_file pov_file_name = xmlfile.replace(".xml", ".pov").replace(".nml1", ".pov").replace(".nml.h5", ".pov").replace(".nml", ".pov") pov_file = open(pov_file_name, "w") header=''' /* POV-Ray file generated from NeuroML network */ #version 3.6; #include "colors.inc" background {rgbt %s} \n''' ### end of header pov_file.write(header%(args.background)) cells_file = pov_file net_file = pov_file splitOut = False cf = pov_file_name.replace(".pov", "_cells.inc") nf = pov_file_name.replace(".pov", "_net.inc") if args.split: splitOut = True cells_file = open(cf, "w") net_file = open(nf, "w") print_comment_v("Saving into %s and %s and %s"%(pov_file_name, cf, nf)) print_comment_v("Converting XML file: %s to %s"%(xmlfile, pov_file_name)) nml_doc = pynml.read_neuroml2_file(xmlfile, include_includes=True, verbose=args.v) cell_elements = [] cell_elements.extend(nml_doc.cells) cell_elements.extend(nml_doc.cell2_ca_poolses) minXc = 1e9 minYc = 1e9 minZc = 1e9 maxXc = -1e9 maxYc = -1e9 maxZc = -1e9 minX = 1e9 minY = 1e9 minZ = 1e9 maxX = -1e9 maxY = -1e9 maxZ = -1e9 declaredcells = {} print_comment_v("There are %i cells in the file"%len(cell_elements)) cell_id_vs_seg_id_vs_proximal = {} cell_id_vs_seg_id_vs_distal = {} cell_id_vs_cell = {} for cell in cell_elements: cellName = cell.id cell_id_vs_cell[cell.id] = cell print_comment_v("Handling cell: %s"%cellName) cell_id_vs_seg_id_vs_proximal[cell.id] = {} cell_id_vs_seg_id_vs_distal[cell.id] = {} declaredcell = "cell_"+cellName declaredcells[cellName] = declaredcell cells_file.write("#declare %s = \n"%declaredcell) cells_file.write("union {\n") prefix = "" segments = cell.morphology.segments distpoints = {} proxpoints = {} for segment in segments: id = int(segment.id) distal = segment.distal x = float(distal.x) y = float(distal.y) z = float(distal.z) r = max(float(distal.diameter)/2.0, args.mindiam) if x-r<minXc: minXc=x-r if y-r<minYc: minYc=y-r if z-r<minZc: minZc=z-r if x+r>maxXc: maxXc=x+r if y+r>maxYc: maxYc=y+r if z+r>maxZc: maxZc=z+r distalpoint = "<%f, %f, %f>, %f "%(x,y,z,r) distpoints[id] = distalpoint cell_id_vs_seg_id_vs_distal[cell.id][id] = (x,y,z) proximalpoint = "" if segment.proximal is not None: proximal = segment.proximal proximalpoint = "<%f, %f, %f>, %f "%(float(proximal.x),float(proximal.y),float(proximal.z),max(float(proximal.diameter)/2.0, args.mindiam)) cell_id_vs_seg_id_vs_proximal[cell.id][id] = (float(proximal.x),float(proximal.y),float(proximal.z)) else: parent = int(segment.parent.segments) proximalpoint = distpoints[parent] cell_id_vs_seg_id_vs_proximal[cell.id][id] = cell_id_vs_seg_id_vs_distal[cell.id][parent] proxpoints[id] = proximalpoint shape = "cone" if proximalpoint == distalpoint: shape = "sphere" proximalpoint = "" if ( shape == "cone" and (proximalpoint.split('>')[0] == distalpoint.split('>')[0])): comment = "Ignoring zero length segment (id = %i): %s -> %s\n"%(id, proximalpoint, distalpoint) print_comment_v(comment) cells_file.write(" // "+comment) else: cells_file.write(" %s {\n"%shape) cells_file.write(" %s\n"%distalpoint) if len(proximalpoint): cells_file.write(" %s\n"%proximalpoint) cells_file.write(" //%s_%s.%s\n"%('CELL_GROUP_NAME','0', id)) cells_file.write(" }\n") cells_file.write(" pigment { color rgb <%f,%f,%f> }\n"%(random.random(),random.random(),random.random())) cells_file.write("}\n\n") if splitOut: pov_file.write("#include \""+cf+"\"\n\n") pov_file.write("#include \""+nf+"\"\n\n") pov_file.write('''\n/*\n Defining a dummy cell to use when cell in population is not found in NeuroML file...\n*/\n#declare %s = union { sphere { <0.000000, 0.000000, 0.000000>, 5.000000 } pigment { color rgb <1,0,0> } }\n'''%_DUMMY_CELL) pov_file.write('''\n/*\n Defining the spheres to use for end points of connections...\n*/\n#declare conn_start_point = union { sphere { <0.000000, 0.000000, 0.000000>, 3.000000 } pigment { color rgb <0,1,0> } }\n\n#declare conn_end_point = union { sphere { <0.000000, 0.000000, 0.000000>, 3.000000 } pigment { color rgb <1,0,0> } }\n''') positions = {} popElements = nml_doc.networks[0].populations pop_id_vs_cell = {} print_comment_v("There are %i populations in the file"%len(popElements)) for pop in popElements: name = pop.id celltype = pop.component instances = pop.instances if pop.component in cell_id_vs_cell.keys(): #if cell_id_vs_cell.has_key(pop.component): pop_id_vs_cell[pop.id] = cell_id_vs_cell[pop.component] info = "Population: %s has %i positioned cells of type: %s"%(name,len(instances),celltype) print_comment_v(info) colour = "1" for prop in pop.properties: if prop.tag == 'color': colour = prop.value colour = colour.replace(" ", ",") #print "Colour determined to be: "+colour net_file.write("\n\n/* "+info+" */\n\n") pop_positions = {} if not celltype in declaredcells: cell_definition = _DUMMY_CELL minXc = 0 minYc = 0 minZc = 0 maxXc = 0 maxYc = 0 maxZc = 0 else: cell_definition = declaredcells[celltype] for instance in instances: location = instance.location id = int(instance.id) net_file.write("object {\n") net_file.write(" %s\n"%cell_definition) x = float(location.x) y = float(location.y) z = float(location.z) pop_positions[id] = (x,y,z) if x+minXc<minX: minX=x+minXc if y+minYc<minY: minY=y+minYc if z+minZc<minZ: minZ=z+minZc if x+maxXc>maxX: maxX=x+maxXc if y+maxYc>maxY: maxY=y+maxYc if z+maxZc>maxZ: maxZ=z+maxZc net_file.write(" translate <%s, %s, %s>\n"%(x,y,z)) if colour == '1': colour = "%f,%f,%f"%(random.random(),random.random(),random.random()) if colour is not None: net_file.write(" pigment { color rgb <%s> }"%(colour)) net_file.write("\n //%s_%s\n"%(name, id)) net_file.write("}\n") positions[name] = pop_positions if len(instances) == 0 and int(pop.size>0): info = "Population: %s has %i unpositioned cells of type: %s"%(name,pop.size,celltype) print_comment_v(info) colour = "1" ''' if pop.annotation: print dir(pop.annotation) print pop.annotation.anytypeobjs_ print pop.annotation.member_data_items_[0].name print dir(pop.annotation.member_data_items_[0]) for prop in pop.annotation.anytypeobjs_: print prop if len(prop.getElementsByTagName('meta:tag'))>0 and prop.getElementsByTagName('meta:tag')[0].childNodes[0].data == 'color': #print prop.getElementsByTagName('meta:tag')[0].childNodes colour = prop.getElementsByTagName('meta:value')[0].childNodes[0].data colour = colour.replace(" ", ",") elif prop.hasAttribute('tag') and prop.getAttribute('tag') == 'color': colour = prop.getAttribute('value') colour = colour.replace(" ", ",") print "Colour determined to be: "+colour ''' net_file.write("\n\n/* "+info+" */\n\n") net_file.write("object {\n") net_file.write(" %s\n"%cell_definition) x = 0 y = 0 z = 0 if x+minXc<minX: minX=x+minXc if y+minYc<minY: minY=y+minYc if z+minZc<minZ: minZ=z+minZc if x+maxXc>maxX: maxX=x+maxXc if y+maxYc>maxY: maxY=y+maxYc if z+maxZc>maxZ: maxZ=z+maxZc net_file.write(" translate <%s, %s, %s>\n"%(x,y,z)) if colour == '1': colour = "%f,%f,%f"%(random.random(),random.random(),random.random()) if colour is not None: net_file.write(" pigment { color rgb <%s> }"%(colour)) net_file.write("\n //%s_%s\n"%(name, id)) net_file.write("}\n") #print positions if args.conns or args.conn_points: # Note: segment specific connections not implemented yet... i.e. connections from dends to axons... #print_comment_v("************************\n*\n* Note: connection lines in 3D do not yet target dendritic locations!\n*\n************************") for projection in nml_doc.networks[0].projections: pre = projection.presynaptic_population post = projection.postsynaptic_population connections = projection.connections + projection.connection_wds print_comment_v("Adding %i connections %s -> %s "%(len(connections),pre,post)) #print cell_id_vs_seg_id_vs_distal #print cell_id_vs_seg_id_vs_proximal for connection in connections: pre_cell_id = connection.get_pre_cell_id() post_cell_id = connection.get_post_cell_id() pre_loc = (0,0,0) if pre in positions.keys():# positions.has_key(pre): if len(positions[pre])>0: pre_loc = positions[pre][pre_cell_id] post_loc = (0,0,0) if post in positions.keys(): #positions.has_key(post): post_loc = positions[post][post_cell_id] #if pop_id_vs_cell.has_key(projection.presynaptic_population): if projection.presynaptic_population in pop_id_vs_cell.keys(): pre_cell = pop_id_vs_cell[projection.presynaptic_population] d = cell_id_vs_seg_id_vs_distal[pre_cell.id][int(connection.pre_segment_id)] p = cell_id_vs_seg_id_vs_proximal[pre_cell.id][int(connection.pre_segment_id)] m = [ p[i]+float(connection.pre_fraction_along)*(d[i]-p[i]) for i in [0,1,2] ] print_comment("Pre point is %s, %s between %s and %s"%(m,connection.pre_fraction_along,p,d)) pre_loc = [ pre_loc[i]+m[i] for i in [0,1,2] ] if projection.postsynaptic_population in pop_id_vs_cell.keys(): #has_key(projection.postsynaptic_population): #if pop_id_vs_cell.has_key(projection.postsynaptic_population): post_cell = pop_id_vs_cell[projection.postsynaptic_population] d = cell_id_vs_seg_id_vs_distal[post_cell.id][int(connection.post_segment_id)] p = cell_id_vs_seg_id_vs_proximal[post_cell.id][int(connection.post_segment_id)] m = [ p[i]+float(connection.post_fraction_along)*(d[i]-p[i]) for i in [0,1,2] ] print_comment("Post point is %s, %s between %s and %s"%(m,connection.post_fraction_along,p,d)) post_loc = [ post_loc[i]+m[i] for i in [0,1,2] ] if post_loc != pre_loc: info = "// Connection from %s:%s %s -> %s:%s %s\n"%(pre, pre_cell_id, pre_loc, post, post_cell_id, post_loc) print_comment(info) net_file.write("// %s"%info) if args.conns: net_file.write("cylinder { <%s,%s,%s>, <%s,%s,%s>, .5 pigment{color Grey}}\n"%(pre_loc[0],pre_loc[1],pre_loc[2], post_loc[0],post_loc[1],post_loc[2])) if args.conn_points: net_file.write("object { conn_start_point translate <%s,%s,%s> }\n"%(pre_loc[0],pre_loc[1],pre_loc[2])) net_file.write("object { conn_end_point translate <%s,%s,%s> }\n"%(post_loc[0],post_loc[1],post_loc[2])) plane = ''' plane { y, vv(-1) pigment {checker color rgb 1.0, color rgb 0.8 scale 20} } ''' footer=''' #declare minX = %f; #declare minY = %f; #declare minZ = %f; #declare maxX = %f; #declare maxY = %f; #declare maxZ = %f; #macro uu(xx) 0.5 * (maxX *(1+xx) + minX*(1-xx)) #end #macro vv(xx) 0.5 * (maxY *(1+xx) + minY*(1-xx)) #end #macro ww(xx) 0.5 * (maxZ *(1+xx) + minZ*(1-xx)) #end light_source { <uu(5),uu(2),uu(5)> color rgb <1,1,1> } light_source { <uu(-5),uu(2),uu(-5)> color rgb <1,1,1> } light_source { <uu(5),uu(-2),uu(-5)> color rgb <1,1,1> } light_source { <uu(-5),uu(-2),uu(5)> color rgb <1,1,1> } // Trying to view box camera { location < uu(%s + %s * sin (clock * 2 * 3.141)) , vv(%s + %s * sin (clock * 2 * 3.141)) , ww(%s + %s * cos (clock * 2 * 3.141)) > look_at < uu(%s + 0) , vv(%s + 0.05+0.3*sin (clock * 2 * 3.141)) , ww(%s + 0)> } %s \n'''%(minX,minY,minZ,maxX,maxY,maxZ, args.posx, args.scalex, args.posy, args.scaley, args.posz, args.scalez, args.viewx, args.viewy, args.viewz, (plane if args.plane else "")) ### end of footer pov_file.write(footer) pov_file.close() if args.movie: ini_file_name = pov_file_name.replace(".pov", "_movie.ini") ini_movie = ''' Antialias=On +W800 +H600 Antialias_Threshold=0.3 Antialias_Depth=4 Input_File_Name=%s Initial_Frame=1 Final_Frame=%i Initial_Clock=0 Final_Clock=1 Cyclic_Animation=on Pause_when_Done=off ''' ini_file = open(ini_file_name, 'w') ini_file.write(ini_movie%(pov_file_name, args.frames)) ini_file.close() print_comment_v("Created file for generating %i movie frames at: %s. To run this type:\n\n povray %s\n"%(args.frames,ini_file_name,ini_file_name)) else: print_comment_v("Created file for generating image of network. To run this type:\n\n povray %s\n"%(pov_file_name)) print_comment_v("Or for higher resolution:\n\n povray Antialias=On Antialias_Depth=10 Antialias_Threshold=0.1 +W1200 +H900 %s\n"%(pov_file_name))
def generate_lems_file_for_neuroml( sim_id, neuroml_file, target, duration, dt, lems_file_name, target_dir, gen_plots_for_all_v=True, plot_all_segments=False, gen_plots_for_only=[], # List of populations gen_plots_for_quantities={}, # Dict with displays vs lists of quantity paths gen_saves_for_all_v=True, save_all_segments=False, gen_saves_for_only=[], # List of populations gen_saves_for_quantities={}, # Dict with file names vs lists of quantity paths copy_neuroml=True, seed=None): if seed: random.seed( seed ) # To ensure same LEMS file (e.g. colours of plots) are generated every time for the same input file_name_full = '%s/%s' % (target_dir, lems_file_name) print_comment_v('Creating LEMS file at: %s for NeuroML 2 file: %s' % (file_name_full, neuroml_file)) ls = LEMSSimulation(sim_id, duration, dt, target) nml_doc = read_neuroml2_file(neuroml_file, include_includes=True, verbose=True) quantities_saved = [] if not copy_neuroml: rel_nml_file = os.path.relpath(os.path.abspath(neuroml_file), os.path.abspath(target_dir)) print_comment_v("Including existing NeuroML file (%s) as: %s" % (neuroml_file, rel_nml_file)) ls.include_neuroml2_file(rel_nml_file, include_included=True, relative_to_dir=os.path.abspath(target_dir)) else: print_comment_v( "Copying NeuroML file (%s) to: %s (%s)" % (neuroml_file, target_dir, os.path.abspath(target_dir))) if os.path.abspath( os.path.dirname(neuroml_file)) != os.path.abspath(target_dir): shutil.copy(neuroml_file, target_dir) neuroml_file_name = os.path.basename(neuroml_file) ls.include_neuroml2_file(neuroml_file_name, include_included=False) for include in nml_doc.includes: incl_curr = '%s/%s' % (os.path.dirname(neuroml_file), include.href) print_comment_v(' - Including %s located at %s' % (include.href, incl_curr)) shutil.copy(incl_curr, target_dir) ls.include_neuroml2_file(include.href, include_included=False) sub_doc = read_neuroml2_file(incl_curr) for include in sub_doc.includes: incl_curr = '%s/%s' % (os.path.dirname(neuroml_file), include.href) print_comment_v(' -- Including %s located at %s' % (include.href, incl_curr)) shutil.copy(incl_curr, target_dir) ls.include_neuroml2_file(include.href, include_included=False) if gen_plots_for_all_v or gen_saves_for_all_v or len( gen_plots_for_only) > 0 or len(gen_saves_for_only) > 0: for network in nml_doc.networks: for population in network.populations: quantity_template = "%s[%i]/v" component = population.component size = population.size cell = None segment_ids = [] if plot_all_segments: for c in nml_doc.cells: if c.id == component: cell = c for segment in cell.morphology.segments: segment_ids.append(segment.id) segment_ids.sort() if population.type and population.type == 'populationList': quantity_template = "%s/%i/" + component + "/v" size = len(population.instances) if gen_plots_for_all_v or population.id in gen_plots_for_only: print_comment( 'Generating %i plots for %s in population %s' % (size, component, population.id)) disp0 = 'DispPop__%s' % population.id ls.create_display(disp0, "Voltages of %s" % disp0, "-90", "50") for i in range(size): if plot_all_segments: quantity_template_seg = "%s/%i/" + component + "/%i/v" for segment_id in segment_ids: quantity = quantity_template_seg % ( population.id, i, segment_id) ls.add_line_to_display( disp0, "v in seg %i %s" % (segment_id, safe_variable(quantity)), quantity, "1mV", get_next_hex_color()) else: quantity = quantity_template % (population.id, i) ls.add_line_to_display( disp0, "v %s" % safe_variable(quantity), quantity, "1mV", get_next_hex_color()) if gen_saves_for_all_v or population.id in gen_saves_for_only: print_comment( 'Saving %i values of v for %s in population %s' % (size, component, population.id)) of0 = 'Volts_file__%s' % population.id ls.create_output_file( of0, "%s.%s.v.dat" % (sim_id, population.id)) for i in range(size): if save_all_segments: quantity_template_seg = "%s/%i/" + component + "/%i/v" for segment_id in segment_ids: quantity = quantity_template_seg % ( population.id, i, segment_id) ls.add_column_to_output_file( of0, 'v_%s' % safe_variable(quantity), quantity) quantities_saved.append(quantity) else: quantity = quantity_template % (population.id, i) ls.add_column_to_output_file( of0, 'v_%s' % safe_variable(quantity), quantity) quantities_saved.append(quantity) for display in gen_plots_for_quantities.keys(): quantities = gen_plots_for_quantities[display] ls.create_display(display, "Plots of %s" % display, "-90", "50") for q in quantities: ls.add_line_to_display(display, safe_variable(q), q, "1", get_next_hex_color()) for file_name in gen_saves_for_quantities.keys(): quantities = gen_saves_for_quantities[file_name] ls.create_output_file(file_name, file_name) for q in quantities: ls.add_column_to_output_file(file_name, safe_variable(q), q) ls.save_to_file(file_name=file_name_full) return quantities_saved