Beispiel #1
0
    def __call__(self, **params):
        p = ParamOverrides(self, params)

        measured_sheets = [s for s in topo.sim.objects(CFSheet).values()
                           if hasattr(s,'measure_maps') and s.measure_maps]

        results = AttrTree()

        # Could easily be extended to measure CoG of all projections
        # and e.g. register them using different names (e.g. "Afferent
        # XCoG"), but then it's not clear how the PlotGroup would be
        # able to find them automatically (as it currently supports
        # only a fixed-named plot).
        requested_proj=p.proj_name
        for sheet in measured_sheets:
            for proj in sheet.in_connections:
                if (proj.name == requested_proj) or \
                   (requested_proj == '' and (proj.src != sheet)):
                    cog_data = self._update_proj_cog(p, proj)
                    for key, data in cog_data.items():
                        name = proj.name[0].upper() + proj.name[1:]
                        results.set_path((key, name), data)


        if p.measurement_storage_hook:
            p.measurement_storage_hook(results)

        return results
Beispiel #2
0
    def __init__(self, **params):
        """
        Initialize this object as an EventProcessor, then also as
        a SheetCoordinateSystem with equal xdensity and ydensity.

        views is an AttrTree, which stores associated measurements,
        i.e. representations of the sheet for use by analysis or plotting
        code.
        """
        EventProcessor.__init__(self, **params)

        # Initialize this object as a SheetCoordinateSystem, with
        # the same density along y as along x.
        SheetCoordinateSystem.__init__(self, self.nominal_bounds,
                                       self.nominal_density)

        n_units = round((self.lbrt[2] - self.lbrt[0]) * self.xdensity, 0)
        if n_units < 1:            raise ValueError(
                "Sheet bounds and density must be specified such that the "+ \
 "sheet has at least one unit in each direction; " \
 +self.name+ " does not.")

        # setup the activity matrix
        self.activity = zeros(self.shape, activity_type)

        # For non-plastic inputs
        self.__saved_activity = []
        self._plasticity_setting_stack = []

        self.views = AttrTree()
        self.views.Maps = AttrTree()
        self.views.Curves = AttrTree()
Beispiel #3
0
    def __call__(self, **params):
        p = ParamOverrides(self, params)

        measured_sheets = [
            s for s in topo.sim.objects(CFSheet).values()
            if hasattr(s, 'measure_maps') and s.measure_maps
        ]

        results = AttrTree()

        # Could easily be extended to measure CoG of all projections
        # and e.g. register them using different names (e.g. "Afferent
        # XCoG"), but then it's not clear how the PlotGroup would be
        # able to find them automatically (as it currently supports
        # only a fixed-named plot).
        requested_proj = p.proj_name
        for sheet in measured_sheets:
            for proj in sheet.in_connections:
                if (proj.name == requested_proj) or \
                   (requested_proj == '' and (proj.src != sheet)):
                    cog_data = self._update_proj_cog(p, proj)
                    for key, data in cog_data.items():
                        name = proj.name[0].upper() + proj.name[1:]
                        results.set_path((key, name), data)

        if p.measurement_storage_hook:
            p.measurement_storage_hook(results)

        return results
Beispiel #4
0
    def __init__(self, model, properties):
        self.training_patterns = AttrTree()
        self.sheets = AttrTree()
        self.projections = AttrTree()

        self._instantiated = False

        self.properties = properties
        super(ModelSpec, self).__init__(model)
        self.model = model
Beispiel #5
0
    def __init__(self, setup_options=True, register=True, time_dependent=True, **params):
        numbergen.TimeAware.time_dependent = time_dependent
        if register:
            self._register_global_params(params)
        super(Model,self).__init__(**params)

        self._sheet_types = {}
        self._projection_types = {}

        self.attrs = AttrTree()
        self.training_patterns = AttrTree()
        self.sheets = AttrTree()
        self.projections = AttrTree()

        self.setup(setup_options)
