Beispiel #1
0
    def insert_subnode(self, namespace, subnode):
        """Insert a subnode into this component

        :param subnode: An object of type ``DynamicsClass``.
        :param namespace: A `string` specifying the name of the component in
            this components namespace.

        :raises: ``NineMLRuntimeException`` if there is already a subcomponent
                  at the same namespace location

        .. note::

            This method will clone the subnode.

        """
        if not isinstance(namespace, basestring):
            err = 'Invalid namespace: %s' % type(subnode)
            raise NineMLRuntimeError(err)

        if not isinstance(subnode, DynamicsClass):
            err = 'Attempting to insert invalid '
            err += 'object as subcomponent: %s' % type(subnode)
            raise NineMLRuntimeError(err)

        if namespace in self.subnodes:
            err = 'Key already exists in namespace: %s' % namespace
            raise NineMLRuntimeError(err)
        self.subnodes[namespace] = DynamicsClonerVisitor().visit(subnode)
        self.subnodes[namespace].set_parent_model(self)

        self._validate_self()
Beispiel #2
0
    def __init__(self, filename):
        cls = TestableComponent

        # If we recieve a filename like 'iaf', that doesn't
        # end in '.py', then lets prepend the component directory
        # and append .py
        if not filename.endswith('.py'):
            compdir = LocationMgr.getComponentDir()
            filename = os.path.join(compdir, '%s.py' % filename)

        self.filename = filename
        self.mod = load_py_module(filename)

        # Get the component functor:
        if cls.functor_name not in self.mod.__dict__.keys():
            err = """Can't load TestableComponnet from %s""" % self.filename
            err += """Can't find required method: %s""" % cls.functor_name
            raise NineMLRuntimeError(err)

        self.component_functor = self.mod.__dict__[cls.functor_name]

        # Check the functor will actually return us an object:
        try:
            c = self.component_functor()
        except Exception:
            raise NineMLRuntimeError('component_functor() threw an exception')

        if not isinstance(c, DynamicsClass):
            raise NineMLRuntimeError('Functor does not return Component Class')

        # Try and get the meta-data
        self.metadata = None
        if cls.metadata_name in self.mod.__dict__.keys():
            self.metadata = self.mod.__dict__[cls.metadata_name]
Beispiel #3
0
 def set_flattener(self, flattener):
     """Specifies the flattening object used to create this component, if
     this component was flattened from a hierarchical component"""
     if not flattener:
         raise NineMLRuntimeError('Setting flattener to None??')
     if self.flattener:
         raise NineMLRuntimeError('Trying to change flattener')
     self._flattener = flattener
Beispiel #4
0
 def standardize_units(self):
     """
     Standardized the units into a single set (no duplicates). Used to avoid
     naming conflicts when writing to file.
     """
     # Get the set of all units and dimensions that are used in the document
     # Note that Dimension & Unit objects are equal even if they have
     # different names so when this set is traversed the dimension/unit will
     # be substituted for the first equivalent dimension/unit.
     all_units = set(chain(*[o.all_units for o in self.itervalues()]))
     all_dimensions = set(
         chain([u.dimension for u in all_units],
               *[o.all_dimensions for o in self.itervalues()]))
     # Delete unused units from the document
     for k, o in self.items():
         if ((isinstance(o, nineml.abstraction_layer.Unit)
              and o not in all_units)
                 or (isinstance(o, nineml.abstraction_layer.Dimension)
                     and o not in all_dimensions)):
             del self[k]
     # Add missing units and dimensions to the document
     for unit in all_units:
         if unit.name in self:
             if unit != self[unit.name]:
                 raise NineMLRuntimeError(
                     "Name of unit '{}' conflicts with existing object of "
                     "differring value or type '{}' and '{}'".format(
                         unit.name, unit, self[unit.name]))
         self[unit.name] = unit
     for dimension in all_dimensions:
         if dimension.name in self:
             if dimension != self[dimension.name]:
                 raise NineMLRuntimeError(
                     "Name of dimension '{}' conflicts with existing object"
                     " of differring value or type '{}' and '{}'".format(
                         dimension.name, dimension, self[unit.name]))
         self[dimension.name] = dimension
     # Replace units and dimensions with those in the superset
     for obj in self.itervalues():
         for a in obj.attributes_with_dimension:
             try:
                 std_dim = next(d for d in all_dimensions
                                if d == a.dimension)
             except StopIteration:
                 assert False, \
                     ("Did not find matching dimension in supposed superset"
                      " of dimensions")
             a.set_dimension(std_dim)
         for a in obj.attributes_with_units:
             try:
                 std_units = next(u for u in all_units if u == a.units)
             except StopIteration:
                 assert False, \
                     ("Did not find matching unit in supposed superset"
                      " of units")
             a.set_units(std_units)
