Пример #1
0
    def spreadPlot(self, xdim=None, fixed=None, sampleKwargs=None,
                   meanKwargs=None, ax=None, xlabel=None,
                   ylabel=None, logx=False, logy=False, loglog=False,
                   legend=True):
        """
        Plot the mean tally value against all sampled detector data.

        Parameters
        ----------
        xdim: str
            Bin index to place on the x-axis
        fixed: None or dict
            Dictionary controlling the reduction in data down to one dimension
        sampleKwargs : dict, optional
            Additional matplotlib-acceptable arguments to be passed into the
            plot when plotting data from unique runs, e.g.
            ``{"c": k, "alpha": 0.5}``.
        meanKwargs : dict, optional
            Additional matplotlib-acceptable argumentst to be used when
            plotting the mean value, e.g. ``{"c": "b", "marker": "o"}``
        {ax}
        {xlabel}
        {ylabel}
        {logx}
        {logy}
        {loglog}
        {legend}

        Returns
        -------
        {rax}

        """
        if self.allTallies is None:
            raise AttributeError(
                "allTallies is None, cannot plot all tally data")

        samplerData = self.slice(fixed, 'tallies')
        slices = self._getSlices(fixed)
        if len(samplerData.shape) != 1:
            raise SerpentToolsException(
                'Data must be constrained to 1D, not {}'.format(
                    samplerData.shape))
        xdata, autoX = self._getPlotXData(xdim, samplerData)
        xlabel = xlabel or autoX

        if sampleKwargs is None:
            sampleKwargs = {"c": "k", "alpha": 0.5, "marker": ""}
        if meanKwargs is None:
            meanKwargs = {"c": "#0173b2", "marker": "o"}

        ax = ax or pyplot.gca()
        for data in self.allTallies:
            ax.plot(xdata, data[slices], **sampleKwargs)

        ax.plot(xdata, samplerData, label='Mean value', **meanKwargs)
        formatPlot(ax, logx=logx, logy=logy, loglog=loglog, xlabel=xlabel,
                   ylabel=ylabel, legend=legend)
        return ax
Пример #2
0
 def test_formatPlot(self):
     """Test the capabilities of the formatPlot function"""
     ax = self.buildPlot()
     newX = 'new x label'
     newY = 'new y label'
     title = 'plot title'
     formatPlot(ax, xlabel=newX, ylabel=newY, loglog=True, title=title)
     plotAttrTest(self,
                  ax,
                  xlabel=newX,
                  ylabel=newY,
                  xscale='log',
                  yscale='log',
                  title=title)
Пример #3
0
    def spreadPlot(self,
                   xUnits,
                   yUnits,
                   isotope=None,
                   zai=None,
                   sampleKwargs=None,
                   meanKwargs=None,
                   timePoints=None,
                   ax=None,
                   xlabel=None,
                   ylabel=None,
                   logx=False,
                   logy=False,
                   loglog=False,
                   legend=True):
        """
        Plot the mean quantity and data from all sampled files.

        Parameters
        ----------
        xUnits : str
            name of x value to obtain, e.g. ``'days'``, ``'burnup'``
        yUnits : str
            name of y value to return, e.g. ``'adens'``, ``'burnup'``
        isotope : str, optional
            Plot data for this isotope
        zai : int, optional
            Plot data for this isotope. Not allowed if ``isotope`` given.
        sampleKwargs : dict, optional
            Additional matplotlib-acceptable arguments to be passed into the
            plot when plotting data from unique runs, e.g.
            ``{"c": k, "alpha": 0.5}``.
        meanKwargs : dict, optional
            Additional matplotlib-acceptable argumentst to be used when
            plotting the mean value, e.g. ``{"c": "b", "marker": "o"}``
        timePoints : list or None
            If given, select the time points according to those
            specified here. Otherwise, select all points
        {ax}
        {xlabel}
        {ylabel}
        {logx}
        {logy}
        {loglog}
        {legend}

        Returns
        -------
        {rax}

        """
        if not self.allData:
            raise SamplerError("Data from all sampled files has been freed "
                               "and cannot be used in this plot method")
        if isotope is not None and zai is not None:
            raise ValueError("Please specify isotope name or zai, not both")
        elif isotope is None and zai is None:
            raise ValueError("Isotope name or zai needed")

        if sampleKwargs is None:
            sampleKwargs = {"c": "k", "alpha": 0.5, "marker": ""}
        if meanKwargs is None:
            meanKwargs = {"c": "#0173b2", "marker": "o"}

        ax = ax or pyplot.gca()
        if xUnits not in ('days', 'burnup'):
            raise KeyError("Plot method only uses x-axis data from <days> "
                           "and <burnup>, not {}".format(xUnits))
        xVals = timePoints if timePoints is not None else (
            self.days if xUnits == 'days' else self.burnup)
        if isotope is not None:
            rows = self._getRowIndices("names", [isotope])
        else:
            rows = self._getRowIndices("zai", [zai])
        cols = self._getColIndices(xUnits, timePoints)
        primaryData = self._slice(self.data[yUnits], rows, cols)[0]

        for data in self.allData[yUnits][:self._index]:
            plotData = self._slice(data, rows, cols)[0]
            ax.plot(xVals, plotData, **sampleKwargs)

        ax.plot(xVals, primaryData, label='Mean value', **meanKwargs)

        ax = sigmaLabel(ax, xlabel or DEPLETION_PLOT_LABELS[xUnits], ylabel
                        or DEPLETION_PLOT_LABELS[yUnits])

        formatPlot(ax, legend=legend, logx=logx, logy=logy, loglog=loglog)
        return ax
