Пример #1
0
    def plot(self, experiment, **kwargs):
        """Plot a bar chart"""
        
        if not experiment:
            raise util.CytoflowViewError("No experiment specified")
        
        if not self.variable:
            raise util.CytoflowViewError("variable not set")
            
        if self.variable not in experiment.conditions:
            raise util.CytoflowViewError("variable {0} not in the experiment"
                                    .format(self.variable))
        
        if not (experiment.conditions[self.variable] == "float" or
                experiment.conditions[self.variable] == "int"):
            raise util.CytoflowViewError("variable {0} isn't numeric"
                                    .format(self.variable)) 
            
        if not self.xchannel:
            raise util.CytoflowViewError("X channel isn't set.")
        
        if self.xchannel not in experiment.data:
            raise util.CytoflowViewError("X channel {0} isn't in the experiment"
                                    .format(self.xchannel))
        
        if not self.xfunction:
            raise util.CytoflowViewError("X summary function isn't set")
                
        if not self.ychannel:
            raise util.CytoflowViewError("Y channel isn't set.")
        
        if self.ychannel not in experiment.data:
            raise util.CytoflowViewError("Y channel {0} isn't in the experiment"
                                    .format(self.ychannel))
        
        if not self.yfunction:
            raise util.CytoflowViewError("Y summary function isn't set")
        
        if self.xfacet and self.xfacet not in experiment.conditions:
            raise util.CytoflowViewError("X facet {0} not in the experiment")
        
        if self.yfacet and self.yfacet not in experiment.conditions:
            raise util.CytoflowViewError("Y facet {0} not in the experiment")
        
        if self.huefacet and self.huefacet not in experiment.metadata:
            raise util.CytoflowViewError("Hue facet {0} not in the experiment")        

        if self.x_error_bars and self.x_error_bars != 'data' \
                             and self.x_error_bars not in experiment.conditions:
            raise util.CytoflowViewError("x_error_bars must be either 'data' or "
                                         "a condition in the experiment") 
            
        if self.x_error_bars and not self.x_error_function:
            raise util.CytoflowViewError("didn't set an x error function")

        if self.y_error_bars and self.y_error_bars != 'data' \
                             and self.y_error_bars not in experiment.conditions:
            raise util.CytoflowViewError("y_error_bars must be either 'data' or "
                                         "a condition in the experiment") 
            
        if self.y_error_bars and not self.y_error_function:
            raise util.CytoflowViewError("didn't set an error function")
                
        kwargs.setdefault('antialiased', True)
        
        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.index) == 0:
                raise util.CytoflowViewError("Subset string '{0}' returned no events"
                                        .format(self.subset))
        else:
            data = experiment.data
            
        group_vars = [self.variable]
        if self.xfacet: group_vars.append(self.xfacet)
        if self.yfacet: group_vars.append(self.yfacet)
        if self.huefacet: group_vars.append(self.huefacet)
            
        g = data.groupby(by = group_vars)
        
        plot_data = pd.DataFrame(
                {self.xchannel : g[self.xchannel].aggregate(self.xfunction), 
                 self.ychannel : g[self.ychannel].aggregate(self.yfunction)}) \
                      .reset_index()
                      
        # compute the x error statistic
        if self.x_error_bars:
            if self.x_error_bars == 'data':
                # compute the error statistic on the same subsets as the summary
                # statistic
                error_stat = g[self.xchannel].aggregate(self.x_error_function).reset_index()
            else:
                # subdivide the data set further by the error_bars condition
                err_vars = list(group_vars)
                err_vars.append(self.x_error_bars)
                
                # apply the summary statistic to each subgroup
                data_g = data.groupby(by = err_vars)
                data_stat = data_g[self.xchannel].aggregate(self.xfunction).reset_index()
                
                # apply the error function to the summary statistics
                err_g = data_stat.groupby(by = group_vars)
                error_stat = err_g[self.xchannel].aggregate(self.x_error_function).reset_index()
        
            x_err_name = util.random_string(6)
            plot_data[x_err_name] = error_stat[self.xchannel]
            
        # compute the y error statistic
        if self.y_error_bars:
            if self.y_error_bars == 'data':
                # compute the error statistic on the same subsets as the summary
                # statistic
                error_stat = g[self.ychannel].aggregate(self.y_error_function).reset_index()
            else:
                # subdivide the data set further by the error_bars condition
                err_vars = list(group_vars)
                err_vars.append(self.y_error_bars)
                
                # apply the summary statistic to each subgroup
                data_g = data.groupby(by = err_vars)
                data_stat = data_g[self.ychannel].aggregate(self.yfunction).reset_index()
                
                # apply the error function to the summary statistics
                err_g = data_stat.groupby(by = group_vars)
                error_stat = err_g[self.ychannel].aggregate(self.y_error_function).reset_index()
        
            y_err_name = util.random_string(6)
            plot_data[y_err_name] = error_stat[self.ychannel]
        
 
        grid = sns.FacetGrid(plot_data,
                             size = 6,
                             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),
                             legend_out = False,
                             sharex = False,
                             sharey = False)
        
        xscale = util.scale_factory(self.xscale, experiment, self.xchannel)
        yscale = util.scale_factory(self.yscale, experiment, self.ychannel)
        
        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 self.x_error_bars:
            grid.map(_x_error_bars, self.xchannel, x_err_name, self.ychannel)
            
        if self.y_error_bars:
            grid.map(_y_error_bars, self.xchannel, self.ychannel, y_err_name)

        grid.map(plt.plot, self.xchannel, self.ychannel, **kwargs)


        # 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 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, _ = 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)
                plt.sca(plot_ax)
            else:
                grid.add_legend(title = self.huefacet)