Beispiel #5
0
    def __init__(self, lhs, rhs):
        ExpressionWithLHS.__init__(self, rhs)

        if not MathUtil.is_single_symbol(lhs):
            err = 'Expecting a single symbol on the LHS; got: %s' % lhs
            raise NineMLRuntimeError(err)
        if not is_valid_lhs_target(lhs):
            err = 'Invalid LHS target: %s' % lhs
            raise NineMLRuntimeError(err)

        self._lhs = lhs.strip()
Beispiel #6
0
 def add(self, element):
     try:
         if not isinstance(element, TopLevelObject):
             raise NineMLRuntimeError(
                 "Could not add {} as it is not a document level NineML "
                 "object ('{}') ".format(element.element_name,
                                         "', '".join(self.top_level_types)))
     except AttributeError:
         raise NineMLRuntimeError("Could not add {} as it is not a NineML "
                                  "object".format(element))
     if element.name in self:
         raise NineMLRuntimeError(
             "Could not add element '{}' as an element with that name "
             "already exists in the document".format(element.name))
     self[element.name] = element
Beispiel #7
0
 def from_xml(cls, element, url=None):
     if element.tag != NINEML + cls.element_name:
         raise Exception("Not a NineML root ('{}')".format(element.tag))
     # Initialise the document
     elements = {'_url': url}
     # Loop through child elements, determine the class needed to extract
     # them and add them to the dictionary
     annotations = None
     for child in element.getchildren():
         if child.tag.startswith(NINEML):
             element_name = child.tag[len(NINEML):]
             if element_name == Annotations.element_name:
                 assert annotations is None, \
                     "Multiple annotations tags found"
                 annotations = Annotations.from_xml(child)
                 continue
             try:
                 child_cls = getattr(nineml.user_layer, element_name)
             except AttributeError:
                 try:
                     child_cls = getattr(nineml.abstraction_layer,
                                         element_name)
                 except AttributeError:
                     raise NineMLRuntimeError(
                         "Did not find matching NineML class for '{}' "
                         "element".format(element_name))
             if not issubclass(child_cls, TopLevelObject):
                 raise NineMLRuntimeError(
                     "'{}' is not a valid top-level NineML element".format(
                         element_name))
         else:
             raise NotImplementedError(
                 "Cannot load '{}' element (extensions not implemented)".
                 format(child.tag))
         # Units use 'symbol' as their unique identifier (from LEMS) all
         # other elements use 'name'
         name = child.attrib.get('name', child.attrib.get('symbol'))
         if name in elements:
             raise NineMLRuntimeError(
                 "Duplicate identifier '{ob1}:{name}'in NineML file '{url}'"
                 .format(name=name,
                         ob1=elements[name].cls.element_name,
                         ob2=child_cls.element_name,
                         url=url or ''))
         elements[name] = cls._Unloaded(name, child, child_cls)
     document = cls(**elements)
     document.annotations = annotations
     return document
