def _grouped_in_projections(self, ptype):
        """
        Return a dictionary of lists of incoming Projections, grouped by type.

        Each projection of type <ptype> is grouped according to the
        name of the port, into a single list within the dictionary.

        The entry None will contain those that are not of type
        <ptype>, while the other entries will contain a list of
        Projections, each of which has type ptype.

        Example: to obtain the lists of projections that should be
        jointly normalised together, call
        __grouped_in_projection('JointNormalize').
        """
        in_proj = KeyedList()
        in_proj[None] = []  # Independent (ungrouped) connections

        for c in self.in_connections:
            d = c.dest_port
            if not isinstance(c, Projection):
                self.debug("Skipping non-Projection " + c.name)
            elif isinstance(d, tuple) and len(d) > 2 and d[1] == ptype:
                if in_proj.get(d[2]):
                    in_proj[d[2]].append(c)
                else:
                    in_proj[d[2]] = [c]
            # elif isinstance(d,tuple):
            #    raise ValueError("Unable to determine appropriate action for dest_port: %s (connection %s)." % (d,c.name))
            else:
                in_proj[None].append(c)

        return in_proj
Exemple #2
0
    def _grouped_in_projections(self,ptype):
        """
        Return a dictionary of lists of incoming Projections, grouped by type.

        Each projection of type <ptype> is grouped according to the
        name of the port, into a single list within the dictionary.

        The entry None will contain those that are not of type
        <ptype>, while the other entries will contain a list of
        Projections, each of which has type ptype.

        Example: to obtain the lists of projections that should be
        jointly normalised together, call
        __grouped_in_projection('JointNormalize').
        """
        in_proj = KeyedList()
        in_proj[None]=[] # Independent (ungrouped) connections

        for c in self.in_connections:
            d = c.dest_port
            if not isinstance(c,Projection):
                self.debug("Skipping non-Projection "+c.name)
            elif isinstance(d,tuple) and len(d)>2 and d[1]==ptype:
                if in_proj.get(d[2]):
                    in_proj[d[2]].append(c)
                else:
                    in_proj[d[2]]=[c]
            #elif isinstance(d,tuple):
            #    raise ValueError("Unable to determine appropriate action for dest_port: %s (connection %s)." % (d,c.name))
            else:
                in_proj[None].append(c)

        return in_proj
Exemple #3
0
    def refresh_plots_menu(self):
        plots_menu = self['Plots']
        plots_menu.delete(0, 'end')

        # create menu entries, and get list of categories
        entries = KeyedList(
        )  # keep the order of plotgroup_templates (which is also KL)
        categories = []
        for label, plotgroup in plotgroups.items():
            entries[label] = PlotsMenuEntry(plotgroup)
            categories.append(plotgroup.category)
        categories = sorted(set(categories))

        # The Basic category items appear on the menu itself.
        assert 'Basic' in categories, "'Basic' is the category for the standard Plots menu entries."
        for label, entry in entries:
            if entry.plotgroup.category == 'Basic':
                plots_menu.add_command(label=label, command=entry.__call__)

        categories.remove('Basic')

        plots_menu.add_separator()

        # Add the other categories to the menu as cascades, and the plots of each category to
        # their cascades.
        for category in categories:
            category_menu = ControllableMenu(plots_menu, tearoff=0)
            plots_menu.add_cascade(label=category, menu=category_menu)

            # could probably search more efficiently than this
            for label, entry in sorted(entries):
                if entry.plotgroup.category == category:
                    category_menu.add_command(label=label,
                                              command=entry.__call__)

        plots_menu.add_separator()

        plots_menu.add_command(
            label="Help",
            command=(lambda x=plotting_help_locations: self.open_location(x)))
Exemple #4
0
 def __init__(self,plot_templates=None,static_images=None,**params):
     super(TemplatePlotGroup,self).__init__(**params)
     self.plot_templates = KeyedList(plot_templates or [])
     # Add plots for the static images, if any
     for image_name,file_path in static_images or []:
         self.add_static_image(image_name,file_path)
