Exemplo n.º 1
0
 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()
Exemplo n.º 2
0
Arquivo: session.py Projeto: op3/hdtv
 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()
Exemplo n.º 3
0
 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
Exemplo n.º 4
0
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()
Exemplo n.º 5
0
    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]
Exemplo n.º 6
0
    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)
Exemplo n.º 7
0
 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)