Beispiel #8
0
 def __init__(self, name, dimension=None, reduce_op='+'):
     if reduce_op not in self._reduce_op_map.keys():
         err = ("%s('%s')" + "specified undefined reduce_op: '%s'") %\
               (self.__class__.__name__, name, str(reduce_op))
         raise NineMLRuntimeError(err)
     super(AnalogReducePort, self).__init__(name, dimension)
     self._reduce_op = reduce_op
Beispiel #9
0
    def action_componentclass(self, componentclass, namespace):

        unresolved_aliases = dict((a.lhs, a) for a in componentclass.aliases)

        def alias_contains_unresolved_symbols(alias):
            unresolved = [sym for sym in alias.rhs_atoms
                          if sym in unresolved_aliases]
            return len(unresolved) != 0

        def get_resolved_aliases():
            return [alias for alias in unresolved_aliases.values()
                    if not alias_contains_unresolved_symbols(alias)]

        while(unresolved_aliases):

            resolved_aliases = get_resolved_aliases()
            if resolved_aliases:
                for r in resolved_aliases:
                    del unresolved_aliases[r.lhs]

            else:
                errmsg = "Unable to resolve all aliases in %s. " % namespace
                errmsg += "You may have a recursion issue."
                errmsg += ("Remaining Aliases: %s" %
                           ','.join(unresolved_aliases.keys()))
                raise NineMLRuntimeError(errmsg)
Beispiel #10
0
    def __init__(self, componentclass):
        PerNamespaceDynamicsValidator.__init__(
            self, require_explicit_overrides=False)

        self.connected_regimes_from_regime = defaultdict(set)
        self.regimes_in_namespace = defaultdict(set)

        self.visit(componentclass)

        def add_connected_regimes_recursive(regime, connected):
            connected.add(regime)
            for r in self.connected_regimes_from_regime[regime]:
                if r not in connected:
                    add_connected_regimes_recursive(r, connected)

        for namespace, regimes in self.regimes_in_namespace.iteritems():

            # Perhaps we have no transition graph; this is OK:
            if len(regimes) == 0:
                continue

            connected = set()
            add_connected_regimes_recursive(regimes[0], connected)
            if len(connected) != len(self.regimes_in_namespace[namespace]):
                raise NineMLRuntimeError('Transition graph is contains '
                                         'islands')
Beispiel #11
0
    def from_str(cls, alias_string):
        """Creates an Alias object from a string"""
        if not cls.is_alias_str(alias_string):
            errmsg = "Invalid Alias: %s" % alias_string
            raise NineMLRuntimeError(errmsg)

        lhs, rhs = alias_string.split(':=')
        return Alias(lhs=lhs.strip(), rhs=rhs.strip())
Beispiel #12
0
    def get_new_regime(self, old_regime_string):
        """
        for example:
        old_regime_string = ('iaf:subthresholdregime '
                             'cobaInhib:cobadefaultregime '
                             'cobaExcit:cobadefaultregime')
        """

        # Lets create a dictionary that maps 'NamespaceAddress' to regime name
        # from the input string:
        # old_regime_string = 'iaf:subthresholdregime'
        #                     'cobaInhib:cobadefaultregime'
        #                     'cobaExcit:cobadefaultregime'
        nsstr_regimename = [l.split(':') for l in old_regime_string.split()]
        ns_regimename = dict([(NamespaceAddress(ns), regime_name)
                              for (ns, regime_name) in nsstr_regimename])

        # OK, now lets go through our old componentswithregimes,
        # and find the regime that was specified.
        target_regime_tuple = []
        for c in self.componentswithregimes:
            comp_ns = c.get_node_addr()
            if comp_ns not in ns_regimename:
                err = ('Looking for a regime in namespace: {}, but not found.'
                       .format(comp_ns))
                err += ('\nNamespaces: {}'
                        .format(','.join([str(ns)
                                          for ns in ns_regimename.keys()])))
                err += '\nSpecified String: {}'.format(old_regime_string)
                raise NineMLRuntimeError(err)
            target_regime_name = ns_regimename[comp_ns]

            regime_map = dict([(r.name, r) for r in c.regimes])
            if target_regime_name not in regime_map:
                err = 'Namespace has no regime named: %s'
                err += '\nRegimes: %s' % (str(regime_map.keys()))
                raise NineMLRuntimeError(err)

            target_regime_tuple.append(regime_map[target_regime_name])

        target_regime_tuple = tuple(target_regime_tuple)

        new_regime = self.old_regime_tuple_to_new_regime_map[
            target_regime_tuple]
        return new_regime
