Exemple #1
0
 def bind(self, container, to_roles=False):
     """
     Binds the PortConnection to the components it is connecting
     """
     # If the sender and receiver should be identified by their role
     # i.e. pre, pos, response, plasticity, etc... or by name
     if to_roles:
         self._sender = getattr(container, self.sender_role)
         self._receiver = getattr(container, self.receiver_role)
     else:
         self._sender = container[self.sender_name]
         self._receiver = container[self.receiver_name]
     try:
         self._send_port = self._sender.send_port(self.send_port_name)
     except NineMLNameError:
         raise NineMLNameError(
             "Could not bind to missing send port, '{}', in '{}'".format(
                 self.send_port_name, self.sender.name))
     try:
         self._receive_port = self._receiver.receive_port(
             self.receive_port_name)
     except NineMLNameError:
         raise NineMLNameError(
             "Could not bind {} to missing receive port, '{}', in '{}'".
             format(self, self.receive_port_name, self.receiver.name))
     self._check_ports()
Exemple #2
0
 def get_attr(self, serial_elem, name, **options):  # @UnusedVariable
     try:
         value = serial_elem[name]
     except KeyError:
         raise NineMLNameError(
             "Element {} doesn't contain an '{}' attribute".format(
                 serial_elem, name))
     except TypeError:
         raise
     if self._is_child(value):
         raise NineMLNameError(
             "Element {} contains a '{}' child ({}) not an attribute".
             format(serial_elem, name, value))
     return value
Exemple #3
0
    def set(self, key, *args):
        """
        Sets the attribute of an annotations "leaf", creating intermediate
        branches if required

        Parameters
        ----------
        key : str | tuple(str, str)
            Name of the next branch in the annotations tree, optionally with
            a namespace, provided as a tuple (key, namespace). If the namespace
            is not provided it is taken to be the same as the containing branch
        *args : list(str) + (int|float|str)
            A list of subsequent branches to the leaf node followed by the
            attribute name and a value
        """
        key = self._parse_key(key)
        # Recurse into branches while there are remaining args
        key_branches = self._branches[key]
        if len(key_branches) == 1:
            branch = key_branches[0]
        elif not key_branches:
            name, ns = key
            branch = _AnnotationsBranch(name, ns, rel_index=len(key_branches))
            key_branches.append(branch)
        else:
            raise NineMLNameError(
                "Multiple branches found for key '{}' in annoations branch"
                " '{}', cannot use 'set' method".format(
                    key, self._name))
        branch.set(*args)  # recurse into branch
Exemple #4
0
    def add(self, key, *args):
        """
        Adds a new branch for the given key. If the key exists already then
        then an additional branch is appended for that key.

        Parameters
        ----------
        key : str | tuple(str, str)
            Name of the next branch in the annotations tree, optionally with
            a namespace, provided as a tuple (key, namespace). If the namespace
            is not provided it is taken to be the same as the containing branch
        *args : list(str)
            A list of keys for the sub-branches ending in the key of the new
            sub-branch to add. Intermediate branches that are not present are
            added implicitly.
        """
        key = self._parse_key(key)
        key_branches = self._branches[key]
        if not key_branches or not args:
            name, ns = key
            branch = _AnnotationsBranch(name, ns, rel_index=len(key_branches))
            key_branches.append(branch)
        if args:
            if len(key_branches) > 1:
                raise NineMLNameError(
                    "Multiple branches found for key '{}' in annoations branch"
                    " '{}', cannot use 'add' method to add a sub-branch"
                    .format(key, self._name))
            branch = key_branches[0]
            branch.add(*args)
        return branch
Exemple #5
0
    def get(self, key, *args, **kwargs):
        """
        Gets the attribute of an annotations "leaf"

        Parameters
        ----------
        key : str | tuple(str, str)
            Name of the next branch in the annotations tree, optionally with
            a namespace, provided as a tuple (key, namespace). If the namespace
            is not provided it is taken to be the same as the containing branch
        *args : list(str) + (int|float|str)
            A list of subsequent branches to the leaf node followed by the
            attribute name to return the value of
        default: (int|float|str)
            The default value to return if the specified annotation has not
            been set

        Returns
        -------
        val : (int|float|str)
            The value of the annotation attribute
        """
        if not args:
            if 'default' in kwargs:
                val = self._attr.get(key, kwargs['default'])
            else:
                try:
                    val = self._attr[key]
                except KeyError:
                    raise NineMLNameError(
                        "Annotations branch {{{}}}{} does not contain '{}' "
                        "attribute".format(self.ns, self.name, key))
        else:
            val = super(_AnnotationsBranch, self).get(key, *args, **kwargs)
        return val
