def Clear(self): """ Clear everything """ self.workFit = Fit(Fitter(peakModel="theuerkauf", bgdeg=1)) self.workFit.active = True self.workFit.Draw(self.window.viewport) self.caldict = dict() return super(Session, self).Clear()
def Clear(self): """ Clear everything """ self.workFit = Fit( Fitter(peakModel="theuerkauf", backgroundModel="polynomial")) self.workFit.active = True self.workFit.Draw(self.viewport) self.caldict = dict() return super(Session, self).Clear()
def __init__(self): self.window = Window() super(Session, self).__init__(viewport=self.window.viewport) # TODO: make peakModel and bgdeg configurable self.workFit = Fit(Fitter(peakModel="theuerkauf", bgdeg=1)) self.workFit.active = True self.workFit.Draw(self.window.viewport) self.workCut = Cut() self.workCut.active = True self.workCut.Draw(self.window.viewport) self.caldict = dict() # main session is always active self._active = True
class Session(DrawableManager): """ Main session of hdtv First of all this provides a list of spectra, which is why this is called spectra in most contexts. But this also keeps track of the basic fit interface and of a list of calibrations. """ def __init__(self): self.window = Window() super(Session, self).__init__(viewport=self.window.viewport) # TODO: make peakModel and bgdeg configurable self.workFit = Fit(Fitter(peakModel="theuerkauf", bgdeg=1)) self.workFit.active = True self.workFit.Draw(self.window.viewport) self.workCut = Cut() self.workCut.active = True self.workCut.Draw(self.window.viewport) self.caldict = dict() # main session is always active self._active = True def ApplyCalibration(self, specIDs, cal): """ Apply calibration cal to spectra with ids """ if isinstance(specIDs, (str, int, float)): specIDs = hdtv.util.ID.ParseIds(str(specIDs), self) for ID in specIDs: try: spec = self.dict[ID] except KeyError: hdtv.ui.warn("There is no spectrum with id: %s" % ID) else: if cal is None: hdtv.ui.msg( "Unsetting calibration of spectrum with id %s" % ID) try: self.caldict.pop(spec.name) except KeyError: pass spec.cal = None else: hdtv.ui.msg("Calibrated spectrum with id %s" % ID) cal = hdtv.cal.MakeCalibration(cal) self.caldict[spec.name] = cal spec.cal = cal if self.workFit.spec == spec: self.workFit.cal = cal # Marker handling def SetMarker(self, mtype, pos=None): """ Set Marker of type "mtype" (bg, peak, region, cut) to position pos, if pos is not given, the current position of the cursor is used. """ if pos is None: pos = self.viewport.GetCursorX() if mtype in ["bg", "peak", "region"]: self.workFit.ChangeMarker(mtype, pos, action="set") elif mtype in ["cut", "cutregion", "cutbg"]: mtype = mtype[3:] self.workCut.SetMarker(mtype, pos) def RemoveMarker(self, mtype, pos=None): """ Remove the marker of type "mtype" (bg, peak, region), that is closest to position "pos", if position is not given, the current position of the cursor is used. """ if pos is None: pos = self.viewport.GetCursorX() if mtype in ["bg", "peak", "region"]: self.workFit.ChangeMarker(mtype, pos, action="remove") elif mtype in ["cutregion", "cutbg"]: mtype = mtype[3:] self.workCut.RemoveMarker(mtype, pos) def ExecuteIntegral(self): spec = self.GetActiveObject() if spec is None: hdtv.ui.error("There is no active spectrum.") return fit = self.workFit fit.spec = spec if not fit.regionMarkers.IsFull(): hdtv.ui.error("Region not set.") return if len(fit.bgMarkers) > 0: if fit.fitter.bgdeg == -1: hdtv.ui.error( "Background degree of -1 contradicts background fit.") return # pure background fit fit.FitBgFunc(spec) region = [ fit.regionMarkers[0].p1.pos_uncal, fit.regionMarkers[0].p2.pos_uncal ] bg = fit.fitter.bgFitter fit.integral = Integrate(spec, bg, region) fit.Draw(self.window.viewport) hdtv.ui.msg(fit.print_integral()) # Functions to handle workFit def ExecuteFit(self, peaks=True): """ Execute the fit If peaks=False, just an background fit is done, else a peak fit is done. """ hdtv.ui.debug("Executing the fit") spec = self.GetActiveObject() if spec is None: hdtv.ui.error("There is no active spectrum.") return fit = self.workFit try: if not peaks and len(fit.bgMarkers) > 0: if fit.fitter.bgdeg == -1: hdtv.ui.error( "Background degree of -1 contradicts background fit.") return # pure background fit fit.FitBgFunc(spec) if peaks: # full fit fit.FitPeakFunc(spec) # show fit result hdtv.ui.msg(str(fit), newline=False) fit.Draw(self.window.viewport) except OverflowError as msg: hdtv.ui.error("Fit failed: %s" % msg) if fit.regionMarkers.IsFull(): region = [ fit.regionMarkers[0].p1.pos_uncal, fit.regionMarkers[0].p2.pos_uncal ] fit.integral = Integrate(spec, fit.fitter.bgFitter, region) def ClearFit(self, bg_only=False): """ Clear the markers and erase a previously executed fit. If bg_only is True, only the background fit is cleared and a peak fit is repeated now with internal background. """ if bg_only: self.workFit.bgMarkers.Clear() self.workFit.Erase(bg_only) self.workFit.Refresh() else: self.workFit.bgMarkers.Clear() self.workFit.peakMarkers.Clear() self.workFit.regionMarkers.Clear() # Keeping positions on hold for a new fit is not really sensible if "pos" in self.workFit.fitter.params: self.workFit.fitter.SetParameter("pos", "free") hdtv.ui.msg("\'pos\' fit parameter reset to \'free\'") self.workFit.spec = None def ActivateFit(self, ID, sid=None): """ Copy markers of a already stored fit to workFit. Note: that a call to Store will overwrite the active fit with workFit """ # for interactive use of this function if isinstance(ID, (str, int, float)): ID = hdtv.util.ID.ParseIds(ID, self)[0] if sid is None: sid = self.activeID if sid is None: hdtv.ui.warn("There is no active spectrum") return spec = self.dict[sid] spec.ActivateObject(ID) if ID is not None: # make a copy for workFit self.workFit = copy.copy(spec.GetActiveObject()) self.workFit.active = True self.workFit.Draw(self.window.viewport) def StoreFit(self, ID=None): """ Stores current workFit with ID. If no ID is given, the next free ID is used. The markers are kept in workFit, for possible re-use. """ spec = self.workFit.spec # for interactive use of this function if isinstance(ID, (str, int, float)): ids = hdtv.util.ID.ParseIds(ID, self.dict[self.activeID], only_existent=False) if len(ids) > 1: raise hdtv.cmdline.HDTVCommandError("More than one ID given") ID = ids[0] if spec is None: hdtv.ui.warn("No fit available to store") return if ID is None: ID = spec.activeID ID = spec.Insert(self.workFit, ID) spec.dict[ID].active = False spec.ActivateObject(None) hdtv.ui.msg("Storing workFit with ID %s" % ID) self.workFit = copy.copy(self.workFit) self.workFit.active = True self.workFit.Draw(self.window.viewport) # Functions to handle workCut def ExecuteCut(self): spec = self.GetActiveObject() if spec is None: hdtv.ui.error("There is no active spectrum") return if not hasattr(spec, "matrix") or spec.matrix is None: hdtv.ui.error("Active spectrum does not belong to a matrix") return cutSpec = self.workCut.ExecuteCut(spec.matrix, spec.axis) if cutSpec is not None: ID = spec.matrix.ID self.Insert(cutSpec, ID=hdtv.util.ID(ID.major, 1010)) def ClearCut(self): self.workCut.regionMarkers.Clear() self.workCut.bgMarkers.Clear() self.workCut.axis = None if self.workCut.spec is not None: self.Pop(self.Index(self.workCut.spec)) def ActivateCut(self, ID): # for interactive use of this function if isinstance(ID, (str, int, float)): ID = hdtv.util.ID.ParseIds(ID, self)[0] spec = self.GetActiveObject() if spec is None: hdtv.ui.error("There is no active spectrum") return if not hasattr(spec, "matrix") or spec.matrix is None: hdtv.ui.error("Active spectrum does not belong to a matrix") return spec.matrix.ActivateObject(ID) if ID is not None: self.workCut = copy.copy(spec.matrix.GetActiveObject()) self.workCut.active = True self.workCut.Draw(self.window.viewport) def StoreCut(self, ID=None): # for interactive use of this function if isinstance(ID, (str, int, float)): ID = hdtv.util.ID.ParseIds(ID, self)[0] spec = self.GetActiveObject() if spec is None: hdtv.ui.error("There is no active spectrum") return if not hasattr(spec, "matrix") or spec.matrix is None: hdtv.ui.error("Active spectrum does not belong to a matrix") return mat = spec.matrix ID = mat.Insert(self.workCut, ID) mat.dict[ID].active = False mat.ActivateObject(None) if self.workCut.spec is not None: spec = self.Pop(self.Index(self.workCut.spec)) # give it a new color spec.color = hdtv.color.ColorForID(ID.major) self.Insert(spec, ID=hdtv.util.ID(mat.ID.major, ID.major)) hdtv.ui.msg("Storing workCut with ID %s" % ID) self.workCut = copy.copy(self.workCut) self.workCut.active = True self.workCut.Draw(self.window.viewport) # Overwrite some functions of DrawableManager to do some extra work def ActivateObject(self, ID): """ Activate Object and reset workFit when activating another spectrum """ # for interactive use of this function if isinstance(ID, (str, int, float)): ID = hdtv.util.ID.ParseIds(ID, self)[0] if ID is not self.activeID: # reset workFit self.workFit.spec = None # deactivate a possible active fit spec = self.GetActiveObject() if spec is not None: spec.ActivateObject(None) super(Session, self).ActivateObject(ID) def Pop(self, ID): """ Pop spectrum with ID and activate prevID if ID was activeID """ # for interactive use of this function if isinstance(ID, (str, int, float)): ID = hdtv.util.ID.ParseIds(ID, self)[0] if self.activeID is ID: self.ActivateObject(self.prevID) return super(Session, self).Pop(ID) def ShowObjects(self, ids, clear=True): """ Show spectra and make sure one of the visible objects is active """ ids = super(Session, self).ShowObjects(ids, clear) if self.activeID not in self.visible: if len(self.visible) > 0: self.ActivateObject(max(self.visible)) else: self.ActivateObject(None) return ids def HideObjects(self, ids): """ Hide spectra and make sure one of the visible objects is active """ ids = super(Session, self).HideObjects(ids) if self.activeID not in self.visible: if len(self.visible) > 0: self.ActivateObject(max(self.visible)) else: self.ActivateObject(None) return ids def Clear(self): """ Clear everything """ self.workFit = Fit(Fitter(peakModel="theuerkauf", bgdeg=1)) self.workFit.active = True self.workFit.Draw(self.window.viewport) self.caldict = dict() return super(Session, self).Clear()
def RestoreFromXml_v0(self, root, do_fit=False): """ Reads fits from xml file (version = 0.*) Note: For performance reasons this does not reconstruct the fit results. It only sets the markers and restores the status of the fitter. The user must repeat the fit, if he/she wants to see the results again. (This should be improved in later versions.) """ count = 0 spectra = self.spectra # <spectrum> for specElement in root.iter(): name = specElement.get("name") # find this spectrum from Element in the real world spec = None for sid in spectra.ids: if spectra.dict[sid].name == name: spec = spectra.dict[sid] # maybe the spectrum that is referred to in XML is currently not # loaded if spec is None: continue # <fit> for fitElement in specElement: count = count + 1 peakModel = fitElement.get("peakModel") # Simple fix for older xml file versions, where the only background # model was a polynomial, and therefore it did not have to be stored fitter = Fitter(peakModel, "polynomial") # <result> params = dict() for resultElement in fitElement.findall("result"): for paramElement in resultElement: parname = paramElement.tag status = paramElement.get("status") try: params[parname].append(status) except KeyError: params[parname] = [status] for parname in list(params.keys()): status = params[parname] fitter.SetParameter(parname, status) fit = Fit(fitter, cal=spec.cal) # <background> for bgElement in fitElement.findall("background"): # Read begin/p1 marker beginElement = bgElement.find("begin") if beginElement is None: # Maybe old Element (ver 0.1) beginElement = bgElement.find("p1") begin = float(beginElement.find("uncal").text) fit.ChangeMarker("bg", fit.cal.Ch2E(begin), "set") # Read end/p2 marker endElement = bgElement.find("end") if endElement is None: # Maybe old Element (ver 0.1) endElement = bgElement.find("p2") end = float(endElement.find("uncal").text) fit.ChangeMarker("bg", fit.cal.Ch2E(end), "set") # <region> for regionElement in fitElement.findall("region"): # Read begin/p1 marker beginElement = regionElement.find("begin") if beginElement is None: # Maybe old Element (ver 0.1) beginElement = regionElement.find("p1") begin = float(beginElement.find("uncal").text) fit.ChangeMarker("region", fit.cal.Ch2E(begin), "set") # Read end/p2 marker endElement = regionElement.find("end") if endElement is None: # Maybe old Element (ver 0.1) endElement = regionElement.find("p2") end = float(endElement.find("uncal").text) fit.ChangeMarker("region", fit.cal.Ch2E(end), "set") # <peak> for peakElement in fitElement.findall("peak"): # Read position/p1 marker posElement = peakElement.find("position") if posElement is None: posElement = peakElement.find("p1") pos = float(posElement.find("uncal").text) fit.ChangeMarker("peak", fit.cal.Ch2E(pos), "set") if do_fit: fit.FitPeakFunc(spec) spec.Insert(fit) return count, [fit]
def Xml2Fit_v1(self, fitElement, calibration=None): """ Creates a fit object from information found in a xml file """ # <fit> success = True peakModel = fitElement.get("peakModel") bgElement = fitElement.find("background") # Simple fix for older xml file versions, where the only background # model was a polynomial, and therefore it did not have to be stored try: backgroundModel = bgElement.get("backgroundModel") except AttributeError: backgroundModel = "polynomial" if backgroundModel is None: backgroundModel = "polynomial" fitter = Fitter(peakModel, backgroundModel) fit = Fit(fitter, cal=calibration) try: fit.chi = float(fitElement.get("chi")) except ValueError: fit.chi = None # <bgMarker> for bgElement in fitElement.findall("bgMarker"): # Read begin marker beginElement = bgElement.find("begin") begin = self._getPosFromElement(beginElement, fit) fit.ChangeMarker("bg", begin, "set") # Read end marker endElement = bgElement.find("end") end = self._getPosFromElement(endElement, fit) fit.ChangeMarker("bg", end, "set") # <regionMarker> for regionElement in fitElement.findall("regionMarker"): # Read begin marker beginElement = regionElement.find("begin") begin = self._getPosFromElement(beginElement, fit) fit.ChangeMarker("region", begin, "set") # Read end marker endElement = regionElement.find("end") end = self._getPosFromElement(endElement, fit) fit.ChangeMarker("region", end, "set") # <peakMarker> for peakElement in fitElement.findall("peakMarker"): # Read position marker posElement = peakElement.find("position") pos = self._getPosFromElement(posElement, fit) fit.ChangeMarker("peak", pos, "set") # <background> bgElement = fitElement.find("background") if bgElement: try: fit.bgChi = float(bgElement.get("chisquare")) except ValueError: pass params = list() # Distinguish between old notation of background parameters (coeff, ncoeff), # which interprets the parameters as coefficients of a polynomial, and the # new notation (params, npar), which interprets them as arbitrary parameters. paramCounterName = 'npar' paramElements = bgElement.findall('param') if not paramElements: paramElements = bgElement.findall('coeff') paramCounterName = 'deg' for paramElement in paramElements: npar = int(paramElement.get(paramCounterName)) # <value> valueElement = paramElement.find("value") value = float(valueElement.text) # <error> errorElement = paramElement.find("error") error = float(errorElement.text) param = ufloat(value, error) params.append([npar, param]) params.sort() fit.bgParams = [p[1] for p in params] # <peak> statusdict = dict() for peakElement in fitElement.findall("peak"): # <uncal> uncalElement = peakElement.find("uncal") parameter = dict() for paramElement in uncalElement: # parameter value/error name = paramElement.tag parameter[name] = self._readParamElement(paramElement) # parameter status status = paramElement.get("status", "free") try: statusdict[name].append(status) except KeyError: statusdict[name] = [status] # <extras> extraElement = peakElement.find("extras") extras = dict() if extraElement is not None: for paramElement in extraElement: name = paramElement.tag if len(paramElement) == 1: extras[name] = paramElement.text else: # <value> valueElement = paramElement.find("value") value = float(valueElement.text) # <error> errorElement = paramElement.find("error") error = float(errorElement.text) extras[name] = ufloat(value, error) # create peak try: peak = fit.fitter.peakModel.Peak(cal=calibration, **parameter) except TypeError: hdtv.ui.error("Error reading peak with parameters: %s" % str(parameter)) success = False continue peak.extras = extras fit.peaks.append(peak) # set parameter status of fitter for name in list(statusdict.keys()): # check if status is the same for all peaks check = set(statusdict[name]) if len(check) == 1: status = statusdict[name][0] else: status = statusdict[name] fitter.SetParameter(name, status) integrals = dict() for integral in fitElement.findall('integral'): integral_type = integral.get("integraltype") integrals[integral_type] = dict() for calElement in integral: cal_type = calElement.tag integrals[integral_type][cal_type] = dict() for paramElement in calElement: # <value> valueElement = paramElement.find("value") value = float(valueElement.text) # <error> errorElement = paramElement.find("error") error = float(errorElement.text) coeff = ufloat(value, error) integrals[integral_type][cal_type][ paramElement.tag] = coeff if not integrals: integrals = None for integral_type in ['sub', 'bg']: if integrals and not integral_type in integrals: integrals[integral_type] = None fit.integral = integrals return (fit, success)
def Xml2Fit_v1(self, fitElement, calibration=None): """ Creates a fit object from information found in a xml file """ # <fit> success = True peakModel = fitElement.get("peakModel") bgdeg = int(fitElement.get("bgDegree")) fitter = Fitter(peakModel, bgdeg) fit = Fit(fitter, cal=calibration) try: fit.chi = float(fitElement.get("chi")) except ValueError: fit.chi = None # <bgMarker> for bgElement in fitElement.findall("bgMarker"): # Read begin marker beginElement = bgElement.find("begin") begin = self._getPosFromElement(beginElement, fit) fit.ChangeMarker("bg", begin, "set") # Read end marker endElement = bgElement.find("end") end = self._getPosFromElement(endElement, fit) fit.ChangeMarker("bg", end, "set") # <regionMarker> for regionElement in fitElement.findall("regionMarker"): # Read begin marker beginElement = regionElement.find("begin") begin = self._getPosFromElement(beginElement, fit) fit.ChangeMarker("region", begin, "set") # Read end marker endElement = regionElement.find("end") end = self._getPosFromElement(endElement, fit) fit.ChangeMarker("region", end, "set") # <peakMarker> for peakElement in fitElement.findall("peakMarker"): # Read position marker posElement = peakElement.find("position") pos = self._getPosFromElement(posElement, fit) fit.ChangeMarker("peak", pos, "set") # <background> bgElement = fitElement.find("background") if bgElement: try: fit.bgChi = float(bgElement.get("chisquare")) except ValueError: pass coeffs = list() for coeffElement in bgElement.findall("coeff"): deg = int(coeffElement.get("deg")) # <value> valueElement = coeffElement.find("value") value = float(valueElement.text) # <error> errorElement = coeffElement.find("error") error = float(errorElement.text) coeff = ufloat(value, error) coeffs.append([deg, coeff]) coeffs.sort() fit.bgCoeffs = [c[1] for c in coeffs] # <peak> statusdict = dict() for peakElement in fitElement.findall("peak"): # <uncal> uncalElement = peakElement.find("uncal") parameter = dict() for paramElement in uncalElement: # parameter value/error name = paramElement.tag parameter[name] = self._readParamElement(paramElement) # parameter status status = paramElement.get("status", "free") try: statusdict[name].append(status) except KeyError: statusdict[name] = [status] # <extras> extraElement = peakElement.find("extras") extras = dict() if extraElement is not None: for paramElement in extraElement: name = paramElement.tag if len(paramElement) == 1: extras[name] = paramElement.text else: # <value> valueElement = paramElement.find("value") value = float(valueElement.text) # <error> errorElement = paramElement.find("error") error = float(errorElement.text) extras[name] = ufloat(value, error) # create peak try: peak = fit.fitter.peakModel.Peak(cal=calibration, **parameter) except TypeError: hdtv.ui.error( "Error reading peak with parameters: %s" % str(parameter)) success = False continue peak.extras = extras fit.peaks.append(peak) # set parameter status of fitter for name in list(statusdict.keys()): # check if status is the same for all peaks check = set(statusdict[name]) if len(check) == 1: status = statusdict[name][0] else: status = statusdict[name] fitter.SetParameter(name, status) integrals = dict() for integral in fitElement.findall('integral'): integral_type = integral.get("integraltype") integrals[integral_type] = dict() for calElement in integral: cal_type = calElement.tag integrals[integral_type][cal_type] = dict() for paramElement in calElement: # <value> valueElement = paramElement.find("value") value = float(valueElement.text) # <error> errorElement = paramElement.find("error") error = float(errorElement.text) coeff = ufloat(value, error) integrals[integral_type][cal_type][paramElement.tag] = coeff if not integrals: integrals = None for integral_type in ['sub', 'bg']: if integrals and not integral_type in integrals: integrals[integral_type] = None fit.integral = integrals return (fit, success)