def plot_variation(baseline_maps,
                   up_maps,
                   down_maps,
                   h1_name,
                   fulltitle,
                   savename,
                   outdir,
                   ftype='pdf'):
    matplotlib.rcParams['font.family'] = 'sans-serif'
    matplotlib.rcParams['mathtext.fontset'] = 'stixsans'

    gridspec_kw = dict(left=0.04, right=0.966, wspace=0.32)
    fig, axes = plt.subplots(nrows=1,
                             ncols=3,
                             gridspec_kw=gridspec_kw,
                             sharex=False,
                             sharey=False,
                             figsize=(15, 5))

    asymmetry_hist = (h1_map.hist - h0_map.hist) / np.sqrt(h0_map.hist)
    asymmetry_to_plot = Map(name='asymmetry',
                            hist=asymmetry_hist,
                            binning=h0_map.binning)

    asymmetrylabel = (
        r'$\left(N_{%s}-N_{%s}\right)'
        r'/\sqrt{N_{%s}}$' %
        (text2tex(h1_name), text2tex(h0_name), text2tex(h0_name)))

    vmax = max(np.nanmax(h0_map.hist), np.nanmax(h1_map.hist))

    h0_map.plot(fig=fig,
                ax=axes[0],
                title='Hypothesis 0: $%s$' % text2tex(h0_name),
                cmap=plt.cm.afmhot,
                vmax=vmax)

    h1_map.plot(fig=fig,
                ax=axes[1],
                title='Hypothesis 1: $%s$' % text2tex(h1_name),
                cmap=plt.cm.afmhot,
                vmax=vmax)

    asymmetry_to_plot.plot(fig=fig,
                           ax=axes[2],
                           title='Asymmetry',
                           symm=True,
                           cmap=plt.cm.seismic)

    plt.subplots_adjust(bottom=0.12, top=0.8)
    plt.suptitle(fulltitle, size='xx-large')
    if savename != '' and savename[-1] != '_':
        savename += '_'
    fname = '%s%s_%s_asymmetry.pdf' % (savename, h0_name, h1_name)
    fname = fname.replace(' ', '_')
    mkdir(outdir, warn=False)
    fig.savefig(os.path.join(outdir, fname))
    plt.close(fig.number)
Exemplo n.º 2
0
Arquivo: fit.py Projeto: terliuk/pisa
    def _compute_outputs(self, inputs=None):
        """Compute histograms for output channels."""
        logging.debug('Entering fit._compute_outputs')
        if not isinstance(inputs, Data):
            raise AssertionError('inputs is not a Data object, instead is '
                                 'type {0}'.format(type(inputs)))
        self.weight_hash = deepcopy(inputs.metadata['weight_hash'])
        logging.trace('{0} fit weight_hash = '
                      '{1}'.format(inputs.metadata['name'], self.weight_hash))
        logging.trace('{0} fit fit_hash = '
                      '{1}'.format(inputs.metadata['name'], self.fit_hash))
        self._data = inputs
        self.reweight()

        if self.output_events:
            return self._data

        outputs = []
        if self.neutrinos:
            trans_nu_data = self._data.transform_groups(
                self._output_nu_groups
            )
            for fig in trans_nu_data.iterkeys():
                outputs.append(
                    trans_nu_data.histogram(
                        kinds=fig,
                        binning=self.output_binning,
                        weights_col='pisa_weight',
                        errors=True,
                        name=str(NuFlavIntGroup(fig)),
                    )
                )

        if self.muons:
            outputs.append(
                self._data.histogram(
                    kinds='muons',
                    binning=self.output_binning,
                    weights_col='pisa_weight',
                    errors=True,
                    name='muons',
                    tex=text2tex('muons')
                )
            )

        if self.noise:
            outputs.append(
                self._data.histogram(
                    kinds='noise',
                    binning=self.output_binning,
                    weights_col='pisa_weight',
                    errors=True,
                    name='noise',
                    tex=text2tex('noise')
                )
            )

        return MapSet(maps=outputs, name=self._data.metadata['name'])
