def plot(self, resp, zai=None, pert=None, mat=None, mevscale=False, egrid=None, sigma=3, normalize=True, ax=None, labelFmt=None, title=None, logx=True, logy=False, loglog=False, xlabel=None, ylabel=None, legend=None, ncol=1): """ Plot sensitivities due to some or all perturbations. .. note:: Without passing ``zai``, ``pert``, or ``mat`` arguments, this method will plot all permutations of sensitivities for a given response. Parameters ---------- resp: str Name of the specific response to be examined. Must be a key in ``sensitivities`` and ``energyIntegratedSens`` zai: None or str or int or iterable Plot sensitivities due to these isotopes. Passing ``None`` will plot against all isotopes. pert: None or str or list of strings Plot sensitivities due to these perturbations. Passing ``None`` will plot against all perturbations. mat: None or str or list of strings Plot sensitivities due to these materials. Passing ``None`` will plot against all materials. mevscale : bool, optional Flag for plotting energy grid in MeV units. If ``True``, the energy axis is expressed in MeV. Default is ``False``. egrid : numpy.array, optional User-defined energy grid boundaries displayed on the sensitivities as vblack, dashed vertical lines. Default is ``None``. {sigma} normalize: True Normalize plotted data per unit lethargy {ax} labelFmt: None or str Formattable string to be applied to the labels. The following entries will be formatted for each plot permuation:: {m} - name of the material {z} - isotope zai {p} - specific perturbation {r} - response being plotted {logx} {logy} {loglog} {xlabel} {ylabel} {legend} {ncol} Returns ------- {rax} Raises ------ KeyError If response or any passed perturbation settings are not present on the object See Also -------- * :py:meth:`str.format` - used for formatting labels """ for subDict in {'sensitivities', 'energyIntegratedSens'}: if resp not in getattr(self, subDict): raise KeyError("Response {} missing from {}" .format(resp, subDict)) labelFmt = labelFmt or "mat: {m} zai: {z} pert: {p}" if isinstance(zai, (str, int)): zai = {zai, } zais = self._getCleanedPertOpt('zais', zai) perts = self._getCleanedPertOpt('perts', pert) mats = self._getCleanedPertOpt('materials', mat) ax = ax or gca() sigma = max(int(sigma), 0) resMat = self.sensitivities[resp] values = resMat[..., 0] if normalize: values = values.copy() / self.lethargyWidths errors = resMat[..., 1] * values * sigma energies = self.energies if mevscale else self.energies * 1E6 for z, m, p in product(zais, mats, perts): iZ = self.zais[z] iM = self.materials[m] iP = self.perts[p] yVals = values[iM, iZ, iP] yVals = hstack((yVals, yVals[-1])) yErrs = errors[iM, iZ, iP] yErrs = hstack((yErrs, yErrs[-1])) label = labelFmt.format(r=resp, z=z, m=m, p=p) ax.errorbar(energies, yVals, yErrs, label=label, drawstyle='steps-post') if egrid is not None: for group in egrid: ax.axvline(group, color='k', linestyle='dashed') if xlabel is None: xlabel = "Energy [MeV]" if mevscale else "Energy [eV]" if ylabel is None: parts = ["Sensitivity"] if normalize: parts.append("per unit lethargy") if sigma: parts.append(r"$\pm{}\sigma$".format(sigma)) ylabel = " ".join(parts) ax = formatPlot(ax, loglog=loglog, logx=logx, logy=logy, legendcols=ncol, legend=legend, xlabel=xlabel, ylabel=ylabel) return ax
def plot(self, resp, zai=None, pert=None, mat=None, sigma=3, normalize=True, ax=None, labelFmt=None, title=None, logx=True, logy=False, loglog=False, xlabel=None, ylabel=None, legend=None, ncol=1): """ Plot sensitivities due to some or all perturbations. .. note:: Without passing ``zai``, ``pert``, or ``mat`` arguments, this method will plot all permutations of sensitivities for a given response. Parameters ---------- resp: str Name of the specific response to be examined. Must be a key in ``sensitivities`` and ``energyIntegratedSens`` zai: None or str or int or iterable Plot sensitivities due to these isotopes. Passing ``None`` will plot against all isotopes. pert: None or str or list of strings Plot sensitivities due to these perturbations. Passing ``None`` will plot against all perturbations. mat: None or str or list of strings Plot sensitivities due to these materials. Passing ``None`` will plot against all materials. {sigma} normalize: True Normalize plotted data per unit lethargy {ax} labelFmt: None or str Formattable string to be applied to the labels. The following entries will be formatted for each plot permuation:: {m} - name of the material {z} - isotope zai {p} - specific perturbation {r} - response being plotted {logx} {logy} {loglog} {xlabel} {ylabel} {legend} {ncol} Returns ------- {rax} Raises ------ KeyError If response or any passed perturbation settings are not present on the object See Also -------- * :py:meth:`str.format` - used for formatting labels """ for subDict in {'sensitivities', 'energyIntegratedSens'}: if resp not in getattr(self, subDict): raise KeyError("Response {} missing from {}".format( resp, subDict)) labelFmt = labelFmt or "mat: {m} zai: {z} pert: {p}" if isinstance(zai, (str, int)): zai = { zai, } zais = self._getCleanedPertOpt('zais', zai) perts = self._getCleanedPertOpt('perts', pert) mats = self._getCleanedPertOpt('materials', mat) ax = ax or gca() sigma = max(int(sigma), 0) resMat = self.sensitivities[resp] values = resMat[..., 0] if normalize: values = values.copy() / self.lethargyWidths errors = resMat[..., 1] * values * sigma energies = self.energies * 1E6 for z, m, p in product(zais, mats, perts): iZ = self.zais[z] iM = self.materials[m] iP = self.perts[p] yVals = values[iM, iZ, iP] yVals = hstack((yVals, yVals[-1])) yErrs = errors[iM, iZ, iP] yErrs = hstack((yErrs, yErrs[-1])) label = labelFmt.format(r=resp, z=z, m=m, p=p) ax.errorbar(energies, yVals, yErrs, label=label, drawstyle='steps-post') xlabel = 'Energy [eV]' if xlabel is None else xlabel ylabel = ylabel if ylabel is not None else ('Sensitivity {} {}'.format( 'per unit lethargy' if normalize else '', r'$\pm{}\sigma$'.format(sigma) if sigma else '')) ax = formatPlot(ax, loglog=loglog, logx=logx, logy=logy, ncol=ncol, legend=legend, xlabel=xlabel, ylabel=ylabel.strip()) return ax
def plot(self, mts='all', ax=None, loglog=False, xlabel=None, ylabel=None, logx=True, logy=False, title=None, legend=None, ncol=1, **kwargs): """ Return a matplotlib figure for plotting XS. mts should be a list of the desired MT numbers to plot for this XS. Units should automatically be fixed between micro and macro XS. Parameters ---------- mts: int, string, or list of ints If it's a string, it should be 'all'. A single int indicates one MT reaction number. A list should be a list of MT numbers to plot. {ax} {loglog} {logx} {logy} {xlabel} {ylabel} {title} {legend} {ncol} {kwargs} :py:func:`matplotlib.pyplot.plot` Returns ------- {rax} Raises ------ TypeError if MT numbers that don't make sense come up """ if mts == 'all': mts = self.MT elif isinstance(mts, int): # convert to list if it's just one MT mts = [mts] elif isinstance(mts, list) and all([isinstance(ii, int) for ii in mts]): pass else: msg = ("mts argument must be a string saying 'all'," "a list of integer MTs, or a single interger" "instead, {} of type {} was passed.".format(mts, type(mts))) raise TypeError(msg) for mt in mts: if mt not in self.MT: error("{} not in collected MT numbers, {}".format(mt, self.MT)) ax = ax or pyplot.gca() x = self.metadata['egrid'] for mt in mts: for i, MT in enumerate(self.MT): if mt == MT: y = self.xsdata[:, i] ax.plot(x, y, drawstyle='steps', label=self.MTdescrip[i]) title = title or '{} cross section{}'.format( self.name, 's' if len(mts) > 1 else '') xlabel = xlabel or "Energy [MeV]" ylabel = ylabel or ( 'Cross Section ({})'.format('b' if self.isIso else 'cm$^{-1}$')) ax = formatPlot(ax, loglog=loglog, logx=logx, logy=logy, ncol=ncol, legend=legend, title=title, xlabel=xlabel, ylabel=ylabel) return ax
def plot(self, mts='all', ax=None, loglog=False, xlabel=None, ylabel=None, logx=True, logy=False, title=None, legend=None, ncol=1, labels=None, **kwargs): """ Plot XS corresponding to their MTs. Parameters ---------- mts : int, string, or list of ints If it's a string, it should be 'all'. A single int indicates one MT reaction number. A list should be a list of MT numbers to plot. {ax} {loglog} {logx} {logy} {xlabel} {ylabel} {title} {legend} {ncol} labels : str or list of str or dict {int: str} Labels to apply to the plot. Defaults to labeling by MT description. If a string, then ``mts`` must be a single integer. If a list of strings, each label will be applied to each entry in ``mts``. If a dictionary, keys must be mts and their labels as values. The number of keys do not have to align with the number of MTs {kwargs} :func:`matplotlib.pyplot.plot` Returns ------- {rax} Raises ------ TypeError If MT numbers that don't make sense come up """ mts = self._processPlotMts(mts) userlabel = kwargs.pop("label", None) if userlabel is not None: # Allow label to be passed for single MT plots # Little easier to remember and it makes more sense. # Don't allow mixed label / labels arguments if labels is not None: raise ValueError( "Passing label and labels is not allowed. Prefer labels") if len(mts) == 1: labels = [userlabel] else: raise ValueError("Use labels when plotting multiple MTs") else: labels = self._processPlotLabels(mts, labels) ax = ax or pyplot.gca() kwargs.setdefault("drawstyle", "steps") for mt, label in zip(mts, labels): y = self[mt] ax.plot(self.energies, y, label=label, **kwargs) title = title or '{} cross section{}'.format( self.name, 's' if len(mts) > 1 else '') xlabel = xlabel or "Energy [MeV]" ylabel = ylabel or ( 'Cross Section ({})'.format('b' if self.isIso else 'cm$^{-1}$')) ax = formatPlot(ax, loglog=loglog, logx=logx, logy=logy, legendcols=ncol, legend=legend, title=title, xlabel=xlabel, ylabel=ylabel) return ax