Beispiel #6
0
 def load(self, path_filters=[], merge=True):
     """
     Load and filter the file contents for the selected parameter
     space.  If merge is set to True all AttrTrees are merged,
     otherwise an NdMapping containing all the AttrTrees is
     returned.
     """
     constant_dims = self.constant_dims
     ndmapping = NdMapping(dimensions=self.dimensions)
     for key, filename in self.items():
        file_data = self.filetype.data(filename)
        attrtree = self._filter_attrtree(file_data[self.filetype.data_key],
                                         path_filters)
        if merge:
           dim_keys = zip(self.dimension_labels, key)
           varying_keys = [(d, k) for d, k in dim_keys
                           if d not in constant_dims]
           constant_keys = [(d, k) for d, k in dim_keys
                            if d in constant_dims]
           attrtree = self._add_dimensions(attrtree, varying_keys,
                                           dict(constant_keys))
        ndmapping[key] = attrtree
     if merge:
        return AttrTree.merge(ndmapping.values())
     return ndmapping
Beispiel #7
0
    def __call__(self):
        """
      Calls the collector specified by the user in the run_batch
      context. Invoked as an analysis function by RunBatchCommand.
      """
        from dataviews.collector import AttrTree
        self.collector.interval_hook = topo.sim.run

        topo_time = topo.sim.time()
        filename = '%s%s_%s' % (self._info.batch_name,
                                ('[%s]' % self._info.batch_tag
                                 if self._info.batch_tag else ''), topo_time)

        viewtree = AttrTree()
        viewtree = self.collector(viewtree, times=[topo_time])

        spec_metadata = [(key, self._info.specs[key]) for key in self.metadata
                         if '.' not in key]

        path_metadata = [(key,
                          viewtree.path_items.get(tuple(key.split('.')),
                                                  float('nan')))
                         for key in self.metadata if '.' in key]

        ViewFile(directory=param.normalize_path.prefix,
                 hash_suffix=False).save(
                     filename,
                     viewtree,
                     metadata=dict(spec_metadata + path_metadata +
                                   [('time', topo_time)]))
Beispiel #8
0
 def load(self, path_filters=[], merge=True):
     """
     Load and filter the file contents for the selected parameter
     space.  If merge is set to True all AttrTrees are merged,
     otherwise an NdMapping containing all the AttrTrees is
     returned.
     """
     constant_dims = self.constant_dims
     ndmapping = NdMapping(dimensions=self.dimensions)
     for key, filename in self.items():
         file_data = self.filetype.data(filename)
         attrtree = self._filter_attrtree(file_data[self.filetype.data_key],
                                          path_filters)
         if merge:
             dim_keys = zip(self.dimension_labels, key)
             varying_keys = [(d, k) for d, k in dim_keys
                             if d not in constant_dims]
             constant_keys = [(d, k) for d, k in dim_keys
                              if d in constant_dims]
             attrtree = self._add_dimensions(attrtree, varying_keys,
                                             dict(constant_keys))
         ndmapping[key] = attrtree
     if merge:
         return AttrTree.merge(ndmapping.values())
     return ndmapping
Beispiel #9
0
    def _filter_attrtree(self, attrtree, path_filters):
        """
        Filters the loaded AttrTree using the supplied path_filters.
        """
        if not path_filters: return attrtree

        # Convert string path filters
        path_filters = [tuple(pf.split('.')) if not isinstance(pf, tuple)
                        else pf for pf in path_filters]

        # Search for substring matches between paths and path filters
        new_attrtree = AttrTree()
        for path, item in attrtree.path_items.items():
            if any([all([subpath in path for subpath in pf]) for pf in path_filters]):
                new_attrtree.set_path(path, item)

        return new_attrtree
Beispiel #10
0
    def __init__(self, register=True, time_dependent=True, **params):
        numbergen.TimeAware.time_dependent = time_dependent
        if register:
            self._register_global_params(params)
        super(Model, self).__init__(**params)

        self.specification = None
        self.properties = {}
        # Training patterns need to be accessed by GeneratorSheets
        self.properties['training_patterns'] = AttrTree()
Beispiel #11
0
    def _filter_attrtree(self, attrtree, path_filters):
        """
        Filters the loaded AttrTree using the supplied path_filters.
        """
        if not path_filters: return attrtree

        # Convert string path filters
        path_filters = [
            tuple(pf.split('.')) if not isinstance(pf, tuple) else pf
            for pf in path_filters
        ]

        # Search for substring matches between paths and path filters
        new_attrtree = AttrTree()
        for path, item in attrtree.path_items.items():
            if any([
                    all([subpath in path for subpath in pf])
                    for pf in path_filters
            ]):
                new_attrtree.set_path(path, item)

        return new_attrtree
