Example #1
0
    def loadYaml(self, filePath, strict=True):
        """
        Update the settings based on the contents of the yaml file

        .. versionadded:: 0.2.0

        Parameters
        ----------
        filePath: str, or FileType
            Path to config file
        strict: bool
            Fail at the first incorrect setting. If false, failed settings
            will not be loaded and alerts will be raised

        Raises
        ------
        KeyError or TypeError
            If settings found in the config file are not
            valid
        FileNotFound or OSError
            If the file does not exist

        """
        messages.debug('Attempting to read from {}'.format(filePath))
        with open(filePath) as yFile:
            configSettings = safe_load(yFile)
        messages.debug(
            'Loading settings onto object with strict:{}'.format(strict))

        for key, value in iteritems(configSettings):
            if isinstance(value, dict):
                self.__recursiveLoad(value, strict, key)
            else:
                self.__safeLoad(key, value, strict)
        messages.info('Done')
Example #2
0
    def setValue(self, name, value):
        """Set the value of a specific setting.

        Parameters
        ----------
        name: str
            Full name of the setting
        value: value to be set

        Raises
        ------
        KeyError
            If the value is not one of the allowable options or if the
            setting does not match an existing setting
        TypeError
            If the value is not of the correct type

        """
        if self.__inside:
            self.__originals[name] = self[name]
        if name not in self:
            raise KeyError('Setting {} does not exist'.format(name))
        self._defaultLoader[name].validate(value)
        # if we've made it here, then the value is valid
        if self._defaultLoader[name].updater is not None:
            value = self._defaultLoader[name].updater(value)
        dict.__setitem__(self, name, value)
        messages.debug('Updated setting {} to {}'.format(name, value))
def inferReader(filePath):
    """
    Attempt to infer the correct reader type.

    Parameters
    ----------
    filePath: str or path-like
        File to be read.

    Raises
    ------
    SerpentToolsException
        If a reader cannot be inferred
    """
    filePath = str(filePath)
    for reg, reader in REGEXES.items():
        match = re.match(reg, filePath)
        if match and match.group() == filePath:
            debug('Inferred reader for {}: {}'
                  .format(filePath, reader.__name__))
            return reader
    raise SerpentToolsException(
        'Failed to infer filetype and thus accurate reader from'
        'file path {}. Pass one of the below options to ensure '
        'a specific reader:\n{}'.format(filePath, SUPPORTED_READER_MSG)
    )
Example #4
0
 def __safeLoad(self, key, value, strict):
     messages.debug('Attempting to set setting {} to {}'.format(key, value))
     try:
         self.setValue(key, value)
     except (KeyError, TypeError) as error:
         if strict:
             raise error
         else:
             messages.error(str(error))
Example #5
0
 def __processDet(self, name, grids):
     """Add this detector with it's grid data to the reader."""
     if not self._loadAll and name in self.settings['names']:
         debug(
             "Skipping detector {} due to setting <detector.names>".format(
                 name))
         return
     if name in self.detectors:
         raise KeyError("Detector {} already stored on reader".format(name))
     self.detectors[name] = detectorFactory(name, grids)
Example #6
0
    def _postcheck(self):
        """ensure the parser grabbed expected materials."""
        if not self.materials:
            error("No materials obtained from {}".format(self.filePath))
            return

        for mKey, mat in iteritems(self.materials):
            assert isinstance(mat, DepletedMaterial), (
                'Unexpected key {}: {} in materials dictionary'.format(
                    mKey, type(mat)))
        debug('  found {} materials'.format(len(self.materials)))
Example #7
0
 def read(self):
     """Read all the files and create parser objects"""
     self._readAll()
     if not self.settings['skipPrecheck']:
         self._precheck()
     else:
         debug('Skipping pre-check')
     self.process()
     if self.settings['freeAll']:
         info("Removing all parsers and containers from memory since "
              "setting <sampler.freeAll> is ``True``")
         self.free()
