Source code for fudge.gnds.covariances.summed

# <<BEGIN-copyright>>
# <<END-copyright>>

from xData.ancestry import ancestry
from xData import link as linkModule
from pqu import PQU

__metaclass__ = type

[docs]class summedCovariance( ancestry ): """ Covariance matrix stored as sum/difference of other matrices. """ moniker = 'sum' def __init__( self, label, domainMin, domainMax, domainUnit='eV', pointerList=None, coefficients=None ): ancestry.__init__( self ) self.label = label self.domainMin = domainMin #: lower bound of row/column direction. self.domainMax = domainMax #: upper bound of row/column direction. self.domainUnit = domainUnit self.pointerList = pointerList or [] #a list of pointers (type: xData.link.link). Each pointer has a dictionary with entry "coefficient" to use to weight the covariance referred to @property def label( self ) : return( self.__label ) @label.setter def label( self, value ) : if( value is not None ) : if( not( isinstance( value, str ) ) ) : raise TypeError( 'label must be a string' ) self.__label = value
[docs] def check( self, info ): return []
[docs] def convertUnits( self, unitMap ): if self.domainUnit in unitMap: for bound in ('domainMin','domainMax'): pqu = PQU.PQU( getattr(self, bound), self.domainUnit ) newVal = pqu.getValueAs( unitMap[self.domainUnit] ) setattr(self, bound, newVal)
[docs] def fix( self, **kw ): return []
[docs] def plot( self, title = None, scalelabel = None, xlim=None, ylim=None, xlog=False, ylog=False ): self.toCovarianceMatrix().plot( title=title, scalelabel=scalelabel, xlim=xlim, ylim=ylim, xlog=xlog, ylog=ylog )
[docs] def getRowBounds(self,unit=None): """Get the bounds of the row. If unit is specified, return the bounds in that unit.""" if unit is None: return (self.domainMin, self.domainMax) else: factor = PQU.PQU(1, self.domainUnit).getValueAs(unit) return (self.domainMin * factor, self.domainMax * factor)
[docs] def getColumnBounds(self,unit=None): """Get the bounds of the column. If unit is specified, return the bounds in that unit.""" if unit is None: return (self.domainMin, self.domainMax) else: factor = PQU.PQU(1, self.domainUnit).getValueAs(unit) return (self.domainMin * factor, self.domainMax * factor)
[docs] def toCorrelationMatrix( self ): return self.toCovarianceMatrix().toCorrelationMatrix()
[docs] def toCovarianceMatrix( self, label="composed" ): """ Sum the parts to construct the covariance matrix. Note, each part must be converted to an absolute covariance before summing. """ if len( self.pointerList ) == 1: return self.pointerList[0].link['eval'].toCovarianceMatrix() import numpy, copy from .mixed import mixedForm from .base import covarianceMatrix from xData import values as valuesModule from xData import axes as axesModule from xData import array as arrayModule from xData import gridded as griddedModule # We need all the covariances to be either absolute or relative commonType=None def make_common_type(p): cm = p.link['eval'] if isinstance(cm,covarianceMatrix): cm = cm.toCovarianceMatrix() elif isinstance(cm,mixedForm): def inRange(thisBounds, otherBounds): return otherBounds[0] >= thisBounds[0] and otherBounds[1] <= thisBounds[1] newMixed = mixedForm() for ic, c in enumerate(cm.components): if c.getRowBounds() != c.getColumnBounds(): raise ValueError("All components must have their row and column covarianceAxes matching.") c = copy.copy(c) # prune zero rows/columns covarianceMatrices, just in case if isinstance(c, covarianceMatrix): c.removeExtraZeros() # newMixed.addComponent(c) elif isinstance(c, mixedForm): c.makeSafeBounds() # add sub matrix if it fits if inRange(self.getRowBounds(), c.getRowBounds()): newMixed.addComponent(c) cm= newMixed.toCovarianceMatrix() if commonType == 'relative': return cm.toRelative() elif commonType == 'absolute': return cm.toAbsolute() else: return cm # Set up common data using first element in pointerList firstCovMtx = make_common_type(self.pointerList[0]) commonRowAxis = firstCovMtx.matrix.axes[2].copy([])#FIXME: unresolvedLinks are still unresolved! if firstCovMtx.matrix.axes[1].style=='link': commonColAxis = firstCovMtx.matrix.axes[2].copy([])#FIXME: unresolvedLinks are still unresolved! else: commonColAxis = firstCovMtx.matrix.axes[1].copy([])#FIXME: unresolvedLinks are still unresolved! commonMatrixAxis = firstCovMtx.matrix.axes[0].copy( [] )#FIXME: unresolvedLinks are still unresolved! commonType = firstCovMtx.type # We're going to have to merge grids, so we'll need this function to do the dirty work def add_values(v1,v2): v=set() v.update(v1.values) v.update(v2.values) return valuesModule.values(sorted(v)) # First pass through components is to collect bins to set up the common grid + do assorted checking for p in self.pointerList[1:]: cc = make_common_type( p ) #__get_abs_cov_mtx(p) #.link['eval'].toCovarianceMatrix().toAbsolute() # a little recursion to take care of nested covariances if cc.type != commonType: raise ValueError( "Incompatable types in "+str(self.__class__)+": "+str(commonType)+' vs. '+str(cc.type) ) cc.matrix.axes[0].unit = commonMatrixAxis.unit cc.matrix.axes[1].convertToUnit(commonColAxis.unit) cc.matrix.axes[2].convertToUnit(commonRowAxis.unit) commonRowAxis.values.values = add_values(commonRowAxis.values, cc.matrix.axes[2].values) if cc.matrix.axes[1].style=='link': commonColAxis.values.values = add_values(commonColAxis.values, cc.matrix.axes[2].values) else: commonColAxis.values.values = add_values(commonColAxis.values, cc.matrix.axes[1].values) # Now sum up the components commonMatrix = self.pointerList[0]['coefficient'] * firstCovMtx.group( ( commonRowAxis.values.values, commonColAxis.values.values ), ( commonRowAxis.unit, commonColAxis.unit ) ).matrix.array.constructArray() for p in self.pointerList[1:]: cc = make_common_type( p ) # a little recursion to take care of nested covariances commonMatrix += p['coefficient'] * cc.group( ( commonRowAxis.values.values, commonColAxis.values.values ), ( commonRowAxis.unit, commonColAxis.unit ) ).matrix.array.constructArray() # Now create the instance of the resulting covarianceMatrix newAxes = axesModule.axes( labelsUnits={0: (commonMatrixAxis.label, commonMatrixAxis.unit), 1: (commonColAxis.label, commonColAxis.unit), 2: (commonRowAxis.label, commonRowAxis.unit)}) newAxes[2] = axesModule.grid(commonRowAxis.label, commonRowAxis.index, commonRowAxis.unit, style=axesModule.boundariesGridToken, values=commonRowAxis.values) newAxes[1] = axesModule.grid(commonColAxis.label, commonColAxis.index, commonColAxis.unit, style=axesModule.linkGridToken, values=linkModule.link(link=commonRowAxis.values, relative=True)) newAxes[0] = axesModule.axis(commonMatrixAxis.label, commonMatrixAxis.index, commonMatrixAxis.unit) trigdata = commonMatrix[numpy.tri(commonMatrix.shape[0])==1.0].tolist() gridded= griddedModule.gridded2d( axes=newAxes, array=arrayModule.full(shape=commonMatrix.shape,data=trigdata,symmetry=arrayModule.symmetryLowerToken) ) newCov = covarianceMatrix(label=label, type=commonType, matrix=gridded) newCov.setAncestor(self.ancestor) return newCov
[docs] def toAbsolute(self, rowData=None, colData=None): """ Rescales self (if it is a relative covariance) using XYs1d rowData and colData to convert self into an absolute covariance matrix. :param rowData: an XYs1d instance containing data to rescale covariance in the "row direction" :param colData: an XYs1d instance containing data to rescale covariance in the "col direction" .. note:: If the column axis is set to 'mirrorOtherAxis', only rowData is needed. If neither rowData nor colData are specified, you'd better hope that the covariance is already absolute because this will throw an error. :returns: a copy of self, but rescaled and with the type set to absoluteToken """ return self.toCovarianceMatrix().toAbsolute(rowData=rowData, colData=colData)
[docs] def toRelative(self, rowData=None, colData=None): """ Rescales self (if it is a absolute covariance) using XYs1d rowData and colData to convert self into a relative covariance matrix. :param rowData: an XYs1d instance containing data to rescale covariance in the "row direction" :param colData: an XYs1d instance containing data to rescale covariance in the "col direction" .. note:: If the column axis is set to 'mirrorOtherAxis', only rowData is needed. If neither rowData nor colData are specified, you'd better hope that the covariance is already relative because this will throw an error. :returns: a copy of self, but rescaled and with the type set to relativeToken """ return self.toCovarianceMatrix().toRelative(rowData=rowData, colData=colData)
[docs] def toXMLList( self, indent = '', **kwargs ) : """ :param indent: :param kwargs: :return: """ indent2 = indent + kwargs.get( 'incrementalIndent', ' ' ) xmlString = [ '%s<%s label="%s" domainMin="%s" domainMax="%s" domainUnit="%s">' % ( indent, self.moniker, self.label, self.domainMin, self.domainMax, self.domainUnit ) ] xmlString.append( indent2 + '<!-- The matrix for this reaction equals the weighted sum of the following matrices: -->' ) for pointer in self.pointerList: xmlString.append( pointer.toXML( indent2, **kwargs ) ) xmlString[-1] += '</%s>' % self.moniker return xmlString
[docs] def getReferredCovariance( self, pointer ): """ :param pointer: :return: """ if pointer.link is not None: return pointer.link if 'covarianceSuite' in pointer.path: return pointer.link.follow( pointer.path, self.getRootAncestor() ) #elif'reactionSuite' in pointer.path: return link.follow( pointer.path, None ) else : raise ValueError( "Need reference to root node of "+str( pointer.path ) )
[docs] def getUncertaintyVector( self, theData=None, relative=True ): """ Combine all subsections into single uncertainty vector, converting to relative if requested. :returns: an XYs1d instance """ #xys = [ self.getReferredCovariance( p ).getUncertaintyVector( theData=theData, relative=relative ) for p in self.pointerList ] xys = [ p.link['eval'].getUncertaintyVector( theData=theData, relative=relative ) for p in self.pointerList ] coefficients = [ p['coefficient'] for p in self.pointerList ] uncert = coefficients[0] * xys[0] for i, xy in enumerate( xys[1:] ): uncert, xy = uncert.mutualify( 1e-8, 0, 0, xy, 1e-8, 0, 0 ) uncert += coefficients[ i ] * xy return uncert
[docs] @staticmethod def parseXMLNode( element, xPath, linkData ): xPath.append( element.tag ) label = element.get( "label" ) lower = float( element.get("domainMin") ) upper = float( element.get("domainMax") ) summed_ = summedCovariance(label=label, domainMin=lower, domainMax=upper, domainUnit=element.get('domainUnit')) for summandElement in element: link_ = summand.parseXMLNode( summandElement, xPath, linkData ) link_['coefficient'] = float( link_['coefficient'] ) linkData['unresolvedLinks'].append( link_ ) summed_.pointerList.append( link_ ) xPath.pop() return summed_
[docs]class summand( linkModule.link ): moniker = 'summand'