Beispiel #12
0
    def __init__(self, initialize_cfs=True, **params):
        """
        Initialize the Projection with a set of cf_type objects
        (typically ConnectionFields), each located at the location
        in the source sheet corresponding to the unit in the target
        sheet. The cf_type objects are stored in the 'cfs' array.

        The nominal_bounds_template specified may be altered: the
        bounds must be fitted to the Sheet's matrix, and the weights
        matrix must have odd dimensions. These altered bounds are
        passed to the individual connection fields.

        A mask for the weights matrix is constructed. The shape is
        specified by cf_shape; the size defaults to the size
        of the nominal_bounds_template.
        """
        super(CFProjection, self).__init__(**params)

        self.weights_generator.set_dynamic_time_fn(None,
                                                   sublistattr='generators')
        # get the actual bounds_template by adjusting a copy of the
        # nominal_bounds_template to ensure an odd slice, and to be
        # cropped to sheet if necessary
        self._slice_template = Slice(copy(self.nominal_bounds_template),
                                     self.src,
                                     force_odd=True,
                                     min_matrix_radius=self.min_matrix_radius)

        self.bounds_template = self._slice_template.compute_bounds(self.src)

        self.mask_template = _create_mask(self.cf_shape, self.bounds_template,
                                          self.src, self.autosize_mask,
                                          self.mask_threshold)

        self.n_units = self._calc_n_units()

        if initialize_cfs:
            self._create_cfs()

        if self.apply_output_fns_init:
            self.apply_learn_output_fns(active_units_mask=False)

        ### JCALERT! We might want to change the default value of the
        ### input value to self.src.activity; but it fails, raising a
        ### type error. It probably has to be clarified why this is
        ### happening
        self.input_buffer = None
        self.activity = np.array(self.dest.activity)
        if 'cfs' not in self.dest.views:
            self.dest.views.CFs = AttrTree()
        self.dest.views.CFs[self.name] = self._cf_grid()
Beispiel #13
0
    def __init__(self,
                 setup_options=True,
                 register=True,
                 time_dependent=True,
                 **params):
        numbergen.TimeAware.time_dependent = time_dependent
        if register:
            self._register_global_params(params)
        super(Model, self).__init__(**params)

        self._sheet_types = {}
        self._projection_types = {}

        self.attrs = AttrTree()
        self.training_patterns = AttrTree()
        self.sheets = AttrTree()
        self.projections = AttrTree()

        self.setup(setup_options)
Beispiel #14
0
def _reset_views(sheet):
    if hasattr(sheet.views,'Maps'):
        sheet.views.Maps = AttrTree()
    if hasattr(sheet.views,'Curves'):
        sheet.views.Curves = AttrTree()