Exemple #6
0
 def get_attr(self, serial_elem, name, **options):  # @UnusedVariable
     try:
         return serial_elem.attrib[name]
     except KeyError:
         raise NineMLNameError(
             "Element {} doesn't contain '{}' attribute".format(
                 serial_elem, name))
Exemple #7
0
 def accessor(self, name):
     try:
         ports = [population_accessor(p, name) for p in self.populations]
     except NineMLNameError:
         raise NineMLNameError(
             "'{}' {} is not present in all populations '{}' of the "
             "selection"
             .format(name, population_accessor.__name__,
                     "', '".join(p.name for p in self.populations)))
     port = ports[0]
     if any(p != port for p in ports):
         raise NineMLNameError(
             "{} '{}' in populations '{}' are not equivalent"
             .format(population_accessor.__name__.capitalize(),
                     name, "', '".join(p.name for p in self.populations)))
     return port
Exemple #8
0
    def delete(self, key, *args, **kwargs):
        """
        Gets the attribute of an annotations "leaf"

        Parameters
        ----------
        key : str | tuple(str, str)
            Name of the next branch in the annotations tree, optionally with
            a namespace, provided as a tuple (key, namespace). If the namespace
            is not provided it is taken to be the same as the containing branch
        *args : list(str) + (int|float|str)
            A list of subsequent branches to the leaf node followed by the
            attribute name to delete
        """
        key = self._parse_key(key)
        if key in self._branches:
            key_branches = self._branches[key]
            if len(key_branches) == 1:
                # Recurse into branches while there are remaining args
                key_branches[0].delete(*args, **kwargs)
                if key_branches[0].empty():
                    del self._branches[key]
            else:
                raise NineMLNameError(
                    "Multiple branches found for key '{}' in annoations "
                    "branch '{}', cannot use 'delete' method".format(
                        key, self._name))
Exemple #9
0
 def property(self, name):
     try:
         return self._properties[name]
     except KeyError:
         try:
             return self.definition.component.property(name)
         except AttributeError:
             raise NineMLNameError(
                 "No property named '{}' in component class".format(name))
Exemple #10
0
 def on_condition(self, condition):
     if not isinstance(condition, sympy.Basic):
         condition = Trigger(condition).rhs
     try:
         local_on_condition = next(oc for oc in self.on_conditions
                                   if oc.trigger.rhs == condition)
     except StopIteration:
         raise NineMLNameError(condition)
     return _NamespaceOnCondition(self.sub_component, local_on_condition,
                                  self)
Exemple #11
0
 def send_port(self, name):
     try:
         return self.event_send_port(name)
     except NineMLNameError:
         try:
             return self.analog_send_port(name)
         except NineMLNameError:
             raise NineMLNameError(
                 "'{}' Dynamics object does not have a send port "
                 "named '{}'".format(self.name, name))
Exemple #12
0
 def port(self, name):
     try:
         return self.send_port(name)
     except NineMLNameError:
         try:
             return self.receive_port(name)
         except NineMLNameError:
             raise NineMLNameError(
                 "'{}' Dynamics object does not have a port named '{}'".
                 format(self.name, name))
Exemple #13
0
 def initial_value(self, name):
     try:
         return self._initial_values[name]
     except KeyError:
         try:
             return self.definition.component.initial_value(name)
         except AttributeError:
             raise NineMLNameError(
                 "No initial value named '{}' in component class".format(
                     name))