Example #8
0
    def getUniv(self, univ, burnup=None, index=None, timeDays=None):
        """
        Return a specific universe given the ID and time of interest

        If more than one time parameter is given, the hierarchy of search is:
        index (highest priority), burnup, timeDays (lowest priority)

        Parameters
        ----------
        univ: str
            Unique str for the desired universe
        burnup: float or int
            Burnup [MWd/kgU] of the desired universe
        timeDays: float or int
            Time [days] of the desired universe
        index: int
            Point of interest in the burnup/days index

        Returns
        -------
        :py:class:`~serpentTools.objects.containers.HomogUniv`
            Requested universe

        Raises
        ------
        KeyError:
            If the requested universe could not be found
        SerpentToolsException:
            If burnup, days and index are not given
        """
        if index is None and burnup is None and timeDays is None:
            raise SerpentToolsException(
                'Burnup, time or index are required inputs')
        searchIndex = (2 if index is not None else
                       1 if burnup is not None else 3)
        searchValue = (index if index is not None else
                       burnup if burnup is not None else timeDays)
        if searchIndex == 2 and searchValue < 1:  # index must be non-zero
            raise KeyError(
                'Index read is {}, however only integers above zero are '
                'allowed'.format(searchValue))
        for key, dictUniv in iteritems(self.universes):
            if key[0] == univ and key[searchIndex] == searchValue:
                debug('Found universe that matches with keys {}'.format(key))
                return self.universes[key]
        searchName = ('index '
                      if index else 'burnup ' if burnup else 'timeDays ')
        raise KeyError(
            'Could not find a universe that matched requested universe {} and '
            '{} {}'.format(univ, searchName, searchValue))
Example #9
0
    def reshape(self):
        """
        Reshape the tally data into a multidimensional array

        This method reshapes the tally and uncertainty data into arrays
        where the array axes correspond to specific bin types.
        If a detector was set up to tally two group flux in a 5 x 5
        xy mesh, then the resulting tally data would be in a 50 x 12/13
        matrix in the original ``detN.m`` file.
        The tally data and relative error would be rebroadcasted into
        2 x 5 x 5 arrays, and the indexing information is stored in
        ``self.indexes``

        Returns
        -------
        shape: list
            Dimensionality of the resulting array

        Raises
        ------
        SerpentToolsException:
            If the bin data has not been loaded
        """
        if self.bins is None:
            raise SerpentToolsException('Tally data for detector {} has not '
                                        'been loaded'.format(self.name))
        if self.__reshaped:
            warning('Data has already been reshaped')
            return
        debug('Starting to sort tally data...')
        shape = []
        self.indexes = OrderedDict()
        for index, indexName in enumerate(DET_COLS):
            if 0 < index < 10:
                uniqueVals = unique(self.bins[:, index])
                if len(uniqueVals) > 1:
                    self.indexes[indexName] = array(uniqueVals, dtype=int) - 1
                    shape.append(len(uniqueVals))
        self.tallies = self.bins[:, 10].reshape(shape)
        self.errors = self.bins[:, 11].reshape(shape)
        if self.bins.shape[1] == 13:
            self.scores = self.bins[:, 12].reshape(shape)
        self._map = {
            'tallies': self.tallies,
            'errors': self.errors,
            'scores': self.scores
        }
        debug('Done')
        self.__reshaped = True
        return shape
Example #10
0
 def _processBranchBlock(self):
     fromHeader = self._processHeader()
     if fromHeader is None:
         return
     thisBranch, totUniv = fromHeader
     burnup, burnupIndex = self._advance()[:-1]
     self._whereAmI['buIndx'] = int(burnupIndex)
     for univNum in range(totUniv):
         self._whereAmI['universe'] = univNum
         debug(
             'Reading run {runIndx} of {coefIndx} - universe {universe} at '
             'burnup step {buIndx}'.format(**self._whereAmI))
         self._processBranchUniverses(thisBranch, float(burnup),
                                      self._whereAmI['buIndx'])
Example #11
0
 def _processChunk(self, chunk, name, variable):
     if (self.settings['materialVariables']
             and variable not in self.settings['materialVariables']):
         return
     if name not in self.materials:
         debug('Adding material {}...'.format(name))
         self.materials[name] = DepletedMaterial(name, self.metadata)
     if len(chunk) == 1:  # single line values, e.g. volume or burnup
         cleaned = self._cleanSingleLine(chunk)
     else:
         cleaned = []
         for line in chunk:
             if '[' in line or ']' in line:
                 continue
             cleaned.append(line[:line.index('%')])
     self.materials[name].addData(variable, cleaned)
Example #12
0
 def _addDetector(self, chunk, detName, binType):
     if binType is None:
         data = empty(shape=(len(chunk), NUM_COLS))
     else:
         data = empty(shape=(len(chunk), len(chunk[0].split())))
     for indx, line in enumerate(chunk):
         data[indx] = [float(xx) for xx in line.split()]
     if detName not in self.detectors:
         # new detector, this data is the tallies
         detector = Detector(detName)
         detector.addTallyData(data)
         self.detectors[detName] = detector
         debug('Adding detector {}'.format(detName))
         return
     # detector has already been defined, this must be a mesh
     detector = self.detectors[detName]
     detector.grids[binType] = asfortranarray(data)
     debug('Added bin data {} to detector {}'.format(binType, detName))