Пример #4
0
    def plot(self,
             xUnits,
             yUnits,
             timePoints=None,
             names=None,
             ax=None,
             sigma=3,
             xlabel=None,
             ylabel=None,
             logx=False,
             logy=False,
             loglog=False,
             legend=None,
             ncol=1,
             labelFmt=None,
             **kwargs):
        """
        Plot the average of some data vs. time for some or all isotopes.

        .. note::

            ``kwargs`` will be passed to the errorbar plot for all
            isotopes. If ``c='r'`` is passed, to make a plot red, then
            data for all isotopes plotted will be red and potentially
            very confusing.

        Parameters
        ----------
        xUnits: str
            name of x value to obtain, e.g. ``'days'``, ``'burnup'``
        yUnits: str
            name of y value to return, e.g. ``'adens'``, ``'burnup'``
        timePoints: list or None
            If given, select the time points according to those
            specified here. Otherwise, select all points
        names: list or None
            If given, return y values corresponding to these isotope
            names. Otherwise, return values for all isotopes.
        {ax}
        {sigma}
        {xlabel}
        {ylabel}
        {logx}
        {logy}
        {loglog}
        {legend}
        {ncol}
        {matLabelFmt}
        {kwargs} :py:func:`matplotlib.pyplot.errorbar`

        Returns
        -------
        {rax}

        See Also
        --------
        * :meth:`~serpentTools.objects.materials.
          DepletedMaterialBase.getValues`
        * :func:`matplotlib.pyplot.errorbar`

        """
        if sigma and yUnits not in self.uncertainties:
            raise KeyError("Uncertainties for {} not stored".format(yUnits))
        if xUnits not in ('days', 'burnup'):
            raise KeyError("Plot method only uses x-axis data from <days> "
                           "and <burnup>, not {}".format(xUnits))
        xVals = timePoints if timePoints is not None else (
            self.days if xUnits == 'days' else self.burnup)
        sigma = int(fabs(sigma))
        colIndices = self._getColIndices(xUnits, timePoints)
        rowIndices = self._getRowIndices(names)
        yVals = self._slice(self.data[yUnits], rowIndices, colIndices)
        yUncs = self._slice(self.uncertainties[yUnits], rowIndices, colIndices)
        if xUnits in self.uncertainties and sigma:
            xUncs = (sigma *
                     self._slice(self.uncertainties[xUnits], None, colIndices))
        else:
            xUncs = zeros_like(xVals)
        ax = ax or pyplot.gca()
        labels = self._formatLabel(labelFmt, names)
        yVals = yVals.copy(order='F')
        yUncs = yUncs.copy(order='F') * sigma

        for row in range(yVals.shape[0]):
            ax.errorbar(xVals,
                        yVals[row],
                        yerr=yUncs[row],
                        xerr=xUncs,
                        label=labels[row],
                        **kwargs)

        ax = sigmaLabel(ax, xlabel or DEPLETION_PLOT_LABELS[xUnits], ylabel
                        or DEPLETION_PLOT_LABELS[yUnits], sigma)
        formatPlot(ax,
                   legend=legend,
                   ncol=ncol,
                   loglog=loglog,
                   logx=logx,
                   logy=logy)
        return ax
Пример #5
0
    def plotDensity(self,
                    what='both',
                    ax=None,
                    logx=False,
                    logy=True,
                    loglog=None,
                    legend=None,
                    title=None,
                    labels=None,
                    markers=None,
                    xlabel=None,
                    ylabel=None,
                    ylim=None):
        """
        Plot initial, final, or both number densities.

        Parameters
        ----------
        what: str
            Concentrations to plot.

                1. ``'both'``: plot initial and final
                2. ``'n0'`` or ``'initial'``: only initial
                3. ``'n1'`` or ``'final'``: only final
        {ax}
        {logx}
        {logy}
        {loglog}
        {legend}
        {title}
        labels: None or str or list of strings
            Labels to apply to concentration plot(s). If given, must have
            length equal to the number of quantities plotted, e.g.
            plotting both concentrations and passing a single string
            for ``labels`` is not allowed
        markers: None or str or list of strings
            Markers to apply to each plot. Must be a valid
            ``matplotlib`` marker such as ``'o'``, ``'>'``, etc.
            If given, the number of markers given must equal the
            number of quantities to plot.
        {xlabel}
        {ylabel}
        ylim: None or float or list of floats
            If a single value is given, set the lower y-axis limit to
            this value. If two values are given, set the upper and
            lower y-axis limits to this value

        Returns
        -------
        {rax}
        """
        from matplotlib.pyplot import gca
        ax = gca() if ax is None else ax
        if what == 'both':
            plotAttrs = [self.n0, self.n1]
        elif what in ['n0', 'initial']:
            plotAttrs = self.n0,
        elif what in ['n1', 'final']:
            plotAttrs = self.n1,
        else:
            raise ValueError(
                "Value of {} not understood. Please pass one of {}".format(
                    what, ' '.join(DENS_PLOT_WHAT_VALS)))

        if isinstance(labels, str):
            labels = labels,
        elif labels is None:
            if len(plotAttrs) == 2:
                labels = ('Initial', 'Final')
            else:
                labels = (None, )
        if len(labels) != len(plotAttrs):
            raise ValueError(
                "Number of labels {} not equal to number of quantities "
                "to plot {}".format(len(labels), len(plotAttrs)))

        if isinstance(markers, str):
            markers = markers,
        elif markers is None:
            markers = ['x'] if len(plotAttrs) == 1 else ['o', 'x']

        if len(markers) != len(plotAttrs):
            raise ValueError(
                "Number of markers {} not equal to number of quantities "
                "to plot {}".format(len(markers), len(plotAttrs)))

        for qty, label, marker in zip(plotAttrs, labels, markers):
            ax.plot(self.zai, qty, 'o', marker=marker, label=label)

        if ylim is not None:
            ax.set_ylim(ylim)

        ylabel = r"Atomic Density $[\#/b-cm]$" if ylabel is None else ylabel

        formatPlot(
            ax,
            legend=legend,
            title=title,
            logx=logx,
            logy=logy,
            loglog=loglog,
            xlabel="Isotope ZAI" if xlabel is None else xlabel,
            ylabel=ylabel,
        )
        return ax