Exemplo n.º 3
0
 def plot_1d_projection(self, map, plot_axis, **kwargs):
     """plot map projected on plot_axis"""
     r_vmin = kwargs.pop('r_vmin', None)
     r_vmax = kwargs.pop('r_vmax', None)
     axis = plt.gca()
     plt_binning = map.binning[plot_axis]
     hist = self.project_1d(map, plot_axis)
     if map.tex == 'data':
         axis.errorbar(plt_binning.weighted_centers.m,
                       unp.nominal_values(hist),
                       yerr=unp.std_devs(hist),
                       fmt='o',
                       markersize='4',
                       label=tex_dollars(text2tex('data')),
                       color='k',
                       ecolor='k',
                       mec='k',
                       **kwargs)
     else:
         axis.hist(inf2finite(plt_binning.weighted_centers.m),
                   weights=unp.nominal_values(hist),
                   bins=inf2finite(plt_binning.bin_edges.m),
                   histtype='step',
                   lw=1.5,
                   label=tex_dollars(text2tex(map.tex)),
                   color=self.color,
                   **kwargs)
         axis.bar(plt_binning.bin_edges.m[:-1],
                  2 * unp.std_devs(hist),
                  bottom=unp.nominal_values(hist) - unp.std_devs(hist),
                  width=plt_binning.bin_widths.m,
                  alpha=0.25,
                  linewidth=0,
                  color=self.color,
                  **kwargs)
     axis.set_xlabel(tex_dollars(plt_binning.label))
     if self.label:
         axis.set_ylabel(tex_dollars(text2tex(self.label)))
     if plt_binning.is_log:
         axis.set_xscale('log')
     if self.log:
         axis.set_yscale('log')
     else:
         axis.set_ylim(0, np.max(unp.nominal_values(hist)) * 1.4)
     axis.set_xlim(
         inf2finite(plt_binning.bin_edges.m)[0],
         inf2finite(plt_binning.bin_edges.m)[-1])
     if self.grid:
         plt.grid(True, which="both", ls='-', alpha=0.2)
Exemplo n.º 4
0
    def plot_xsec(self, map_set, ylim=None, logx=True):
        from pisa.utils import fileio

        zero_np_element = np.array([0])
        for map in map_set:
            binning = map.binning
            if 'true_energy' in binning.names:
                energy_binning = binning.true_energy
            elif 'reco_energy' in binning.names:
                energy_binning = binning.reco_energy
            else:
                dim_idx = binning.index('energy', use_basenames=True)
                energy_binning = binning.dims[dim_idx]

            fig = plt.figure(figsize=self.size)
            fig.suptitle(map.name, y=0.95)
            ax = fig.add_subplot(111)
            ax.grid(b=True, which='major')
            ax.grid(b=True, which='minor', linestyle=':')
            plt.xlabel(tex_dollars(energy_binning.label), size=18)
            plt.ylabel(tex_dollars(text2tex(self.label)), size=18)
            if self.log:
                ax.set_yscale('log')
            if logx:
                ax.set_xscale('log')
            if ylim:
                ax.set_ylim(ylim)
            ax.set_xlim(np.min(energy_binning.bin_edges.m),
                        np.max(energy_binning.bin_edges.m))

            hist = map.hist
            array_element = np.hstack((hist, zero_np_element))
            ax.step(energy_binning.bin_edges.m, array_element, where='post')

            fileio.mkdir(self.outdir)
            fig.savefig(self.outdir + '/' + map.name + '.png',
                        bbox_inches='tight',
                        dpi=150)
