Beispiel #1
0
    def plot(self, experiment, data, **kwargs):
        """
        Base function for facetted plotting
        
        Parameters
        ----------
        experiment: Experiment
            The :class:`.Experiment` to plot using this view.
            
        title : str
            Set the plot title
            
        xlabel, ylabel : str
            Set the X and Y axis labels
            
        huelabel : str
            Set the label for the hue facet (in the legend)
            
        legend : bool
            Plot a legend for the color or hue facet?  Defaults to `True`.
            
        sharex, sharey : bool
            If there are multiple subplots, should they share axes?  Defaults
            to `True`.

        col_wrap : int
            If `xfacet` is set and `yfacet` is not set, you can "wrap" the
            subplots around so that they form a multi-row grid by setting
            `col_wrap` to the number of columns you want. 
            
        sns_style : {"darkgrid", "whitegrid", "dark", "white", "ticks"}
            Which `seaborn` style to apply to the plot?  Default is `whitegrid`.
            
        sns_context : {"paper", "notebook", "talk", "poster"}
            Which `seaborn` context to use?  Controls the scaling of plot 
            elements such as tick labels and the legend.  Default is `talk`.
            
        despine : Bool
            Remove the top and right axes from the plot?  Default is `True`.

        Other Parameters
        ----------------
        cmap : matplotlib colormap
            If plotting a huefacet with many values, use this color map instead
            of the default.
            
        norm : matplotlib.colors.Normalize
            If plotting a huefacet with many values, use this object for color
            scale normalization.

        """

        if experiment is None:
            raise util.CytoflowViewError('experiment',
                                         "No experiment specified")

        col_wrap = kwargs.pop('col_wrap', None)

        if col_wrap is not None and self.yfacet:
            raise util.CytoflowViewError(
                'yfacet', "Can't set yfacet and col_wrap at the same time.")

        if col_wrap is not None and not self.xfacet:
            raise util.CytoflowViewError('xfacet',
                                         "Must set xfacet to use col_wrap.")

        if col_wrap is not None and col_wrap < 2:
            raise util.CytoflowViewError(None, "col_wrap must be None or > 1")

        title = kwargs.pop("title", None)
        xlabel = kwargs.pop("xlabel", None)
        ylabel = kwargs.pop("ylabel", None)
        huelabel = kwargs.pop("huelabel", self.huefacet)

        sharex = kwargs.pop("sharex", True)
        sharey = kwargs.pop("sharey", True)

        legend = kwargs.pop('legend', True)

        sns_style = kwargs.pop('sns_style', 'whitegrid')
        sns_context = kwargs.pop('sns_context', 'talk')
        despine = kwargs.pop('despine', False)

        cols = col_wrap if col_wrap else \
               len(data[self.xfacet].unique()) if self.xfacet else 1

        sns.set_style(sns_style)
        sns.set_context(sns_context)

        g = sns.FacetGrid(data,
                          height=6 / cols,
                          aspect=1.5,
                          col=(self.xfacet if self.xfacet else None),
                          row=(self.yfacet if self.yfacet else None),
                          hue=(self.huefacet if self.huefacet else None),
                          col_order=(np.sort(data[self.xfacet].unique())
                                     if self.xfacet else None),
                          row_order=(np.sort(data[self.yfacet].unique())
                                     if self.yfacet else None),
                          hue_order=(np.sort(data[self.huefacet].unique())
                                     if self.huefacet else None),
                          col_wrap=col_wrap,
                          legend_out=False,
                          sharex=sharex,
                          sharey=sharey)

        plot_ret = self._grid_plot(experiment=experiment, grid=g, **kwargs)

        kwargs.update(plot_ret)

        xscale = kwargs.pop("xscale", None)
        yscale = kwargs.pop("yscale", None)
        xlim = kwargs.pop("xlim", None)
        ylim = kwargs.pop("ylim", None)

        for ax in g.axes.flatten():
            if xscale:
                ax.set_xscale(xscale.name,
                              **xscale.get_mpl_params(ax.get_xaxis()))
            if yscale:
                ax.set_yscale(yscale.name,
                              **yscale.get_mpl_params(ax.get_yaxis()))
            if xlim:
                ax.set_xlim(xlim)
            if ylim:
                ax.set_ylim(ylim)

        # if we are sharing x axes, make sure the x limits are the same for each
        if sharex:
            fig = plt.gcf()
            fig_x_min = float("inf")
            fig_x_max = float("-inf")

            for ax in fig.get_axes():
                ax_x_min, ax_x_max = ax.get_xlim()
                if ax_x_min < fig_x_min:
                    fig_x_min = ax_x_min
                if ax_x_max > fig_x_max:
                    fig_x_max = ax_x_max

            for ax in fig.get_axes():
                ax.set_xlim(fig_x_min, fig_x_max)

        # if we are sharing y axes, make sure the y limits are the same for each
        if sharey:
            fig = plt.gcf()
            fig_y_max = float("-inf")

            for ax in fig.get_axes():
                _, ax_y_max = ax.get_ylim()
                if ax_y_max > fig_y_max:
                    fig_y_max = ax_y_max

            for ax in fig.get_axes():
                ax.set_ylim(None, fig_y_max)

        # if we have a hue facet and a lot of hues, make a color bar instead
        # of a super-long legend.

        cmap = kwargs.pop('cmap', None)
        norm = kwargs.pop('norm', None)
        legend_data = kwargs.pop('legend_data', None)

        if legend:
            if cmap and norm:
                plot_ax = plt.gca()
                cax, _ = mpl.colorbar.make_axes(plt.gcf().get_axes())
                mpl.colorbar.ColorbarBase(cax, cmap, norm)
                plt.sca(plot_ax)
            elif self.huefacet:

                current_palette = mpl.rcParams['axes.prop_cycle']

                if util.is_numeric(data[self.huefacet]) and \
                   len(g.hue_names) > len(current_palette):

                    cmap = mpl.colors.ListedColormap(
                        sns.color_palette("husl", n_colors=len(g.hue_names)))
                    hue_scale = util.scale_factory(
                        self.huescale,
                        experiment,
                        data=data[self.huefacet].values)

                    plot_ax = plt.gca()

                    cax, _ = mpl.colorbar.make_axes(plt.gcf().get_axes())

                    mpl.colorbar.ColorbarBase(cax,
                                              cmap=cmap,
                                              norm=hue_scale.norm(),
                                              label=huelabel)
                    plt.sca(plot_ax)
                else:
                    g.add_legend(title=huelabel, legend_data=legend_data)
                    ax = g.axes.flat[0]
                    legend = ax.legend_
                    self._update_legend(legend)