Пример #6
0
    def plot(self, xUnits, yUnits=None, timePoints=None, names=None, zai=None,
             ax=None, legend=None, xlabel=None, ylabel=None, logx=False,
             logy=False, loglog=False, labelFmt=None, ncol=1, title=None,
             **kwargs):
        """
        Plot some data as a function of time for some or all isotopes.

        .. note::

            ``kwargs`` will be passed to the plot for all isotopes.
            If ``c='r'`` is passed, to make a plot red, then data for
            all isotopes plotted will be red and potentially very confusing.

        Parameters
        ----------
        xUnits: str
            name of x value to obtain, e.g. ``'days'``, ``'burnup'``
            If ``xUnits`` is given and ``yUnits`` is ``None``, then
            the plotted data will be ``xUnits`` against ``'days'``
        yUnits: str
            name of y value to return, e.g. ``'adens'``, ``'burnup'``
        timePoints: list or None
            If given, select the time points according to those
            specified here. Otherwise, select all points

            .. deprecated:: 0.7.0
               Will plot against all time points

        names: str or list or None
            If given, plot  values corresponding to these isotope
            names. Otherwise, plot values for all isotopes.
        zai: int or list or None
            If given, plot values corresponding to these
            isotope ``ZZAAAI`` values. Otherwise, plot for all isotopes

            .. versionadded:: 0.5.1

        {ax}
        {legend}
        {xlabel} Otherwise, use ``xUnits``
        {ylabel} Otherwise, use ``yUnits``
        {logx}
        {logy}
        {loglog}
        {matLabelFmt}
        {ncol}
        {title}

        {kwargs} :py:func:`matplotlib.pyplot.plot`

        Returns
        -------
        {rax}

        See Also
        --------
        * :py:func:`~serpentTools.objects.materials.DepletedMaterial.getValues`
        * :py:func:`matplotlib.pyplot.plot`
        * :py:meth:`str.format` - used for formatting labels

        Raises
        ------
        KeyError
            If x axis units are not ``'days'`` nor ``'burnup'``
        TypeError
            If both ``names`` and ``zai`` are given
        """
        if yUnits is None:
            yUnits = xUnits
            xUnits = 'days'

        if xUnits not in ('days', 'burnup'):
            raise KeyError("Plot method only uses x-axis data from <days> "
                           "and <burnup>, not {}".format(xUnits))

        if timePoints is not None:
            deprecateTimepointsWarning()
            xVals = timePoints
        else:
            xVals = self.days if xUnits == 'days' else self.burnup

        if names is None and zai is None:
            names = self.names
            zai = self.zai if names is None else None
        else:
            if isinstance(names, str):
                names = [names, ]
            if isinstance(zai, (int, str)):
                zai = [zai, ]
        yVals = self.getValues(xUnits, yUnits, xVals, names, zai)
        ax = ax or pyplot.gca()
        labels = self._formatLabel(labelFmt, names, zai)
        for row in range(yVals.shape[0]):
            ax.plot(xVals, yVals[row], label=labels[row], **kwargs)

        ax = formatPlot(ax, loglog=loglog, logx=logx, logy=logy, ncol=ncol,
                        xlabel=xlabel or DEPLETION_PLOT_LABELS[xUnits],
                        ylabel=ylabel or DEPLETION_PLOT_LABELS[yUnits],
                        title=title, legend=legend)
        return ax
Пример #7
0
    def plot(self,
             qtys,
             limitE=True,
             ax=None,
             logx=None,
             logy=None,
             loglog=None,
             sigma=3,
             xlabel=None,
             ylabel=None,
             legend=None,
             ncol=1,
             steps=True,
             labelFmt=None,
             labels=None):
        """
        Plot homogenized data as a function of energy.

        Parameters
        ----------
        qtys: str or iterable
            Plot this or these value against energy.
        limitE: bool
            If given, set the maximum energy value to be
            that of the micro group structure. By default,
            SERPENT macro group structures can reach
            1E37, leading for a very large tail on the plots.
        {ax}
        {labels}
        {logx}
        {logy}
        {loglog}
        {sigma}
        {xlabel}
        {ylabel}
        {legend}
        {ncol}
        steps: bool
            If ``True``, plot values as constant within
            energy bins.
        {univLabelFmt}

        Returns
        -------
        {rax}

        """
        qtys = [
            qtys,
        ] if isinstance(qtys, str) else qtys
        ax = ax or pyplot.gca()
        onlyXS = True
        sigma = max(0, int(sigma))
        drawstyle = 'steps-post' if steps else None
        limitE = limitE and (self.groups is not None
                             and self.microGroups is not None)
        macroBins = self.numGroups + 1 if self.numGroups is not None else None
        microBins = (self.numMicroGroups +
                     1 if self.numMicroGroups is not None else None)
        labelFmt = labelFmt or "{k}"
        if limitE:
            eneCap = min(self.microGroups.max(), self.groups.max())

        if isinstance(labels, str):
            labels = [
                labels,
            ]
        if labels is None:
            labels = [
                labelFmt,
            ] * len(qtys)
        else:
            if len(labels) != len(qtys):
                raise IndexError(
                    "Need equal number of labels for plot quantities. "
                    "Given {} expected: {}".format(len(labels), len(qtys)))

        for key, label in zip(qtys, labels):
            yVals = self.__getitem__(key)
            if len(yVals.shape) != 1 and 1 not in yVals.shape:
                warning("Data for {} is not 1D. Will not plot".format(key))
                continue
            uncD = self._lookup(key, True)
            yUncs = uncD.get(key, zeros_like(yVals))

            if 'Flx' in key:
                onlyXS = False
            yVals = hstack((yVals, yVals[-1]))
            nbins = yVals.size
            yUncs = hstack((yUncs, yUncs[-1])) * yVals * sigma

            xdata, foundE = self.__getEGrid(nbins, macroBins, microBins)

            if limitE and foundE:
                xdata = xdata.copy()
                xdata[xdata.argmax()] = eneCap

            label = self.__formatLabel(label, key)

            ax.errorbar(xdata,
                        yVals,
                        yerr=yUncs,
                        label=label,
                        drawstyle=drawstyle)

        if ylabel is None:
            ylabel, yUnits = (("Cross Section", "[cm$^{-1}$]") if onlyXS else
                              ("Group Constant", ""))
            sigStr = r" $\pm{}\sigma$".format(sigma) if sigma else ""
            ylabel = ' '.join((ylabel, sigStr, yUnits))

        if xlabel is None:
            xlabel = "Energy [MeV]" if foundE else "Energy Group"

        if legend is None:
            legend = len(qtys) > 1
        if loglog is not None:
            logx = logy = loglog
        else:
            if logx is None:
                logx = foundE
            if logy is None:
                logy = inferAxScale(ax, 'y')

        formatPlot(ax,
                   logx=logx,
                   logy=logy,
                   legendcols=ncol,
                   legend=legend,
                   xlabel=xlabel or "Energy [MeV]",
                   ylabel=ylabel)
        return ax
