def _raiseErrorMsgFromDict(misMatches, header, objName): msg = 'Files do not contain a consistent set of {}'.format(objName) critMsgs = [msg, header + ": Parser files"] for key, values in iteritems(misMatches): critMsgs.append('{}: {}'.format(key, ', '.join(values))) error('\n'.join(str(item) for item in critMsgs)) raise MismatchedContainersError(msg)
def _readAll(self): self.map = {} self.parsers = set() allExistFlag = self.settings['allExist'] missing = [] raiseErrors = self.settings['raiseErrors'] for filePath in self.files: if not exists(filePath): if allExistFlag: raise OSError('File {} does not exist'.format(filePath)) else: missing.append(filePath) continue try: parser = self.__parserCls(filePath) parser.read() except Exception as ee: if raiseErrors: raise ee else: error('The following error occurred while reading file {} ' 'and was suppressed since setting <raiseErrors> is ' 'True}:\n{}'.format(filePath, str(ee))) continue self.parsers.add(parser) self.map[filePath] = parser if missing: warning('The following files did not exist and were not processed ' '\n\t{}'.format(', '.join(missing)))
def _compare(self, other, lower, upper, sigma): myShape = self.tallies.shape otherShape = other.tallies.shape if myShape != otherShape: error("Detector tallies do not have identical shapes" + BAD_OBJ_SUBJ.format('tallies', myShape, otherShape)) return False similar = compareDictOfArrays(self.grids, other.grids, 'grids', lower=lower, upper=upper) similar &= getLogOverlaps('tallies', self.tallies, other.tallies, self.errors, other.errors, sigma, relative=True) hasScores = [obj.scores is not None for obj in (self, other)] similar &= hasScores[0] == hasScores[1] if not any(hasScores): return similar if all(hasScores): similar &= getLogOverlaps('scores', self.scores, other.scores, self.errors, other.errors, sigma, relative=True) return similar firstK, secondK = "first", "second" if hasScores[1]: firstK, secondK = secondK, firstK error("{} detector has scores while {} does not" .format(firstK.capitalize(), secondK)) return similar
def _precheck(self): """Currently, just grabs total number of coeff calcs.""" with open(self.filePath) as fObj: try: self._totalBranches = int(fObj.readline().split()[1]) except: error("COE output at {} likely malformatted or misnamed".format( self.filePath))
def _comparePrecheckMetadata(self, other): for key, myVec in self.metadata.items(): otherVec = other.metadata[key] if len(myVec) != len(otherVec): error("Stopping comparison early due to mismatched {} vectors" "\n\t>{}\n\t<{}".format(key, myVec, otherVec)) return False return True
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))
def _precheck(self): """ Count how many detectors are in the file.""" with open(self.filePath) as fh: for line in fh: sline = line.split() if not sline: continue elif 'DET' in sline[0]: return error("No detectors found in {}".format(self.filePath))
def _comparePrecheckMetadata(self, other): for key in ["names", "zais", "days", "burnup"]: myVec = getattr(self, key) otherVec = getattr(other, key, None) if ((otherVec is None and myVec is not None) or len(myVec) != len(otherVec)): error("Stopping comparison early due to mismatched {} vectors" "\n\t>{}\n\t<{}".format(key, myVec, otherVec)) return False return True
def _precheck(self): """do a quick scan to ensure this looks like a material file.""" with open(self.filePath) as fh: for line in fh: sline = line.split() if not sline: continue elif 'MAT' == line.split('_')[0]: return error("No materials found in {}".format(self.filePath))
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)))
def _precheck(self): """do a quick scan to ensure this looks like a xsplot file.""" if '_xs' not in self.filePath: warning("This file doesn't look like the file format serpent" "gives for xsplot stuff.") with open(self.filePath) as fh: # first chunk should be energy bins line = next(fh) if line != 'E = [\n': error("It looks like {} doesn't start with an energy bin " "structure. Are you sure it's an xsplot file?" .format(self.filePath))
def _precheck(self): """Total number of branches and check for uncertainties""" with open(self.filePath) as fObj: try: self._totalBranches = int(fObj.readline().split()[1]) except Exception as ee: error("COE output at {} likely malformatted or misnamed\n{}" .format(self.filePath, str(ee))) # skip first few lines with integer until first named value for _x in range(4): fObj.readline() lsplt = fObj.readline().split() nvals = int(lsplt[1]) self._hasUncs = not nvals == len(lsplt) - 2
def _postcheck(self): """ensure the parser grabbed expected stuff.""" try: for xs in self.xsections.values(): assert xs.hasExpectedData() except AssertionError: error("Seems either the file was cut off, or data incomplete." "The incomplete XS is {}".format(xs.name)) # check energy grid found try: assert 'egrid' in self.metadata.keys() except AssertionError as e: e.args += 'No energy grid found in xsplot parser.'
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)))
def _helpCompareGCDict(self, other, attrBase, sigma): """ Method that actually compare group constant dictionaries. ``attrBase`` is used to find dictionaries by appending ``'Exp'`` and ``'Unc'`` to ``attrBase`` """ self._checkCompareObj(other) valName = (attrBase + 'Exp') if attrBase != 'gc' else 'gc' uncName = attrBase + 'Unc' try: myVals = getattr(self, valName) myUncs = getattr(self, uncName) otherVals = getattr(other, valName) otherUncs = getattr(other, uncName) except Exception as ee: critical("The following error was raised extracting {} and " "{} from universes {} and {}:\n\t{}".format( valName, uncName, self, other, ee)) return False keys = getKeyMatchingShapes(myVals, otherVals, valName) similar = len(keys) == len(myVals) == len(otherVals) for key in keys: if key not in myUncs or key not in otherUncs: loc = self if key in otherUncs else other error("Uncertainty data for {} missing from {}".format( key, loc)) similar = False continue myVal = myVals[key] myUnc = myUncs[key] otherVal = otherVals[key] otherUnc = otherUncs[key] similar &= getLogOverlaps(key, myVal, otherVal, myUnc, otherUnc, sigma, relative=True) return similar
def _toMatlab(args): """ Write contents of a file to matlab. Return codes: 0: all good 1: need scipy 3: conversion for file type not supported yet """ inFile = args.file outFile = args.output if not outFile: base = splitext(inFile)[0] outFile = base + '.mat' # inferReader returns the class, but we need an instance reader = inferReader(inFile)(inFile) try: converter = MatlabConverter(reader, outFile) except ImportError: error("scipy >= 1.0 required to convert to matlab") return 1 except NotImplementedError: error("Conversion not supported for {} reader at this time. ".format( reader.__class__.__name__)) error("Please alert the developers of your need.") return 3 reader.read() converter.convert(True, append=args.append, format=args.format, longNames=args.longNames, compress=not args.large, oned=args.oned) if not args.q: if args.v: info("Wrote contents of {} to {}".format(inFile, outFile)) else: print(outFile) return 0
def _postcheck(self): if not self.arrays: error("No history data found in {}".format(self.filePath)) if self.numInactive is None: error('Unable to acertain the number of inactive cycles')
def tabulate(self, mts='all', colnames=None): """ Returns a pandas table, for pretty tabulation in Jupyter notebooks. Parameters ---------- mts: int, string, or list of ints If it's a string, it should be 'all', which is default. A single int indicates one MT reaction number. A list should be a list of MT numbers to plot. colnames: any type with string representation Column names for each MT number, if you'd like to change them. Returns ------- Pandas Dataframe version of the XS data. Raises ------ ImportError If ``pandas`` is not installed TypeError if MT numbers that don't make sense come up """ import pandas as pd if len(self.metadata['egrid']) > 99: y = input('This is about to be a big table. Still want it? (y/n)') if not (y == 'y' or y == 'Y'): pass else: return None 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)) cols2use = [] mtnums = [] for mt in mts: for i, MT in enumerate(self.MT): if mt == MT: cols2use.append(i) mtnums.append(mt) frame = pd.DataFrame(self.xsdata[:, cols2use]) unit = ' b' if self.isIso else ' cm$^{-1}$' frame.columns = colnames or ['MT ' + str(mt) + unit for mt in mtnums] frame.insert(0, 'Energy (MeV)', self.metadata['egrid']) return frame
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
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 negativeMTDescription(mt): """ Gives descriptions for negative MT numbers used by Serpent for whole materials, for neutrons only. """ if mt > 0: error("Uh, that's not a negative MT.") return XSData.MTdescriptions[mt]
def _postcheck(self): """Make sure Serpent finished printing output.""" if self._totalBranches != self._whereAmI['runIndx']: error("Serpent appears to have stopped printing coefficient\n" "mode output early for file {}".format(self.filePath))