Пример #2
0
    def plot(self, experiment, plot_name=None, **kwargs):
        """Plot a bar chart"""

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

        if not self.variable:
            raise util.CytoflowViewError("variable not set")

        if self.variable not in experiment.conditions:
            raise util.CytoflowViewError(
                "variable {0} not in the experiment".format(self.variable))

        if not self.xstatistic:
            raise util.CytoflowViewError("X statistic not set")

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

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

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

        if not xstat.index.equals(ystat.index):
            raise util.CytoflowViewError(
                "X statistic and Y statistic must have "
                "the same indices: {}".format(xstat.index.names))

        if self.x_error_statistic[0]:
            if self.x_error_statistic not in experiment.statistics:
                raise util.CytoflowViewError(
                    "X error statistic not in experiment")
            else:
                x_error_stat = experiment.statistics[self.x_error_statistic]

            if not x_error_stat.index.equals(xstat.index):
                raise util.CytoflowViewError(
                    "X error statistic doesn't have the "
                    "same indices as the X statistic")
        else:
            x_error_stat = None

        if self.y_error_statistic[0]:
            if self.y_error_statistic not in experiment.statistics:
                raise util.CytoflowViewError(
                    "Y error statistic not in experiment")
            else:
                y_error_stat = experiment.statistics[self.y_error_statistic]

            if not y_error_stat.index.equals(ystat.index):
                raise util.CytoflowViewError(
                    "Y error statistic doesn't have the "
                    "same indices as the Y statistic")
        else:
            y_error_stat = None

        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.")

        data = pd.DataFrame(index=xstat.index)

        xname = util.random_string(6)
        data[xname] = xstat

        yname = util.random_string(6)
        data[yname] = ystat

        if x_error_stat is not None:
            #x_error_data = x_error_stat.reset_index()
            x_error_name = util.random_string(6)
            data[x_error_name] = x_error_stat

        if y_error_stat is not None:
            y_error_name = util.random_string(6)
            data[y_error_name] = y_error_stat

        if y_error_stat is not None:
            y_error_data = y_error_stat.reset_index()
            y_error_name = util.random_string()
            data[y_error_name] = y_error_data[y_error_stat.name]

        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 in experiment.conditions:
            raise util.CytoflowViewError(
                "Variable {} not in experiment".format(self.variable))

        if not self.variable in data.index.names:
            raise util.CytoflowViewError(
                "Variable {} not in statistic; must be one of {}".format(
                    self.variable, data.index.names))

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

        if self.xfacet and self.xfacet not in data.index.names:
            raise util.CytoflowViewError(
                "X facet {} not in statistics; must be one of {}".format(
                    self.xfacet, data.index.names))

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

        if self.yfacet and self.yfacet not in data.index.names:
            raise util.CytoflowViewError(
                "Y facet {} not in statistics; must be one of {}".format(
                    self.yfacet, data.index.names))

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

        if self.huefacet and self.huefacet not in data.index.names:
            raise util.CytoflowViewError(
                "Hue facet {} not in statistics; must be one of {}".format(
                    self.huefacet, data.index.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 plot_name is not None and not unused_names:
            raise util.CytoflowViewError("You specified a plot name, but all "
                                         "the facets are already used")

        data.reset_index(inplace=True)

        if unused_names:
            groupby = data.groupby(unused_names)

            if plot_name is None:
                raise util.CytoflowViewError(
                    "You must use facets {} in either the "
                    "plot variables or the plot name. "
                    "Possible plot names: {}".format(unused_names,
                                                     groupby.groups.keys()))

            if plot_name not in set(groupby.groups.keys()):
                raise util.CytoflowViewError(
                    "Plot {} not from plot_enum; must "
                    "be one of {}".format(plot_name, groupby.groups.keys()))

            data = groupby.get_group(plot_name)

        if self.x_error_statistic is not None:
            xscale = util.scale_factory(self.xscale,
                                        experiment,
                                        statistic=self.xstatistic)
        else:
            xscale = util.scale_factory(self.xscale,
                                        experiment,
                                        statistic=self.x_error_statistic)

        if self.y_error_statistic is not None:
            yscale = util.scale_factory(self.yscale,
                                        experiment,
                                        statistic=self.ystatistic)
        else:
            yscale = util.scale_factory(self.yscale,
                                        experiment,
                                        statistic=self.y_error_statistic)

        xlim = kwargs.pop("xlim", None)
        if xlim is None:
            xlim = (xscale.clip(data[xname].min() * 0.9),
                    xscale.clip(data[xname].max() * 1.1))

            if x_error_stat is not None:
                try:
                    xlim = (xscale.clip(
                        min([x[0] for x in x_error_stat]) * 0.9),
                            xscale.clip(
                                max([x[1] for x in x_error_stat]) * 1.1))
                except IndexError:
                    xlim = (xscale.clip(x_error_stat.min() * 0.9),
                            xscale.clip(x_error_stat.max() * 1.1))

        ylim = kwargs.pop("ylim", None)
        if ylim is None:
            ylim = (yscale.clip(data[yname].min() * 0.9),
                    yscale.clip(data[yname].max() * 1.1))

            if y_error_stat is not None:
                try:
                    ylim = (yscale.clip(
                        min([x[0] for x in y_error_stat]) * 0.9),
                            yscale.clip(
                                max([x[1] for x in y_error_stat]) * 1.1))
                except IndexError:
                    ylim = (yscale.clip(y_error_stat.min() * 0.9),
                            yscale.clip(y_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 x_error_stat:
            grid.map(_x_error_bars, xname, yname, x_error_name)

        if y_error_stat:
            grid.map(_y_error_bars, xname, yname, y_error_name)

        grid.map(plt.plot, xname, yname, **kwargs)

        # if we have an xfacet, make sure the y scale is the same for each
        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 have a yfacet, make sure the x scale is the same for each
        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

        # 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, _ = 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:
                grid.add_legend(title=self.huefacet)

        plt.xlabel(self.xstatistic)
        plt.ylabel(self.ystatistic)

        if unused_names and plot_name is not None:
            plt.title("{0} = {1}".format(unused_names, plot_name))
Пример #3
0
    def plot(self, experiment, plot_name=None, **kwargs):
        """Plot a bar chart"""

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

        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
        else:
            error_name = None

        if self.subset:
            try:
                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("variable not specified")

        if not self.variable in names:
            raise util.CytoflowViewError("Variable {} isn't in the statistic; "
                                         "must be one of {}".format(
                                             self.variable, names))

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

        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} isn't in the experiment".format(self.yfacet))

        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.conditions:
            raise util.CytoflowViewError(
                "Hue facet {0} isn't in the experiment".format(self.huefacet))

        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 plot_name is not None and not unused_names:
            raise util.CytoflowViewError("You specified a plot name, but all "
                                         "the facets are already used")

        data.reset_index(inplace=True)
        if unused_names:
            groupby = data.groupby(unused_names)

            if plot_name is None:
                raise util.CytoflowViewError(
                    "You must use facets {} in either the "
                    "plot variables or the plot name. "
                    "Possible plot names: {}".format(unused_names,
                                                     groupby.groups.keys()))

            if plot_name not in set(groupby.groups.keys()):
                raise util.CytoflowViewError(
                    "Plot {} not from plot_enum; must "
                    "be one of {}".format(plot_name, groupby.groups.keys()))

            data = groupby.get_group(plot_name)

        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),
                          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),
                          col_wrap=col_wrap,
                          legend_out=False,
                          sharex=sharex,
                          sharey=sharey)

        scale = util.scale_factory(self.scale,
                                   experiment,
                                   statistic=self.statistic)

        # because the bottom of a bar chart is "0", masking out bad
        # values on a log scale doesn't work.  we must clip instead.
        if self.scale == "log":
            scale.mode = "clip"

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

        map_args = [self.variable, stat.name]

        if self.huefacet:
            map_args.append(self.huefacet)

        if error_stat is not None:
            map_args.append(error_name)

        g.map(_barplot,
              *map_args,
              view=self,
              stat_name=stat.name,
              error_name=error_name,
              **kwargs)

        if sharex:
            # if are sharing axes make sure the x scale is the same for each
            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 sharey:
            # if we are sharing y axes, make sure the y scale is the same for each
            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 self.huefacet:
            labels = np.sort(data[self.huefacet].unique())
            labels = [str(x) for x in labels]
            g.add_legend(title=self.huefacet, label_order=labels)

        if self.orientation == 'horizontal':
            plt.sca(fig.get_axes()[0])
            plt.xlabel(self.statistic)
        else:
            plt.sca(fig.get_axes()[0])
            plt.ylabel(self.statistic)

        if unused_names and plot_name is not None:
            plt.title("{0} = {1}".format(unused_names, plot_name))