Example #13
0
 def read(self):
     """Read through the depletion file and store requested data."""
     messages.info('Preparing to read {}'.format(self.filePath))
     keys = ['MAT', 'TOT'] if self.settings['processTotal'] else ['MAT']
     keys.extend(self.settings['metadataKeys'])
     separators = ['\n', '];', '\r\n']
     with KeywordParser(self.filePath, keys, separators) as parser:
         for chunk in parser.yieldChunks():
             if 'MAT' in chunk[0]:
                 self._addMaterial(chunk)
             elif 'TOT' in chunk[0]:
                 self._addTotal(chunk)
             else:
                 self._addMetadata(chunk)
     if 'days' in self.metadata:
         for mKey in self.materials:
             self.materials[mKey].days = self.metadata['days']
     messages.info('Done reading depletion file')
     messages.debug('  found {} materials'.format(len(self.materials)))
Example #14
0
 def _processBranchUniverses(self, branch, burnup, burnupIndex):
     """Add universe data to this branch at this burnup."""
     unvID, numVariables = [int(xx) for xx in self._advance()]
     univ = branch.addUniverse(unvID, burnup, burnupIndex - 1)
     for step in range(numVariables):
         splitList = self._advance(
             possibleEndOfFile=step == numVariables - 1)
         varName = splitList[0]
         varValues = [float(xx) for xx in splitList[2:]]
         if not varValues:
             debug("No data present for variable {}. Skipping"
                   .format(varName))
             continue
         if self._checkAddVariable(varName):
             if self._hasUncs:
                 vals, uncs = splitValsUncs(varValues)
                 univ.addData(varName, array(vals), uncertainty=False)
                 univ.addData(varName, array(uncs), uncertainty=True)
             else:
                 univ.addData(varName, array(varValues), uncertainty=False)
Example #15
0
    def addData(self, variable, rawData):
        """
        Add data straight from the file onto a variable.

        Parameters
        ----------
        variable: str
            Name of the variable directly from ``SERPENT``
        rawData: list
            List of strings corresponding to the raw data from the file
        """
        newName = convertVariableName(variable)
        debug('Adding {} data to {}'.format(newName, self.name))
        if isinstance(rawData, str):
            scratch = [float(item) for item in rawData.split()]
        else:
            scratch = []
            for line in rawData:
                if line:
                    scratch.append([float(item) for item in line.split()])
        self.data[newName] = numpy.array(scratch)
Example #16
0
    def getUniv(self, univID, burnup=None, index=None):
        """
        Return a specific universe given the ID and time of interest

        If burnup and index are given, burnup is used to search

        Parameters
        ----------
        univID: int
            Unique ID for the desired universe
        burnup: float or int
            Burnup [MWd/kgU] of the desired universe
        index: int
            Point of interest in the burnup index

        Returns
        -------
        :py:class:`~serpentTools.objects.containers.HomogUniv`
            Requested universe

        Raises
        ------
        KeyError:
            If the requested universe could not be found
        SerpentToolsException:
            If neither burnup nor index are given
        """
        if burnup is None and index is None:
            raise SerpentToolsException('Burnup or index are required inputs')
        searchIndex = 2 if index is not None else 1
        searchValue = index if index is not None else burnup
        for key in self.__keys:
            if key[0] == univID and key[searchIndex] == searchValue:
                debug('Found universe that matches with keys {}'.format(key))
                return self.universes[key]
        searchName = 'burnup' + ('' if index is None else ' index')
        raise KeyError(
            'Could not find a universe that matched requested universe {} and '
            '{} {}'.format(univID, searchName, searchValue))
Example #17
0
    def _read(self):
        """Read through the depletion file and store requested data."""
        info('Preparing to read {}'.format(self.filePath))
        keys = ['E', 'i\d{4,5}', 'm\w']
        separators = ['\n', '];', '\r\n']

        with KeywordParser(self.filePath, keys, separators) as parser:
            for chunk in parser.yieldChunks():

                if chunk[0][:5] == 'E = [':
                    # The energy grid
                    self.metadata['egrid'] = np.array(chunk[1:],
                                                      dtype=np.float64)

                elif chunk[0][:15] == 'majorant_xs = [':
                    # L-inf norm on all XS on all materials
                    self.metadata['majorant_xs'] = np.array(chunk[1:],
                                                            dtype=np.float64)

                elif chunk[0][-7:] == 'mt = [\n':
                    debug('found mt specification')
                    xsname = chunk[0][:-8]
                    isiso = True if chunk[0][0] == 'i' else False
                    self.xsections[xsname] = XSData(xsname,
                                                    self.metadata,
                                                    isIso=isiso)
                    self.xsections[xsname].setMTs(chunk)

                elif chunk[0][-7:] == 'xs = [\n':
                    debug('found xs specification')
                    xsname = chunk[0][:-8]
                    self.xsections[xsname].setData(chunk)

                elif chunk[0][-7:] == 'nu = [\n':
                    debug('found nu specification')
                    xsname = chunk[0][:-8]
                    self.xsections[xsname].setNuData(chunk)

                elif 'bra_f' in chunk[0]:
                    warning("There is this weird 'bra_f' XS. these seem to be"
                            " constant. recording to metadata instead.")
                    self.metadata[xsname].setData(chunk)

                else:
                    print(chunk)
                    error('Unidentifiable entry {}'.format(chunk[0]))

        info('Done reading xsplot file')
        debug('  found {} xs listings'.format(len(self.xsections)))