#                     for lh in legend.legendHandles:
#                         lh.set_facecolor(lh.get_facecolor())  # i don't know why
#                         lh.set_edgecolor(lh.get_edgecolor())  # these are needed
#                         lh.set_alpha(1.0)

        if title:
            if self.xfacet or self.yfacet:
                plt.subplots_adjust(top=0.9)
            else:
                plt.subplots_adjust(top=0.94)

            plt.suptitle(title)

        if xlabel == "":
            xlabel = None

        if ylabel == "":
            ylabel = None

        g.set_axis_labels(xlabel, ylabel)

        sns.despine(top=despine, right=despine, bottom=False, left=False)
Beispiel #2
0
    def _make_data(self, experiment):
        if experiment is None:
            raise util.CytoflowViewError('experiment',
                                         "No experiment specified")

        if not self.xstatistic:
            raise util.CytoflowViewError('xstatistic', "X Statistic not set")

        if self.xstatistic not in experiment.statistics:
            raise util.CytoflowViewError(
                'xstatistic',
                "Can't find the statistic {} in the experiment".format(
                    self.xstatistic))
        else:
            xstat = experiment.statistics[self.xstatistic]

        if not util.is_numeric(xstat):
            raise util.CytoflowViewError('xstatistic',
                                         "X statistic must be numeric")

        if self.x_error_statistic[0]:
            if self.x_error_statistic not in experiment.statistics:
                raise util.CytoflowViewError(
                    'x_error_statistic',
                    "Can't find the X error statistic in the experiment")
            else:
                x_error_stat = experiment.statistics[self.x_error_statistic]
        else:
            x_error_stat = None

        if x_error_stat is not None:

            if set(xstat.index.names) != set(x_error_stat.index.names):
                raise util.CytoflowViewError(
                    'x_error_statistic',
                    "X data statistic and error statistic "
                    "don't have the same index.")

            try:
                x_error_stat.index = x_error_stat.index.reorder_levels(
                    xstat.index.names)
                x_error_stat.sort_index(inplace=True)
            except AttributeError:
                pass

            if not xstat.index.equals(x_error_stat.index):
                raise util.CytoflowViewError(
                    'x_error_statistic',
                    "X data statistic and error statistic "
                    " don't have the same index.")

            if xstat.name == x_error_stat.name:
                raise util.CytoflowViewError(
                    'x_error_statistic',
                    "X data statistic and error statistic can "
                    "not have the same name.")

        if not self.ystatistic:
            raise util.CytoflowViewError('ystatistic', "Y statistic not set")

        if self.ystatistic not in experiment.statistics:
            raise util.CytoflowViewError(
                'ystatistic',
                "Can't find the Y statistic {} in the experiment".format(
                    self.ystatistic))
        else:
            ystat = experiment.statistics[self.ystatistic]

        if not util.is_numeric(ystat):
            raise util.CytoflowViewError('ystatistic',
                                         "Y statistic must be numeric")

        if self.y_error_statistic[0]:
            if self.y_error_statistic not in experiment.statistics:
                raise util.CytoflowViewError(
                    'y_error_statistic',
                    "Can't find the Y error statistic in the experiment")
            else:
                y_error_stat = experiment.statistics[self.y_error_statistic]
        else:
            y_error_stat = None

        if y_error_stat is not None:

            if set(ystat.index.names) != set(y_error_stat.index.names):
                raise util.CytoflowViewError(
                    'y_error_statistic',
                    "Y data statistic and error statistic "
                    "don't have the same index.")

            try:
                y_error_stat.index = y_error_stat.index.reorder_levels(
                    ystat.index.names)
                y_error_stat.sort_index(inplace=True)
            except AttributeError:
                pass

            if not ystat.index.equals(y_error_stat.index):
                raise util.CytoflowViewError(
                    'y_error_statistic',
                    "Y data statistic and error statistic "
                    " don't have the same index.")

            if ystat.name == y_error_stat.name:
                raise util.CytoflowViewError(
                    'y_error_statistic',
                    "Data statistic and error statistic can "
                    "not have the same name.")

        if xstat.name == ystat.name:
            raise util.CytoflowViewError(
                'ystatistic', "X and Y statistics can "
                "not have the same name.")

        if set(xstat.index.names) != set(ystat.index.names):
            raise util.CytoflowViewError(
                'ystatistic', "X and Y data statistics "
                "don't have the same index.")

        try:
            ystat.index = ystat.index.reorder_levels(xstat.index.names)
            ystat.sort_index(inplace=True)
        except AttributeError:
            pass

        intersect_idx = xstat.index.intersection(ystat.index)
        xstat = xstat.reindex(intersect_idx)
        xstat.sort_index(inplace=True)
        ystat = ystat.reindex(intersect_idx)
        ystat.sort_index(inplace=True)

        data = pd.DataFrame(index=xstat.index)
        data[xstat.name] = xstat
        data[ystat.name] = ystat

        if x_error_stat is not None:
            data[x_error_stat.name] = x_error_stat

        if y_error_stat is not None:
            data[y_error_stat.name] = y_error_stat

        return data