Exemple #14
0
    def get(self, key, *args, **kwargs):
        """
        Gets the attribute of an annotations "leaf"

        Parameters
        ----------
        key : str | tuple(str, str)
            Name of the next branch in the annotations tree, optionally with
            a namespace, provided as a tuple (key, namespace). If the namespace
            is not provided it is taken to be the same as the containing branch
        *args : list(str) + (int|float|str)
            A list of subsequent branches to the leaf node followed by the
            attribute name to return the value of
        default: (int|float|str)
            The default value to return if the specified annotation has not
            been set

        Returns
        -------
        val : (int|float|str)
            The value of the annotation attribute
        """
        key = self._parse_key(key)
        if key in self._branches:
            key_branches = self._branches[key]
            if len(key_branches) == 1:
                # Recurse into branches while there are remaining args
                val = key_branches[0].get(*args, **kwargs)
            else:
                raise NineMLNameError(
                    "Multiple branches found for key '{}' in annoations "
                    "branch '{}', cannot use 'get' method".format(
                        key, self._name))
        else:
            if 'default' in kwargs:
                return kwargs['default']
            else:
                raise NineMLNameError(
                    "No annotation at path '{}'".format("', '".join(args)))
        return val
Exemple #15
0
 def branch(self, key_index):
     try:
         name, ns, index = key_index
     except:
         raise
     try:
         return self._branches[(name, ns)][index]
     except (KeyError, IndexError):
         raise NineMLNameError(
             "{} branch not present in annotations ({})"
             .format('{}-{}-{}'.format(*key_index),
                     ", ".join('{}-{}-{}'.format(*k)
                               for k in self.branch_keys)))
Exemple #16
0
 def receive_port(self, name):
     try:
         return self.event_receive_port(name)
     except NineMLNameError:
         try:
             return self.analog_receive_port(name)
         except NineMLNameError:
             try:
                 return self.analog_reduce_port(name)
             except NineMLNameError:
                 raise NineMLNameError(
                     "'{}' Dynamics object does not have a receive port "
                     "named '{}'".format(self.name, name))
Exemple #17
0
def split_namespace(identifier_in_namespace):
    """
    Splits an identifer and a namespace that have been concatenated by
    'append_namespace'
    """
    parts = double_underscore_re.split(identifier_in_namespace)
    if len(parts) < 2:
        raise NineMLNameError(
            "Identifier '{}' does not belong to a sub-namespace".format(
                identifier_in_namespace))
    name = '__'.join(parts[:-1])
    comp_name = parts[-1]
    comp_name = more_than_double_underscore_re.sub(r'\1', comp_name)
    return name, comp_name
Exemple #18
0
 def find_element(self, sym):
     name = Expression.symbol_to_str(sym)
     element = None
     for context in reversed(self.contexts):
         try:
             element = context.parent.element(
                 name, child_types=context.parent_cls.nineml_children)
         except KeyError:
             pass
     if element is None:
         raise NineMLNameError(
             "'{}' element was not found in component class '{}'"
             .format(sym, self.component_class.name))
     return element
Exemple #19
0
    def add(self, nineml_obj, clone=True, cloner=None, **kwargs):
        """
        Adds a cloned version of the element to the document, setting the
        document reference (and the corresponding url) of clones to the
        document.

        Parameters
        ----------
        nineml_obj : DocumentLevelObject
            A document level object to add to the document
        clone : bool
            Whether to clone the element before adding it to the document
        clone_definitions : str
            Whether to clone definitions of user layer objects
        kwargs : dict
            Keyword arguments passed to the clone method
        """
        if not isinstance(nineml_obj, DocumentLevelObject):
            raise NineMLUsageError(
                "Cannot add {} element to document as it is not a \"document"
                "-level\" object".format(nineml_obj))
        if nineml_obj.name in self:
            # Ignore if the element is already added (this can happen
            # implictly when writing other elements that refer to this element)
            if nineml_obj is not self[nineml_obj.name]:
                if nineml_obj == self[nineml_obj.name]:
                    nineml_obj = self[nineml_obj.name]
                else:
                    nineml_obj.find_mismatch(self[nineml_obj.name])
                    raise NineMLNameError(
                        "Could not add '{}' as a different object with that "
                        "name already exists in the document '{}':\n{}"
                        .format(nineml_obj.name, self.url,
                                nineml_obj.find_mismatch(
                                    self[nineml_obj.name])))
        elif nineml_obj.document is not None and not clone:
            raise NineMLUsageError(
                "Attempting to add the same object '{}' {} to document"
                " '{}' document when it is already in another "
                "document, '{}' and 'clone' kwarg is False"
                .format(nineml_obj.name, nineml_obj.nineml_type,
                        self.url, nineml_obj.document.url))
        else:
            if clone:
                if cloner is None:
                    cloner = Cloner(**kwargs)
                nineml_obj = cloner.clone(nineml_obj, **kwargs)
            AddToDocumentVisitor(self).visit(nineml_obj, **kwargs)
        return nineml_obj