Beispiel #13
0
    def get_local_name(self):
        """ Returns the local reference; i.e. the last field in the
        address, as a ``string``
        """

        if self.is_root_namespace():
            err = "Can't call get_local_name() on root namespace"
            raise NineMLRuntimeError(err)
        return self.loctuple[-1]
Beispiel #14
0
    def rename_port(cls, componentclass, old_port_name, new_port_name):
        """ Renames a port in a componentclass """
        if not componentclass.is_flat():
            raise NineMLRuntimeError('rename_port() on non-flat '
                                     'componentclass')

        # Find the old port:
        port = filter_expect_single(componentclass.analog_ports,
                                    lambda ap: ap.name == old_port_name)
        port._name = new_port_name
Beispiel #15
0
    def __init__(self, componentclass):
        PerNamespaceComponentValidator.__init__(
            self, require_explicit_overrides=False)

        self.available_symbols = defaultdict(list)
        self.aliases = defaultdict(list)
        self.time_derivatives = defaultdict(list)
        self.state_assignments = defaultdict(list)

        self.visit(componentclass)

        excludes = get_reserved_and_builtin_symbols()

        # Check Aliases:
        for ns, aliases in self.aliases.iteritems():
            for alias in aliases:
                for rhs_atom in alias.rhs_atoms:
                    if rhs_atom in excludes:
                        continue
                    if rhs_atom not in self.available_symbols[ns]:
                        err = ('Unresolved Symbol in Alias: %s [%s]' %
                               (rhs_atom, alias))
                        raise NineMLRuntimeError(err)

        # Check TimeDerivatives:
        for ns, timederivatives in self.time_derivatives.iteritems():
            for timederivative in timederivatives:
                for rhs_atom in timederivative.rhs_atoms:
                    if (rhs_atom not in self.available_symbols[ns] and
                            rhs_atom not in excludes):
                        err = ('Unresolved Symbol in Time Derivative: %s [%s]'
                               % (rhs_atom, timederivative))
                        raise NineMLRuntimeError(err)

        # Check StateAssignments
        for ns, state_assignments in self.state_assignments.iteritems():
            for state_assignment in state_assignments:
                for rhs_atom in state_assignment.rhs_atoms:
                    if (rhs_atom not in self.available_symbols[ns] and
                            rhs_atom not in excludes):
                        err = ('Unresolved Symbol in Assignment: %s [%s]' %
                               (rhs_atom, state_assignment))
                        raise NineMLRuntimeError(err)
Beispiel #16
0
 def check_conflicting_dimension(self, dimension):
     try:
         if dimension != self.dimensions[dimension.name]:
             err = ("Duplication of dimension name '{}' for differing "
                    "dimensions ('{}', '{}')".format(
                        dimension.name, dimension,
                        self.dimensions[dimension.name]))
             raise NineMLRuntimeError(err)
     except KeyError:
         self.dimensions[dimension.name] = dimension
Beispiel #17
0
    def resolve_transitions(self):
        while self.unresolved_transitions:
            transition, regime_index = self.unresolved_transitions.pop()

            if regime_index in self.changed_regime_indices:
                raise NineMLRuntimeError(
                    'Something has gone wrong with event resolution. '
                    'Changing Regime Twice!')
            self.changed_regime_indices.add(regime_index)

            self.resolve_transition(transition, regime_index)