Пример #8
0
    def plot(self, xUnits, yUnits=None, timePoints=None, names=None, zai=None,
             materials=None, ax=None, legend=None, logx=False, logy=False,
             loglog=False, labelFmt=None, xlabel=None, ylabel=None, ncol=1,
             **kwargs):
        """
        Plot properties for all materials in this file together.

        Parameters
        ----------
        xUnits: str
            If ``xUnits`` is given and ``yUnits`` is ``None``, then
            the plotted data will be ``xUnits`` against ``'days'``
            name of x value to obtain, e.g. ``'days'``, ``'burnup'``
        yUnits: str
            name of y value to return, e.g. ``'adens'``, ``'ingTox'``
        timePoints: list or None
            If given, select the time points according to those
            specified here. Otherwise, select all points

            .. deprecated:: 0.7.0
               Will plot against all time points

        names: str or list or None
            If given, plot  values corresponding to these isotope
            names. Otherwise, plot values for all isotopes.
        zai: int or list or None
            If given, plot values corresponding to these
            isotope ``ZZAAAI`` values. Otherwise, plot for all isotopes

            .. versionadded:: 0.5.1

        materials: None or list
            Selection of materials from ``self.materials`` to plot.
            If None, plot all materials, potentially including ``tot``
        {ax}
        {legend}
        {xlabel} Otherwise, use ``xUnits``
        {ylabel} Otherwise, use ``yUnits``
        {logx}
        {logy}
        {loglog}
        {matLabelFmt}
        {ncol}
        {kwargs} :py:func:`matplotlib.pyplot.plot`

        Returns
        -------
        {rax}

        See Also
        --------
        * :py:func:`~serpentTools.objects.materials.DepletedMaterial.getValues`
        * :py:func:`matplotlib.pyplot.plot`
        * :py:meth:`str.format` - used for formatting labels
        * :py:func:`~serpentTools.objects.materials.DepletedMaterial.plot`

        Raises
        ------
        KeyError
            If x axis units are not ``'days'`` nor ``'burnup'``
        SerpentToolsException
            If the materials dictionary does not contain any items
        """
        if yUnits is None:
            yUnits = xUnits
            xUnits = 'days'

        if not self.materials:
            raise SerpentToolsException("Material dictionary is empty")

        if xUnits not in ('days', 'burnup'):
            raise KeyError("Plot method only uses x-axis data from <days> and "
                           "<burnup>, not {}".format(xUnits))
        missing = set()
        ax = ax or pyplot.gca()
        materials = materials or self.materials.keys()
        labelFmt = labelFmt or '{mat} {iso}'
        for mat in materials:
            if mat not in self.materials:
                missing.add(mat)
                continue

            ax = self.materials[mat].plot(
                xUnits, yUnits, timePoints, names,
                zai, ax, legend=False, xlabel=xlabel, ylabel=ylabel,
                logx=False, logy=False, loglog=False, labelFmt=labelFmt,
                **kwargs)
        if missing:
            warning("The following materials were not found in materials "
                    "dictionary: {}".format(', '.join(missing)))
        formatPlot(ax, legend=legend, legendcols=ncol, logx=logx, logy=logy,
                   loglog=loglog,
                   xlabel=xlabel or DEPLETION_PLOT_LABELS[xUnits],
                   ylabel=ylabel or DEPLETION_PLOT_LABELS[yUnits],
                   )

        return ax
Пример #9
0
 def plot(self, **kwargs):
     """Emulate plotting."""
     self.ax = formatPlot(self.ax, **kwargs)
