def check(self, info): """ check product multiplicity, distribution and breakup products (if applicable) """ from fudge.gnd import warning warnings = [] multWarnings = self.multiplicity.check(info) if multWarnings: warnings.append(warning.context("Multiplicity:", multWarnings)) if ((self.label in info['transportables']) and (not self.distribution.hasData())): warnings.append(warning.missingDistribution(self.label, self)) distributionWarnings = self.distribution.check(info) if distributionWarnings: warnings.append( warning.context("Distribution:", distributionWarnings)) if self.outputChannel is not None: parentIsTwoBody = info['isTwoBody'] info['isTwoBody'] = isinstance(self.outputChannel, channelsModule.twoBodyOutputChannel) for decayProduct in self.outputChannel: decayWarnings = decayProduct.check(info) if decayWarnings: warnings.append( warning.context( "Decay product: %s" % decayProduct.label, decayWarnings)) info['isTwoBody'] = parentIsTwoBody # reset to parent channel return warnings
def check(self, **kwargs): """ Check all data in the reactionSuite, returning a list of warnings. """ from fudge.gnd import warning options = {} for key in kwargs: if key in options: options[key] = kwargs[key] else: raise KeyError, "check() received unknown keyword argument '%s'" % key # assemble some useful info, to be handed down to children's check() functions: info = { 'reactionSuite': self, } info.update(options) warnings = [] result = warning.context( 'ReactionSuite: %s + %s' % (self.projectile, self.material), warnings) result.info = info return result
def check(self, info): from fudge.gnd import warning warnings = [] for term in self.ancestryMembers: fwarnings = getattr(self, term).check(info) if fwarnings: warnings.append(warning.context('%s:' % term, fwarnings)) return warnings
def check(self, info): from fudge.gnd import warning warnings = [] for form in self.forms: fwarnings = self.forms[form].check(info) if fwarnings: warnings.append(warning.context('%s:' % form, fwarnings)) return warnings
def check(self, info): from fudge.gnd import warning warnings = [] matrixWarnings = self.matrix.check(info) if matrixWarnings: warnings.append( warning.context("Model parameter covariances", matrixWarnings)) return warnings
def check(self, info): from fudge.gnd import warning warnings = [] for particle in self: particleWarnings = particle.check(info) if particleWarnings: warnings.append( warning.context("%s" % particle, particleWarnings)) return warnings
def check(self, info): from fudge.gnd import warning warnings = [] crossSectionWarnings = self.crossSection.check(info) if crossSectionWarnings: warnings.append( warning.context("Cross section:", crossSectionWarnings)) return warnings
def check(self, info): from fudge.gnd import warning warnings = [] for section in (self.scatteringRadius, self.resolved, self.unresolved): if section is not None: warningList = section.check(info) if warningList: warnings.append( warning.context(section.moniker, warningList)) return warnings
def check( self, info ): from fudge.gnd import warning warnings = [] for Lvalue in self: Lvalue_warnings = Lvalue.check( info ) if Lvalue_warnings: warnings.append( warning.context( '%s L=%i vs %i' % (Lvalue.moniker,Lvalue.L1,Lvalue.L2), Lvalue_warnings ) ) return warnings
def check(self, info): from fudge.gnd import warning warnings = [] if self.parameters.nParameters != self.matrix.nrows: warnings.append("need real warning here") # FIXME matrixWarnings = self.matrix.check(info) if matrixWarnings: warnings.append( warning.context("Model parameter covariances", matrixWarnings)) return warnings
def check(self, info): from fudge.gnd import warning warnings = [] for idx, region in enumerate(self): regionWarnings = region.check(info) if regionWarnings: warnings.append( warning.context("Region %d:" % idx, regionWarnings)) return warnings
def check(self, info): """ check each section """ from fudge.gnd import warning warnings = [] for form in self: formWarnings = form.check(info) if formWarnings: warnings.append( warning.context("Form '%s':" % form.label, formWarnings)) return warnings
def check(self, info): from fudge.gnd import warning warnings = [] for form in self: formWarnings = form.check(info) if formWarnings: warnings.append( warning.context('form "%s":' % form.label, formWarnings)) return warnings
def check(self, info): from fudge.gnd import warning warnings = [] for component in self.components: componentWarnings = component.check(info) if componentWarnings: warnings.append( warning.context('Component %s' % component.label, componentWarnings)) #if warnings: # warnings = [warning.context('Section "%s": %s' % (self.id, form), warnings)] return warnings
def check(self, info): from fudge.gnd import warning warnings = [] for idx, region in enumerate(self): regionWarnings = region.check(info) if regionWarnings: warnings.append( warning.context( 'region index %i: %s' % (idx, region.moniker), regionWarnings)) return warnings
def checkSubform(subform, contextMessage): distributionErrors = [] if hasattr(subform, 'domainMin') and ( subform.domainMin, subform.domainMax) != info['crossSectionDomain']: domain = (subform.domainMin, subform.domainMax) # For gamma products, domainMin should be >= cross section start, upper bounds should match. if (self.getAncestor().id == IDsPoPsModule.photon): startRatio = subform.domainMin / info[ 'crossSectionDomain'][0] endRatio = subform.domainMax / info[ 'crossSectionDomain'][1] if (startRatio < 1 - standardsModule.floats.epsilon or endRatio < 1 - standardsModule.floats.epsilon or endRatio > 1 + standardsModule.floats.epsilon): distributionErrors.append( warning.domain_mismatch( *(domain + info['crossSectionDomain']), obj=subform)) # For all other products, check lower and upper edges: only warn if they disagree by > eps else: for e1, e2 in zip(domain, info['crossSectionDomain']): ratio = e1 / e2 if (ratio < 1 - standardsModule.floats.epsilon or ratio > 1 + standardsModule.floats.epsilon): distributionErrors.append( warning.domain_mismatch( *(domain + info['crossSectionDomain']), obj=subform)) break if not hasattr(subform, 'check'): distributionErrors.append( warning.NotImplemented(subform.moniker, subform)) if info['failOnException']: raise NotImplementedError( "Checking distribution form '%s'" % subform.moniker) else: distributionErrors += subform.check(info) if distributionErrors: warnings.append( warning.context( contextMessage + " - %s:" % subform.moniker, distributionErrors))
def fix(self, **kwargs): ''' Apply basic fixes to a covariance :param bool removeNegativeEVs: Should we remove eigenspaces corresponding to negative eigenvalues? (Default: True) :param bool removeSmallEVs: Should we remove eigenspaces corresponding to small eigenvalues? (Default: False) :param bool fixUncLimits: Should we fix the uncertainties to lie within bounds imposed by minRelUnc and maxRelUnc? (Default: False) :param minRelUnc: Minimum allowable uncertainty for this covariance :type minRelUnc: float or None :param maxRelUnc: Maximum allowable uncertainty for this covariance :type maxRelUnc: float or None :param theData: Reference to the data that accompanies this covariance so that we may convert between absolute and relative covariance as needed. :type theData: instance or None ''' from fudge.gnd import warning # default input options options = { 'removeNegativeEVs': True, 'removeSmallEVs': False, 'fixUncLimits': False, 'minRelUnc': None, 'maxRelUnc': None, 'theData': None, 'negativeEigenTolerance': -1e-6, # ignore smaller negative eigenvalues 'eigenvalueRatioTolerance': 1e-8, # warn if smallest eival < 1e-8 * biggest 'eigenvalueAbsoluteTolerance': 1e-14, } for key in kwargs: if key in options: options[key] = kwargs[key] else: raise KeyError, "fix() received unknown keyword argument '%s'" % key # assemble some useful info, to be handed down to children's check() functions: info = {'covarianceSuite': self} info.update(options) # do the fixing warnings = [] for section_ in self.sections: warnings += section_.fix(**info) return warning.context( 'CovarianceSuite: %s + %s' % (self.projectile, self.target), warnings)
def check(self, info): warnings = [] emax = -1 for level in sorted(self.levels): levelWarnings = self.levels[level].check(info) if levelWarnings: warnings.append( warning.context('Level %s' % level, levelWarnings)) if type(level) is not int: continue # 'c' and 'u' levels may be out of order enow = self.levels[level].getLevelAsFloat('eV') if enow <= emax: warnings.append( warning.discreteLevelsOutOfOrder(level, self.levels[level])) else: emax = enow return warnings
def check(self, info): from fudge.gnd import warning warnings = [] RS = info['reactionSuite'] target = RS.PoPs[RS.target] projectile = RS.PoPs[RS.projectile] identicalParticles = target is projectile if identicalParticles and not self.identicalParticles: warnings.append(warning.missingCoulombIdenticalParticlesFlag()) elif not identicalParticles and self.identicalParticles: warnings.append( warning.incorrectCoulombIdenticalParticlesFlag( RS.projectile, RS.target)) if self.data is not None: dataWarnings = self.data.check(info) if dataWarnings: warnings.append( warning.context('%s:' % self.data.moniker, dataWarnings)) return warnings
and (edep - (ein + Qsum)) > PQUModule.PQU( info['dEnergyBalanceAbsolute']).getValueAs( totalEDep.axes[0].unit)): edepWarnings.append( warning.energyImbalance( PQUModule.PQU(ein, totalEDep.axes[0].unit), i, ein + Qsum, energyDepositedPerProduct(energyDep, ein), self)) if edepWarnings: context = "Energy balance" if decay: context += " (after decay)" context += " for products: " + ', '.join( [prod.id for prod in products]) warnings.append(warning.context(context, edepWarnings)) # now recursively check decay products, if any: for pidx, currentProd in enumerate(products): if currentProd.outputChannel is not None: checkProductsForEnergyBalance( products[:pidx] + [p for p in currentProd.outputChannel] + products[pidx + 1:], Qs + [currentProd.outputChannel.Q.getConstant()], decay=True, fission= False # FIXME what about spontaneous fission decay? ) # end of helper function checkProductsForEnergyBalance
def check(self, **kwargs): """ Check all covariance sections, returning a list of warnings. :keyword bool checkUncLimits: Should we check the uncertainty limits? (default: True) :keyword float minRelUnc: Minimum allowable relative uncertainty (default: 0.0) :keyword float maxRelUnc: Maximum allowable relative uncertainty (default: 10.0) :keyword theData: A reference to the data for this covariance. This is useful for converting between relative and absolute covariance (default: None) :keyword float negativeEigenTolerance: Ignore negative eigenvalues smaller than this (default: -1e-6) :keyword float eigenvalueRatioTolerance: Warn if smallest eigenvalue < this value * biggest (default: 1e-8) :keyword float eigenvalueAbsoluteTolerance: Warn if smallest eigenvalue < this value (default: 1e-14) :rtype: warning.context """ from fudge.gnd import warning # default input options options = { 'checkUncLimits': True, 'minRelUnc': 0.0, 'maxRelUnc': 10.0, 'theData': None, 'negativeEigenTolerance': -1e-6, # ignore smaller negative eigenvalues 'eigenvalueRatioTolerance': 1e-8, # warn if smallest eival < 1e-8 * biggest 'eigenvalueAbsoluteTolerance': 1e-14, } for key in kwargs: if key in options: options[key] = kwargs[key] else: raise KeyError, "check() received unknown keyword argument '%s'" % key # assemble some useful info, to be handed down to children's check() functions: info = {'covarianceSuite': self, 'style': 'eval'} info.update(options) warnings = [] #: summedReactions are sums of other sections, but that opens the possibility of a cyclic dependency #: check for that, using algorithm taken from #: http://neopythonic.blogspot.com/2009/01/detecting-cycles-in-directed-graph.html def find_cycle(NODES, EDGES, style): todo = set(NODES) while todo: node = todo.pop() stack = [node] while stack: top = stack[-1] for node in EDGES(top, style): if node in stack: return stack[stack.index(node):] if node in todo: stack.append(node) todo.remove(node) break else: # this node is not in a cycle node = stack.pop() return None def get_edges(section_, style): #: return list of all pointers from this section natDat = section_[style] if isinstance(natDat, summed.summedCovariance): return [v.link for v in natDat.pointerList] elif isinstance(natDat, mixed.mixedForm): edges = [] for part in natDat: if isinstance(part, summed.summedCovariance): edges += [v.link for v in part.pointerList] return edges nodes = [ sec for sec in self.sections if get_edges(sec, info['style']) ] # sections that contain pointers if nodes: cycle = find_cycle(nodes, get_edges, info['style']) if cycle: warnings.append(warning.cyclicDependency(cycle)) # check each section for section_ in self.sections: sectionWarnings = section_.check(info) if sectionWarnings: warnings.append( warning.context("Section '%s':" % section_.label, sectionWarnings)) return warning.context( 'CovarianceSuite: %s + %s' % (self.projectile, self.target), warnings)
def check(self, info): """ This method is usually not called directly. Use reactionSuite.check() instead. Checks cross section and outputChannel (and differential cross sections if available). Checks include: do Z/A balance? do Q-value and thresholds agree? Does cross section domain agree with each product distribution/multiplicity domain? Does energy balance? @:param info: dict @:return list of warnings """ from fudge.gnd import warning from . import production as productionModule from ..differentialCrossSection.CoulombElastic import CoulombDepositionNotSupported warnings = [] reactionSuite = self.getRootAncestor() def particleZA(particleID): particle = reactionSuite.PoPs[particleID] return (miscPoPsModule.ZA(particle)) try: # BRB6 hardwired info['Q'] = self.getQ('eV') except ValueError: pass cpcount = sum([(particleZA(prod.id) / 1000) > 0 for prod in self.outputChannel]) info['CoulombOutputChannel'] = cpcount > 1 differentialCrossSectionWarnings = self.dCrossSection_dOmega.check( info) if differentialCrossSectionWarnings: warnings.append( warning.context("dCrossSection_dOmega:", differentialCrossSectionWarnings)) crossSectionWarnings = self.crossSection.check(info) if crossSectionWarnings: warnings.append( warning.context("Cross section:", crossSectionWarnings)) if 'Q' in info: del info['Q'] del info['CoulombOutputChannel'] if info['crossSectionOnly']: return warnings # otherwise continue to check outputs # compare calculated and listed Q-values: if not isinstance( self, productionModule.production ): # can't reliably compute Q for production reactions try: Q = self.getQ('eV') Qcalc = info['availableEnergy_eV'] for prod in self.outputChannel: try: Qcalc -= prod.getMass( 'eV/c**2') * prod.multiplicity.getConstant() except Exception: # multiplicity is not constant if (prod.id == IDsPoPsModule.photon): continue raise ValueError, "Non-constant multiplicity" if abs(Q - Qcalc) > PQUModule.PQU(info['dQ']).getValueAs('eV'): warnings.append( warning.Q_mismatch(PQUModule.PQU(Qcalc, 'eV'), PQUModule.PQU(Q, 'eV'), self)) except ValueError: pass # this test only works if multiplicity and Q are both constant for all non-gamma products if not (isinstance(self.outputChannel, channelsModule.sumOfRemainingOutputChannels) or self.outputChannel.isFission() or isinstance(self, productionModule.production)): # check that ZA balances: ZAsum = 0 for product in self.outputChannel: if (product.id == IDsPoPsModule.photon): continue ZAsum += particleZA( product.id) * product.multiplicity.getConstant() if ZAsum != info['compoundZA']: warnings.append(warning.ZAbalanceWarning(self)) if self.outputChannel.isFission(): from fudge.gnd.channelData.fissionEnergyReleased import fissionEnergyReleased if isinstance(self.outputChannel.Q.evaluated, fissionEnergyReleased): info[ 'crossSectionDomain'] = self.crossSection.domainMin, self.crossSection.domainMax FERwarnings = self.outputChannel.Q.evaluated.check(info) if FERwarnings: warnings.append( warning.context("fissionEnergyReleased:", FERwarnings)) del info['crossSectionDomain'] # disabling for now: only complain if distributions are missing for transportables: """ if (not any( [product.distributions.components for product in self.outputChannel] ) and not any( [dProd.distributions.components for prod in [p for p in self.outputChannel if p.outputChannel is not None] for dProd in prod.outputChannel] ) ): # no distributions found for any reaction product or subsequent decay product warnings.append( warning.noDistributions( self ) ) return warnings """ info[ 'crossSectionDomain'] = self.crossSection.domainMin, self.crossSection.domainMax info['isTwoBody'] = isinstance(self.outputChannel, channelsModule.twoBodyOutputChannel) for product in self.outputChannel: productWarnings = product.check(info) if productWarnings: warnings.append( warning.context("Product: %s" % product.label, productWarnings)) del info['crossSectionDomain'] del info['isTwoBody'] if info['checkEnergyBalance'] and not isinstance( self, productionModule.production): # Calculate energy deposition data for all products, and for decay products. # Then recursively check the product list for energy balance at each step of the reaction/decay # At each step, if we have energy deposition for *every* product in the list, we can rigorously check # energy balance. Otherwise, can only check that we don't exceed available energy. try: self.calculateAverageProductData( style=info['averageProductDataStyle'], **info['averageProductDataArgs']) except CoulombDepositionNotSupported, e: warnings.append( warning.SkippedCoulombElasticEnergyDeposition(self)) except Exception, e: warnings.append( warning.EnergyDepositionExceptionRaised(str(e), self)) if info['failOnException']: raise return warnings