Beispiel #18
0
    def remap_port_to_parameter(cls, componentclass, port_name):
        """ Renames a port in a componentclass """
        if not componentclass.is_flat():
            raise NineMLRuntimeError('rename_port_to_parameter() on non-flat '
                                     'componentclass')

        # Find the old port:
        port = filter_expect_single(componentclass.analog_ports,
                                    lambda ap: ap.name == port_name)
        componentclass._analog_ports.remove(port)

        # Add a new parameter:
        componentclass._parameters[port_name] = Parameter(port_name)
Beispiel #19
0
    def __init__(self, componentclass):
        PerNamespaceDynamicsValidator.__init__(
            self, require_explicit_overrides=False)
        self.sv_declared = defaultdict(list)
        self.state_assignments_lhses = defaultdict(list)

        self.visit(componentclass)

        for namespace, state_assignments_lhs in self.state_assignments_lhses.\
                                                                   iteritems():
            for td in state_assignments_lhs:
                if td not in self.sv_declared[namespace]:
                    err = 'Not Assigning to state-variable: {}'.format(td)
                    raise NineMLRuntimeError(err)
Beispiel #20
0
    def __init__(self, componentclass):
        PerNamespaceDynamicsValidator.__init__(
            self, require_explicit_overrides=False)
        self.sv_declared = defaultdict(list)
        self.time_derivatives_used = defaultdict(list)

        self.visit(componentclass)

        for namespace, time_derivatives in self.time_derivatives_used.\
                                                                   iteritems():
            for td in time_derivatives:
                if td not in self.sv_declared[namespace]:
                    err = 'StateVariable not declared: %s' % td
                    raise NineMLRuntimeError(err)
Beispiel #21
0
    def close_all_reduce_ports(cls, componentclass, exclude=None):
        """
        Closes all the ``reduce`` ports on a componentclass by assigning them a
        value of 0
        """
        if not componentclass.is_flat():
            raise NineMLRuntimeError('close_all_reduce_ports() on non-flat '
                                     'componentclass')

        for arp in componentclass.query.analog_reduce_ports:
            if exclude and arp.name in exclude:
                continue
            cls.close_analog_port(componentclass=componentclass, port_name=arp.name,
                                  value='0')
Beispiel #22
0
    def from_str(cls, time_derivative_string):
        """Creates an TimeDerivative object from a string"""
        # Note: \w = [a-zA-Z0-9_]
        tdre = re.compile(r"""\s* d(?P<dependent_var>[a-zA-Z][a-zA-Z0-9_]*)/dt
                           \s* = \s*
                           (?P<rhs> .*) """, re.VERBOSE)

        match = tdre.match(time_derivative_string)
        if not match:
            err = "Unable to load time derivative: %s" % time_derivative_string
            raise NineMLRuntimeError(err)
        dependent_variable = match.groupdict()['dependent_var']
        rhs = match.groupdict()['rhs']
        return TimeDerivative(dependent_variable=dependent_variable, rhs=rhs)
Beispiel #23
0
    def __init__(self, name, document, url=None):
        """
        docstring needed

        `name`     -- a name of an existing componentclass to refer to
        `document` -- a Document object containing the top-level
                      objects in the current file
        `url`      -- a url of the file containing the exiting componentclass
        """
        super(Reference, self).__init__(name, document, url)
        if not isinstance(self._referred_to, BaseULObject):
            msg = ("Reference points to a non-user-layer object '{}'".format(
                self._referred_to.name))
            raise NineMLRuntimeError(msg)
        self._referred_to.from_reference = self