Beispiel #3
0
    def plot(self, experiment, **kwargs):
        """Plot a faceted histogram view of a channel"""

        if not experiment:
            raise util.CytoflowViewError("No experiment specified")

        if not self.channel:
            raise util.CytoflowViewError("Must specify a channel")

        if self.channel not in experiment.data:
            raise util.CytoflowViewError(
                "Channel {0} not in the experiment".format(self.channel))

        if self.xfacet and self.xfacet not in experiment.conditions:
            raise util.CytoflowViewError(
                "X facet {0} not in the experiment".format(self.xfacet))

        if self.yfacet and self.yfacet not in experiment.conditions:
            raise util.CytoflowViewError(
                "Y facet {0} not in the experiment".format(self.yfacet))

        if self.huefacet and self.huefacet not in experiment.conditions:
            raise util.CytoflowViewError(
                "Hue facet {0} not in the experiment".format(self.huefacet))

        facets = filter(lambda x: x, [self.xfacet, self.yfacet, self.huefacet])
        if len(facets) != len(set(facets)):
            raise util.CytoflowViewError("Can't reuse facets")

        col_wrap = kwargs.pop('col_wrap', None)

        if col_wrap and self.yfacet:
            raise util.CytoflowViewError(
                "Can't set yfacet and col_wrap at the same time.")

        if col_wrap and not self.xfacet:
            raise util.CytoflowViewError("Must set xfacet to use col_wrap.")

        if self.subset:
            try:
                data = experiment.query(self.subset).data.reset_index()
            except:
                raise util.CytoflowViewError(
                    "Subset string '{0}' isn't valid".format(self.subset))

            if len(data) == 0:
                raise util.CytoflowViewError(
                    "Subset string '{0}' returned no events".format(
                        self.subset))
        else:
            data = experiment.data

        kwargs.setdefault('shade', True)
        kwargs['label'] = self.name

        # get the scale
        kwargs['scale'] = scale = util.scale_factory(self.scale,
                                                     experiment,
                                                     channel=self.channel)

        # adjust the limits to clip extreme values
        min_quantile = kwargs.pop("min_quantile", 0.001)
        max_quantile = kwargs.pop("max_quantile", 0.999)

        xlim = kwargs.pop("xlim", None)
        if xlim is None:
            xlim = (scale.clip(data[self.channel].quantile(min_quantile)),
                    scale.clip(data[self.channel].quantile(max_quantile)))

        sharex = kwargs.pop('sharex', True)
        sharey = kwargs.pop('sharey', True)

        cols = col_wrap if col_wrap else \
               len(data[self.xfacet].unique()) if self.xfacet else 1

        g = sns.FacetGrid(data,
                          size=(6 / cols),
                          aspect=1.5,
                          col=(self.xfacet if self.xfacet else None),
                          row=(self.yfacet if self.yfacet else None),
                          hue=(self.huefacet if self.huefacet else None),
                          col_order=(np.sort(data[self.xfacet].unique())
                                     if self.xfacet else None),
                          row_order=(np.sort(data[self.yfacet].unique())
                                     if self.yfacet else None),
                          hue_order=(np.sort(data[self.huefacet].unique())
                                     if self.huefacet else None),
                          col_wrap=col_wrap,
                          legend_out=False,
                          sharex=sharex,
                          sharey=sharey,
                          xlim=xlim)

        # set the scale for each set of axes; can't just call plt.xscale()
        for ax in g.axes.flatten():
            ax.set_xscale(self.scale, **scale.mpl_params)

        g.map(_univariate_kdeplot, self.channel, **kwargs)

        # adjust the limits to clip extreme values
        min_quantile = kwargs.pop("min_quantile", 0.001)
        max_quantile = kwargs.pop("max_quantile", 0.999)

        def autoscale_x(*args, **kwargs):
            d = args[0]
            plt.gca().set_xlim(d.quantile(min_quantile),
                               d.quantile(max_quantile))

        g.map(autoscale_x, self.channel)

        # if we are sharing y axes, make sure the y scale is the same for each
        if sharey:
            fig = plt.gcf()
            fig_y_max = float("-inf")

            for ax in fig.get_axes():
                _, ax_y_max = ax.get_ylim()
                if ax_y_max > fig_y_max:
                    fig_y_max = ax_y_max

            for ax in fig.get_axes():
                ax.set_ylim(None, fig_y_max)

        # if we are sharing x axes, make sure the x scale is the same for each
        if sharex:
            fig = plt.gcf()
            fig_x_min = float("inf")
            fig_x_max = float("-inf")

            for ax in fig.get_axes():
                ax_x_min, ax_x_max = ax.get_xlim()
                if ax_x_min < fig_x_min:
                    fig_x_min = ax_x_min
                if ax_x_max > fig_x_max:
                    fig_x_max = ax_x_max

            for ax in fig.get_axes():
                ax.set_xlim(fig_x_min, fig_x_max)

        # if we have a hue facet and a lot of hues, make a color bar instead
        # of a super-long legend.

        if self.huefacet:
            current_palette = mpl.rcParams['axes.color_cycle']
            if util.is_numeric(experiment.data[self.huefacet]) and \
               len(g.hue_names) > len(current_palette):

                plot_ax = plt.gca()
                cmap = mpl.colors.ListedColormap(
                    sns.color_palette("husl", n_colors=len(g.hue_names)))
                cax, _ = mpl.colorbar.make_axes(plt.gca())
                hue_scale = util.scale_factory(self.huescale,
                                               experiment,
                                               condition=self.huefacet)
                mpl.colorbar.ColorbarBase(cax,
                                          cmap=cmap,
                                          norm=hue_scale.color_norm(),
                                          label=self.huefacet)
                plt.sca(plot_ax)
            else:
                g.add_legend(title=self.huefacet)