Beispiel #15
0
class Model(param.Parameterized):
    """
    The available setup options are:

        :'training_patterns': fills the training_patterns AttrTree
        with pattern generator instances. The path is the name of the
        input sheet. Usually calls PatternCoordinator to do this.
        :'setup_sheets': determines the number of sheets, their types
        and names sets sheet parameters according to the registered
        methods in level sets sheet matchconditions according to the
        registered methods in matchconditions
        :'projections': determines which connections should be present
        between the sheets according to the matchconditions of
        SheetSpec objects, using connect to specify the
        connection type and sets their parameters according to the
        registered methods in connect


    The available instantiate options are:

        :'sheets': instantiates all sheets and registers them in
        topo.sim
        :'projections': instantiates all projections and registers
        them in topo.sim
    """
    __abstract = True

    matchconditions = MatchConditions()

    sheet_decorators = set()
    projection_decorators = set()

    @classmethod
    def register_decorator(cls, object_type):
        name = object_type.name
        decorator = ClassDecorator(name, object_type)
        setattr(cls, name,  decorator)

        if issubclass(object_type, topo.sheet.Sheet):
            cls.sheet_decorators.add(decorator)
        if issubclass(object_type, topo.projection.Projection):
            cls.projection_decorators.add(decorator)

    @classmethod
    def _collect(cls, decorators, name):
        """
        Given a list of ClassDecorators (e.g self.sheet_decorators or
        self.projection_decorators), collate the named attribute
        (i.e. 'types' or 'labels') across the decorators according to
        priority.
        """
        flattened = [el for d in decorators for el in getattr(d, name).items()]
        return dict((k,v) for (k, (_, v)) in sorted(flattened, key=lambda x: x[1][0]))


    @property
    def sheet_labels(self):
        "The mapping of level method to corresponding label"
        return self._collect(self.sheet_decorators, 'labels')

    @property
    def sheet_types(self):
        "The mapping of level label to sheet type"
        return self._collect(self.sheet_decorators, 'types')

    @property
    def projection_labels(self):
        "The mapping of projection method to corresponding label"
        return self._collect(self.projection_decorators, 'labels')

    @property
    def projection_types(self):
        "The mapping of projection label to projection type"
        return self._collect(self.projection_decorators, 'types')

    @property
    def modified_parameters(self):
        "Dictionary of modified model parameters"
        return {k:v for k,v in self.get_param_values(onlychanged=True)}


    def __init__(self, setup_options=True, register=True, time_dependent=True, **params):
        numbergen.TimeAware.time_dependent = time_dependent
        if register:
            self._register_global_params(params)
        super(Model,self).__init__(**params)

        self._sheet_types = {}
        self._projection_types = {}

        self.attrs = AttrTree()
        self.training_patterns = AttrTree()
        self.sheets = AttrTree()
        self.projections = AttrTree()

        self.setup(setup_options)


    def _register_global_params(self, params):
        """
        Register the parameters of this object as global parameters
        available for users to set from the command line.  Values
        supplied as global parameters will override those of the given
        dictionary of params.
        """

        for name,obj in self.params().items():
            global_params.add(**{name:obj})

        for name,val in params.items():
            global_params.params(name).default=val

        params.update(global_params.get_param_values())
        params["name"]=self.name


    #==============================================#
    # Public methods to be implemented by modelers #
    #==============================================#

    def setup_attributes(self, attrs):
        """
        Method to precompute any useful attributes from the class
        parameters. For instance, if there is a ``num_lags``
        parameter, this method could compute the actual projection
        delays and store it as attrs.lags. The return value is the
        updated attrs AttrTree.

        In addition, this method can be used to configure class
        attributes of the model components.
        """
        return attrs


    def setup_training_patterns(self, **overrides):
        """
        Returns a dictionary of PatternGenerators to be added to
        self.training_patterns, with the target sheet name keys and
        pattern generator values.

        The overrides keywords can be used by a subclass to
        parameterize the training patterns e.g. override the default
        parameters of a PatternCoordinator object.
        """
        raise NotImplementedError


    def setup_sheets(self):
        """
        Returns a dictionary of properties or equivalent Lancet.Args
        object. Each outer key must be the level name and the values
        are lists of property dictionaries for the sheets at that
        level (or equivalent Lancet Args object). For instance, two
        LGN sheets at the 'LGN' level could be defined by either:

        {'LGN':[{'polarity':'ON'}, {'polarity':'OFF'}]}
        OR
        {'LGN':lancet.List('polarity', ['ON', 'OFF'])}

        The specified properties are used to initialize the sheets
        AttrTree with SheetSpec objects.
        """
        raise NotImplementedError


    def setup_analysis(self):
        """
        Set up appropriate defaults for analysis functions in
        topo.analysis.featureresponses.
        """
        pass


    #====================================================#
    # Remaining methods should not need to be overridden #
    #====================================================#

    def setup(self,setup_options):
        """
        This method can be used to setup certain parts of the
        submodel.  If setup_options=True, all setup methods are
        called.  setup_options can also be a list, whereas all list
        items of available_setup_options are accepted.

        Available setup options are:
        'training_patterns','sheets','projections' and 'analysis'.

        Please consult the docstring of the Model class for more
        information about each setup option.
        """
        available_setup_options = ['attributes',
                                   'training_patterns',
                                   'sheets',
                                   'projections',
                                   'analysis']

        if setup_options==True:
            setup_options = available_setup_options

        if 'attributes' in setup_options:
            self.attrs = self.setup_attributes(self.attrs)

        if 'training_patterns' in setup_options:
            training_patterns = self.setup_training_patterns()
            for name, training_pattern in training_patterns.items():
                self.training_patterns.set_path(name, training_pattern)
        if 'sheets' in setup_options:
            sheet_properties = self.setup_sheets()

            enumeration = enumerate(sheet_properties.items())
            for (ordering, (level, property_list)) in enumeration:
                sheet_type = self.sheet_types[level]

                if isinstance(property_list, lancet.Identity):
                    property_list = [{}]
                elif isinstance(property_list, lancet.Args):
                    property_list = property_list.specs
                # If an empty list or Args()
                elif not property_list:
                    continue

                for properties in property_list:
                    spec_properties = dict(level=level, **properties)
                    sheet_spec = SheetSpec(sheet_type, spec_properties)
                    sheet_spec.sort_precedence = ordering
                    self.sheets.set_path(str(sheet_spec), sheet_spec)

            self._update_sheet_spec_parameters()
        if 'projections' in setup_options:
            self._compute_projection_specs()
        if 'analysis' in setup_options:
            self._setup_analysis()


    def _update_sheet_spec_parameters(self):
        for sheet_spec in self.sheets.path_items.values():
            param_method = self.sheet_labels.get(sheet_spec.level, None)
            if not param_method:
                raise Exception("Parameters for sheet level %r not specified" % sheet_spec.level)

            updated_params = param_method(self,sheet_spec.properties)
            sheet_spec.update(**updated_params)


    def _matchcondition_holds(self, matchconditions, src_sheet):
        """
        Given a dictionary of properties to match and a target sheet
        spec, return True if the matchcondition holds else False.
        """
        matches=True
        if matchconditions is None:
            return False
        for incoming_key, incoming_value in matchconditions.items():
            if incoming_key in src_sheet.properties and \
                    str(src_sheet.properties[incoming_key]) not in str(incoming_value):
                matches=False
                break

        return matches

    def _compute_projection_specs(self):
        """
        Loop through all possible combinations of SheetSpec objects in
        self.sheets If the src_sheet fulfills all criteria specified
        in dest_sheet.matchconditions, create a new ProjectionSpec
        object and add this item to self.projections.
        """
        sheetspec_product = itertools.product(self.sheets.path_items.values(),
                                              self.sheets.path_items.values())
        for src_sheet, dest_sheet in sheetspec_product:

            has_matchcondition = (dest_sheet.level in self.matchconditions)
            conditions = (self.matchconditions.compute_conditions(
                          dest_sheet.level, self,dest_sheet.properties)
                          if has_matchcondition else {})

            for matchname, matchconditions in conditions.items():

                if self._matchcondition_holds(matchconditions, src_sheet):
                    proj = ProjectionSpec(self.projection_types[matchname],
                                          src_sheet, dest_sheet)

                    paramsets = self.projection_labels[matchname](self, src_sheet.properties,
                                                                  dest_sheet.properties)
                    paramsets = [paramsets] if isinstance(paramsets, dict) else paramsets
                    for paramset in paramsets:
                        proj = ProjectionSpec(self.projection_types[matchname],
                                              src_sheet, dest_sheet)
                        proj.update(**paramset)
                        # Only used when time_dependent=False
                        # (which is to be deprecated)
                        proj.matchname = matchname

                        path = (str(dest_sheet), paramset['name'])
                        self.projections.set_path(path, proj)


    def __call__(self,instantiate_options=True, verbose=False):
        """
        Instantiates all sheets or projections in self.sheets or
        self.projections and registers them in the topo.sim instance.

        If instantiate_options=True, all items are initialised
        instantiate_options can also be a list, whereas all list items
        of available_instantiate_options are accepted.

        Available instantiation options are: 'sheets' and
        'projections'.

        Please consult the docstring of the Model class for more
        information about each instantiation option.
        """
        msglevel = self.message if verbose else self.debug
        available_instantiate_options = ['sheets','projections']
        if instantiate_options==True:
            instantiate_options=available_instantiate_options

        if 'sheets' in instantiate_options:
            for sheet_spec in self.sheets.path_items.itervalues():
                msglevel('Level ' + sheet_spec.level + ': Sheet ' + str(sheet_spec))
                sheet_spec()

        if 'projections' in instantiate_options:
            for proj in sorted(self.projections):
                msglevel('Match: ' + proj.matchname + ': Connection ' + str(proj.src) + \
                             '->' + str(proj.dest) + ' ' + proj.parameters['name'])
                proj()

    def summary(self, printed=True):

        heading_line = '=' * len(self.name)
        summary = [heading_line, self.name, heading_line, '']

        for sheet_spec in sorted(self.sheets):
            summary.append(sheet_spec.summary(printed=False))
            projections = [proj for proj in self.projections
                           if str(proj).startswith(str(sheet_spec))]
            for projection_spec in sorted(projections, key=lambda p: str(p)):
                summary.append("   " + projection_spec.summary(printed=False))
            summary.append('')

        if printed: print "\n".join(summary)
        else:       return "\n".join(summary)


    def __str__(self):
        return self.name


    def _repr_pretty_(self, p, cycle):
        p.text(self.summary(printed=False))


    def modifications(self, components=['model', 'sheets', 'projections']):
        """
        Display the names of all modified parameters for the specified
        set of components.

        By default all modified parameters are listed - first with the
        model parameters, then the sheet parameters and lastly the
        projection parameters.
        """
        mapping = {'model': [self],
                   'sheets':self.sheets,
                   'projections':self.projections}

        lines = []
        for component in components:
            heading = "=" * len(component)
            lines.extend([heading, component.capitalize(), heading, ''])
            specs = mapping[component]
            padding = max(len(str(spec)) for spec in specs)
            for spec in sorted(specs):
                modified = [str(el) for el in sorted(spec.modified_parameters)]
                lines.append("%s : [%s]" % (str(spec).ljust(padding), ", ".join(modified)))
            lines.append('')
        print "\n".join(lines)