Пример #10
0
    def meshPlot(self,
                 xdim='x',
                 ydim='y',
                 what='tallies',
                 fixed=None,
                 ax=None,
                 cmap=None,
                 cbarLabel=None,
                 logColor=False,
                 xlabel=None,
                 ylabel=None,
                 logx=False,
                 logy=False,
                 loglog=False,
                 title=None,
                 **kwargs):
        """
        Plot tally data as a function of two bin types on a cartesian mesh.

        Parameters
        ----------
        xdim: str
            Primary dimension - will correspond to x-axis on plot
        ydim: str
            Secondary dimension - will correspond to y-axis on plot
        what: {'tallies', 'errors', 'scores'}
            Color meshes from tally data, uncertainties, or scores
        fixed: None or dict
            Dictionary controlling the reduction in data down to one dimension
        {ax}
        {cmap}
        logColor: bool
            If true, apply a logarithmic coloring to the data positive
            data
        {xlabel}
        {ylabel}
        {logx}
        {logy}
        {loglog}
        {title}
        cbarLabel: str
            Label to apply to colorbar. If not given, infer from ``what``
        {kwargs} :py:func:`~matplotlib.pyplot.pcolormesh`

        Returns
        -------
        {rax}

        Raises
        ------
        :class:`~serpentTools.SerpentToolsException`
            If data to be plotted, with or without constraints, is not 1D
        KeyError
            If the data set by ``what`` not in the allowed selection
        ValueError
            If the data contains negative quantities and ``logColor`` is
            ``True``

        See Also
        --------
        * :meth:`slice`
        * :func:`matplotlib.pyplot.pcolormesh`
        """
        if fixed:
            for qty, name in zip((xdim, ydim), ('x', 'y')):
                if qty in fixed:
                    raise SerpentToolsException(
                        'Requested {} dimension {} is one of the axis to be '
                        'constrained. '.format(name, qty))

        data = self.slice(fixed, what)
        dShape = data.shape
        if len(dShape) != 2:
            raise SerpentToolsException(
                'Data must be 2D for mesh plot, currently is {}.\nConstraints:'
                '{}'.format(dShape, fixed))
        xgrid = self._getGrid(xdim)
        ygrid = self._getGrid(ydim)
        if data.shape != (ygrid.size - 1, xgrid.size - 1):
            data = data.T
        if cbarLabel is None:
            cbarLabel = self._CBAR_LABELS[what]
        ax = cartMeshPlot(data,
                          xgrid,
                          ygrid,
                          ax,
                          cmap,
                          logColor,
                          cbarLabel=cbarLabel,
                          **kwargs)
        if xlabel is None:
            xlabel = DETECTOR_PLOT_LABELS.get(xdim, xdim)
        if ylabel is None:
            ylabel = DETECTOR_PLOT_LABELS.get(ydim, ydim)
        ax = formatPlot(ax,
                        loglog=loglog,
                        logx=logx,
                        logy=logy,
                        xlabel=xlabel,
                        ylabel=ylabel,
                        title=title)
        return ax
Пример #11
0
    def plot(self,
             xdim=None,
             what='tallies',
             sigma=None,
             fixed=None,
             ax=None,
             xlabel=None,
             ylabel=None,
             steps=False,
             labels=None,
             logx=False,
             logy=False,
             loglog=False,
             legend=None,
             ncol=1,
             title=None,
             **kwargs):
        """
        Simple plot routine for 1- or 2-D data

        Parameters
        ----------
        xdim: None or str
            If not None, use the array under this key in ``indexes`` as
            the x axis
        what: {'tallies', 'errors', 'scores'}
            Primary data to plot
        {sigma}
        fixed: None or dict
            Dictionary controlling the reduction in data down to one dimension
        {ax}
        {xlabel} If ``xdim`` is given and ``xlabel`` is ``None``, then
            ``xdim`` will be applied to the x-axis.
        {ylabel}
        steps: bool
            If true, plot the data as constant inside the respective bins.
            Sets ``drawstyle`` to be ``steps-post`` unless ``drawstyle``
            given in ``kwargs``
        {labels}
        {logx}
        {logy}
        {loglog}
        {legend}
        {ncol}
        {title}
        {kwargs} :py:func:`~matplotlib.pyplot.plot` or
            :py:func:`~matplotlib.pyplot.errorbar` function.

        Returns
        -------
        {rax}

        Raises
        ------
        :class:`~serpentTools.SerpentToolsException`
            If data contains more than 2 dimensions

        See Also
        --------
        * :meth:`slice`
        * :meth:`spectrumPlot`
          better options for plotting energy spectra
        """

        data = self.slice(fixed, what)
        if len(data.shape) > 2:
            raise SerpentToolsException(
                'Data must be constrained to 1- or 2-D, not {}'.format(
                    data.shape))
        elif len(data.shape) == 1:
            data = data.reshape(data.size, 1)

        if sigma:
            if what != 'errors':
                yerr = (self.slice(fixed, 'errors').reshape(data.shape) *
                        data * sigma)
            else:
                warning(
                    'Will not plot error bars on the error plot. Data to be '
                    'plotted: {}.  Sigma: {}'.format(what, sigma))
                yerr = None
        else:
            yerr = None

        xdata, autoX = self._getPlotXData(xdim, data)
        xlabel = xlabel or autoX
        ylabel = ylabel or "Tally data"
        ax = ax or gca()

        if steps:
            if 'drawstyle' in kwargs:
                debug(
                    'Defaulting to drawstyle specified in kwargs as {}'.format(
                        kwargs['drawstyle']))
            else:
                kwargs['drawstyle'] = 'steps-post'
        ax = plot(xdata, data, ax, labels, yerr, **kwargs)

        if legend is None and labels:
            legend = True

        ax = formatPlot(ax,
                        loglog=loglog,
                        logx=logx,
                        logy=logy,
                        ncol=ncol,
                        xlabel=xlabel,
                        ylabel=ylabel,
                        legend=legend,
                        title=title)
        return ax
