Changeset 2666 for trunk/python


Ignore:
Timestamp:
10/15/12 15:52:38 (12 years ago)
Author:
Malte Marquarding
Message:

Ticket #173: added setting of constraints on the fitter.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/python/asapfitter.py

    r2541 r2666  
    33from asap.logging import asaplog, asaplog_post_dec
    44from asap.utils import _n_bools, mask_and
    5 
     5from numpy import ndarray
    66
    77class fitter:
     
    2626        self._selection = None
    2727        self.uselinear = False
     28        self._constraints = []
    2829
    2930    def set_data(self, xdat, ydat, mask=None):
     
    7374        Set the function to be fit.
    7475        Parameters:
    75             poly:     use a polynomial of the order given with nonlinear least squares fit
    76             lpoly:    use polynomial of the order given with linear least squares fit
     76            poly:     use a polynomial of the order given with nonlinear
     77                      least squares fit
     78            lpoly:    use polynomial of the order given with linear least
     79                      squares fit
    7780            gauss:    fit the number of gaussian specified
    7881            lorentz:  fit the number of lorentzian specified
    7982            sinusoid: fit the number of sinusoid specified
    8083        Example:
    81             fitter.set_function(poly=3)  # will fit a 3rd order polynomial via nonlinear method
    82             fitter.set_function(lpoly=3)  # will fit a 3rd order polynomial via linear method
     84            fitter.set_function(poly=3)  # will fit a 3rd order polynomial
     85                                         # via nonlinear method
     86            fitter.set_function(lpoly=3)  # will fit a 3rd order polynomial
     87                                          # via linear method
    8388            fitter.set_function(gauss=2) # will fit two gaussians
    8489            fitter.set_function(lorentz=2) # will fit two lorentzians
     
    117122            self.components = [ 3 for i in range(n) ]
    118123            self.uselinear = False
     124        elif kwargs.has_key('expression'):
     125            self.uselinear = False
     126            raise RuntimeError("Not yet implemented")
    119127        else:
    120128            msg = "Invalid function type."
     
    122130
    123131        self.fitter.setexpression(self.fitfunc,n)
     132        self._constraints = []
    124133        self.fitted = False
    125134        return
     
    147156            raise RuntimeError(msg)
    148157
    149         else:
    150             if self.data is not None:
    151                 self.x = self.data._getabcissa(row)
    152                 self.y = self.data._getspectrum(row)
    153                 #self.mask = mask_and(self.mask, self.data._getmask(row))
    154                 if len(self.x) == len(self.mask):
    155                     self.mask = mask_and(self.mask, self.data._getmask(row))
    156                 else:
    157                     asaplog.push('lengths of data and mask are not the same. preset mask will be ignored')
    158                     asaplog.post('WARN','asapfit.fit')
    159                     self.mask=self.data._getmask(row)
    160                 asaplog.push("Fitting:")
    161                 i = row
    162                 out = "Scan[%d] Beam[%d] IF[%d] Pol[%d] Cycle[%d]" % (self.data.getscan(i),
    163                                                                       self.data.getbeam(i),
    164                                                                       self.data.getif(i),
    165                                                                       self.data.getpol(i),
    166                                                                       self.data.getcycle(i))
    167                 asaplog.push(out,False)
     158        if self.data is not None:
     159            self.x = self.data._getabcissa(row)
     160            self.y = self.data._getspectrum(row)
     161            #self.mask = mask_and(self.mask, self.data._getmask(row))
     162            if len(self.x) == len(self.mask):
     163                self.mask = mask_and(self.mask, self.data._getmask(row))
     164            else:
     165                asaplog.push('lengths of data and mask are not the same. '
     166                             'preset mask will be ignored')
     167                asaplog.post('WARN','asapfit.fit')
     168                self.mask=self.data._getmask(row)
     169            asaplog.push("Fitting:")
     170            i = row
     171            out = "Scan[%d] Beam[%d] IF[%d] Pol[%d] Cycle[%d]" % (
     172                self.data.getscan(i),
     173                self.data.getbeam(i),
     174                self.data.getif(i),
     175                self.data.getpol(i),
     176                self.data.getcycle(i))
     177           
     178            asaplog.push(out, False)
     179
    168180        self.fitter.setdata(self.x, self.y, self.mask)
    169181        if self.fitfunc == 'gauss' or self.fitfunc == 'lorentz':
     
    174186        if len(fxdpar) and fxdpar.count(0) == 0:
    175187             raise RuntimeError,"No point fitting, if all parameters are fixed."
     188        if self._constraints:
     189            for c in self._constraints:
     190                self.fitter.addconstraint(c[0]+[c[-1]])
    176191        if self.uselinear:
    177192            converged = self.fitter.lfit()
     
    234249            msg = "Please specify a fitting function first."
    235250            raise RuntimeError(msg)
    236         if (self.fitfunc == "gauss" or self.fitfunc == "lorentz" or self.fitfunc == "sinusoid") and component is not None:
     251        if (self.fitfunc == "gauss" or self.fitfunc == "lorentz"
     252            or self.fitfunc == "sinusoid") and component is not None:
    237253            if not self.fitted and sum(self.fitter.getparameters()) == 0:
    238254                pars = _n_bools(len(self.components)*3, False)
     
    338354            raise ValueError(msg)
    339355
     356
     357    def add_constraint(self, xpar, y):
     358        """Add parameter constraints to the fit. This is done by setting up
     359        linear equations for the related parameters.
     360
     361        For example a two component gaussian fit where the amplitudes are
     362        constraint by amp1 = 2*amp2
     363        needs a constraint   
     364
     365            add_constraint([1, 0, 0, -2, 0, 0, 0], 0)
     366
     367        a velocity difference of v2-v1=17
     368
     369            add_constraint([0.,-1.,0.,0.,1.,0.], 17.)
     370
     371        """
     372        self._constraints.append((xpar, y))
     373       
     374
    340375    def get_area(self, component=None):
    341376        """
     
    381416        cerrs = errs
    382417        if component is not None:
    383             if self.fitfunc == "gauss" or self.fitfunc == "lorentz" or self.fitfunc == "sinusoid":
     418            if self.fitfunc == "gauss" or self.fitfunc == "lorentz" \
     419                    or self.fitfunc == "sinusoid":
    384420                i = 3*component
    385421                if i < len(errs):
     
    463499                out += "%s%s = %3.3f %s, " % (pnam[1], fix1, pars[i+1], aunit)
    464500                out += "%s%s = %3.3f %s\n" % (pnam[2], fix2, pars[i+2], aunit)
    465                 if len(area): out += "      area = %3.3f %s %s\n" % (area[i], ounit, aunit)
     501                if len(area): out += "      area = %3.3f %s %s\n" % (area[i],
     502                                                                     ounit,
     503                                                                     aunit)
    466504                c+=1
    467505                i+=3
     
    571609            ylab = self.data._get_ordinate_label()
    572610
    573         colours = ["#777777","#dddddd","red","orange","purple","green","magenta", "cyan"]
     611        colours = ["#777777","#dddddd","red","orange","purple","green",
     612                   "magenta", "cyan"]
    574613        nomask=True
    575614        for i in range(len(m)):
     
    604643            if isinstance(components,int): cs = [components]
    605644            if plotparms:
    606                 self._p.text(0.15,0.15,str(self.get_parameters()['formatted']),size=8)
     645                self._p.text(0.15,0.15,
     646                             str(self.get_parameters()['formatted']),size=8)
    607647            n = len(self.components)
    608648            self._p.palette(3)
     
    656696        asaplog.push("Fitting:")
    657697        for r in rows:
    658             out = " Scan[%d] Beam[%d] IF[%d] Pol[%d] Cycle[%d]" % (scan.getscan(r),
    659                                                                    scan.getbeam(r),
    660                                                                    scan.getif(r),
    661                                                                    scan.getpol(r),
    662                                                                    scan.getcycle(r))
     698            out = " Scan[%d] Beam[%d] IF[%d] Pol[%d] Cycle[%d]" % (
     699                scan.getscan(r),
     700                scan.getbeam(r),
     701                scan.getif(r),
     702                scan.getpol(r),
     703                scan.getcycle(r)
     704                )
    663705            asaplog.push(out, False)
    664706            self.x = scan._getabcissa(r)
     
    668710                self.mask = mask_and(self.mask, self.data._getmask(row))
    669711            else:
    670                 asaplog.push('lengths of data and mask are not the same. preset mask will be ignored')
     712                asaplog.push('lengths of data and mask are not the same. '
     713                             'preset mask will be ignored')
    671714                asaplog.post('WARN','asapfit.fit')
    672715                self.mask=self.data._getmask(row)
Note: See TracChangeset for help on using the changeset viewer.