def validate(self, qstring, pos): text = str(qstring) if text == '-': return (self.Valid, pos) try: # this test is needed even if pyflakes complains! float(text) return (self.Invalid, pos) except: pass if text.endswith(' '): return (self.Invalid, pos) if Elements.isValidFormula(text): return (self.Valid, pos) elif Elements.isValidMaterial(text): return (self.Valid, pos) else: return (self.Invalid, pos)
def _checkDensityThickness(self, text, row): try: currentDensity = float(str(self.text(row, 3))) except: currentDensity = 0.0 try: currentThickness = float(str(self.text(row, 4))) except: currentThickness = 0.0 defaultDensity = -1.0 defaultThickness = -0.1 #check if default density is there if Elements.isValidFormula(text): #check if single element if text in Elements.Element.keys(): defaultDensity = Elements.Element[text]['density'] else: elts = [ w for w in re.split('[0-9]', text) if w != ''] nbs = [ int(w) for w in re.split('[a-zA-Z]', text) if w != ''] if len(elts) == 1 and len(nbs) == 1: defaultDensity = Elements.Element[elts[0]]['density'] elif Elements.isValidMaterial(text): key = Elements.getMaterialKey(text) if key is not None: if 'Density' in Elements.Material[key]: defaultDensity = Elements.Material[key]['Density'] if 'Thickness' in Elements.Material[key]: defaultThickness = Elements.Material[key]['Thickness'] if defaultDensity >= 0.0: self.setText(row, 3, "%g" % defaultDensity) elif currentDensity <= 0: # should not be better to raise an exception if the # entered density or thickness were negative? self.setText(row, 3, "%g" % 1.0) if defaultThickness >= 0.0: self.setText(row, 4, "%g" % defaultThickness) elif currentThickness <= 0.0: # should not be better to raise an exception if the # entered density or thickness were negative? self.setText(row, 4, "%g" % 0.1)
def processFitResult(self, config=None, fitresult=None, elementsfrommatrix=False, fluorates=None, addinfo=False): # I should check if fit was successful ... if fitresult is None: fitresult = self.fitresult else: self.fitresult = fitresult if config is None: config = self.config else: self.config = config if 'usemultilayersecondary' not in self.config: self.config['usemultilayersecondary'] = 0 if 'usexrfmc' not in self.config: self.config['usexrfmc'] = 0 secondary = self.config['usemultilayersecondary'] xrfmcSecondary = self.config['usexrfmc'] if secondary and xrfmcSecondary: txt = "Only one of built-in secondary and Monte Carlo correction can be used" raise ValueError(txt) # get attenuators and matrix from fit attenuators = [] beamfilters = [] funnyfilters = [] matrix = None detectoratt = None multilayer = None for attenuator in fitresult['result']['config']['attenuators'].keys(): if not fitresult['result']['config']['attenuators'][attenuator][0]: continue if attenuator.upper() == "MATRIX": matrix = fitresult['result']['config']['attenuators'][ attenuator][1:4] alphain = fitresult['result']['config']['attenuators'][ attenuator][4] alphaout = fitresult['result']['config']['attenuators'][ attenuator][5] elif attenuator.upper()[:-1] == "BEAMFILTER": beamfilters.append(fitresult['result']['config']['attenuators']\ [attenuator][1:]) elif attenuator.upper() == "DETECTOR": detectoratt = fitresult['result']['config']['attenuators'][ attenuator][1:] else: if len(fitresult['result']['config']['attenuators'][attenuator] [1:]) == 4: fitresult['result']['config']['attenuators'][ attenuator].append(1.0) if abs(fitresult['result']['config']['attenuators'][attenuator] [4] - 1.0) > 1.0e-10: #funny attenuator funnyfilters.append(fitresult['result']['config']['attenuators']\ [attenuator][1:]) else: attenuators.append(fitresult['result']['config']['attenuators']\ [attenuator][1:]) if matrix is None: raise ValueError("Invalid or undefined sample matrix") if matrix[0].upper() == "MULTILAYER": layerlist = fitresult['result']['config']['multilayer'].keys() layerlist.sort() for layer in layerlist: if fitresult['result']['config']['multilayer'][layer][0]: if multilayer is None: multilayer = [] multilayer.append( fitresult['result']['config']['multilayer'][layer][1:]) if not Elements.isValidMaterial(multilayer[-1][0]): raise ValueError("Material %s is not defined" % multilayer[-1][0]) else: layerlist = ["Layer0"] multilayer = [matrix] if not Elements.isValidMaterial(matrix[0]): raise ValueError("Material %s is not defined" % matrix[0]) if xrfmcSecondary and (len(layerlist) > 1): txt = "Multilayer Monte Carlo correction not implemented yet" raise ValueError(txt) energyList = fitresult['result']['config']['fit']['energy'] if energyList is None: raise ValueError("Invalid energy") if type(energyList) != type([]): energyList = [energyList] flagList = [1] weightList = [1.0] else: flagList = fitresult['result']['config']['fit']['energyflag'] weightList = fitresult['result']['config']['fit']['energyweight'] finalEnergy = [] finalWeight = [] finalFlag = [] for idx in range(len(energyList)): if flagList[idx]: energy = energyList[idx] if energy is None: raise ValueError(\ "Energy %d isn't a valid energy" % idx) if energy <= 0.001: raise ValueError(\ "Energy %d with value %f isn't a valid energy" %\ (idx, energy)) if weightList[idx] is None: raise ValueError(\ "Weight %d isn't a valid weight" % idx) if weightList[idx] < 0.0: raise ValueError(\ "Weight %d with value %f isn't a valid weight" %\ (idx, weightList[idx])) finalEnergy.append(energy) finalWeight.append(weightList[idx]) finalFlag.append(1) totalWeight = sum(weightList) if totalWeight == 0.0: raise ValueError("Sum of energy weights is 0.0") weightList = [x / totalWeight for x in finalWeight] energyList = finalEnergy flagList = finalFlag # get elements list from fit, not from matrix groupsList = fitresult['result']['groups'] * 1 if type(groupsList) != type([]): groupsList = [groupsList] todelete = [] for i in range(len(groupsList)): ele = groupsList[i].split()[0] if len(ele) > 2: todelete.append(i) if len(todelete): todelete.reverse() for i in todelete: del groupsList[i] elements = [] newelements = [] for group in groupsList: splitted = group.split() ele = splitted[0] newelements.append( [Elements.getz(splitted[0]), splitted[0], splitted[1]]) if len(elements): if elements[-1] != ele: elements.append(ele) else: elements.append(ele) newelements.sort() elements.sort() if not config['useattenuators']: attenuators = None funnyfilters = None #import time #t0=time.time() if elementsfrommatrix: newelementsList = [] for ilayer in range(len(multilayer)): pseudomatrix = multilayer[ilayer] eleDict = Elements.getMaterialMassFractions([pseudomatrix[0]], [1.0]) if eleDict == {}: raise ValueError(\ "Invalid layer material %s" % pseudomatrix[0]) keys = eleDict.keys() for ele in keys: for group in newelements: if ele == group[1]: if not group in newelementsList: newelementsList.append(group) newelementsList.sort() fluo0 = Elements.getMultilayerFluorescence( multilayer, energyList, layerList=None, weightList=weightList, flagList=weightList, fulloutput=1, beamfilters=beamfilters * 1, attenuators=attenuators * 1, elementsList=newelementsList * 1, alphain=alphain, alphaout=alphaout, cascade=True, detector=detectoratt, funnyfilters=funnyfilters * 1, forcepresent=0, secondary=secondary) fluototal = fluo0[0] fluolist = fluo0[1:] else: if matrix[0].upper() != "MULTILAYER": multilayer = [matrix * 1] if fluorates is None: fluo0 = Elements.getMultilayerFluorescence( multilayer, energyList, layerList=None, weightList=weightList, flagList=flagList, fulloutput=1, beamfilters=beamfilters * 1, attenuators=attenuators * 1, elementsList=newelements * 1, alphain=alphain, alphaout=alphaout, cascade=True, detector=detectoratt, funnyfilters=funnyfilters * 1, forcepresent=1, secondary=secondary) else: fluo0 = fluorates fluototal = fluo0[0] fluolist = fluo0[1:] #I'll need total fluo element by element at some point #print "getMatrixFluorescence elapsed = ",time.time()-t0 if config['usematrix']: present = [] referenceLayerDict = {} materialComposition = [] for ilayer in range(len(multilayer)): pseudomatrix = multilayer[ilayer] * 1 #get elemental composition from matrix materialComposition.append( Elements.getMaterialMassFractions([pseudomatrix[0]], [1.0])) keys = materialComposition[-1].keys() materialElements = [[Elements.getz(x), x] for x in keys] materialElements.sort() for z, key in materialElements: for ele in elements: if key == ele: present.append(key) if not (ele in referenceLayerDict): referenceLayerDict[ele] = [] referenceLayerDict[ele].append(ilayer) if len(present) == 0: text = "Matrix must contain at least one fitted element\n" text += "in order to estimate flux and efficiency from it." raise ValueError(text) referenceElement = config['reference'].replace(' ', "") if len(referenceElement) and (referenceElement.upper() != 'AUTO'): if Elements.isValidFormula(referenceElement): if len(referenceElement) == 2: referenceElement = referenceElement.upper()[0] +\ referenceElement.lower()[1] elif len(referenceElement) == 1: referenceElement = referenceElement.upper()[0] if not (referenceElement in elements): text = "Element %s not among fitted elements" % referenceElement raise ValueError(text) elif not (referenceElement in present): text = "Element %s not among matrix elements" % referenceElement raise ValueError(text) referenceLayers = referenceLayerDict[referenceElement] else: text = "Element %s not a valid element" % referenceElement raise ValueError(text) elif len(present) == 1: referenceElement = present[0] referenceLayers = referenceLayerDict[referenceElement] else: # how to choose? Best fitted, largest fit area or # greater concentration? or better to give a weight to # the different shells, energies , ...? referenceElement = present[0] fom = self._figureOfMerit(present[0], fluototal, fitresult) for key in present: #if materialComposition[key] > materialComposition[referenceElement]: # referenceElement = key newfom = self._figureOfMerit(key, fluototal, fitresult) if newfom > fom: fom = newfom referenceElement = key referenceLayers = referenceLayerDict[referenceElement] referenceTransitions = None for group in groupsList: item = group.split() element = item[0] if element == referenceElement: transitions = item[1] + " xrays" if referenceTransitions is None: referenceTransitions = transitions referenceGroup = group elif (referenceTransitions[0] == transitions[0]) and\ (referenceTransitions[0] == 'L'): # this prevents selecting L1 and selects L3 although # given the appropriate area, L2 can be a safer choice. referenceGroup = group referenceTransitions = transitions elif referenceTransitions is not None: break theoretical = 0.0 for ilayer in referenceLayers: if elementsfrommatrix: theoretical += fluolist[ilayer][referenceElement]['rates'][referenceTransitions] * \ fluolist[ilayer][referenceElement]['mass fraction'] else: theoretical += materialComposition[ilayer][referenceElement] * \ fluolist[ilayer][referenceElement]['rates'][referenceTransitions] if theoretical <= 0.0: raise ValueError(\ "Theoretical rate is almost 0.0 Impossible to determine flux") else: if (config['distance'] > 0.0) and (config['area'] > 0.0): #solidangle = config['area']/(4.0 * numpy.pi * pow(config['distance'],2)) radius2 = config['area'] / numpy.pi solidangle = 0.5 * ( 1.0 - (config['distance'] / numpy.sqrt(pow(config['distance'], 2) + radius2))) else: solidangle = 1.0 flux = fitresult['result'][referenceGroup]['fitarea'] / ( theoretical * solidangle) else: referenceElement = None referenceTransitions = None #solidangle = config['area']/(4.0 * numpy.pi * pow(config['distance'],2)) radius2 = config['area'] / numpy.pi solidangle = 0.5 * ( 1.0 - (config['distance'] / numpy.sqrt(pow(config['distance'], 2) + radius2))) flux = config['flux'] * config['time'] #print "OBTAINED FLUX * SOLID ANGLE= ",flux * solidangle #print "flux * time = ",flux #print "actual solid angle = ",0.5 * (1.0 - (config['distance']/sqrt(pow(config['distance'],2)+ config['area']/pi))) #print "solid angle factor= ",solidangle #ele = 'Pb' #rays = "L xrays" #print "theoretical = ",fluototal[ele]['rates'][rays] #print "expected = ",flux * solidangle * fluototal[ele]['rates'][rays] #for ilayer in range(len(multilayer)): # print "ilayer = ",ilayer, "theoretical = ",fluolist[ilayer][ele]['rates'][rays] # print "ilayer = ",ilayer, "expected = ",flux * solidangle * fluolist[ilayer][ele]['rates'][rays] ddict = {} ddict['groups'] = groupsList ddict['elements'] = elements ddict['mass fraction'] = {} if 'mmolarflag' in config: if config['mmolarflag']: ddict['mmolar'] = {} else: config['mmolarflag'] = 0 ddict['area'] = {} ddict['fitarea'] = {} ddict['sigmaarea'] = {} fluo = fluototal for group in groupsList: item = group.split() element = item[0] transitions = item[1] + " xrays" if element in fluo.keys(): if transitions in fluo[element]: #this SHOULD be with concentration one theoretical = fluo[element]['rates'][transitions] * 1.0 expected = theoretical * flux * solidangle concentration = fitresult['result'][group][ 'fitarea'] / expected else: theoretical = 0.0 concentration = 0.0 else: theoretical = 0.0 concentration = 0.0 #ddict['area'][group] = theoretical * flux * solidangle * concentration ddict['fitarea'][group] = fitresult['result'][group]['fitarea'] ddict['sigmaarea'][group] = fitresult['result'][group]['sigmaarea'] if elementsfrommatrix: if element in fluo.keys(): ddict['mass fraction'][ group] = 1.0 * fluo[element]['mass fraction'] else: ddict['mass fraction'][group] = 0.0 ddict['area'][group] = theoretical * flux * solidangle *\ ddict['mass fraction'][group] else: ddict['mass fraction'][group] = concentration ddict['area'][group] = theoretical * flux * solidangle if config['mmolarflag']: #mM = (mass_fraction * density)/atomic_weight ddict['mmolar'] [group]= 1000000. *\ (multilayer[0][1] * ddict['mass fraction'][group])/Elements.Element[element]['mass'] #I have the globals/average values now I calculate layer per layer #if necessary ddict['layerlist'] = [] if matrix[0].upper() == "MULTILAYER": ilayer = 0 for layer in layerlist: if fitresult['result']['config']['multilayer'][layer][0]: ddict['layerlist'].append(layer) ddict[layer] = {} dict2 = ddict[layer] dict2['groups'] = groupsList dict2['elements'] = elements dict2['mass fraction'] = {} if config['mmolarflag']: dict2['mmolar'] = {} dict2['area'] = {} dict2['fitarea'] = {} fluo = fluolist[ilayer] for group in groupsList: item = group.split() element = item[0] transitions = item[1] + " xrays" if element in fluo.keys(): if transitions in fluo[element]: theoretical = fluo[element]['rates'][ transitions] * 1 expected = theoretical * flux * solidangle if expected > 0.0: concentration = fitresult['result'][group][ 'fitarea'] / expected else: concentration = -1 else: theoretical = 0.0 concentration = 0.0 else: theoretical = 0.0 concentration = 0.0 dict2['fitarea'][ group] = 1 * fitresult['result'][group]['fitarea'] if elementsfrommatrix: if element in fluo.keys(): dict2['mass fraction'][ group] = 1 * fluo[element]['mass fraction'] else: dict2['mass fraction'][group] = 0.0 #I calculate matrix in optimized form, #so I have to multiply by the mass fraction dict2['area'][group] = theoretical * flux * solidangle *\ dict2['mass fraction'][group] else: dict2['mass fraction'][group] = concentration dict2['area'][ group] = theoretical * flux * solidangle if config['mmolarflag']: #mM = (mass_fraction * density)/atomic_weight dict2['mmolar'][group] = 1000000. *\ (multilayer[ilayer][1] * dict2['mass fraction'][group]) /\ Elements.Element[element]['mass'] #if group == "Pb L": # print "layer", ilayer,'area ', dict2['area'][group] # print "layer", ilayer,'mass fraction =', dict2['mass fraction'][group] ilayer += 1 if elementsfrommatrix: for group in groupsList: ddict['area'][group] = 0.0 for layer in ddict['layerlist']: if group in ddict[layer]['area'].keys(): ddict['area'][group] += ddict[layer]['area'][group] if xrfmcSecondary and (not elementsfrommatrix): xrfmcCorrections = None if 'xrfmc' in fitresult: xrfmcCorrections = fitresult['xrfmc'].get('corrections', None) if xrfmcCorrections is None: if 'xrfmc' in fitresult['result']: xrfmcCorrections = fitresult['result']['xrfmc'].get( 'corrections', None) if xrfmcCorrections is None: # try to see if they were in the configuration if 'xrfmc' in fitresult['result']['config']: xrfmcCorrections = fitresult['result']['config'][ 'xrfmc'].get('corrections', None) if xrfmcCorrections is None: # calculate the corrections xrfmcCorrections = XRFMCHelper.getXRFMCCorrectionFactors( fitresult['result']['config']) if referenceElement is not None: referenceLines = referenceTransitions.split()[0] referenceCorrection = xrfmcCorrections[referenceElement][referenceLines]\ ['correction_factor'][-1] xrfmcCorrections[referenceElement][referenceLines]\ ['correction_factor'][-1] = 1.0 for group in groupsList: item = group.split() element = item[0] lines = item[1] if element in xrfmcCorrections: if element != referenceElement: if lines != referenceLines: xrfmcCorrections[element][lines][ 'correction_factor'][ -1] *= referenceCorrection # now we have to apply the corrections for group in groupsList: item = group.split() element = item[0] lines = item[1] if element in xrfmcCorrections: correction = xrfmcCorrections[element][ item[1]]['correction_factor'][-1] ddict['mass fraction'][group] /= correction if addinfo: addInfo = {} addInfo['ReferenceElement'] = referenceElement addInfo['ReferenceTransitions'] = referenceTransitions addInfo['SolidAngle'] = solidangle if config['time'] > 0.0: addInfo['Time'] = config['time'] else: addInfo['Time'] = 1.0 addInfo['Flux'] = flux / addInfo['Time'] addInfo['I0'] = flux addInfo['DetectorDistance'] = config['distance'] addInfo['DetectorArea'] = config['area'] return ddict, addInfo else: return ddict