Beispiel #4
0
    def plot(self, experiment, plot_name = None, **kwargs):
        """Plot a chart"""
        
        if not experiment:
            raise util.CytoflowViewError("No experiment specified")
        
        if not self.statistic:
            raise util.CytoflowViewError("Statistic not set")
        
        if self.statistic not in experiment.statistics:
            raise util.CytoflowViewError("Can't find the statistic {} in the experiment"
                                         .format(self.statistic))
        else:
            stat = experiment.statistics[self.statistic]
            
        if self.error_statistic[0]:
            if self.error_statistic not in experiment.statistics:
                raise util.CytoflowViewError("Can't find the error statistic in the experiment")
            else:
                error_stat = experiment.statistics[self.error_statistic]
        else:
            error_stat = None
         
        if error_stat is not None:
            if not stat.index.equals(error_stat.index):
                raise util.CytoflowViewError("Data statistic and error statistic "
                                             " don't have the same index.")
               
        data = pd.DataFrame(index = stat.index)
        data[stat.name] = stat
        
        if error_stat is not None:
            error_name = util.random_string(6)
            data[error_name] = error_stat
        
        if self.subset:
            try:
                # TODO - either sanitize column names, or check to see that
                # all conditions are valid Python variables
                data = data.query(self.subset)
            except:
                raise util.CytoflowViewError("Subset string '{0}' isn't valid"
                                        .format(self.subset))
                
            if len(data) == 0:
                raise util.CytoflowViewError("Subset string '{0}' returned no values"
                                        .format(self.subset))
                
        names = list(data.index.names)
        for name in names:
            unique_values = data.index.get_level_values(name).unique()
            if len(unique_values) == 1:
                warn("Only one value for level {}; dropping it.".format(name),
                     util.CytoflowViewWarning)
                try:
                    data.index = data.index.droplevel(name)
                except AttributeError:
                    raise util.CytoflowViewError("Must have more than one "
                                                 "value to plot.")

        names = list(data.index.names)
               
        if not self.variable:
            raise util.CytoflowViewError("X variable not set")
            
        if self.variable not in experiment.conditions:
            raise util.CytoflowViewError("X variable {0} not in the experiment"
                                    .format(self.variable))
                        
        if self.variable not in names:
            raise util.CytoflowViewError("X variable {} is not a statistic index; "
                                         "must be one of {}".format(self.variable, names))
                
        if experiment.conditions[self.variable].dtype.kind not in "biufc": 
            raise util.CytoflowViewError("X variable {0} isn't numeric"
                                    .format(self.variable))
        
        if self.xfacet and self.xfacet not in experiment.conditions:
            raise util.CytoflowViewError("X facet {0} not in the experiment")
        
        if self.xfacet and self.xfacet not in names:
            raise util.CytoflowViewError("X facet {} is not a statistic index; "
                                         "must be one of {}".format(self.xfacet, names))
        
        if self.yfacet and self.yfacet not in experiment.conditions:
            raise util.CytoflowViewError("Y facet {0} not in the experiment")
        
        if self.yfacet and self.yfacet not in names:
            raise util.CytoflowViewError("Y facet {} is not a statistic index; "
                                         "must be one of {}".format(self.yfacet, names))
        
        if self.huefacet and self.huefacet not in experiment.metadata:
            raise util.CytoflowViewError("Hue facet {0} not in the experiment")   
        
        if self.huefacet and self.huefacet not in names:
            raise util.CytoflowViewError("Hue facet {} is not a statistic index; "
                                         "must be one of {}".format(self.huefacet, names))  
            
        col_wrap = kwargs.pop('col_wrap', None)
        
        if col_wrap and self.yfacet:
            raise util.CytoflowViewError("Can't set yfacet and col_wrap at the same time.") 
        
        if col_wrap and not self.xfacet:
            raise util.CytoflowViewError("Must set xfacet to use col_wrap.")
            
        facets = filter(lambda x: x, [self.variable, self.xfacet, self.yfacet, self.huefacet])
        if len(facets) != len(set(facets)):
            raise util.CytoflowViewError("Can't reuse facets")
        
        unused_names = list(set(names) - set(facets))

        if unused_names and plot_name is None:
            for plot in self.enum_plots(experiment):
                self.plot(experiment, plot, **kwargs)
            return

        data.reset_index(inplace = True)
        
        if plot_name is not None:
            if plot_name is not None and not unused_names:
                raise util.CytoflowViewError("Plot {} not from plot_enum"
                                             .format(plot_name))
                               
            groupby = data.groupby(unused_names)

            if plot_name not in set(groupby.groups.keys()):
                raise util.CytoflowViewError("Plot {} not from plot_enum"
                                             .format(plot_name))
                
            data = groupby.get_group(plot_name)
            data.reset_index(drop = True, inplace = True)
            
        xscale = util.scale_factory(self.xscale, experiment, condition = self.variable) 
        
        if error_stat is not None:
            yscale = util.scale_factory(self.yscale, experiment, statistic = self.error_statistic)
        else:
            yscale = util.scale_factory(self.yscale, experiment, statistic = self.statistic)
                        
        xlim = kwargs.pop("xlim", None)
        if xlim is None:
            xlim = (xscale.clip(data[self.variable].min() * 0.9),
                    xscale.clip(data[self.variable].max() * 1.1))
                      
        ylim = kwargs.pop("ylim", None)
        if ylim is None:
            ylim = (yscale.clip(data[stat.name].min() * 0.9),
                    yscale.clip(data[stat.name].max() * 1.1))
            
            if error_stat is not None:
                try: 
                    ylim = (yscale.clip(min([x[0] for x in error_stat]) * 0.9),
                            yscale.clip(max([x[1] for x in error_stat]) * 1.1))
                except IndexError:
                    ylim = (yscale.clip(error_stat.min() * 0.9), 
                            yscale.clip(error_stat.max() * 1.1))

        kwargs.setdefault('antialiased', True)  
        
        cols = col_wrap if col_wrap else \
               len(data[self.xfacet].unique()) if self.xfacet else 1
               
        sharex = kwargs.pop('sharex', True)
        sharey = kwargs.pop('sharey', True)
                  
        grid = sns.FacetGrid(data,
                             size = (6 / cols),
                             aspect = 1.5,
                             col = (self.xfacet if self.xfacet else None),
                             row = (self.yfacet if self.yfacet else None),
                             hue = (self.huefacet if self.huefacet else None),
                             col_order = (np.sort(data[self.xfacet].unique()) if self.xfacet else None),
                             row_order = (np.sort(data[self.yfacet].unique()) if self.yfacet else None),
                             hue_order = (np.sort(data[self.huefacet].unique()) if self.huefacet else None),
                             col_wrap = col_wrap,
                             legend_out = False,
                             sharex = sharex,
                             sharey = sharey,
                             xlim = xlim,
                             ylim = ylim)

        for ax in grid.axes.flatten():
            ax.set_xscale(self.xscale, **xscale.mpl_params)
            ax.set_yscale(self.yscale, **yscale.mpl_params)

        # plot the error bars first so the axis labels don't get overwritten
        if error_stat is not None:
            grid.map(_error_bars, self.variable, stat.name, error_name, **kwargs)
        
        grid.map(plt.plot, self.variable, stat.name, **kwargs)
        
        # if we are sharing y axes, make sure the y scale is the same for each
        if sharey:
            fig = plt.gcf()
            fig_y_min = float("inf")
            fig_y_max = float("-inf")
            
            for ax in fig.get_axes():
                ax_y_min, ax_y_max = ax.get_ylim()
                if ax_y_min < fig_y_min:
                    fig_y_min = ax_y_min
                if ax_y_max > fig_y_max:
                    fig_y_max = ax_y_max
                    
            for ax in fig.get_axes():
                ax.set_ylim(fig_y_min, fig_y_max)
            
        # if we are sharing x axes, make sure the x scale is the same for each
        if sharex:
            fig = plt.gcf()
            fig_x_min = float("inf")
            fig_x_max = float("-inf")
            
            for ax in fig.get_axes():
                ax_x_min, ax_x_max = ax.get_xlim()
                if ax_x_min < fig_x_min:
                    fig_x_min = ax_x_min
                if ax_x_max > fig_x_max:
                    fig_x_max = ax_x_max
            
            for ax in fig.get_axes():
                ax.set_xlim(fig_x_min, fig_x_max)
        
        # if we have a hue facet and a lot of hues, make a color bar instead
        # of a super-long legend.
        
        if self.huefacet:
            current_palette = mpl.rcParams['axes.color_cycle']
            if util.is_numeric(experiment.data[self.huefacet]) and \
               len(grid.hue_names) > len(current_palette):
                
                plot_ax = plt.gca()
                cmap = mpl.colors.ListedColormap(sns.color_palette("husl", 
                                                                   n_colors = len(grid.hue_names)))
                cax, kw = mpl.colorbar.make_axes(plt.gca())
                norm = mpl.colors.Normalize(vmin = np.min(grid.hue_names), 
                                            vmax = np.max(grid.hue_names), 
                                            clip = False)
                mpl.colorbar.ColorbarBase(cax, 
                                          cmap = cmap, 
                                          norm = norm,
                                          label = self.huefacet, 
                                          **kw)
                plt.sca(plot_ax)
            else:
                grid.add_legend(title = self.huefacet)
                
        if unused_names and plot_name:
            plt.title("{0} = {1}".format(unused_names, plot_name))
                
        plt.ylabel(self.statistic)