Beispiel #24
0
    def _resolve_transition_regime_names(self):
        # Check that the names of the regimes are unique:
        names = [r.name for r in self.regimes]
        assert_no_duplicates(names)

        # Create a map of regime names to regimes:
        regime_map = dict([(r.name, r) for r in self.regimes])

        # We only worry about 'target' regimes, since source regimes are taken
        # care of for us by the Regime objects they are attached to.
        for trans in self.transitions:
            if trans.target_regime_name not in regime_map:
                raise NineMLRuntimeError("Can't find regime '{}'".format(
                    trans.target_regime_name))
            trans.set_target_regime(regime_map[trans.target_regime_name])
Beispiel #25
0
    def __init__(self, componentclass):
        super(OutputAnalogPortsDynamicsValidator,
              self).__init__(require_explicit_overrides=False)

        self.output_analogports = defaultdict(list)
        self.available_symbols = defaultdict(list)

        self.visit(componentclass)

        for namespace, analogports in self.output_analogports.iteritems():
            for ap in analogports:
                if ap not in self.available_symbols[namespace]:
                    raise NineMLRuntimeError(
                        'Unable to find an Alias or State variable for '
                        'analog-port: %s' % ap)
Beispiel #26
0
    def __init__(self, componentclass, old_symbol_name, new_symbol_name):
        ComponentActionVisitor.__init__(
            self, require_explicit_overrides=True)
        self.old_symbol_name = old_symbol_name
        self.new_symbol_name = new_symbol_name
        self.namemap = {old_symbol_name: new_symbol_name}

        if not componentclass.is_flat():
            raise NineMLRuntimeError('Rename Symbol called on non-flat model')

        self.lhs_changes = []
        self.rhs_changes = []
        self.port_changes = []

        self.visit(componentclass)
        componentclass._validate_self()
Beispiel #27
0
    def get_parent_addr(self):
        """Return the address of an namespace higher

        >>> a = NamespaceAddress('level1.level2.level3')
        >>> a
        NameSpaceAddress: '/level1/level2/level3/'
        >>> a.get_parent_addr()
        NameSpaceAddress: '/level1/level2/'

        """

        if self.is_root_namespace():
            err = "Can't call get_parent_addr() on root namespace"
            raise NineMLRuntimeError(err)

        return NamespaceAddress(loc=tuple(self.loctuple[:-1]))
Beispiel #28
0
    def _load_blocks(self, element, blocks):
        """
        Creates a dictionary that maps class-types to instantiated objects
        """
        # Initialise loaded objects with empty lists
        loaded_objects = dict((block, []) for block in blocks)

        for t in element.iterchildren(tag=etree.Element):
            # Strip namespace
            tag = t.tag[len(NINEML):] if t.tag.startswith(NINEML) else t.tag
            if tag not in blocks:
                err = "Unexpected block tag: %s " % tag
                err += '\n Expected: %s' % ','.join(blocks)
                raise NineMLRuntimeError(err)
            loaded_objects[tag].append(self._get_loader(tag)(self, t))
        return loaded_objects
Beispiel #29
0
    def add_on_condition(self, on_condition):
        """Add an |OnCondition| transition which leaves this regime

        If the on_condition object has not had its target regime name
        set in the constructor, or by calling its ``set_target_regime_name()``,
        then the target is assumed to be this regime, and will be set
        appropriately.

        The source regime for this transition will be set as this regime.

        """
        if not isinstance(on_condition, OnCondition):
            err = ("Expected 'OnCondition' Obj, but got %s" %
                   (type(on_condition)))
            raise NineMLRuntimeError(err)
        self._resolve_references_on_transition(on_condition)
        self._on_conditions.append(on_condition)
Beispiel #30
0
def load_py_module(filename):
    """Takes the fully qualified path of a python file,
    loads it and returns the module object
    """

    if not os.path.exists(filename):
        print "CWD:", os.getcwd()
        raise NineMLRuntimeError('File does not exist %s' % filename)

    dirname, fname = os.path.split(filename)
    sys.path = [dirname] + sys.path

    module_name = fname.replace('.py', '')
    module_name_short = module_name

    module = __import__(module_name)
    return module