Пример #12
0
    def spectrumPlot(self,
                     fixed=None,
                     ax=None,
                     normalize=True,
                     xlabel=None,
                     ylabel=None,
                     steps=True,
                     logx=True,
                     logy=False,
                     loglog=False,
                     sigma=3,
                     labels=None,
                     legend=None,
                     ncol=1,
                     title=None,
                     **kwargs):
        """
        Quick plot of the detector value as a function of energy.

        Parameters
        ----------
        fixed: None or dict
            Dictionary controlling the reduction in data
        {ax}
        normalize: bool
            Normalize quantities per unit lethargy
        {xlabel}
        {ylabel}
        steps: bool
            Plot tally as constant inside bin
        {logx}
        {logy}
        {loglog}
        {sigma}
        {labels}
        {legend}
        {ncol}
        {title}
        {kwargs} :py:func:`matplotlib.pyplot.plot` or
            :py:func:`matplotlib.pyplot.errorbar`

        Returns
        -------
        {rax}

        Raises
        ------
        :class:`~serpentTools.SerpentToolsException`
            if number of rows in data not equal to
            number of energy groups

        See Also
        --------
        * :meth:`slice`
        """
        slicedTallies = self.slice(fixed, 'tallies').copy()
        if len(slicedTallies.shape) > 2:
            raise SerpentToolsException(
                'Sliced data cannot exceed 2-D for spectrum plot, not '
                '{}'.format(slicedTallies.shape))
        elif len(slicedTallies.shape) == 1:
            slicedTallies = slicedTallies.reshape(slicedTallies.size, 1)
        lowerE = self.grids['E'][:, 0]
        if normalize:
            lethBins = log(divide(self.grids['E'][:, -1], lowerE))
            for indx in range(slicedTallies.shape[1]):
                scratch = divide(slicedTallies[:, indx], lethBins)
                slicedTallies[:, indx] = scratch / scratch.max()

        if steps:
            if 'drawstyle' in kwargs:
                debug(
                    'Defaulting to drawstyle specified in kwargs as {}'.format(
                        kwargs['drawstyle']))
            else:
                kwargs['drawstyle'] = 'steps-post'

        if sigma:
            slicedErrors = sigma * self.slice(fixed, 'errors').copy()
            slicedErrors = slicedErrors.reshape(slicedTallies.shape)
            slicedErrors *= slicedTallies
        else:
            slicedErrors = None
        ax = plot(lowerE,
                  slicedTallies,
                  ax=ax,
                  labels=labels,
                  yerr=slicedErrors,
                  **kwargs)
        if ylabel is None:
            ylabel = 'Tally data'
            ylabel += ' normalized per unit lethargy' if normalize else ''
            ylabel += r' $\pm{}\sigma$'.format(sigma) if sigma else ''

        if legend is None and labels:
            legend = True
        ax = formatPlot(ax,
                        loglog=loglog,
                        logx=logx,
                        ncol=ncol,
                        xlabel=xlabel or "Energy [MeV]",
                        ylabel=ylabel,
                        legend=legend,
                        title=title)
        return ax
Пример #13
0
    def plot(self,
             x,
             y=None,
             right=None,
             sigma=3,
             ax=None,
             legend=None,
             ncol=None,
             xlabel=True,
             ylabel=None,
             logx=False,
             logy=False,
             loglog=False,
             rightlabel=None,
             **kwargs):
        """
        Plot quantities over time

        Parameters
        ----------
        x: str or iterable of strings
            ``y`` is not given, then plot these quantites against
            burnup in days. Otherwise, plot this quantity as the x
            axis with same rules as if called by ``plot('burndays', x)``.
            Burnup options are ``{'burnup', 'days', 'burnDays', 'burnStep'}``
        y: str or iterable of strings
            Quantity or quantities to plot. For all entries, only
            the first column, with respect to time, will be plotted.
            If the second column exists, and sigma is > 0, that column
            will be treated as the relative uncertainty for an
            errorbar plot. If a dictionary is passed, then plots will
            be labeled by the values of that dictionary, e.g.
            ``{'anaKeff': $k_{eff}$}`` would plot the first column of
            ``anaKeff`` with a ``LaTeX``-ready :math:`k_{eff}`
        right: str or iterable of strings
            Quantites to plot on the same plot, but with a different
            y axis and common x axis. Same rules apply as for arguments
            to ``y``. Each label will modified to have a unique identifier
            indicating the plot uses the right y-axis
        {ax}
        {sigma}
        {legend}
        {ncol}
        {xlabel}
        {ylabel}
        {logx}
        logy: bool or list or tuple
            Apply a log scale to the y-axis. If passing values to
            ``right``, this can be a two item list or tuple,
            corresponding to log-scaling the left and right axis,
            respectively.
        {loglog}
        rlabel: str or None
            If given and passing values to ``right``, use this to label
            the y-axis.
        {kwargs} : pyplot plot or errorbar depending on if ``sigma`` evaluates
            to ``True``. Will be passed for both right and left plots. Passing
            ``"label"`` to label a single plot is not allowed. Instead, pass
            a dictionary for ``y`` and/or ``right``. Values will be used to
            label a given quantity.

        Returns
        -------
        :class:`matplotlib.axes.Axes` or tuple of axes
            If right is not given, then only the primary axes object
            is returned. Otherwise, the primary and the "right"
            axes object are returned

        """

        # cleanup some inputs
        if y is None:
            y = x
            x = "burnDays"

        sigma = max(int(sigma), 0)

        y = self._expandPlotIterables(y)

        if right is not None:
            right = self._expandPlotIterables(right, ' [right]')

        if xlabel is True:
            xlabel = RESULTS_PLOT_XLABELS[x]

        if "label" in kwargs:
            raise KeyError("Passing label as kwargs is not supported")

        if len(y) == 1 and ylabel is None:
            ylabel = next(iter(y.values()))
            if sigma:
                ylabel += r'$ \pm {}\sigma$'.format(sigma)

        ax = ax or gca()

        self._plot(x, y, ax, sigma, **kwargs)

        if right is None:
            formatPlot(ax,
                       logx=logx,
                       logy=logy,
                       loglog=loglog,
                       xlabel=xlabel,
                       ylabel=ylabel,
                       legend=legend,
                       legendcols=ncol)
            return ax

        # plot some other quantity on the same x axis
        other = ax.twinx()

        # update color cycle to not repeat
        colors = rcParams['axes.prop_cycle'].by_key()['color']
        colors = colors[len(y):] + colors[:len(y)]
        other.set_prop_cycle(cycler('color', colors))

        self._plot(x, right, other, sigma, **kwargs)

        # formatting
        if logy is None or isinstance(logy, bool):
            logy = [
                logy,
            ] * 2

        if loglog is None or isinstance(loglog, bool):
            loglog = [loglog, None]

        if legend or legend is None:
            leftHandles, leftLabels = ax.get_legend_handles_labels()
            rightHandles, rightLabels = other.get_legend_handles_labels()

            placeLegend(ax,
                        legend,
                        (leftHandles + rightHandles, leftLabels + rightLabels),
                        ncol=ncol)

        if len(right) == 1 and rightlabel is None:
            rightlabel = next(iter(right.values()))
            if sigma:
                rightlabel += r'$ \pm {}\sigma$'.format(sigma)

        formatPlot(ax,
                   logx=logx,
                   logy=logy[0],
                   loglog=loglog[0],
                   legend=False,
                   xlabel=xlabel,
                   ylabel=ylabel)
        formatPlot(other,
                   logx=False,
                   loglog=False,
                   logy=logy[1],
                   legend=False,
                   ylabel=rightlabel.replace(' [right]', ''))

        return ax, other