Exemple #20
0
 def remove(self, nineml_obj, ignore_missing=False):
     if not isinstance(nineml_obj, DocumentLevelObject):
         raise NineMLUsageError(
             "Could not remove {} from document as it is not a document "
             "level NineML object ('{}') ".format(nineml_obj.key,
                                                  nineml_obj.nineml_type))
     try:
         del self[nineml_obj.name]
     except KeyError:
         if not ignore_missing:
             raise NineMLNameError(
                 "Could not find '{}' element to remove from document '{}'"
                 .format(nineml_obj.name, self.url))
     assert nineml_obj.document is self
     nineml_obj._document = None
Exemple #21
0
    def __getitem__(self, key):
        """
        Returns the list of sub-branches for the given key

        Parameters
        ----------
        key : str
            The name of the annotations branch(es) to return
        """
        key = self._parse_key(key)
        if key in self._branches:
            key_branches = self._branches[key]
        else:
            raise NineMLNameError(
                "{} annotations branch does not have branch or attribute '{}'"
                .format(self._name, key))
        return key_branches
Exemple #22
0
 def set(self, prop):
     try:
         super(DynamicsProperties, self).set(prop)
     except NineMLNameError:
         try:
             state_variable = self.component_class.state_variable(prop.name)
         except NineMLNameError:
             raise NineMLNameError(
                 "'{}' Dynamics does not have a Parameter or StateVariable "
                 "named '{}'".format(self.component_class.name, prop.name))
         if prop.units.dimension != state_variable.dimension:
             raise NineMLUnitMismatchError(
                 "Dimensions for '{}' initial value ('{}') don't match that"
                 " of state variable in component class ('{}').".format(
                     prop.name, prop.units.dimension.name,
                     state_variable.dimension.name))
         self._initial_values[prop.name] = prop
Exemple #23
0
 def synapse(self, name):
     try:
         synapses = set(
             ca.nineml.dynamics_properties.synapse_properties(name)
             for ca in self.component_arrays)
     except NineMLNameError:
         raise NineMLNameError(
             "Could not return synapse '{}' because it is missing from "
             "one or more of the component arrays in '{}' Selection"
             .format(name, self.name))
     if len(synapses) > 1:
         raise Pype9RuntimeError(
             "'{}' varies ({}) between component arrays in '{}' Selection"
             .format(name, ', '.join(str(s) for s in synapses), self.name))
     try:
         return next(iter(synapses))  # Return the only synapse
     except:
         raise
Exemple #24
0
    def element(self, name, child_types=None, include_send_ports=False):
        """
        Looks a member item by "name" (identifying characteristic)

        Parameters
        ----------
        name : str
            Name of the element to return
        nineml_children : dict[str, str]
            Mapping from element type to accessor name
        include_send_ports:
            As send ports will typically mask the name as an alias or
            state variable (although not necessarily in MultiDynamics objects)
            they are ignored unless this kwarg is set to True, in which case
            they will be returned only if no state variable or alias is found.

        Returns
        -------
        elem : NineMLBaseObject
            The element corresponding to the provided 'name' argument
        """
        if child_types is None:
            child_types = self.nineml_children
        send_port = None
        for child_type in child_types:
            try:
                elem = self._member_accessor(child_type)(name)
                # Ignore send ports as they otherwise mask
                # aliases/state variables
                if isinstance(elem, SendPortBase):
                    send_port = elem
                else:
                    return elem  # No need to wait to end of loop
            except NineMLNameError:
                pass
        if include_send_ports and send_port is not None:
            return send_port
        else:
            raise NineMLNameError(
                "'{}' was not found in '{}' {} object".format(
                    name, self.key, self.__class__.__name__))