Beispiel #16
0
class Model(param.Parameterized):
    """
    The available setup options are:

        :'training_patterns': fills the training_patterns AttrTree
        with pattern generator instances. The path is the name of the
        input sheet. Usually calls PatternCoordinator to do this.
        :'setup_sheets': determines the number of sheets, their types
        and names sets sheet parameters according to the registered
        methods in level sets sheet matchconditions according to the
        registered methods in matchconditions
        :'projections': determines which connections should be present
        between the sheets according to the matchconditions of
        SheetSpec objects, using connect to specify the
        connection type and sets their parameters according to the
        registered methods in connect


    The available instantiate options are:

        :'sheets': instantiates all sheets and registers them in
        topo.sim
        :'projections': instantiates all projections and registers
        them in topo.sim
    """
    __abstract = True

    matchconditions = MatchConditions()

    sheet_decorators = set()
    projection_decorators = set()

    @classmethod
    def register_decorator(cls, object_type):
        name = object_type.name
        decorator = ClassDecorator(name, object_type)
        setattr(cls, name, decorator)

        if issubclass(object_type, topo.sheet.Sheet):
            cls.sheet_decorators.add(decorator)
        if issubclass(object_type, topo.projection.Projection):
            cls.projection_decorators.add(decorator)

    @classmethod
    def _collect(cls, decorators, name):
        """
        Given a list of ClassDecorators (e.g self.sheet_decorators or
        self.projection_decorators), collate the named attribute
        (i.e. 'types' or 'labels') across the decorators according to
        priority.
        """
        flattened = [el for d in decorators for el in getattr(d, name).items()]
        return dict(
            (k, v) for (k, (_, v)) in sorted(flattened, key=lambda x: x[1][0]))

    @property
    def sheet_labels(self):
        "The mapping of level method to corresponding label"
        return self._collect(self.sheet_decorators, 'labels')

    @property
    def sheet_types(self):
        "The mapping of level label to sheet type"
        return self._collect(self.sheet_decorators, 'types')

    @property
    def projection_labels(self):
        "The mapping of projection method to corresponding label"
        return self._collect(self.projection_decorators, 'labels')

    @property
    def projection_types(self):
        "The mapping of projection label to projection type"
        return self._collect(self.projection_decorators, 'types')

    @property
    def modified_parameters(self):
        "Dictionary of modified model parameters"
        return {k: v for k, v in self.get_param_values(onlychanged=True)}

    def __init__(self,
                 setup_options=True,
                 register=True,
                 time_dependent=True,
                 **params):
        numbergen.TimeAware.time_dependent = time_dependent
        if register:
            self._register_global_params(params)
        super(Model, self).__init__(**params)

        self._sheet_types = {}
        self._projection_types = {}

        self.attrs = AttrTree()
        self.training_patterns = AttrTree()
        self.sheets = AttrTree()
        self.projections = AttrTree()

        self.setup(setup_options)

    def _register_global_params(self, params):
        """
        Register the parameters of this object as global parameters
        available for users to set from the command line.  Values
        supplied as global parameters will override those of the given
        dictionary of params.
        """

        for name, obj in self.params().items():
            global_params.add(**{name: obj})

        for name, val in params.items():
            global_params.params(name).default = val

        params.update(global_params.get_param_values())
        params["name"] = self.name

    #==============================================#
    # Public methods to be implemented by modelers #
    #==============================================#

    def setup_attributes(self, attrs):
        """
        Method to precompute any useful attributes from the class
        parameters. For instance, if there is a ``num_lags``
        parameter, this method could compute the actual projection
        delays and store it as attrs.lags. The return value is the
        updated attrs AttrTree.

        In addition, this method can be used to configure class
        attributes of the model components.
        """
        return attrs

    def setup_training_patterns(self, **overrides):
        """
        Returns a dictionary of PatternGenerators to be added to
        self.training_patterns, with the target sheet name keys and
        pattern generator values.

        The overrides keywords can be used by a subclass to
        parameterize the training patterns e.g. override the default
        parameters of a PatternCoordinator object.
        """
        raise NotImplementedError

    def setup_sheets(self):
        """
        Returns a dictionary of properties or equivalent Lancet.Args
        object. Each outer key must be the level name and the values
        are lists of property dictionaries for the sheets at that
        level (or equivalent Lancet Args object). For instance, two
        LGN sheets at the 'LGN' level could be defined by either:

        {'LGN':[{'polarity':'ON'}, {'polarity':'OFF'}]}
        OR
        {'LGN':lancet.List('polarity', ['ON', 'OFF'])}

        The specified properties are used to initialize the sheets
        AttrTree with SheetSpec objects.
        """
        raise NotImplementedError

    def setup_analysis(self):
        """
        Set up appropriate defaults for analysis functions in
        topo.analysis.featureresponses.
        """
        pass

    #====================================================#
    # Remaining methods should not need to be overridden #
    #====================================================#

    def setup(self, setup_options):
        """
        This method can be used to setup certain parts of the
        submodel.  If setup_options=True, all setup methods are
        called.  setup_options can also be a list, whereas all list
        items of available_setup_options are accepted.

        Available setup options are:
        'training_patterns','sheets','projections' and 'analysis'.

        Please consult the docstring of the Model class for more
        information about each setup option.
        """
        available_setup_options = [
            'attributes', 'training_patterns', 'sheets', 'projections',
            'analysis'
        ]

        if setup_options == True:
            setup_options = available_setup_options

        if 'attributes' in setup_options:
            self.attrs = self.setup_attributes(self.attrs)

        if 'training_patterns' in setup_options:
            training_patterns = self.setup_training_patterns()
            for name, training_pattern in training_patterns.items():
                self.training_patterns.set_path(name, training_pattern)
        if 'sheets' in setup_options:
            sheet_properties = self.setup_sheets()

            enumeration = enumerate(sheet_properties.items())
            for (ordering, (level, property_list)) in enumeration:
                sheet_type = self.sheet_types[level]

                if isinstance(property_list, lancet.Identity):
                    property_list = [{}]
                elif isinstance(property_list, lancet.Args):
                    property_list = property_list.specs
                # If an empty list or Args()
                elif not property_list:
                    continue

                for properties in property_list:
                    spec_properties = dict(level=level, **properties)
                    sheet_spec = SheetSpec(sheet_type, spec_properties)
                    sheet_spec.sort_precedence = ordering
                    self.sheets.set_path(str(sheet_spec), sheet_spec)

            self._update_sheet_spec_parameters()
        if 'projections' in setup_options:
            self._compute_projection_specs()
        if 'analysis' in setup_options:
            self._setup_analysis()

    def _update_sheet_spec_parameters(self):
        for sheet_spec in self.sheets.path_items.values():
            param_method = self.sheet_labels.get(sheet_spec.level, None)
            if not param_method:
                raise Exception("Parameters for sheet level %r not specified" %
                                sheet_spec.level)

            updated_params = param_method(self, sheet_spec.properties)
            sheet_spec.update(**updated_params)

    def _matchcondition_holds(self, matchconditions, src_sheet):
        """
        Given a dictionary of properties to match and a target sheet
        spec, return True if the matchcondition holds else False.
        """
        matches = True
        if matchconditions is None:
            return False
        for incoming_key, incoming_value in matchconditions.items():
            if incoming_key in src_sheet.properties and \
                    str(src_sheet.properties[incoming_key]) not in str(incoming_value):
                matches = False
                break

        return matches

    def _compute_projection_specs(self):
        """
        Loop through all possible combinations of SheetSpec objects in
        self.sheets If the src_sheet fulfills all criteria specified
        in dest_sheet.matchconditions, create a new ProjectionSpec
        object and add this item to self.projections.
        """
        sheetspec_product = itertools.product(self.sheets.path_items.values(),
                                              self.sheets.path_items.values())
        for src_sheet, dest_sheet in sheetspec_product:

            has_matchcondition = (dest_sheet.level in self.matchconditions)
            conditions = (self.matchconditions.compute_conditions(
                dest_sheet.level, self, dest_sheet.properties)
                          if has_matchcondition else {})

            for matchname, matchconditions in conditions.items():

                if self._matchcondition_holds(matchconditions, src_sheet):
                    proj = ProjectionSpec(self.projection_types[matchname],
                                          src_sheet, dest_sheet)

                    paramsets = self.projection_labels[matchname](
                        self, src_sheet.properties, dest_sheet.properties)
                    paramsets = [paramsets] if isinstance(paramsets,
                                                          dict) else paramsets
                    for paramset in paramsets:
                        proj = ProjectionSpec(self.projection_types[matchname],
                                              src_sheet, dest_sheet)
                        proj.update(**paramset)
                        # Only used when time_dependent=False
                        # (which is to be deprecated)
                        proj.matchname = matchname

                        path = (str(dest_sheet), paramset['name'])
                        self.projections.set_path(path, proj)

    def __call__(self, instantiate_options=True, verbose=False):
        """
        Instantiates all sheets or projections in self.sheets or
        self.projections and registers them in the topo.sim instance.

        If instantiate_options=True, all items are initialised
        instantiate_options can also be a list, whereas all list items
        of available_instantiate_options are accepted.

        Available instantiation options are: 'sheets' and
        'projections'.

        Please consult the docstring of the Model class for more
        information about each instantiation option.
        """
        msglevel = self.message if verbose else self.debug
        available_instantiate_options = ['sheets', 'projections']
        if instantiate_options == True:
            instantiate_options = available_instantiate_options

        if 'sheets' in instantiate_options:
            for sheet_spec in self.sheets.path_items.itervalues():
                msglevel('Level ' + sheet_spec.level + ': Sheet ' +
                         str(sheet_spec))
                sheet_spec()

        if 'projections' in instantiate_options:
            for proj in sorted(self.projections):
                msglevel('Match: ' + proj.matchname + ': Connection ' + str(proj.src) + \
                             '->' + str(proj.dest) + ' ' + proj.parameters['name'])
                proj()

    def summary(self, printed=True):

        heading_line = '=' * len(self.name)
        summary = [heading_line, self.name, heading_line, '']

        for sheet_spec in sorted(self.sheets):
            summary.append(sheet_spec.summary(printed=False))
            projections = [
                proj for proj in self.projections
                if str(proj).startswith(str(sheet_spec))
            ]
            for projection_spec in sorted(projections, key=lambda p: str(p)):
                summary.append("   " + projection_spec.summary(printed=False))
            summary.append('')

        if printed: print "\n".join(summary)
        else: return "\n".join(summary)

    def __str__(self):
        return self.name

    def _repr_pretty_(self, p, cycle):
        p.text(self.summary(printed=False))

    def modifications(self, components=['model', 'sheets', 'projections']):
        """
        Display the names of all modified parameters for the specified
        set of components.

        By default all modified parameters are listed - first with the
        model parameters, then the sheet parameters and lastly the
        projection parameters.
        """
        mapping = {
            'model': [self],
            'sheets': self.sheets,
            'projections': self.projections
        }

        lines = []
        for component in components:
            heading = "=" * len(component)
            lines.extend([heading, component.capitalize(), heading, ''])
            specs = mapping[component]
            padding = max(len(str(spec)) for spec in specs)
            for spec in sorted(specs):
                modified = [str(el) for el in sorted(spec.modified_parameters)]
                lines.append("%s : [%s]" %
                             (str(spec).ljust(padding), ", ".join(modified)))
            lines.append('')
        print "\n".join(lines)
Beispiel #17
0
 def __init__(self, **params):
     super(ProjectionSheet,self).__init__(**params)
     self.new_input = False
     self.mask.sheet = self
     self.old_a = self.activity.copy()*0.0
     self.views['RFs'] = AttrTree()