Beispiel #5
0
    def plot(self, experiment, plot_name = None, **kwargs):
        """Plot a chart of a variable's values against a statistic.
        
        Parameters
        ----------
        
        variable_lim : (float, float)
            The limits on the variable axis
        
        color : a matplotlib color
            The color to plot with.  Overridden if `huefacet` is not `None`
            
        linewidth : float
            The width of the line, in points
            
        linestyle : ['solid' | 'dashed', 'dashdot', 'dotted' | (offset, on-off-dash-seq) | '-' | '--' | '-.' | ':' | 'None' | ' ' | '']
            
        marker : a matplotlib marker style
            See http://matplotlib.org/api/markers_api.html#module-matplotlib.markers
            
        markersize : int
            The marker size in points
            
        markerfacecolor : a matplotlib color
            The color to make the markers.  Overridden (?) if `huefacet` is not `None`
            
        alpha : the alpha blending value, from 0.0 (transparent) to 1.0 (opaque)
        
        capsize : scalar
            The size of the error bar caps, in points
            
        shade_error : bool
            If `False` (the default), plot the error statistic as traditional 
            "error bars."  If `True`, plot error statistic as a filled, shaded
            region.
            
        shade_alpha : float
            The transparency of the shaded error region, from 0.0 (transparent)
            to 1.0 (opaque.)  Default is 0.2.
        
        Notes
        -----
                
        Other `kwargs` are passed to `matplotlib.pyplot.plot <https://matplotlib.org/devdocs/api/_as_gen/matplotlib.pyplot.plot.html>`_
        
        """

        if experiment is None:
            raise util.CytoflowViewError('experiment', "No experiment specified")
        
        if self.variable not in experiment.conditions:
            raise util.CytoflowError('variable',
                                     "Variable {} not in the experiment"
                                     .format(self.variable))
        
        if not util.is_numeric(experiment[self.variable]):
            raise util.CytoflowError('variable',
                                     "Variable {} must be numeric"
                                     .format(self.variable))
        
        variable_scale = util.scale_factory(self.variable_scale, 
                                            experiment, 
                                            condition = self.variable)
        
        super().plot(experiment, 
                     plot_name, 
                     variable_scale = variable_scale,
                     **kwargs)