Example #18
0
def inferReader(filePath):
    """
    Attempt to infer the correct reader type.

    Parameters
    ----------
    filePath: str
        File to be read.

    Raises
    ------
    SerpentToolsException
        If a reader cannot be inferred
    """
    for reg, reader in six.iteritems(REGEXES):
        match = re.match(reg, filePath)
        if match and match.group() == filePath:
            debug('Inferred reader for {}: {}'.format(filePath,
                                                      reader.__name__))
            return reader
    raise SerpentToolsException(
        'Failed to infer filetype and thus accurate reader from'
        'file path {}'.format(filePath))
Example #19
0
import os

ROOT_DIR = os.path.dirname(__file__)

from serpentTools.parsers import read
from serpentTools import messages
from ._version import get_versions
__version__ = get_versions()['version']
del get_versions

messages.debug('Using version {}'.format(__version__))
Example #20
0
def seedFiles(inputFile, numSeeds, seed=None, outputDir=None, link=False,
              digits=10):
    """
    Copy input file multiple times with unique seeds.

    Parameters
    ----------
    inputFile: str
        Path to input file
    numSeeds: int
        Number of files to create
    seed: int
        Optional argument to set the seed of the builtin random
        number generator
    outputDir: str
        Path to desired output directory. Files will be copied here.
        If the folder does not exist, try to make the directory. Assumes path
        relative to directory that contains the input file
    link: bool
        If True, do not copy the full file. Instead, create a new file
        with 'include <inputFile>' and the new seed declaration.
    digits: int
        Average number of digits for random seeds

    See Also
    --------
    :py:mod:`random`
    :py:func:`random.seed()`
    :py:func:`random.getrandbits()`

    """
    if '~' in inputFile:
        inputFile = os.path.expanduser(inputFile)

    if not path.exists(inputFile):
        error('Input file {} does not exist'.format(inputFile))
        return

    if numSeeds < 1:
        error('Require positive number of files to create')
        return

    if digits < 1:
        error('Require positive number of digits in random seeds')
    bits = int((digits - OFFSET) / SLOPE)

    random.seed(seed)

    inputPath = path.abspath(path.join(os.getcwd(), inputFile))
    inputRoot = path.dirname(inputPath)

    if outputDir is not None:
        fPrefix = path.abspath(path.join(inputRoot, outputDir))
        if not path.isdir(fPrefix):
            debug('Creating directory at {}'.format(fPrefix))
            os.mkdir(fPrefix)
    else:
        fPrefix = inputRoot

    fileFmt = path.join(fPrefix, _makeFileFmt(inputFile))

    writeFunc = _include if link else _copy
    writeFunc(inputPath, numSeeds, fileFmt, bits, digits)

    return
Example #21
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
Example #22
0
 def process(self):
     """Process the repeated files to obtain true uncertainties"""
     debug('Processing data from {} parsers'.format(len(self.parsers)))
     self._process()
     debug('Done')
