def removeExtraZeros(self): """ Remove all extra zeros from the underlying matrix :return: """ matrix = self.matrix.array.constructArray() rowStart, colStart = 0,0 rowEnd, colEnd = matrix.shape while numpy.all(matrix[rowStart,:]==0): rowStart += 1 while numpy.all(matrix[:,colStart]==0): colStart += 1 while numpy.all(matrix[rowEnd-1,:]==0): rowEnd -= 1 while numpy.all(matrix[:,colEnd-1]==0): colEnd -= 1 matrix = matrix[rowStart:rowEnd, colStart:colEnd] if self.matrix.axes[-2].style=='link': assert (rowStart,rowEnd) == (colStart,colEnd) self.matrix.axes[-1].__values = self.matrix.axes[-1].values[rowStart:rowEnd] else: self.matrix.axes[-1].__values = self.matrix.axes[-1].values[rowStart:rowEnd] self.matrix.axes[-2].__values = self.matrix.axes[-2].values[colStart:colEnd] self.matrix.array = arrayModule.full(shape=matrix.shape,data=matrix[numpy.tri(matrix.shape[0])==1.0].tolist(),symmetry=arrayModule.symmetryLowerToken)
def removeExtraZeros(self, verbose=False): """ Remove all extra zeros from the underlying matrix :return: """ theMatrix = self.matrix.array.constructArray() rowStart, colStart = 0,0 rowEnd, colEnd = theMatrix.shape if verbose: print 'before',theMatrix # Figure out which end rows/columns are full of zeros. We can remove those while numpy.all(theMatrix[rowStart,:]==0): rowStart += 1 while numpy.all(theMatrix[:,colStart]==0): colStart += 1 while numpy.all(theMatrix[rowEnd-1,:]==0): rowEnd -= 1 while numpy.all(theMatrix[:,colEnd-1]==0): colEnd -= 1 theMatrix = theMatrix[rowStart:rowEnd, colStart:colEnd] if verbose: print 'after',theMatrix if verbose: print 'before',self.matrix.axes[-1].toXML(), self.matrix.axes[-2].toXML() if self.matrix.axes[-2].style=='link': assert (rowStart,rowEnd) == (colStart,colEnd) self.matrix.axes[-1].values.values = self.matrix.axes[-1].values[rowStart:rowEnd+1] else: self.matrix.axes[-1].values.values = self.matrix.axes[-1].values[rowStart:rowEnd+1] self.matrix.axes[-2].values.values = self.matrix.axes[-2].values[colStart:colEnd+1] if verbose: print 'after',self.matrix.axes[-1].toXML(), self.matrix.axes[-2].toXML() self.matrix.array = arrayModule.full(shape=theMatrix.shape,data=theMatrix[numpy.tri(theMatrix.shape[0])==1.0].tolist(),symmetry=arrayModule.symmetryLowerToken)
def getCorrelationMatrix( self ): """ Returns the correlation matrix generated from self's covariance matrix. This is essentially a copy of self, but renormalized by the uncertainty: correlation[i,j] = covariance[i,j]/sqrt(covariance[i,i])/sqrt(covariance[j,j]) We reuse the covariance matrix class so that we can do plotting, etc. If you have a correlation matrix, you can safely recover it provided you have the uncertainty vector. Currently only works for a square covariance matrix and not a off-diagonal part of another covariance. """ # Check if is full, square covariance matrix if not self.isSymmetric(): raise TypeError( "Can only extract correlation matrices from symmetric covariance matrices" ) # Rescale result matrix theCorrelationMatrix = self.matrix.array.constructArray() theUncertainty = copy.copy( numpy.diag( theCorrelationMatrix ) ) theUncertainty[ theUncertainty < 0.0 ] = 0.0 theUncertainty = numpy.sqrt( theUncertainty ) for i1 in range( theCorrelationMatrix.shape[0] ): for i2 in range( theCorrelationMatrix.shape[1] ): theCorrelationMatrix[i1,i2] /= ( theUncertainty[i1] * theUncertainty[i2] ) # Return the result tridata = theCorrelationMatrix[numpy.tri(theCorrelationMatrix.shape[0])==1.0].tolist() correlation = griddedModule.gridded2d( axes=self.matrix.axes.copy(),#FIXME: unresolvedLinks still unresolved! array=arrayModule.full(shape=theCorrelationMatrix.shape, data=tridata, symmetry=arrayModule.symmetryLowerToken) ) correlation.axes[0].unit = '' return correlation
def toCovarianceMatrix(self, label="composed"): """ Sum all parts together to build a single matrix. """ if len(self.components) == 1: return self.components[0].toCovarianceMatrix() import fudge.gnd.covariances.base as base import numpy import xData.values as valuesModule import xData.array as arrayModule # Set up common data using first component firstCovMtx = self.components[0].toCovarianceMatrix() if not isinstance(firstCovMtx, base.covarianceMatrix): raise TypeError( "Shoudd have gotten base.covarianceMatrix, instead got %s" % str(firstCovMtx.__class__)) 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 need all the covariances to be either absolute or relative def make_common_type(cm): if commonType == 'relative': return cm.toRelative() else: return cm.toAbsolute() # 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 c in self.components[1:]: cc = make_common_type(c.toCovarianceMatrix( )) # a little recursion to take care of nested covariances if cc.type != commonType: raise ValueError("Incompatible types in %s: %s vs. %s" % (self.__class__, commonType, cc.type)) if cc.matrix.axes[0].unit != commonMatrixAxis.unit: raise ValueError( "covariance matrix components with different units?!? %s vs. %s" % (cc.matrix.axes[0].unit, commonMatrixAxis.unit)) if cc.matrix.axes[1].style != 'link': 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 = numpy.mat( firstCovMtx.group( (commonRowAxis.values.values, commonColAxis.values.values), (commonRowAxis.unit, commonColAxis.unit)).matrix.array.constructArray()) for c in self.components[1:]: cc = make_common_type(c.toCovarianceMatrix( )) # a little recursion to take care of nested covariances commonMatrix += numpy.mat( cc.group( (commonRowAxis.values.values, commonColAxis.values.values), (commonRowAxis.unit, commonColAxis.unit)).matrix.array.constructArray()) # Now create the instance of the resulting covarianceMatrix if all([ component.toCovarianceMatrix().matrix.axes[1].style == 'link' for component in self.components ]): commonColAxis = self.components[0].toCovarianceMatrix( ).matrix.axes[1].copy( []) #FIXME: unresolvedLinks are still unresolved! 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()[0] gridded = griddedModule.gridded2d( axes=newAxes, array=arrayModule.full(shape=commonMatrix.shape, data=trigdata, symmetry=arrayModule.symmetryLowerToken)) newCov = base.covarianceMatrix(label=label, type=commonType, matrix=gridded) newCov.setAncestor(self.ancestor) return newCov
def group( self, groupBoundaries = ( None, None ), groupUnit = ( None, None ) ): ''' Group the matrix in self :param groupBoundaries: a 2 element list containing the group boundaries for the rows and columns (respectively) of the covariance to be regrouped rows go in the first element, columns in the second :param groupUnit: a 2 element list containing the units in which group boundaries are specified for the rows and columns (respectively) of the covariance to be regrouped :returns: the regrouped matrix (an xData.array.full as the array in a gridded2d.matrix) .. note:: We still need to do flux weighting .. rubric:: Regrouping Theory Given a function :math:`f(E)`, we write the grouped data using fudge's ``flat`` interpolation scheme. We note that we could write this scheme as an expansion over basis functions: .. math:: f(E) = \sum_{i=0}^{N+1} w_i(E) * f_i where the weight functions :math:`w_i(E)` are .. math:: w_i(E) = 1 \;\\text{for}\; E_i <= E <= E_{i+1}; \;\; 0 \;\\textrm{otherwise} These weights are an orthogonal (bot not orthonormal) basis, with .. math:: (E_{i+1}-E_i) \delta_{ij} = \int dE w_i(E) * w_j(E) So, to transform from basis :math:`w_i(E)` to :math:`v_i(E)` (which has group boundaries :math:`[ E'_0, ... ]`), do: .. math:: f'_j = \sum_i m_{ji} f_i where :math:`f'` is the regrouped function coefficients and :math:`m_{ji}` is the matrix .. math:: m_{ij} = (E'_{i+1}-E'_i)^{-1} \int dE v_i(E) w_j(E) .. rubric:: Applying regrouping theory to covariance matrices When we are given a covariance matrix :math:`c_{ij}` in ENDF, it is meant to be interpreted as a grouped covariance in both the direction of the matrix rows and the matrix columns. Therefore, we must regroup in both the row direction and the column direction. The ENDF format gives both the group boundaries for the rows and columns. In other words, ENDF gives us the following rule for evaluating the continuous row- column covariance: .. math:: c( E1, E2 ) = \sum_{ij} w_i(E1) w_j(E2) c_{ij} Computing :math:`m_{ij}` as before, .. math:: cc_{ij} = \sum_{i',j'} m_{ii'} c_{i'j'} m_{j'j} It is straightforward to generalize to the case where the row and column bases are different. In the routine below, we abuse :py:class:`xData.XYs1d` to specify the functions :math:`w_i(E)` and use the :py:func:`XYs1d.groupOneFunction()` method to perform the integrals to get the regrouping matrix. We do this separately for the rows and the columns. The matrix multiplication that converts a covariance from one pair of bases (group structures) to another is accomplished using numpy. .. rubric:: An explanation of fudge's 'flat' interpolation Suppose we have a function :math:`f(E)` specified using fudge's `'flat'` interpolation. Then we have :math:`N` entries :math:`[f_0, f_1, ..., f_{N-1}]` and a set of group boundaries :math:`[E_0, E_1, ..., E_N]` and the following rule for interpolation: * Below :math:`E_0`, :math:`f(E)` evaluates to :math:`0.0` * From :math:`E_0 \\rightarrow E_1`, :math:`f(E)` evaluates to :math:`f_0` * From :math:`E_1 \\rightarrow E_2`, :math:`f(E)` evaluates to :math:`f_1` * ... * From :math:`E_{i} \\rightarrow E_{i+1}`, :math:`f(E)` evaluates to :math:`f_i` * ... * From :math:`E_{N-1} \\rightarrow E_N`, :math:`f(E)` evaluates to :math:`f_{N-1}` * Above :math:`E_N`, :math:`f(E)` evaluates to :math:`0.0` ''' # determine where to get the settings for the potentially mirrored second axis if self.matrix.axes[1].style == 'link': axis1index = 2 else: axis1index = 1 # setup the old axes in a form we can (ab)use in the XYs1d class axes2_ = axesModule.axes( labelsUnits={1:( self.matrix.axes[2].label, self.matrix.axes[2].unit ),0:( 'dummy', '' )} ) axes1_ = axesModule.axes( labelsUnits={1:( self.matrix.axes[axis1index].label, self.matrix.axes[axis1index].unit ),0:( 'dummy', '' )} ) # define basis functions for the rows and columns basis2 = XYsModule.XYs1d( axes=axes2_, data=[ ( x, 0.0 ) for x in self.matrix.axes[2].values ], interpolation='flat' ) basis1 = XYsModule.XYs1d( axes=axes1_, data=[ ( x, 0.0 ) for x in self.matrix.axes[axis1index].values ], interpolation='flat' ) basis2 = basis2.convertAxisToUnit( 1, groupUnit[0] ) basis1 = basis1.convertAxisToUnit( 1, groupUnit[1] ) # build the regrouping matrices for the two bases w0 = [] for idx in range( self.matrix.array.shape[0] ): basis2[idx] = ( basis2[idx][0], 1.0 ) w0.append( basis2.groupOneFunction( groupBoundaries[0], norm = 'dx' ) ) basis2[idx] = ( basis2[idx][0], 0.0 ) w0 = numpy.mat( w0 ) w1 = [] for j in range( self.matrix.array.shape[1] ): basis1[j] = ( basis1[j][0], 1.0 ) w1.append( basis1.groupOneFunction( groupBoundaries[1], norm = 'dx' ) ) basis1[j] = ( basis1[j][0], 0.0 ) w1 = numpy.mat( w1 ) # set up the regrouped covariance matrix grouped = copy.copy( self ) grouped.matrix.axes[2].data = groupBoundaries[0] grouped.matrix.axes[1].data = groupBoundaries[1] grouped.matrix.axes[2].unit = groupUnit[0] grouped.matrix.axes[1].unit = groupUnit[1] odata = numpy.mat( self.matrix.array.constructArray() ) gdata = w0.T * odata * w1 trigdata = gdata[numpy.tri(gdata.shape[0])==1.0].tolist()[0] grouped.matrix.array = arrayModule.full(shape=gdata.shape,data=trigdata,symmetry=arrayModule.symmetryLowerToken) return grouped
def toCovarianceMatrix(self): """ Sum all parts together to build a single matrix. FIXME: currently breaks if the 'mixed' section contains a mixture of absolute/relative/correlation matrices. """ if len(self.components) == 1: return self.components[0].toCovarianceMatrix() import fudge.gnd.covariances.base as base import numpy import xData.values as valuesModule import xData.array as arrayModule # set up common data using first component firstCovMtx = self.components[0].toCovarianceMatrix() commonRowAxis = copy.copy(firstCovMtx.matrix.axes[2]) if firstCovMtx.matrix.axes[1].style == 'link': commonColAxis = copy.copy(firstCovMtx.matrix.axes[2]) else: commonColAxis = copy.copy(firstCovMtx.matrix.axes[1]) commonMatrixAxis = copy.copy(firstCovMtx.matrix.axes[0]) 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 c in self.components[1:]: cc = c.toCovarianceMatrix( ) # a little recursion to take care of nested covariances if cc.type != commonType: raise ValueError("Incompatible types in %s: %s vs. %s" % (self.__class__, commonType, cc.type)) if cc.matrix.axes[0].unit != commonMatrixAxis.unit: raise ValueError( "covariance matrix components with different units?!? %s vs. %s" % (cc.matrix.axes[0].unit, commonMatrixAxis.unit)) if cc.matrix.axes[1].style != 'link': cc.matrix.axes[1].convertToUnit(commonColAxis.unit) cc.matrix.axes[2].convertToUnit(commonRowAxis.unit) commonRowAxis.__values = add_values(commonRowAxis.values, cc.matrix.axes[2].values) if cc.matrix.axes[1].style == 'link': commonColAxis.__values = add_values(commonColAxis.values, cc.matrix.axes[2].values) else: commonColAxis.__values = add_values(commonColAxis.values, cc.matrix.axes[1].values) # now sum up the components commonMatrix = numpy.mat( firstCovMtx.group( (commonRowAxis.values, commonColAxis.values), (commonRowAxis.unit, commonColAxis.unit)).matrix.array.constructArray()) for c in self.components[1:]: cc = c.toCovarianceMatrix( ) # a little recursion to take care of nested covariances commonMatrix += numpy.mat( cc.group((commonRowAxis.values, commonColAxis.values), (commonRowAxis.unit, commonColAxis.unit)).matrix.array.constructArray()) # now create the instance of the resulting covarianceMatrix if all([ component.matrix.axes[1].style == 'link' for component in self.components ]): commonColAxis = self.components[0].matrix.axes[1].copy() newAxes = axesModule.axes( labelsUnits={ 0: (commonMatrixAxis.label, commonMatrixAxis.unit), 1: (commonColAxis.label, commonColAxis.unit), 2: (commonRowAxis.label, commonRowAxis.unit) }) newAxes[0] = commonMatrixAxis newAxes[1] = commonColAxis newAxes[2] = commonRowAxis trigdata = commonMatrix[numpy.tri(commonMatrix.shape[0]) == 1.0].tolist()[0] gridded = griddedModule.gridded( axes=newAxes, array=arrayModule.full(shape=commonMatrix.shape, data=trigdata, symmetry=arrayModule.symmetryLowerToken)) return base.covarianceMatrix(type=commonType, matrix=gridded)
def readMF7(mt, mf7): ZA, AWR, LTHR, LAT, LASYM, dum = endfFileToGNDMisc.sixFunkyFloatStringsToIntsAndFloats( mf7[0], range(2, 6)) if LTHR == 1: # coherent elastic scattering line, temps, energies, dummy, data, e_interp, t_interp = readSTable( 1, mf7) temps, energies = map(valuesModule.values, (temps, energies)) if e_interp != 'flat': raise ValueError("unexpected energy interpolation encountered") axes = axesModule.axes(rank=3) axes[2] = axesModule.grid('temperature', 2, 'K', axesModule.pointsGridToken, values=temps, interpolation=t_interp) axes[1] = axesModule.grid('energy_in', 1, 'eV', axesModule.pointsGridToken, values=energies, interpolation=e_interp) axes[0] = axesModule.axis('S_cumulative', 0, 'eV*b') array = arrayModule.full(shape=(len(temps), len(energies)), data=data) Stab = griddedModule.gridded2d(axes, array, label="eval") section = TS.coherentElastic(TS.S_table(Stab)) elif LTHR == 2: # incoherent elastic line, dat = endfFileToGNDMisc.getTAB1(1, mf7) SB = TS.characteristicCrossSection(float(dat['C1']), 'b') e_interp = dat['interpolationInfo'] if len(e_interp) > 1: raise ValueError( "only one interpolation region allowed for T_eff data") e_interp = endfFileToGNDMisc.ENDFInterpolationToGND1d(e_interp[0][1]) t_axes = axesModule.axes(labelsUnits={ 1: ('temperature', 'K'), 0: ('DebyeWallerIntegral', '1/eV') }) if len(dat['data']) == 2 and dat['data'][0] == dat['data'][1]: dat['data'] = dat['data'][0:1] DbW = TS.DebyeWaller(dat['data'], axes=t_axes, interpolation=e_interp) section = TS.incoherentElastic(SB, DbW) elif LTHR == 0: # incoherent inelastic line, listy = endfFileToGNDMisc.getList(1, mf7) LLN, NI, NS, b_n = listy['L1'], listy['NPL'], listy['N2'], listy[ 'data'] if LLN: raise NotImplementedError("LLN != 0 not yet handled!") # b_n array contains information about principal / secondary scattering atoms atoms = [ TS.scatteringAtom(label="0", numberPerMolecule=int(b_n[5]), mass=TS.mass(b_n[2], 'amu'), freeAtomCrossSection=TS.freeAtomCrossSection( b_n[0], 'b'), e_critical=TS.e_critical(b_n[1], 'eV'), e_max=TS.e_max(b_n[3], 'eV')) ] for idx in range(1, NS + 1): functionalForm = { 0.0: 'SCT', 1.0: 'free_gas', 2.0: 'diffusive_motion' }[b_n[6 * idx]] atoms.append( TS.scatteringAtom(label=str(idx), numberPerMolecule=b_n[6 * idx + 5], mass=TS.mass(b_n[6 * idx + 2], 'amu'), freeAtomCrossSection=TS.freeAtomCrossSection( b_n[6 * idx + 1], 'b'), functionalForm=functionalForm)) line, t2header = endfFileToGNDMisc.getTAB2Header(line, mf7) n_betas = int(t2header['NZ']) # read first beta: line, temps, alphas, beta, data, a_interp, t_interp = readSTable( line, mf7) betas = [beta] # read in remaining betas: for idx in range(n_betas - 1): line, temps_, alphas_, beta, data_, a_interp_, t_interp_ = readSTable( line, mf7) if (temps_ != temps or alphas_ != alphas or a_interp_ != a_interp or t_interp_ != t_interp): raise ValueError("inconsistent values!") betas.append(beta) data.extend(data_) temps, betas, alphas = map(valuesModule.values, (temps, betas, alphas)) axes = axesModule.axes(rank=4) axes[3] = axesModule.grid('temperature', 3, 'K', axesModule.pointsGridToken, values=temps, interpolation=t_interp) axes[2] = axesModule.grid( 'beta', 2, '', axesModule.pointsGridToken, values=betas, interpolation=standardsModule.interpolation.flatToken) axes[1] = axesModule.grid('alpha', 1, '', axesModule.pointsGridToken, values=alphas, interpolation=a_interp) axes[0] = axesModule.axis('S_alpha_beta', 0, 'eV*b') arrayShape_orig = (len(betas), len(temps), len(alphas)) data = numpy.array(data).reshape(arrayShape_orig) # ENDF data are stored as 'beta,T,alpha'. Switch order to 'T,beta,alpha': data = numpy.transpose(data, axes=(1, 0, 2)) arrayShape_new = (len(temps), len(betas), len(alphas)) array = arrayModule.full(shape=arrayShape_new, data=data.flatten()) Stab = griddedModule.gridded3d(axes, array, label="eval") S_tables = TS.S_alpha_beta(Stab) # last read T_eff tables. There must be at least one (for the principal scattering atom), plus more for # any other atoms that specify the short-collision-time approximation: line, t_eff = readT_effective(line, mf7) atoms[0].T_effective = t_eff for atom in atoms[1:]: if atom.functionalForm == 'SCT': line, t_eff = readT_effective(line, mf7) atom.T_effective = t_eff section = TS.incoherentInelastic(S_tables, calculatedAtThermal=LAT, asymmetric=LASYM, atoms=atoms) if line != len(mf7): raise ValueError("Trailing data left in MT%i MF7!" % mt) return LTHR, section
def toCovarianceMatrix(self): ''' 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 xData import values as valuesModule from xData import axes as axesModule from xData import array as arrayModule from xData import gridded as griddedModule # utility function to get a component as an absolute matrix over the correct row/column bounds # need special coding if mixed since only need the part of a mixedForm that overlaps with the current # covariance def __get_abs_cov_mtx(ptr): c = ptr.link['eval'] if isinstance(c, mixedForm): c = c.shrinkToBounds(self.getRowBounds()) return c.toCovarianceMatrix() # set up common data using first element in pointerList firstCovMtx = __get_abs_cov_mtx( self.pointerList[0] ) #.link['eval'].toCovarianceMatrix().toAbsolute() commonRowAxis = copy.copy(firstCovMtx.matrix.axes[2]) if firstCovMtx.matrix.axes[1].style == 'link': commonColAxis = copy.copy(firstCovMtx.matrix.axes[2]) else: commonColAxis = copy.copy(firstCovMtx.matrix.axes[1]) commonMatrixAxis = copy.copy(firstCovMtx.matrix.axes[0]) commonType = firstCovMtx.type coefficients = [p['coefficient'] for p in self.pointerList] # 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 = __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 = add_values(commonRowAxis.values, cc.matrix.axes[2].values) if cc.matrix.axes[1].style == 'link': commonColAxis.__values = add_values(commonColAxis.values, cc.matrix.axes[2].values) else: commonColAxis.__values = add_values(commonColAxis.values, cc.matrix.axes[1].values) # now sum up the components commonMatrix = self.pointerList[0]['coefficient'] * firstCovMtx.group( (commonRowAxis.values, commonColAxis.values), (commonRowAxis.unit, commonColAxis.unit)).matrix.array.constructArray() for p in self.pointerList[1:]: cc = p.link['eval'].toCovarianceMatrix( ) # a little recursion to take care of nested covariances commonMatrix += p['coefficient'] * cc.group( (commonRowAxis.data, commonColAxis.data), (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[0] = commonMatrixAxis newAxes[1] = commonColAxis newAxes[2] = commonRowAxis trigdata = commonMatrix[numpy.tri(commonMatrix.shape[0]) == 1.0].tolist()[0] return griddedModule.gridded( axes=newAxes, array=arrayModule.full(shape=commonMatrix.shape, data=trigdata, symmetry=arrayModule.symmetryLowerToken))
def setUp(self): # ...................... example matrix 'a' ...................... axes = axesModule.axes( labelsUnits={ 0: ('matrix_elements', 'b**2'), 1: ('column_energy_bounds', 'MeV'), 2: ('row_energy_bounds', 'MeV') }) axes[2] = axesModule.grid(axes[2].label, axes[2].index, axes[2].unit, style=axesModule.boundariesGridToken, values=valuesModule.values([ 1.0000E-07, 1.1109E-01, 1.3534E+00, 1.9640E+01 ])) axes[1] = axesModule.grid(axes[1].label, axes[1].index, axes[1].unit, style=axesModule.linkGridToken, values=linkModule.link(link=axes[2].values, relative=True)) myMatrix = arrayModule.full((3, 3), [4.0, 1.0, 9.0, 0.0, 0.0, 25.0], symmetry=arrayModule.symmetryLowerToken) self.a = covariances.covarianceMatrix( 'eval', matrix=griddedModule.gridded2d(axes, myMatrix), type=covariances.tokens.relativeToken) # ...................... example matrix 'b' ...................... axes = axesModule.axes( labelsUnits={ 0: ('matrix_elements', 'b**2'), 1: ('column_energy_bounds', 'MeV'), 2: ('row_energy_bounds', 'MeV') }) axes[2] = axesModule.grid(axes[2].label, axes[2].index, axes[2].unit, style=axesModule.boundariesGridToken, values=valuesModule.values( [1.0e-5, 0.100, 1.0, 20.0])) axes[1] = axesModule.grid(axes[1].label, axes[1].index, axes[1].unit, style=axesModule.linkGridToken, values=linkModule.link(link=axes[2].values, relative=True)) myMatrix = arrayModule.full((3, 3), [4.0, 1.0, 9.0, 0.0, 0.0, 25.0], symmetry=arrayModule.symmetryLowerToken) self.b = covariances.covarianceMatrix( 'eval', matrix=griddedModule.gridded2d(axes, myMatrix), type=covariances.tokens.relativeToken) # ...................... example matrix 'c' ...................... axes = axesModule.axes( labelsUnits={ 0: ('matrix_elements', 'b**2'), 1: ('column_energy_bounds', 'MeV'), 2: ('row_energy_bounds', 'MeV') }) axes[2] = axesModule.grid(axes[2].label, axes[2].index, axes[2].unit, style=axesModule.boundariesGridToken, values=valuesModule.values([ 1.0000E-07, 6.7380E-02, 1.1109E-01, 1.3534E+00 ])) axes[1] = axesModule.grid(axes[1].label, axes[1].index, axes[1].unit, style=axesModule.linkGridToken, values=linkModule.link(link=axes[2].values, relative=True)) myMatrix = arrayModule.full((3, 3), [4.0, 1.0, 9.0, 0.0, 0.0, 25.0], symmetry=arrayModule.symmetryLowerToken) self.c = covariances.covarianceMatrix( 'eval', matrix=griddedModule.gridded2d(axes, myMatrix), type=covariances.tokens.relativeToken) # ...................... combine them for example matrix 'abc' ...................... abc = covariances.mixed.mixedForm(components=[self.a, self.b, self.c]) # FIXME: learn how to add abc to a section & to a covarianceSuite!, sumabc is built wrong! # ...................... 'sumabc' is just a way to exercise the summed class ...................... bds = abc.getRowBounds() self.sumabc = covariances.summed.summedCovariance( label='test', domainMin=float(bds[0]), domainMax=float(bds[1]), domainUnit=abc[0].matrix.axes[-1].unit, pointerList=[ linkModule.link(link=abc, path=abc.toXLink(), coefficient=1.0) ])
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