Пример #4
0
    def enum_plots(self, experiment):
        """
        Returns an iterator over the possible plots that this View can
        produce.  The values returned can be passed to "plot".
        """

        # TODO - all this is copied from below.  can we abstract it out somehow?

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

        if not self.variable:
            raise util.CytoflowViewError("variable not set")

        if self.variable not in experiment.conditions:
            raise util.CytoflowViewError(
                "variable {0} not in the experiment".format(self.variable))

        if not self.xstatistic:
            raise util.CytoflowViewError("X statistic not set")

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

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

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

        if not xstat.index.equals(ystat.index):
            raise util.CytoflowViewError(
                "X statistic and Y statistic must have "
                "the same indices: {}".format(xstat.index.names))

        if self.x_error_statistic[0]:
            if self.x_error_statistic not in experiment.statistics:
                raise util.CytoflowViewError(
                    "X error statistic not in experiment")
            else:
                x_error_stat = experiment.statistics[self.x_error_statistic]

            if not x_error_stat.index.equals(xstat.index):
                raise util.CytoflowViewError(
                    "X error statistic doesn't have the "
                    "same indices as the X statistic")
        else:
            x_error_stat = None

        if self.y_error_statistic[0]:
            if self.y_error_statistic not in experiment.statistics:
                raise util.CytoflowViewError(
                    "Y error statistic not in experiment")
            else:
                y_error_stat = experiment.statistics[self.y_error_statistic]

            if not y_error_stat.index.equals(ystat.index):
                raise util.CytoflowViewError(
                    "Y error statistic doesn't have the "
                    "same indices as the Y statistic")
        else:
            y_error_stat = None

        data = pd.DataFrame(index=xstat.index)

        xname = util.random_string(6)
        data[xname] = xstat

        yname = util.random_string(6)
        data[yname] = ystat

        if x_error_stat is not None:
            #x_error_data = x_error_stat.reset_index()
            x_error_name = util.random_string(6)
            data[x_error_name] = x_error_stat

        if y_error_stat is not None:
            y_error_name = util.random_string(6)
            data[y_error_name] = y_error_stat

        if y_error_stat is not None:
            y_error_data = y_error_stat.reset_index()
            y_error_name = util.random_string()
            data[y_error_name] = y_error_data[y_error_stat.name]

        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 in experiment.conditions:
            raise util.CytoflowViewError(
                "Variable {} not in experiment".format(self.variable))

        if not self.variable in data.index.names:
            raise util.CytoflowViewError(
                "Variable {} not in statistic; must be one of {}".format(
                    self.variable, data.index.names))

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

        if self.xfacet and self.xfacet not in data.index.names:
            raise util.CytoflowViewError(
                "X facet {} not in statistics; must be one of {}".format(
                    self.xfacet, data.index.names))

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

        if self.yfacet and self.yfacet not in data.index.names:
            raise util.CytoflowViewError(
                "Y facet {} not in statistics; must be one of {}".format(
                    self.yfacet, data.index.names))

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

        if self.huefacet and self.huefacet not in data.index.names:
            raise util.CytoflowViewError(
                "Hue facet {} not in statistics; must be one of {}".format(
                    self.huefacet, data.index.names))

        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")

        by = list(set(names) - set(facets))

        class plot_enum(object):
            def __init__(self, experiment, by):
                self._iter = None
                self._returned = False

                if by:
                    self._iter = experiment.data.groupby(by).__iter__()

            def __iter__(self):
                return self

            def next(self):
                if self._iter:
                    return self._iter.next()[0]
                else:
                    if self._returned:
                        raise StopIteration
                    else:
                        self._returned = True
                        return None

        return plot_enum(experiment, by)
