Source code for brian2tools.nmlexport.supporting

import re
import os
import xml.dom.minidom as minidom

from brian2.units.allunits import all_units
from brian2 import get_or_create_dimension


name_to_unit = {u.dispname: u for u in all_units}


[docs]def from_string(rep): """ Returns `Quantity` object from text representation of a value. Parameters ---------- rep : `str` text representation of a value with unit Returns ------- q : `Quantity` Brian Quantity object """ # match value m = re.match('-?[0-9]+\.?([0-9]+)?[eE]?-?([0-9]+)?', rep) if m: value = rep[0:m.end()] rep = rep[m.end():] else: raise ValueError("Empty value given") # match unit m = re.match(' ?([a-zA-Z]+)', rep) unit = None per = None if m: unit = rep[0:m.end()].strip() # special case with per if unit == 'per': mper = re.match(' ?per_([a-zA-Z]+)', rep) per = rep[0:mper.end()].strip()[4:] m = mper rep = rep[m.end():] # match exponent m = re.match('-?([0-9]+)?', rep) exponent = None if len(rep) > 0 and m: exponent = rep[0:m.end()] if unit: if per: b2unit = 1. / name_to_unit[per] else: b2unit = name_to_unit[unit] if value and exponent: return float(value) * b2unit**float(exponent) elif value: return float(value) * b2unit else: return float(value)
[docs]def brian_unit_to_lems(valunit): """ Returns string representation of LEMS unit where * is between value and unit e.g. "20. mV" -> "20.*mV". Parameters ---------- valunit : `Quantity` or `str` text or brian2.Quantity representation of a value with unit Returns ------- valstr : `str` string representation of LEMS unit """ if float(valunit) == 0: return '0' if type(valunit) != str: valunit = str(valunit) return valunit.replace(' ', '*')
[docs]def read_nml_dims(nmlcdpath=""): """ Read from `NeuroMLCoreDimensions.xml` all supported by LEMS dimensions and store it as a Python dict with name as a key and Brian2 unit as value. Parameters ---------- nmlcdpath : `str`, optional Path to 'NeuroMLCoreDimensions.xml' Returns ------- lems_dimenssions : `dict` Dictionary with LEMS dimensions. """ path = os.path.join(nmlcdpath, "NeuroMLCoreDimensions.xml") domtree = minidom.parse(path) collection = domtree.documentElement dimsCollection = collection.getElementsByTagName("Dimension") order_dict = {"m": 1, "l": 0, "t": 2, "i": 3, "k": 4, "n": 5, "j": 6} lems_dimensions = dict() for dc in dimsCollection: name_ = dc.getAttribute("name") tmpdim_ = [0]*7 # 7 base dimensions for k in order_dict.keys(): if dc.hasAttribute(k): tmpdim_[order_dict[k]] = int(dc.getAttribute(k)) lems_dimensions[name_] = get_or_create_dimension(tmpdim_) return lems_dimensions
[docs]def read_nml_units(nmlcdpath=""): """ Read from 'NeuroMLCoreDimensions.xml' all supported by LEMS units. Parameters ---------- nmlcdpath : `str`, optional Path to 'NeuroMLCoreDimensions.xml' Returns ------- lems_units : `list` List with LEMS units. """ path = os.path.join(nmlcdpath, "NeuroMLCoreDimensions.xml") domtree = minidom.parse(path) collection = domtree.documentElement unitsCollection = collection.getElementsByTagName("Unit") lems_units = [] for uc in unitsCollection: if uc.hasAttribute('symbol'): lems_units.append(uc.getAttribute('symbol')) return lems_units
######################################## # All NeuroML2 syntax creation helpers ########################################
[docs]class NeuroMLSimulation(object): ''' NeuroMLSimulation class representing Simulation tag in NeuroML syntax as a XML DOM representation. ''' def __init__(self, simid, target, length="1s", step="0.1ms"): ''' NeuroMLSimulation object constructor. Parameters ---------- simid : str simulation id. target : str target NeuroML object: component or network length : str, optional length of simulation, default 1 sec step : str, optional step of integration, default 0.1 ms ''' self.doc = minidom.Document() self.create_simulation(simid, target, length, step) self.lines = {} self.displays = {} self._disp_idx = -1 self.outcolumns = {} self.output_files = {} self._output_idx = -1 self.eventselections = {} self.event_output_files = {} self._event_output_idx = -1
[docs] def create_simulation(self, simid, target, length, step): """ Adds a Simulation element to DOM structure at init. Parameters ---------- simid : str simulation id. target : str target NeuroML object: component or network length : str, optional length of simulation, default 1 sec step : str, optional step of integration, default 0.1 ms """ self.simulation = self.doc.createElement('Simulation') attributes = [("id", simid), ("target", target), ("length", length), ("step", step)] for attr_name, attr_value in attributes: self.simulation.setAttribute(attr_name, attr_value)
[docs] def update_simulation_attribute(self, attr_name, attr_value): """ Updates simulation attributes. Parameters ---------- attr_name : str attribute name attr_value : str or int or float attribute value """ if not type(attr_value) is str: attr_value = str(attr_value) self.simulation.setAttribute(attr_name, attr_value)
[docs] def add_display(self, dispid, title="", time_scale="1ms", xmin="0", xmax="1000", ymin="0", ymax="11"): """ Adds a Display element to Simulation. Parameters ---------- dispid : str display id title : str title printed on display window time_scale : str time scale of a plot xmin, xmax, ymin, ymax : str limits of plot """ self._disp_idx += 1 self.displays[self._disp_idx] = self.doc.createElement('Display') self.lines[self._disp_idx] = [] attributes = [("id", dispid), ("title", title), ("timeScale", time_scale), ("xmin", xmin), ("xmax", xmax), ("ymin", ymin), ("ymax", ymax)] for attr_name, attr_value in attributes: self.displays[self._disp_idx].setAttribute(attr_name, attr_value)
[docs] def add_line(self, linid, quantity, scale="1mV", time_scale="1ms"): """ Adds a Line element to a recently added Display. Parameters ---------- linid : str line id quantity : str measure to plot scale : str scale of a function time_scale : str time scale of a line """ assert self.displays, "You need to add display first" line = self.doc.createElement('Line') attributes = [("id", linid), ("quantity", quantity), ("scale", scale), ("timeScale", time_scale)] for attr_name, attr_value in attributes: line.setAttribute(attr_name, attr_value) self.lines[self._disp_idx].append(line)
[docs] def add_outputfile(self, outfileid, filename="recordings.dat"): """ Adds an OutputFile to Simulation. Parameters ---------- outfileid : str OutputFile id filename : str name of an output file """ self._output_idx += 1 self.output_files[self._output_idx] = self.doc.createElement('OutputFile') self.outcolumns[self._output_idx] = [] attributes = [("id", outfileid), ("fileName", filename)] for attr_name, attr_value in attributes: self.output_files[self._output_idx].setAttribute(attr_name, attr_value)
[docs] def add_outputcolumn(self, ocid, quantity): """ Adds an OutputColumn element to a recently added OutputFile tag. Parameters ---------- ocid : str OutputColumn id quantity : str measure to store in a column """ assert self.output_files, "You need to add output_files first" outputcolumn = self.doc.createElement('OutputColumn') attributes = [("id", ocid), ("quantity", quantity)] for attr_name, attr_value in attributes: outputcolumn.setAttribute(attr_name, attr_value) self.outcolumns[self._output_idx].append(outputcolumn)
[docs] def add_eventoutputfile(self, outfileid, filename="recordings.spikes", format_="TIME_ID"): """ Adds an EventOutputFile element to a recently added Display. Parameters ---------- outfileid : str EventOutputFile id filename : str name of an output file format : str, optional format of data storage, default TIME_ID """ self._event_output_idx += 1 self.event_output_files[self._event_output_idx] = self.doc.createElement('EventOutputFile') self.eventselections[self._event_output_idx] = [] attributes = [("id", outfileid), ("fileName", filename), ("format", format_)] for attr_name, attr_value in attributes: self.event_output_files[self._event_output_idx].setAttribute(attr_name, attr_value)
[docs] def add_eventselection(self, esid, select, event_port="spike"): """ Adds an EventSelection element to a recently added EventOutputFile. Parameters ---------- esid : str EventSelection id select : str index of selected neuron event_port : str event port name, default 'spike' """ assert self.event_output_files, "You need to add EventOutputFile first" eventselection = self.doc.createElement('EventSelection') attributes = [("id", esid), ("select", select), ("eventPort", event_port)] for attr_name, attr_value in attributes: eventselection.setAttribute(attr_name, attr_value) self.eventselections[self._event_output_idx].append(eventselection)
[docs] def build(self): ''' Builds NeuroML DOM structure of Simulation. It returns DOM object or it can be accessed by *object.simulation*. Returns ------- simulation : xml.minidom.dom DOM representation of simulation. ''' for k in self.displays: for line in self.lines[k]: self.displays[k].appendChild(line) self.simulation.appendChild(self.displays[k]) for k in self.output_files: for outcol in self.outcolumns[k]: self.output_files[k].appendChild(outcol) self.simulation.appendChild(self.output_files[k]) for k in self.event_output_files: for evsel in self.eventselections[k]: self.event_output_files[k].appendChild(evsel) self.simulation.appendChild(self.event_output_files[k]) return self.simulation
def __repr__(self): return self.simulation.toprettyxml(' ', '\n')
[docs]class NeuroMLSimpleNetwork(object): ''' NeuroMLSimpleNetwork class representing network tag in NeuroML syntax as a XML DOM representation. ''' def __init__(self, id_): ''' NeuroMLSimpleNetwork object constructor. Parameters ---------- simid : str network id. ''' self.doc = minidom.Document() self.network = self.doc.createElement('network') self.network.setAttribute("id", id_) self.components = []
[docs] def add_component(self, id_, type_, **attributes): ''' Adds a component to a network. Parameters ---------- id_ : str component id type_ : str type of component attributes : ..., optional more attributes ''' component = self.doc.createElement('Component') component.setAttribute("id", id_) component.setAttribute("type", type_) for attr_name, attr_value in attributes.items(): component.setAttribute(str(attr_name), str(attr_value)) self.components.append(component)
[docs] def build(self): ''' Builds NeuroML DOM structure of network. It returns DOM object. Returns ------- network : xml.minidom.dom DOM representation of network. ''' for comp in self.components: self.network.appendChild(comp) return self.network
def __repr__(self): return self.network.toprettyxml(' ', '\n')
[docs]class NeuroMLPoissonGenerator(object): ''' Makes XML of spikeGeneratorPoisson for NeuroML2/LEMS simulation. ''' def __init__(self, poissid, average_rate): ''' NeuroMLPoissonGenerator object constructor. Parameters ---------- poissid : str generator id average_rate : float average rate of firing in Hz ''' self.doc = minidom.Document() self.generator = self.doc.createElement('spikeGeneratorPoisson') self.generator.setAttribute("id", poissid) average_rate = str(average_rate) + ' Hz' self.generator.setAttribute("averageRate", average_rate)
[docs] def build(self): ''' Builds NeuroML DOM structure of spikeGeneratorPoisson and returns it. Returns ------- generator : xml.minidom.dom DOM representation of generator. ''' return self.generator
def __repr__(self): return self.generator.toprettyxml(' ', '\n')
[docs]class NeuroMLTarget(object): ''' Makes XML of target of NeuroML2/LEMS simulation. ''' def __init__(self, component): ''' NeuroMLTarget object constructor. Parameters ---------- component : str target component ''' self.doc = minidom.Document() self.target = self.doc.createElement('Target') self.target.setAttribute("component", component)
[docs] def build(self): ''' Builds NeuroML DOM structure of target and returns it. Returns ------- target : xml.minidom.dom DOM representation of target. ''' return self.target
def __repr__(self): return self.target.toprettyxml(' ', '\n')