Exemple #25
0
 def __getitem__(self, name):
     """
     Returns the element referenced by the given name
     """
     if name is None:
         # FIXME: This is a hack that should be removed
         # This simplifies code in a few places where an optional
         # attribute refers to a name of an object which
         # should be resolved if present but be set to None if not.
         return None
     try:
         nineml_obj = super(Document, self).__getitem__(name)
     except KeyError:
         if self._unserializer is not None:
             nineml_obj = self._unserializer.load_element(name)
         else:
             raise NineMLNameError(
                 "'{}' was not found in the NineML document {} (elements in"
                 " the document were '{}').".format(
                     name, self.url or '', "', '".join(iter(self.keys()))))
     return nineml_obj
Exemple #26
0
    def delete(self, key, *args, **kwargs):
        """
        Gets the attribute of an annotations "leaf"

        Parameters
        ----------
        key : str | tuple(str, str)
            Name of the next branch in the annotations tree, optionally with
            a namespace, provided as a tuple (key, namespace). If the namespace
            is not provided it is taken to be the same as the containing branch
        *args : list(str) + (int|float|str)
            A list of subsequent branches to the leaf node followed by the
            attribute name to delete
        """
        if not args:
            try:
                del self.attr[key]
            except KeyError:
                raise NineMLNameError(
                    "Annotations branch {{{}}}{} does not contain '{}' "
                    "attribute".format(self.ns, self.name, key))
        else:
            super(_AnnotationsBranch, self).delete(key, *args, **kwargs)
Exemple #27
0
    def load_element(self, name, **options):
        """
        Lazily loads the document-level object named and all elements it
        references

        Parameter
        ---------
        name : str
            Name of the document level object to load
        """
        try:
            serial_elem, nineml_cls = self._doc_elems[name]
        except KeyError:
            raise NineMLNameError(
                "'{}' was not found in the NineML document {} (elements in "
                "the document were '{}').".format(
                    name, self.url or '',
                    "', '".join(iter(self._doc_elems.keys()))))
        nineml_object = self.visit(serial_elem, nineml_cls, **options)
        AddToDocumentVisitor(self.document,
                             **options).visit(nineml_object, **options)
        self._loaded_elems.append(name)
        return nineml_object
Exemple #28
0
 def record(self,
            port_name,
            interval=None,
            **kwargs):  # @UnusedVariable @IgnorePep8
     # Create dictionaries for storing local recordings. These are not
     # created initially to save memory if recordings are not required or
     # handled externally
     self._initialize_local_recording()
     try:
         port = self.component_class.send_port(port_name)
     except NineMLNameError:
         try:
             # For convenient access to state variables
             port = self.component_class.state_variable(port_name)
         except NameError:
             raise NineMLNameError(
                 "No matching state variable or event send port matching "
                 "port name '{}' in component class '{}'".format(
                     port_name, self.component_class.name))
     if port.nineml_type in ('EventSendPort', 'EventSendPortExposure'):
         # FIXME: This assumes that all event send port are spikes, which
         #        I think is currently a limitation of NEST
         self._recorders[port_name] = recorder = nest.Create(
             "spike_detector", params={"precise_times": True})
         nest.Connect(self._cell, recorder)
     else:
         if interval is None:
             interval = Simulation.active().dt
         interval = float(interval.in_units(un.ms))
         variable_name = self.build_name(port_name)
         self._recorders[port_name] = recorder = nest.Create(
             'multimeter', 1, {"interval": interval})
         nest.SetStatus(recorder, {'record_from': [variable_name]})
         nest.Connect(recorder,
                      self._cell,
                      syn_spec={'delay': self.device_delay_ms})
Exemple #29
0
def split_multi_regime_name(name):
    parts = triple_underscore_re.split(name)
    if not parts:
        raise NineMLNameError("'{}' is not a multi-regime name".format(name))
    return tuple(more_than_double_underscore_re.sub(r'\1', p) for p in parts)