def createScatterModelFromDict(paramdict, linefunc): """ Create and initialize a scatter peak model lmfit parse the arguments of the linefunc to create the model parameters. The dictionary input must contain:. paramdict["Acquisition_instrument"]["beam_energy"] (keV) The method will look for the Compton parameter in paramdict["XRF"]["Scatter"] An example parameter is [area] bound_type = Fixed, lohi or free (dont' vary, bound, free) value = 0.5 The guess value min = 0.0 Min used only if bound_type = lohi max = 1.0 Max used only if bound_type = lohi if the arguments aren't in the dict or an empty dict is supplied the value default to [param] bound_type = free value = 1.0 min = -inf max = +inf Parameters: Inputs: paramdict - dictionary containing the compton function parameters linefuc - the function to use for the scatter peak Output: model - lmfit model of the compton peak with parameters initialized - lmfit model prefix set to scatter_ """ # typical names to help identify thr peak position from the parsed linefunc peakcenternames = ["beam_energy", "position", "peak", "centre", "center"] # prefix for the lmfit model prefix = "scatter_" # location of the dictionary parameter values....hopefully pdict = paramdict["XRFFit"]["scatter"] incident_energy = paramdict["Acquisition_instrument"]["XRF"]["beam_energy"] # create a lmfit model model = Model(linefunc, prefix=prefix) # now loop over the uninitialized model parameters and set them using the dictionary values for pname in model.param_names: pname = model._strip_prefix(pname) if pname in peakcenternames: varyp = 'fixed' model.set_param_hint(pname, value=incident_energy, vary=False, min=-np.inf, max=np.inf) continue if pname in pdict.keys(): parm = pdict[pname] varyp = pdict[pname]["bound_type"] if varyp == 'lohi': model.set_param_hint(pname, value=parm["value"], vary=True, min=parm["min"], max=parm["max"]) elif varyp == 'free': model.set_param_hint(pname, value=parm["value"], vary=True, min=-np.inf, max=np.inf) else: model.set_param_hint(pname, value=parm["value"], vary=False, min=parm["min"], max=parm["max"]) else: # if the parameter isn't in the dictionary then just set it to 1 # free to move and between -inf, +inf model.set_param_hint(pname, value=1.0, vary=True, min=-np.inf, max=np.inf) return model
class XRFAllElementModel(Model): def __init__(self, exptdesc,linedict,xrffunc,comptonfunc, elasticfunc,*args,**kwargs): """ An XRF spectrum model LMFIT offers a range of options for coupling parameters and models but in order to be able to do this it needs to manipulate parameters - in particular string expressions and this leads big slowdowns if you've a large number of models or coupled parameters. To speed up the calculation rather than create the XRF spectrum from a sum of Gaussian Models we create a single model with many parameters. The basic lmfit model works as follows: parse the arguments of the input function. Build a list of param names from these arguments Apply paramhints to these param_names or make parameters from the param names This class will pass a basic line """ # Pass an empty function to model super(XRFAllElementModel, self).__init__(None,*args, **kwargs) # Arguments need to be converted to # a list of elements (the peaks -> translating to peak areas) + the line type arguments # The basic model just assigns # self.func = function # parses the function parameters to # # xrf line model self.xrfmodel = Model(xrffunc,prefix="xrf_") self.funcparams_all = self.xrfmodel.make_params() self.xrfparams = self.xrfmodel.make_params() # elastic model self.elasticmodel = Model(elasticfunc,prefix="elastic_") self.elasticparams = self.elasticmodel.make_params() # compton model self.comptonmodel = Model(comptonfunc,prefix="compton_") self.comptonparams = self.comptonmodel.make_params() self.linedict = linedict self.exptdesc = exptdesc self.func = self.funcover def create_full_parameters(self): # remove the area and center parameter # For each element in the linedict add a parameter # which will control the area self.funcparams_all = deepcopy(self.xrfparams) self.funcparams_all.pop("xrf_area",None) self.funcparams_all.pop("xrf_center",None) if [s for s in self.linedict if "compton" in s.lower()]: self.funcparams_all.update(self.comptonparams) self.funcparams_all.pop("compton_area",None) self.funcparams_all.pop("compton_center",None) if [s for s in self.linedict if "elastic" in s.lower()]: self.funcparams_all.update(self.elasticparams) self.funcparams_all.pop("elastic_area",None) self.funcparams_all.pop("elastic_center",None) # # for each model set the parameters... # for key in self.funcparams_all: if key in self.comptonparams: ftype = self.comptonmodel.func.__name__ pdict =self.exptdesc["lineshape"]["compton"][ftype] skey =self.comptonmodel._strip_prefix(key) if skey in pdict: self.funcparams_all[key].value = pdict[skey]["value"] self.funcparams_all[key].min = pdict[skey]["min"] self.funcparams_all[key].max = pdict[skey]["max"] self.funcparams_all[key].vary = pdict[skey]["vary"] elif key in self.elasticparams: ftype = self.elasticmodel.func.__name__ pdict =self.exptdesc["lineshape"]["elastic"][ftype] skey =self.elasticmodel._strip_prefix(key) if skey in pdict: self.funcparams_all[key].value = pdict[skey]["value"] self.funcparams_all[key].min = pdict[skey]["min"] self.funcparams_all[key].max = pdict[skey]["max"] self.funcparams_all[key].vary = pdict[skey]["vary"] elif key in self.xrfparams: ftype =self.xrfmodel.func.__name__ pdict =self.exptdesc["lineshape"]["element"][ftype] skey =self.xrfmodel._strip_prefix(key) if skey in pdict: self.funcparams_all[key].value = pdict[skey]["value"] self.funcparams_all[key].min = pdict[skey]["min"] self.funcparams_all[key].max = pdict[skey]["max"] self.funcparams_all[key].vary = pdict[skey]["vary"] # create a parameter for each line in the line dict... # exclude pileups from the parameters for key in self.linedict: if not '+' in key: if "Elastic" in key: self.funcparams_all.add(key, **self.exptdesc["lineshape"]["elastic"]\ [self.elasticmodel.func.__name__]["area"]) elif "Compton" in key: print "here",key,self.comptonmodel.func.__name__ self.funcparams_all.add(key, **self.exptdesc["lineshape"]["compton"]\ [self.comptonmodel.func.__name__]["area"]) else: self.funcparams_all.add(key, **self.exptdesc["lineshape"]["element"]\ [self.xrfmodel.func.__name__]["area"])
def createComptonModelFromDict(paramdict, linefunc): """ Create and initialize a comptom model lmfit parse the arguments of the linefunc to create the model parameters. The dictionary input must contain:. paramdict["Acquisition_instrument"]["beam_energy"] (keV) paramdict["Acquisition_instrument"]["XRF"]["Detector"]["scattering_angle"] (degrees) A dictionary input can be used to the the parameter values. The method will look for the Compton parameter in paramdict["XRF"]["compton"] An example parameter is [area] bound_type = Fixed, lohi or free (dont' vary, bound, free) value = 0.5 The guess value min = 0.0 Min used only if bound_type = lohi max = 1.0 Max used only if bound_type = lohi if the arguments aren't in the dict or an empty dict is supplied the value default to [param] bound_type = free value = 1.0 min = -inf max = +inf Parameters: Inputs: paramdict - dictionary containing the compton function parameters linefuc - the function to use for the compton peak Output: model - lmfit model of the compton peak with parameters initialized - lmfit model prefix set to compton_ """ prefix = "compton_" pdict = paramdict["XRFFit"]["compton"] incident_energy = paramdict["Acquisition_instrument"]["XRF"]["beam_energy"] angle = paramdict["Acquisition_instrument"]["XRF"]["Detector"][ "scattering_angle"] model = Model(linefunc, prefix=prefix) compton_e = compton_energy(incident_energy, angle) print "compton e", compton_e for pname in model.param_names: pname = model._strip_prefix(pname) if pname in ["beam_energy", "centre", "center"]: varyp = 'fixed' model.set_param_hint(pname, value=compton_e, vary=False, min=-np.inf, max=np.inf) continue if pname in pdict.keys(): parm = pdict[pname] varyp = pdict[pname]["bound_type"] print "pname", pname, parm["value"], varyp, pdict[pname] if varyp == 'lohi': model.set_param_hint(pname, value=parm["value"], vary=True, min=parm["min"], max=parm["max"]) elif varyp == 'free': model.set_param_hint(pname, value=parm["value"], vary=True, min=-np.inf, max=np.inf) else: model.set_param_hint(pname, value=parm["value"], vary=False, min=parm["min"], max=parm["max"]) else: model.set_param_hint(pname, value=1.0, vary=True, min=-np.inf, max=np.inf) return model