Example #23
0
def depmtx(fileP):
    """
    Read the contents of the ``depmtx`` file and return contents

    .. note::

        If ``scipy`` is not installed, matrix ``A`` will be full.
        This can cause some warnings or errors if sparse or
        non-sparse solvers are used.

    Parameters
    ----------
    fileP: str
        Path to depletion matrix file

    Returns
    -------
    t: float
        Length of time
    n0: numpy.ndarray
        Initial isotopic vector
    zai: numpy.array
        String identifiers for each isotope in ``n0`` and ``n1``
    a: numpy.array or scipy.sparse.csc_matrix
        Decay matrix. Will be sparse if scipy is installed
    n1: numpy.array
        Final isotopic vector
    """
    if not path.exists(fileP):
        raise IOError('Cannot find depeletion matrix file {}'.format(fileP))

    tRegex = re.compile(r't\s+=\s+([\d\.E\+-]+)')
    nDensRegex = re.compile(r'N\d\(\s*([\d]+).*=\s+([\d\.E\+-]+)')
    # matches index and quantity for N0 and N1 vectors
    zaiRegex = re.compile(r'ZAI\(\s*[\d]+\).*=\s+(-?\d+)')
    # matches index and name for ZAI vector
    matrixRegex = re.compile(r'A\(\s*(\d+),\s*(\d+)\)\s+=\s+([\dE\.\+-]+)')
    # matrix row, column, and decay constant for A matrix
    failMsg = 'File {} is ill-formed for depmtx reader\nLine: '.format(fileP)

    if not HAS_SCIPY:
        debug('Decay matrix will be returned as full matrix')

    with open(fileP) as f:
        line = f.readline()
        tMatch = re.match(tRegex, line)
        if not tMatch:
            raise SerpentToolsException(failMsg + line)
        t = float(tMatch.groups()[0])
        line = f.readline()

        nMatch = re.match(nDensRegex, line)
        if not nMatch:
            raise SerpentToolsException(failMsg + line)

        n0Storage, line, numIso = _parseIsoBlock(f, {}, nMatch, line,
                                                 nDensRegex)
        debug('Found {} isotopes for file {}'.format(numIso, fileP))
        n0 = empty((numIso, 1), dtype=longfloat)
        for indx, v in six.iteritems(n0Storage):
            n0[indx] = v

        zai = []
        zMatch = re.match(zaiRegex, line)
        if not zMatch:
            raise SerpentToolsException(failMsg + line)
        while zMatch:
            zai.append(zMatch.groups()[0])
            line = f.readline()
            zMatch = re.match(zaiRegex, line)

        if len(zai) != n0.size:
            debug('Stopping at line -' + line)
            raise SerpentToolsException(
                'Did not obtain equal isotopes in ZAI vector [{}] as in N0 '
                'vector [{}]'.format(len(zai), n0.size))

        line = f.readline()
        aMatch = re.match(matrixRegex, line)
        if not aMatch:
            raise SerpentToolsException(failMsg + line)

        a = zeros((numIso, numIso), dtype=longfloat)

        while aMatch:
            row, col, const = aMatch.groups()
            a[int(row) - 1, int(col) - 1] = float(const)
            line = f.readline()
            aMatch = re.match(matrixRegex, line)

        n1 = empty_like(n0)
        nMatch = re.match(nDensRegex, line)
        n1, line, items = _parseIsoBlock(f, n1, nMatch, line, nDensRegex)
        if items != numIso:
            debug('Stopping at line -' + line)
            raise SerpentToolsException(
                'Did not obtain equal isotopes in N1 vector [{}] as in N0 '
                'vector [{}]'.format(items, numIso))

        return t, n0, array(zai), csc_matrix(a) if HAS_SCIPY else a, n1
Example #24
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,
                     **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}
        {kwargs} :py:func:`matplotlib.pyplot.plot` or 
            :py:func:`matplotlib.pyplot.errorbar`

        Returns
        -------
        {rax}

        Raises
        ------
        SerpentToolsException
            if number of rows in data not equal to
            number of energy groups

        See Also
        --------
        :py:meth:`~serpentTools.objects.containers.DetectorBase.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) * slicedTallies
        else:
            slicedErrors = None
        ax = plot(lowerE,
                  slicedTallies,
                  ax=ax,
                  labels=labels,
                  yerr=slicedErrors,
                  **kwargs)
        if loglog or logx:
            ax.set_xscale('log')
        if loglog or logy:
            ax.set_yscale('log')
        ax.set_xlabel(xlabel or 'Energy [MeV]')
        ylabel = ylabel or 'Tally data' + (' normalized per unit lethargy'
                                           if normalize else '')
        ax.set_ylabel(ylabel)

        return ax
Example #25
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,
             **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}
        {kwargs} :py:func:`~matplotlib.pyplot.plot` or
            :py:func:`~matplotlib.pyplot.errorbar` function.

        Returns
        -------
        {rax}

        Raises
        ------
        SerpentToolsException
            If data contains more than 2 dimensions

        See Also
        --------
        * :py:meth:`~serpentTools.objects.containers.Detector.slice`
        * :py:meth:`~serpentTools.objects.containers.DetectorBase.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 pyplot.axes()

        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)

        ax.set_xlabel(xlabel)
        ax.set_ylabel(ylabel)
        if loglog or logx:
            ax.set_xscale('log')
        if loglog or logy:
            ax.set_yscale('log')
        return ax