Exemplo n.º 5
0
    def plot_1d_ratio(self, maps, plot_axis, **kwargs):
        """make a ratio plot for a 1d projection"""
        r_vmin = kwargs.pop('r_vmin', None)
        r_vmax = kwargs.pop('r_vmax', None)
        axis = plt.gca()
        map0 = maps[0]
        plt_binning = map0.binning[plot_axis]
        hist = self.project_1d(map0, plot_axis)
        hist0 = unp.nominal_values(hist)
        # TODO: should this be used somewhere?
        err0 = unp.std_devs(hist)

        axis.set_xlim(
            inf2finite(plt_binning.bin_edges.m)[0],
            inf2finite(plt_binning.bin_edges.m)[-1])
        maximum = 1.0
        minimum = 1.0
        self.reset_colors()
        for map in maps:
            self.next_color()
            hist = self.project_1d(map, plot_axis)
            hist1 = unp.nominal_values(hist)
            err1 = unp.std_devs(hist)
            ratio = np.zeros_like(hist0)
            ratio_error = np.zeros_like(hist0)
            for i, hist0i in enumerate(hist0):
                if hist1[i] == 0 and hist0i == 0:
                    ratio[i] = 1.
                    ratio_error[i] = 1.
                elif hist1[i] != 0 and hist0i == 0:
                    logging.warning('deviding non 0 by 0 for ratio')
                    ratio[i] = 0.
                    ratio_error[i] = 1.
                else:
                    ratio[i] = hist1[i] / hist0i
                    ratio_error[i] = err1[i] / hist0i
                    minimum = min(minimum, ratio[i])
                    maximum = max(maximum, ratio[i])

            if map.tex == 'data':
                axis.errorbar(plt_binning.weighted_centers.m,
                              ratio,
                              yerr=ratio_error,
                              fmt='o',
                              markersize='4',
                              label=tex_dollars(text2tex('data')),
                              color='k',
                              ecolor='k',
                              mec='k')
            else:
                _ = axis.hist(inf2finite(plt_binning.weighted_centers.m),
                              weights=ratio,
                              bins=inf2finite(plt_binning.bin_edges.m),
                              histtype='step',
                              lw=1.5,
                              label=tex_dollars(text2tex(map.tex)),
                              color=self.color)

                axis.bar(plt_binning.bin_edges.m[:-1],
                         2 * ratio_error,
                         bottom=ratio - ratio_error,
                         width=plt_binning.bin_widths.m,
                         alpha=0.25,
                         linewidth=0,
                         color=self.color)

        if self.grid:
            plt.grid(True, which="both", ls='-', alpha=0.2)
        self.fig.subplots_adjust(hspace=0)
        axis.set_ylabel(tex_dollars(text2tex('ratio')))
        axis.set_xlabel(tex_dollars(plt_binning.label))
        # Calculate nice scale:
        if r_vmin is not None and r_vmax is not None:
            axis.set_ylim(1 - r_vmin, 1 + r_vmax)
        else:
            off = max(maximum - 1, 1 - minimum)
            axis.set_ylim(1 - 1.2 * off, 1 + 1.2 * off)
Exemplo n.º 6
0
    def plot_2d_map(self, map, cmap=None, **kwargs):
        """plot map or transform on current axis in 2d"""
        vmin = kwargs.pop('vmin', None)
        vmax = kwargs.pop('vmax', None)
        axis = plt.gca()

        if isinstance(map, BinnedTensorTransform):
            binning = map.input_binning
        elif isinstance(map, Map):
            binning = map.binning
        else:
            raise TypeError('Unhandled `map` type %s' % map.__class__.__name__)

        dims = binning.dims
        bin_centers = binning.weighted_centers
        bin_edges = binning.bin_edges
        linlog = all([(d.is_log or d.is_lin) for d in binning])

        zmap = map.nominal_values
        if self.log:
            zmap = np.log10(zmap)

        if self.symmetric:
            vmax = np.max(np.abs(np.ma.masked_invalid(zmap)))
            vmin = -vmax
            if cmap is None:
                cmap = CMAP_DIV
        else:
            if vmax is None:
                vmax = np.max(zmap[np.isfinite(zmap)])
            if vmin is None:
                vmin = np.min(zmap[np.isfinite(zmap)])
            if cmap is None:
                cmap = CMAP_SEQ
        extent = [
            np.min(bin_edges[0].m),
            np.max(bin_edges[0].m),
            np.min(bin_edges[1].m),
            np.max(bin_edges[1].m)
        ]

        # Only lin or log can be handled by imshow...otherise use colormesh

        # TODO: fix imshow for log-scaled energy vs. lin-scaled coszen, or
        # remove this code altogether
        if False:  #linlog:
            # Needs to be transposed for imshow
            _ = plt.imshow(zmap.T,
                           origin='lower',
                           interpolation='nearest',
                           extent=extent,
                           aspect='auto',
                           cmap=cmap,
                           vmin=vmin,
                           vmax=vmax,
                           **kwargs)
        else:
            x, y = np.meshgrid(bin_edges[0], bin_edges[1])
            pcol = plt.pcolormesh(x,
                                  y,
                                  np.ma.masked_invalid(zmap.T),
                                  vmin=vmin,
                                  vmax=vmax,
                                  cmap=cmap,
                                  linewidth=0,
                                  rasterized=True,
                                  **kwargs)
            pcol.set_edgecolor('face')

        if self.annotate:
            for i in range(len(bin_centers[0])):
                for j in range(len(bin_centers[1])):
                    bin_x = bin_centers[0][i].m
                    bin_y = bin_centers[1][j].m
                    plt.annotate('%.1f' % (zmap[i, j]),
                                 xy=(bin_x, bin_y),
                                 xycoords=('data', 'data'),
                                 xytext=(bin_x, bin_y),
                                 textcoords='data',
                                 va='top',
                                 ha='center',
                                 size=7)

        axis.set_xlabel(tex_dollars(dims[0].label))
        axis.set_ylabel(tex_dollars(dims[1].label))
        axis.set_xlim(extent[0:2])
        axis.set_ylim(extent[2:4])

        # TODO: use log2 scale & integer tick labels if too few major gridlines
        # result from default log10 scale
        if dims[0].is_log:
            axis.set_xscale('log')
        if dims[1].is_log:
            axis.set_yscale('log')

        if self.log:
            col_bar = plt.colorbar(format=r'$10^{%.1f}$')
        else:
            col_bar = plt.colorbar()

        if self.label:
            col_bar.set_label(tex_dollars(text2tex(self.label)))