Пример #5
0
    def enum_plots(self, experiment):
        """
        Returns an iterator over the possible plots that this View can
        produce.  The values returned can be passed to "plot".
        """

        # TODO - all this is copied from below.  can we abstract it out somehow?

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

        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
        else:
            error_name = None

        if self.subset:
            try:
                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("variable not specified")

        if not self.variable in data.index.names:
            raise util.CytoflowViewError("Variable {} isn't in the statistic; "
                                         "must be one of {}".format(
                                             self.variable, data.index.names))

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

        if self.xfacet and self.xfacet not in data.index.names:
            raise util.CytoflowViewError(
                "X facet {} is not a statistic index; "
                "must be one of {}".format(self.xfacet, data.index.names))

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

        if self.yfacet and self.yfacet not in data.index.names:
            raise util.CytoflowViewError(
                "Y facet {} is not a statistic index; "
                "must be one of {}".format(self.yfacet, data.index.names))

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

        if self.huefacet and self.huefacet not in data.index.names:
            raise util.CytoflowViewError(
                "Hue facet {} is not a statistic index; "
                "must be one of {}".format(self.huefacet, data.index.names))

        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")

        by = list(set(names) - set(facets))

        class plot_enum(object):
            def __init__(self, experiment, by):
                self._iter = None
                self._returned = False

                if by:
                    self._iter = experiment.data.groupby(by).__iter__()

            def __iter__(self):
                return self

            def next(self):
                if self._iter:
                    return self._iter.next()[0]
                else:
                    if self._returned:
                        raise StopIteration
                    else:
                        self._returned = True
                        return None

        return plot_enum(experiment, by)