Пример #14
0
    def spreadPlot(self,
                   xUnits,
                   yUnits,
                   isotope,
                   timePoints=None,
                   ax=None,
                   xlabel=None,
                   ylabel=None,
                   logx=False,
                   logy=False,
                   loglog=False,
                   legend=True):
        """
        Plot the mean quantity and data from all sampled files.

        Parameters
        ----------
        xUnits: str
            name of x value to obtain, e.g. ``'days'``, ``'burnup'``
        yUnits: str
            name of y value to return, e.g. ``'adens'``, ``'burnup'``
        isotope: str
            Plot data for this isotope
        timePoints: list or None
            If given, select the time points according to those
            specified here. Otherwise, select all points
        {ax}
        {xlabel}
        {ylabel}
        {logx}
        {logy}
        {loglog}
        {legend}

        Returns
        -------
        {rax}

        Raises
        ------
        :class:`~serpentTools.SamplerError`
            If ``self.allData`` is empty. Sampler was instructed to
            free all materials and does not retain data from all containers

        See Also
        --------
        :meth:`~serpentTools.samplers.depletion.SampledDepletedMaterial.plot`

        """
        if not self.allData:
            raise SamplerError("Data from all sampled files has been freed "
                               "and cannot be used in this plot method")
        ax = ax or pyplot.gca()
        if xUnits not in ('days', 'burnup'):
            raise KeyError("Plot method only uses x-axis data from <days> "
                           "and <burnup>, not {}".format(xUnits))
        xVals = timePoints if timePoints is not None else (
            self.days if xUnits == 'days' else self.burnup)
        rows = self._getRowIndices([isotope])
        cols = self._getColIndices(xUnits, timePoints)
        primaryData = self._slice(self.data[yUnits], rows, cols)[0]
        N = self._index
        sampledData = self.allData[yUnits][:N]
        for n in range(N):
            plotData = self._slice(sampledData[n], rows, cols)[0]
            ax.plot(xVals, plotData, **SPREAD_PLOT_KWARGS)
        ax.plot(xVals, primaryData, label='Mean value')

        ax = sigmaLabel(ax, xlabel or DEPLETION_PLOT_LABELS[xUnits], ylabel
                        or DEPLETION_PLOT_LABELS[yUnits])
        formatPlot(ax, legend=legend, logx=logx, logy=logy, loglog=loglog)
        return ax
Пример #15
0
    def hexPlot(self,
                what='tallies',
                fixed=None,
                ax=None,
                cmap=None,
                logColor=False,
                xlabel=None,
                ylabel=None,
                logx=False,
                logy=False,
                loglog=False,
                title=None,
                normalizer=None,
                cbarLabel=None,
                borderpad=2.5,
                **kwargs):
        """
        Create and return a hexagonal mesh plot.

        Parameters
        ----------
        what: {'tallies', 'errors', 'scores'}
            Quantity to plot
        fixed: None or dict
            Dictionary of slicing arguments to pass to :meth:`slice`
        {ax}
        {cmap}
        {logColor}
        {xlabel}
        {ylabel}
        {logx}
        {logy}
        {loglog}
        {title}
        borderpad: int or float
            Percentage of total plot to apply as a border. A value of
            zero means that the extreme edges of the hexagons will touch
            the x and y axis.
        {kwargs} :class:`matplotlib.patches.RegularPolygon`

        Raises
        ------
        AttributeError
            If :attr:`pitch` and :attr:`hexType` are not set.
        """
        borderpad = max(0, float(borderpad))
        if fixed and ('xcoord' in fixed or 'ycoord' in fixed):
            raise KeyError("Refusing to restrict along one of the hexagonal "
                           "dimensions {x/y}coord")
        for attr in {'pitch', 'hexType'}:
            if getattr(self, attr) is None:
                raise AttributeError("{} is not set.".format(attr))

        for key in {'color', 'fc', 'facecolor', 'orientation'}:
            checkClearKwargs(key, 'hexPlot', **kwargs)
        ec = kwargs.get('ec', None) or kwargs.get('edgecolor', None)
        if ec is None:
            ec = 'k'
        kwargs['ec'] = kwargs['edgecolor'] = ec
        if 'figure' in kwargs and kwargs['figure'] is not None:
            fig = kwargs['figure']
            if not isinstance(fig, Figure):
                raise TypeError(
                    "Expected 'figure' to be of type Figure, is {}".format(
                        type(fig)))
            if len(fig.axes) != 1 and not ax:
                raise TypeError("Don't know where to place the figure since"
                                "'figure' argument has multiple axes.")
            if ax and fig.axes and ax not in fig.axes:
                raise IndexError("Passed argument for 'figure' and 'ax', "
                                 "but ax is not attached to figure.")
            ax = ax or (fig.axes[0] if fig.axes else axes())
        alpha = kwargs.get('alpha', None)

        ny = len(self.indexes['ycoord'])
        nx = len(self.indexes['xcoord'])
        data = self.slice(fixed, what)
        if data.shape != (ny, nx):
            raise IndexError("Constrained data does not agree with hexagonal "
                             "grid structure. Coordinate grid: {}. "
                             "Constrained shape: {}".format((ny, nx),
                                                            data.shape))
        nItems = ny * nx
        patches = empty(nItems, dtype=object)
        values = empty(nItems)
        coords = self.grids['COORD']

        ax = ax or axes()
        pos = 0
        xmax, ymax = [
            -inf,
        ] * 2
        xmin, ymin = [
            inf,
        ] * 2
        radius = self.pitch / sqrt(3)

        for xy, val in zip(coords, data.flat):
            values[pos] = val
            h = RegularPolygon(xy, 6, radius, self.__hexRot, **kwargs)
            verts = h.get_verts()
            vmins = verts.min(0)
            vmaxs = verts.max(0)
            xmax = max(xmax, vmaxs[0])
            xmin = min(xmin, vmins[0])
            ymax = max(ymax, vmaxs[1])
            ymin = min(ymin, vmins[1])
            patches[pos] = h
            pos += 1
        normalizer = normalizerFactory(values, normalizer, logColor,
                                       coords[:, 0], coords[:, 1])
        pc = PatchCollection(patches, cmap=cmap, alpha=alpha)
        pc.set_array(values)
        pc.set_norm(normalizer)
        ax.add_collection(pc)

        addColorbar(ax, pc, None, cbarLabel)

        formatPlot(
            ax,
            loglog=loglog,
            logx=logx,
            logy=logy,
            xlabel=xlabel or "X [cm]",
            ylabel=ylabel or "Y [cm]",
            title=title,
        )
        setAx_xlims(ax, xmin, xmax, pad=borderpad)
        setAx_ylims(ax, ymin, ymax, pad=borderpad)

        return ax