Exemple #5
0
class TemplatePlotGroup(SheetPlotGroup):
    """
    Container that allows creation of different types of plots in a
    way that is independent of particular models or Sheets.

    A TemplatePlotGroup is constructed from a plot_templates list, an
    optional command to run to generate the data, and other optional
    parameters.

    The plot_templates list should contain tuples (plot_name,
    plot_template).  Each plot_template is a list of (name, value)
    pairs, where each name specifies a plotting channel (such as Hue
    or Confidence), and the value is the name of a SheetView (such as
    Activity or OrientationPreference).

    Various types of plots support different channels.  An SHC
    plot supports Strength, Hue, and Confidence channels (with
    Strength usually being visualized as luminance, Hue as a color
    value, and Confidence as the saturation of the color).  An RGB
    plot supports Red, Green, and Blue channels.  Other plot types
    will be added eventually.

    For instance, one could define an Orientation-colored Activity
    plot as::

      plotgroups['Activity'] =
          TemplatePlotGroup(name='Activity', category='Basic',
              pre_plot_hooks=[measure_activity],
              plot_templates=[('Activity',
                  {'Strength': 'Activity', 'Hue': 'OrientationPreference', 'Confidence': None})])

    This specifies that the final TemplatePlotGroup will contain up to
    one Plot named Activity per Sheet, although there could be no
    plots at all if no Sheet has a SheetView named Activity once
    'measure_activity()' has been run.  The Plot will be colored by
    OrientationPreference if such a SheetView exists for that Sheet,
    and the value (luminance) channel will be determined by the
    SheetView Activity.  This plot will be listed in the category
    'Basic' anywhere such categories are relevant (e.g. in the GUI).


    Here's a more complicated example specifying two different plots
    in the same PlotGroup::

      TemplatePlotGroup(name='Orientation Preference', category='Basic'
          pre_plot_hooks=[measure_or_pref.instance()],
          plot_templates=
              [('Orientation Preference',
                  {'Strength': None, 'Hue': 'OrientationPreference'}),
               ('Orientation Selectivity',
                  {'Strength': 'OrientationSelectivity'})])

    Here the TemplatePlotGroup will contain up to two Plots per Sheet,
    depending on which Sheets have OrientationPreference and
    OrientationSelectivity SheetViews.


    The function create_plotgroup provides a convenient way to define plots using
    TemplatePlotGroups; search for create_plotgroup elsewhere in the code to see
    examples.
    """

    doc = param.String(default="",doc="""
        Documentation string describing this type of plot.""")

    plot_immediately=param.Boolean(False,doc="""
        Whether to call the pre-plot hooks at once or only when the user asks for a refresh.

        Should be set to true for quick plots, but false for those that take a long time
        to calculate, so that the user can change the hooks if necessary.""")

    prerequisites=param.List([],doc="""
        List of preference maps that must exist before this plot can be calculated.""")

    category = param.String(default="User",doc="""
        Category to which this plot belongs, which will be created if necessary.""")

    filterfn = param.Callable(default=alwaystrue,doc="""
        Boolean function allowing control over which items will be plotted.
        E.g.: filterfn=lambda x: x.name in ['Retina','V1'] for a plot ranging over
        Sheets, or filterfn=lambda x: x[0]==x[1] for a plot ranging over coordinates.""")

    # CEBALERT: how to avoid repeating documentation?
    # CB: also, documentation for normalization types needs cleaning up.
    normalize = param.ObjectSelector(default='None',
                                     objects=['None','Individually','AllTogether'],doc="""

        'Individually': scale each plot so that its maximum value is
        white and its minimum value black.

        'None': no scaling (0.0 will be black and 1.0 will be white).

        'AllTogether': scale each plot so that the highest maximum value is
        white, and the lowest minimum value is black.


        Normalizing 'Individually' has the advantage of ensuring that
        any data that is present will be visible, but the disadvantage
        that the absolute scale will be obscured.  Non-normalized
        plots are guaranteed to be on a known scale, but only values
        between 0.0 and 1.0 will be visibly distinguishable.""")



    # Overrides:
    # _generate_plots() - supports normalize=='AllTogether'

    # For users, adds:
    # add_template()
    # add_static_image()

    # For subclasses, adds:
    # _template_plots()             -
    # _make_template_plot()         -
    # _kw_for_make_template_plots() -


    #####################
    ########## overridden

    def _generate_plots(self):
        if self.normalize=='AllTogether':
            range_ = _get_value_range(self._template_plots(range_=None))
        else:
            range_ = False
        return self._static_plots[:]+self._template_plots(range_=range_)


    def __init__(self,plot_templates=None,static_images=None,**params):
        super(TemplatePlotGroup,self).__init__(**params)
        self.plot_templates = KeyedList(plot_templates or [])
        # Add plots for the static images, if any
        for image_name,file_path in static_images or []:
            self.add_static_image(image_name,file_path)


    #########################
    ########## adds for users

    # JCALERT! We might eventually write these two functions
    # 'Python-like' by using keyword argument to specify each
    # channel and then get the dictionnary of all remaining
    # arguments.
    #
    # JABALERT: We should also be able to store a documentation string
    # describing each plot (for hovering help text) within each
    # plot template.

    def add_template(self,name,specification_tuple_list):
        dict_={}
        for key,value in specification_tuple_list:
            dict_[key]=value
        self.plot_templates.append((name,dict_))

    add_plot = add_template # CEBALERT: should be removed when callers updated


    def add_static_image(self,name,file_path):
        """
        Construct a static image Plot (e.g. a color key for an Orientation Preference map).
        """
        image = Image.open(resolve_path(file_path))
        plot = Plot(image,name=name)
        self._static_plots.append(plot)



    ##############################
    ########## adds for subclasses

    def _template_plots(self,range_=False):
        # calls make_template_plot for all plot_templates for all kw returned
        # by _kw_for_make_template_plot!!
        template_plots = []
        for plot_template_name,plot_template in self.plot_templates:
            for kw in self._kw_for_make_template_plot(range_):
                template_plots.append(self._make_template_plot(plot_template_name,plot_template,**kw))
        return template_plots


    def _kw_for_make_template_plot(self,range_):
        # Return a list of dictionaries; for each dictionary,
        # _make_template_plot() will be called with that dictionary
        # as keyword arguments.
        #
        # Allows subclasses to control what range of things (sheets,
        # projections) _make_template_plot() is called over, and to
        # control what keyword arguments
        # (sheet=,proj_=,range_=,bounds=,x=,...) are supplied.
        return [dict(sheet=sheet,range_=range_) for sheet in filter(self.filterfn,self.sheets())]


    def _make_template_plot(self,plot_template_name,plot_template,**kw):
        return make_template_plot(plot_template,
                                  kw['sheet'].sheet_views,
                                  kw['sheet'].xdensity,
                                  kw['sheet'].bounds,
                                  self.normalize,
                                  # CEBALERT: after this class, p.t. name never used
                                  name=plot_template_name,
                                  range_=kw['range_'])
Exemple #6
0
        use the max timestamp as the plot label
        Displays a warning if not all curves have been measured at the same time.
        """
        for x_axis in self.sheet.curve_dict.itervalues():
            for curve_label in x_axis.itervalues():
                timestamps = [SheetView.timestamp for SheetView in curve_label.itervalues()]

        if timestamps != []:
            self.time = max(timestamps)
            if max(timestamps) != min(timestamps):
                self.warning("Displaying curves from different times (%s,%s)" %
                             (min(timestamps),max(timestamps)))



plotgroups = KeyedList()
"""
Global repository of PlotGroups, to which users can add their own as
needed.
"""

plotgroup_types = {'Connection Fields': ConnectionFieldsPlotGroup,
                   'Projection': CFProjectionPlotGroup,
                   'RF Projection': RFProjectionPlotGroup,
                   'Retinotopy': RetinotopyPlotGroup,
                   'Projection Activity': ProjectionActivityPlotGroup}


def create_plotgroup(template_plot_type='bitmap',**params):
    """
    Create a new PlotGroup and add it to the plotgroups list.