Exemplo n.º 7
0
    def histogram(self,
                  kinds,
                  binning,
                  binning_cols=None,
                  weights_col=None,
                  errors=False,
                  name=None,
                  tex=None,
                  **kwargs):
        """Histogram the events of all `kinds` specified, with `binning` and
        optionally applying `weights`.

        Parameters
        ----------
        kinds : string, sequence of NuFlavInt, or NuFlavIntGroup
        binning : OneDimBinning, MultiDimBinning or sequence of arrays
            (one array per binning dimension)
        binning_cols : string or sequence of strings
            Bin only these dimensions, ignoring other dimensions in `binning`
        weights_col : None or string
            Column to use for weighting the events
        errors : bool
            Whether to attach errors to the resulting Map
        name : None or string
            Name to give to resulting Map. If None, a default is derived from
            `kinds` and `weights_col`.
        tex : None or string
            TeX label to give to the resulting Map. If None, default is
            dereived from the `name` specified or the derived default.
        **kwargs : Keyword args passed to Map object

        Returns
        -------
        Map : numpy ndarray with as many dimensions as specified by `binning`
            argument

        """
        # TODO: make able to take integer for `binning` and--in combination
        # with units in the Data columns--generate an appropriate
        # MultiDimBinning object, attach this and return the package as a Map.

        if isinstance(kinds, basestring):
            kinds = [kinds]
        if 'muons' not in kinds and 'noise' not in kinds:
            kinds = self._parse_flavint_groups(kinds)
        kinds = kinds[0]

        if isinstance(binning_cols, basestring):
            binning_cols = [binning_cols]
        assert weights_col is None or isinstance(weights_col, basestring)

        # TODO: units of columns, and convert bin edges if necessary
        if isinstance(binning, OneDimBinning):
            binning = MultiDimBinning([binning])
        elif isinstance(binning, MultiDimBinning):
            pass
        elif (isinstance(binning, Iterable)
              and not isinstance(binning, Sequence)):
            binning = list(binning)
        elif isinstance(binning, Sequence):
            pass
        else:
            raise TypeError('Unhandled type %s for `binning`.' % type(binning))

        if isinstance(binning, Sequence):
            raise NotImplementedError(
                'Simle sequences not handled at this time. Please specify a'
                ' OneDimBinning or MultiDimBinning object for `binning`.')
            # assert len(binning_cols) == len(binning)
            # bin_edges = binning

        # TODO: units support for Data will mean we can do `m_as(...)` here!
        bin_edges = [edges.magnitude for edges in binning.bin_edges]
        if binning_cols is None:
            binning_cols = binning.names
        else:
            assert set(binning_cols).issubset(set(binning.names))

        # Extract the columns' data into a list of array(s) for histogramming
        sample = [self[kinds][colname] for colname in binning_cols]
        err_weights = None
        hist_weights = None
        if weights_col is not None:
            hist_weights = self[kinds][weights_col]
            if errors:
                err_weights = np.square(hist_weights)

        hist, edges = np.histogramdd(sample=sample,
                                     weights=hist_weights,
                                     bins=bin_edges)
        if errors:
            sumw2, edges = np.histogramdd(sample=sample,
                                          weights=err_weights,
                                          bins=bin_edges)
            hist = unp.uarray(hist, np.sqrt(sumw2))

        if name is None:
            if tex is None:
                try:
                    tex = kinds.tex
                # TODO: specify specific exception(s)
                except:
                    tex = r'{0}'.format(kinds)
                if weights_col is not None:
                    tex += r', \; {\rm weights} =' + text2tex(weights_col)

            name = str(kinds)
            if weights_col is not None:
                name += ', weights=' + weights_col

        if tex is None:
            tex = text2tex(name)

        return Map(name=name, hist=hist, binning=binning, tex=tex, **kwargs)