Пример #16
0
    def plot(self,
             qtys,
             limitE=True,
             ax=None,
             logx=None,
             logy=None,
             loglog=None,
             sigma=3,
             xlabel=None,
             ylabel=None,
             legend=None,
             ncol=1,
             steps=True,
             labelFmt=None,
             labels=None,
             **kwargs):
        """
        Plot homogenized data as a function of energy.

        Parameters
        ----------
        qtys: str or iterable
            Plot this or these value against energy.
        limitE: bool
            If given, set the maximum energy value to be
            that of the micro group structure. By default,
            SERPENT macro group structures can reach
            1E37, leading for a very large tail on the plots.
        {ax}
        {labels}
        {logx}
        {logy}
        {loglog}
        {sigma}
        {xlabel}
        {ylabel}
        {legend}
        {ncol}
        steps : bool
            If ``True``, plot values as constant within
            energy bins.
        {univLabelFmt}
        {kwargs} :func:`matplotlib.pyplot.plot` or
            :func:`matplotlib.pyplot.errorbar`

        Returns
        -------
        {rax}

        """
        qtys = [
            qtys,
        ] if isinstance(qtys, str) else qtys
        ax = ax or pyplot.gca()
        onlyXS = True
        sigma = max(0, int(sigma))
        limitE = limitE and (self.groups is not None
                             and self.microGroups is not None)
        macroBins = self.numGroups + 1 if self.numGroups is not None else None
        microBins = (self.numMicroGroups +
                     1 if self.numMicroGroups is not None else None)
        labelFmt = labelFmt or "{k}"
        if limitE:
            eneCap = min(self.microGroups.max(), self.groups.max())

        # Check kwargs
        if "drawstyle" in kwargs and steps:
            # Conflicting arguments but defer to user value for now
            warnings.warn(
                "Passing steps and drawstyle will default to using the "
                "drawstyle value and will cause an error after 0.11.0. See "
                "https://github.com/CORE-GATECH-GROUP/serpent-tools/issues/433",
                PendingDeprecationWarning)
        elif steps:
            kwargs.setdefault("drawstyle", "steps-post")

        if "label" in kwargs:
            if len(qtys) > 1:
                raise ValueError(
                    "Passing label while plotting multiple entries {} is "
                    "not allowed".format(qtys))
            if labels is not None:
                raise ValueError("Passing label and labels is not allowed")
            labels = kwargs.pop("label")

        if isinstance(labels, str):
            labels = [
                labels,
            ]
        elif labels is None:
            labels = [
                labelFmt,
            ] * len(qtys)
        elif len(labels) != len(qtys):
            raise IndexError(
                "Need equal number of labels for plot quantities. "
                "Given {} expected: {}".format(len(labels), len(qtys)))

        for key, label in zip(qtys, labels):
            yVals = self.__getitem__(key)
            if len(yVals.shape) != 1 and 1 not in yVals.shape:
                warning("Data for {} is not 1D. Will not plot".format(key))
                continue
            uncD = self._lookup(key, True)
            yUncs = uncD.get(key, zeros_like(yVals))

            if 'Flx' in key:
                onlyXS = False
            yVals = hstack((yVals, yVals[-1]))
            nbins = yVals.size
            yUncs = hstack((yUncs, yUncs[-1])) * yVals * sigma

            xdata, foundE = self.__getEGrid(nbins, macroBins, microBins)

            if limitE and foundE:
                xdata = xdata.copy()
                xdata[xdata.argmax()] = eneCap

            label = self.__formatLabel(label, key)

            ax.errorbar(xdata, yVals, yerr=yUncs, label=label, **kwargs)

        if ylabel is None:
            ylabel, yUnits = (("Cross Section", "[cm$^{-1}$]") if onlyXS else
                              ("Group Constant", ""))
            sigStr = r" $\pm{}\sigma$".format(sigma) if sigma else ""
            ylabel = ' '.join((ylabel, sigStr, yUnits))

        if xlabel is None:
            xlabel = "Energy [MeV]" if foundE else "Energy Group"

        if legend is None:
            legend = len(qtys) > 1
        if loglog is not None:
            logx = logy = loglog
        else:
            if logx is None:
                logx = foundE
            if logy is None:
                logy = inferAxScale(ax, 'y')

        formatPlot(ax,
                   logx=logx,
                   logy=logy,
                   legendcols=ncol,
                   legend=legend,
                   xlabel=xlabel or "Energy [MeV]",
                   ylabel=ylabel)
        return ax