source: trunk/python/asapfitter.py @ 2535

Last change on this file since 2535 was 2535, checked in by Kana Sugimoto, 12 years ago

New Development: No

JIRA Issue: Yes (CAS-3749/TRAC-266)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs:

interactive tests are required

  1. on CASA

(1) plot something by CASA sdplot task
(2) run CASA sdfit with plotlevel!=0
(3) close plotter window by pressing X button on the window
(4) plot something by sdplot task again.

  1. on stand-alone ASAP

(1) plot something by asapplotter
(2) run asapfitter.auto_fit with plot=T
(3) plot something by asapplotter again

Put in Release Notes: No

Module(s): sdplot, asapplotter

Description:

Fixed a bug which caused sdplot and asapplotter crash after closing
plotter loaded by the other modules (tasks) with X button. It was
a bug caused by the fact ID numbers of figure managers are
identical in both sdplot (asapplotter) and the other plotter.
It is also possible, that user loads plotter with the ID identical
to asapplotter and overrides it. This is because, user can select
arbitrary ID when generating a new plot.

asap.plotter._assert_plotter does more tests to make sure the
previous plotter GUI is alive, and properly reloads plotter if not.

Also some minor fixes to reset linewidth for plot invoked by
modules other than asapplot/sdplot, i.e., scantable, asapfitter,
and asapmath.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.9 KB
Line 
1import _asap
2from asap.parameters import rcParams
3from asap.logging import asaplog, asaplog_post_dec
4from asap.utils import _n_bools, mask_and
5
6
7class fitter:
8    """
9    The fitting class for ASAP.
10    """
11    def __init__(self):
12        """
13        Create a fitter object. No state is set.
14        """
15        self.fitter = _asap.fitter()
16        self.x = None
17        self.y = None
18        self.mask = None
19        self.fitfunc = None
20        self.fitfuncs = None
21        self.fitted = False
22        self.data = None
23        self.components = 0
24        self._fittedrow = 0
25        self._p = None
26        self._selection = None
27        self.uselinear = False
28
29    def set_data(self, xdat, ydat, mask=None):
30        """
31        Set the absissa and ordinate for the fit. Also set the mask
32        indicating valid points.
33        This can be used for data vectors retrieved from a scantable.
34        For scantable fitting use 'fitter.set_scan(scan, mask)'.
35        Parameters:
36            xdat:    the abcissa values
37            ydat:    the ordinate values
38            mask:    an optional mask
39
40        """
41        self.fitted = False
42        self.x = xdat
43        self.y = ydat
44        if mask == None:
45            self.mask = _n_bools(len(xdat), True)
46        else:
47            self.mask = mask
48        return
49
50    @asaplog_post_dec
51    def set_scan(self, thescan=None, mask=None):
52        """
53        Set the 'data' (a scantable) of the fitter.
54        Parameters:
55            thescan:     a scantable
56            mask:        a msk retrieved from the scantable
57        """
58        if not thescan:
59            msg = "Please give a correct scan"
60            raise TypeError(msg)
61        self.fitted = False
62        self.data = thescan
63        self.mask = None
64        if mask is None:
65            self.mask = _n_bools(self.data.nchan(), True)
66        else:
67            self.mask = mask
68        return
69
70    @asaplog_post_dec
71    def set_function(self, **kwargs):
72        """
73        Set the function to be fit.
74        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
77            gauss:    fit the number of gaussian specified
78            lorentz:  fit the number of lorentzian specified
79            sinusoid: fit the number of sinusoid specified
80        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
83            fitter.set_function(gauss=2) # will fit two gaussians
84            fitter.set_function(lorentz=2) # will fit two lorentzians
85            fitter.set_function(sinusoid=3) # will fit three sinusoids
86        """
87        #default poly order 0
88        n=0
89        if kwargs.has_key('poly'):
90            self.fitfunc = 'poly'
91            self.fitfuncs = ['poly']
92            n = kwargs.get('poly')
93            self.components = [n+1]
94            self.uselinear = False
95        elif kwargs.has_key('lpoly'):
96            self.fitfunc = 'poly'
97            self.fitfuncs = ['lpoly']
98            n = kwargs.get('lpoly')
99            self.components = [n+1]
100            self.uselinear = True
101        elif kwargs.has_key('gauss'):
102            n = kwargs.get('gauss')
103            self.fitfunc = 'gauss'
104            self.fitfuncs = [ 'gauss' for i in range(n) ]
105            self.components = [ 3 for i in range(n) ]
106            self.uselinear = False
107        elif kwargs.has_key('lorentz'):
108            n = kwargs.get('lorentz')
109            self.fitfunc = 'lorentz'
110            self.fitfuncs = [ 'lorentz' for i in range(n) ]
111            self.components = [ 3 for i in range(n) ]
112            self.uselinear = False
113        elif kwargs.has_key('sinusoid'):
114            n = kwargs.get('sinusoid')
115            self.fitfunc = 'sinusoid'
116            self.fitfuncs = [ 'sinusoid' for i in range(n) ]
117            self.components = [ 3 for i in range(n) ]
118            self.uselinear = False
119        else:
120            msg = "Invalid function type."
121            raise TypeError(msg)
122
123        self.fitter.setexpression(self.fitfunc,n)
124        self.fitted = False
125        return
126
127    @asaplog_post_dec
128    def fit(self, row=0, estimate=False):
129        """
130        Execute the actual fitting process. All the state has to be set.
131        Parameters:
132            row:        specify the row in the scantable
133            estimate:   auto-compute an initial parameter set (default False)
134                        This can be used to compute estimates even if fit was
135                        called before.
136        Example:
137            s = scantable('myscan.asap')
138            s.set_cursor(thepol=1)        # select second pol
139            f = fitter()
140            f.set_scan(s)
141            f.set_function(poly=0)
142            f.fit(row=0)                  # fit first row
143        """
144        if ((self.x is None or self.y is None) and self.data is None) \
145               or self.fitfunc is None:
146            msg = "Fitter not yet initialised. Please set data & fit function"
147            raise RuntimeError(msg)
148
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)
168        self.fitter.setdata(self.x, self.y, self.mask)
169        if self.fitfunc == 'gauss' or self.fitfunc == 'lorentz':
170            ps = self.fitter.getparameters()
171            if len(ps) == 0 or estimate:
172                self.fitter.estimate()
173        fxdpar = list(self.fitter.getfixedparameters())
174        if len(fxdpar) and fxdpar.count(0) == 0:
175             raise RuntimeError,"No point fitting, if all parameters are fixed."
176        if self.uselinear:
177            converged = self.fitter.lfit()
178        else:
179            converged = self.fitter.fit()
180        if not converged:
181            raise RuntimeError,"Fit didn't converge."
182        self._fittedrow = row
183        self.fitted = True
184        return
185
186    def store_fit(self, filename=None):
187        """
188        Save the fit parameters.
189        Parameters:
190            filename:    if specified save as an ASCII file, if None (default)
191                         store it in the scnatable
192        """
193        if self.fitted and self.data is not None:
194            pars = list(self.fitter.getparameters())
195            fixed = list(self.fitter.getfixedparameters())
196            from asap.asapfit import asapfit
197            fit = asapfit()
198            fit.setparameters(pars)
199            fit.setfixedparameters(fixed)
200            fit.setfunctions(self.fitfuncs)
201            fit.setcomponents(self.components)
202            fit.setframeinfo(self.data._getcoordinfo())
203            if filename is not None:
204                import os
205                filename = os.path.expandvars(os.path.expanduser(filename))
206                if os.path.exists(filename):
207                    raise IOError("File '%s' exists." % filename)
208                fit.save(filename)
209            else:
210                self.data._addfit(fit,self._fittedrow)
211
212    @asaplog_post_dec
213    def set_parameters(self,*args,**kwargs):
214        """
215        Set the parameters to be fitted.
216        Parameters:
217              params:    a vector of parameters
218              fixed:     a vector of which parameters are to be held fixed
219                         (default is none)
220              component: in case of multiple gaussians/lorentzians/sinusoidals,
221                         the index of the target component
222        """
223        component = None
224        fixed = None
225        params = None
226
227        if len(args) and isinstance(args[0],dict):
228            kwargs = args[0]
229        if kwargs.has_key("fixed"): fixed = kwargs["fixed"]
230        if kwargs.has_key("params"): params = kwargs["params"]
231        if len(args) == 2 and isinstance(args[1], int):
232            component = args[1]
233        if self.fitfunc is None:
234            msg = "Please specify a fitting function first."
235            raise RuntimeError(msg)
236        if (self.fitfunc == "gauss" or self.fitfunc == "lorentz" or self.fitfunc == "sinusoid") and component is not None:
237            if not self.fitted and sum(self.fitter.getparameters()) == 0:
238                pars = _n_bools(len(self.components)*3, False)
239                fxd  = _n_bools(len(pars), False)
240            else:
241                pars = list(self.fitter.getparameters())
242                fxd  = list(self.fitter.getfixedparameters())
243            i = 3*component
244            pars[i:i+3] = params
245            fxd[i:i+3]  = fixed
246            params = pars
247            fixed  = fxd
248        self.fitter.setparameters(params)
249        if fixed is not None:
250            self.fitter.setfixedparameters(fixed)
251        return
252
253    @asaplog_post_dec
254    def set_gauss_parameters(self, peak, centre, fwhm,
255                             peakfixed=0, centrefixed=0,
256                             fwhmfixed=0,
257                             component=0):
258        """
259        Set the Parameters of a 'Gaussian' component, set with set_function.
260        Parameters:
261            peak, centre, fwhm:  The gaussian parameters
262            peakfixed,
263            centrefixed,
264            fwhmfixed:           Optional parameters to indicate if
265                                 the paramters should be held fixed during
266                                 the fitting process. The default is to keep
267                                 all parameters flexible.
268            component:           The number of the component (Default is the
269                                 component 0)
270        """
271        if self.fitfunc != "gauss":
272            msg = "Function only operates on Gaussian components."
273            raise ValueError(msg)
274        if 0 <= component < len(self.components):
275            d = {'params':[peak, centre, fwhm],
276                 'fixed':[peakfixed, centrefixed, fwhmfixed]}
277            self.set_parameters(d, component)
278        else:
279            msg = "Please select a valid  component."
280            raise ValueError(msg)
281
282    @asaplog_post_dec
283    def set_lorentz_parameters(self, peak, centre, fwhm,
284                             peakfixed=0, centrefixed=0,
285                             fwhmfixed=0,
286                             component=0):
287        """
288        Set the Parameters of a 'Lorentzian' component, set with set_function.
289        Parameters:
290            peak, centre, fwhm:  The lorentzian parameters
291            peakfixed,
292            centrefixed,
293            fwhmfixed:           Optional parameters to indicate if
294                                 the paramters should be held fixed during
295                                 the fitting process. The default is to keep
296                                 all parameters flexible.
297            component:           The number of the component (Default is the
298                                 component 0)
299        """
300        if self.fitfunc != "lorentz":
301            msg = "Function only operates on Lorentzian components."
302            raise ValueError(msg)
303        if 0 <= component < len(self.components):
304            d = {'params':[peak, centre, fwhm],
305                 'fixed':[peakfixed, centrefixed, fwhmfixed]}
306            self.set_parameters(d, component)
307        else:
308            msg = "Please select a valid  component."
309            raise ValueError(msg)
310
311    @asaplog_post_dec
312    def set_sinusoid_parameters(self, ampl, period, x0,
313                             amplfixed=0, periodfixed=0,
314                             x0fixed=0,
315                             component=0):
316        """
317        Set the Parameters of a 'Sinusoidal' component, set with set_function.
318        Parameters:
319            ampl, period, x0:  The sinusoidal parameters
320            amplfixed,
321            periodfixed,
322            x0fixed:             Optional parameters to indicate if
323                                 the paramters should be held fixed during
324                                 the fitting process. The default is to keep
325                                 all parameters flexible.
326            component:           The number of the component (Default is the
327                                 component 0)
328        """
329        if self.fitfunc != "sinusoid":
330            msg = "Function only operates on Sinusoidal components."
331            raise ValueError(msg)
332        if 0 <= component < len(self.components):
333            d = {'params':[ampl, period, x0],
334                 'fixed': [amplfixed, periodfixed, x0fixed]}
335            self.set_parameters(d, component)
336        else:
337            msg = "Please select a valid  component."
338            raise ValueError(msg)
339
340    def get_area(self, component=None):
341        """
342        Return the area under the fitted gaussian/lorentzian component.
343        Parameters:
344              component:   the gaussian/lorentzian component selection,
345                           default (None) is the sum of all components
346        Note:
347              This will only work for gaussian/lorentzian fits.
348        """
349        if not self.fitted: return
350        if self.fitfunc == "gauss" or self.fitfunc == "lorentz":
351            pars = list(self.fitter.getparameters())
352            from math import log,pi,sqrt
353            if self.fitfunc == "gauss":
354                fac = sqrt(pi/log(16.0))
355            elif self.fitfunc == "lorentz":
356                fac = pi/2.0
357            areas = []
358            for i in range(len(self.components)):
359                j = i*3
360                cpars = pars[j:j+3]
361                areas.append(fac * cpars[0] * cpars[2])
362        else:
363            return None
364        if component is not None:
365            return areas[component]
366        else:
367            return sum(areas)
368
369    @asaplog_post_dec
370    def get_errors(self, component=None):
371        """
372        Return the errors in the parameters.
373        Parameters:
374            component:    get the errors for the specified component
375                          only, default is all components
376        """
377        if not self.fitted:
378            msg = "Not yet fitted."
379            raise RuntimeError(msg)
380        errs = list(self.fitter.geterrors())
381        cerrs = errs
382        if component is not None:
383            if self.fitfunc == "gauss" or self.fitfunc == "lorentz" or self.fitfunc == "sinusoid":
384                i = 3*component
385                if i < len(errs):
386                    cerrs = errs[i:i+3]
387        return cerrs
388
389
390    @asaplog_post_dec
391    def get_parameters(self, component=None, errors=False):
392        """
393        Return the fit paramters.
394        Parameters:
395             component:    get the parameters for the specified component
396                           only, default is all components
397        """
398        if not self.fitted:
399            msg = "Not yet fitted."
400            raise RuntimeError(msg)
401        pars = list(self.fitter.getparameters())
402        fixed = list(self.fitter.getfixedparameters())
403        errs = list(self.fitter.geterrors())
404        area = []
405        if component is not None:
406            if self.fitfunc == "poly" or self.fitfunc == "lpoly":
407                cpars = pars
408                cfixed = fixed
409                cerrs = errs
410            else:
411                i = 3*component
412                cpars = pars[i:i+3]
413                cfixed = fixed[i:i+3]
414                cerrs = errs[i:i+3]
415                if self.fitfunc == "gauss" or self.fitfunc == "lorentz":
416                    a = self.get_area(component)
417                    area = [a for i in range(3)]
418        else:
419            cpars = pars
420            cfixed = fixed
421            cerrs = errs
422            if self.fitfunc == "gauss" or self.fitfunc == "lorentz":
423                for c in range(len(self.components)):
424                    a = self.get_area(c)
425                    area += [a for i in range(3)]
426        fpars = self._format_pars(cpars, cfixed, errors and cerrs, area)
427        asaplog.push(fpars)
428        return {'params':cpars, 'fixed':cfixed, 'formatted': fpars,
429                'errors':cerrs}
430
431    def _format_pars(self, pars, fixed, errors, area):
432        out = ''
433        if self.fitfunc == "poly" or self.fitfunc == "lpoly":
434            c = 0
435            for i in range(len(pars)):
436                fix = ""
437                if len(fixed) and fixed[i]: fix = "(fixed)"
438                out += "  p%d%s= %3.6f" % (c, fix, pars[i])
439                if errors : out += " (%1.6f)" % errors[i]
440                out += ","
441                c+=1
442            out = out[:-1]  # remove trailing ','
443        else:
444            i = 0
445            c = 0
446            if self.fitfunc == "gauss" or self.fitfunc == "lorentz":
447                pnam = ["peak", "centre", "FWHM"]
448            elif self.fitfunc == "sinusoid":
449                pnam = ["amplitude", "period", "x0"]
450            aunit = ""
451            ounit = ""
452            if self.data:
453                aunit = self.data.get_unit()
454                ounit = self.data.get_fluxunit()
455            while i < len(pars):
456                fix0 = fix1 = fix2 = ""
457                if i < len(fixed)-2:
458                    if fixed[i]:   fix0 = "(fixed)"
459                    if fixed[i+1]: fix1 = "(fixed)"
460                    if fixed[i+2]: fix2 = "(fixed)"
461                out += "  %2d: " % c
462                out += "%s%s = %3.3f %s, " % (pnam[0], fix0, pars[i],   ounit)
463                out += "%s%s = %3.3f %s, " % (pnam[1], fix1, pars[i+1], aunit)
464                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)
466                c+=1
467                i+=3
468        return out
469
470
471    @asaplog_post_dec
472    def get_estimate(self):
473        """
474        Return the parameter estimates (for non-linear functions).
475        """
476        pars = self.fitter.getestimate()
477        fixed = self.fitter.getfixedparameters()
478        asaplog.push(self._format_pars(pars,fixed,None,None))
479        return pars
480
481    @asaplog_post_dec
482    def get_residual(self):
483        """
484        Return the residual of the fit.
485        """
486        if not self.fitted:
487            msg = "Not yet fitted."
488            raise RuntimeError(msg)
489        return self.fitter.getresidual()
490
491    @asaplog_post_dec
492    def get_chi2(self):
493        """
494        Return chi^2.
495        """
496        if not self.fitted:
497            msg = "Not yet fitted."
498            raise RuntimeError(msg)
499        ch2 = self.fitter.getchi2()
500        asaplog.push( 'Chi^2 = %3.3f' % (ch2) )
501        return ch2
502
503    @asaplog_post_dec
504    def get_fit(self):
505        """
506        Return the fitted ordinate values.
507        """
508        if not self.fitted:
509            msg = "Not yet fitted."
510            raise RuntimeError(msg)
511        return self.fitter.getfit()
512
513    @asaplog_post_dec
514    def commit(self):
515        """
516        Return a new scan where the fits have been commited (subtracted)
517        """
518        if not self.fitted:
519            msg = "Not yet fitted."
520            raise RuntimeError(msg)
521        from asap import scantable
522        if not isinstance(self.data, scantable):
523            msg = "Not a scantable"
524            raise TypeError(msg)
525        scan = self.data.copy()
526        scan._setspectrum(self.fitter.getresidual())
527        return scan
528
529    @asaplog_post_dec
530    def plot(self, residual=False, components=None, plotparms=False,
531             filename=None):
532        """
533        Plot the last fit.
534        Parameters:
535            residual:    an optional parameter indicating if the residual
536                         should be plotted (default 'False')
537            components:  a list of components to plot, e.g [0,1],
538                         -1 plots the total fit. Default is to only
539                         plot the total fit.
540            plotparms:   Inidicates if the parameter values should be present
541                         on the plot
542        """
543        if not self.fitted:
544            return
545        if not self._p or self._p.is_dead:
546            from asap.asapplotter import new_asaplot
547            del self._p
548            self._p = new_asaplot(rcParams['plotter.gui'])
549        self._p.hold()
550        self._p.clear()
551        rcp('lines', linewidth=1)
552        self._p.set_panels()
553        self._p.palette(0)
554        tlab = 'Spectrum'
555        xlab = 'Abcissa'
556        ylab = 'Ordinate'
557        from numpy import ma,logical_not,logical_and,array
558        m = self.mask
559        if self.data:
560            tlab = self.data._getsourcename(self._fittedrow)
561            xlab = self.data._getabcissalabel(self._fittedrow)
562            if self.data._getflagrow(self._fittedrow):
563                m = [False]
564            else:
565                m =  logical_and(self.mask,
566                                 array(self.data._getmask(self._fittedrow),
567                                       copy=False))
568
569            ylab = self.data._get_ordinate_label()
570
571        colours = ["#777777","#dddddd","red","orange","purple","green","magenta", "cyan"]
572        nomask=True
573        for i in range(len(m)):
574            nomask = nomask and m[i]
575        if len(m) == 1:
576            m = m[0]
577            invm = (not m)
578        else:
579            invm = logical_not(m)
580        label0='Masked Region'
581        label1='Spectrum'
582        if ( nomask ):
583            label0=label1
584        else:
585            y = ma.masked_array( self.y, mask = m )
586            self._p.palette(1,colours)
587            self._p.set_line( label = label1 )
588            self._p.plot( self.x, y )
589        self._p.palette(0,colours)
590        self._p.set_line(label=label0)
591        y = ma.masked_array(self.y,mask=invm)
592        self._p.plot(self.x, y)
593        if residual:
594            self._p.palette(7)
595            self._p.set_line(label='Residual')
596            y = ma.masked_array(self.get_residual(),
597                                  mask=invm)
598            self._p.plot(self.x, y)
599        self._p.palette(2)
600        if components is not None:
601            cs = components
602            if isinstance(components,int): cs = [components]
603            if plotparms:
604                self._p.text(0.15,0.15,str(self.get_parameters()['formatted']),size=8)
605            n = len(self.components)
606            self._p.palette(3)
607            for c in cs:
608                if 0 <= c < n:
609                    lab = self.fitfuncs[c]+str(c)
610                    self._p.set_line(label=lab)
611                    y = ma.masked_array(self.fitter.evaluate(c), mask=invm)
612
613                    self._p.plot(self.x, y)
614                elif c == -1:
615                    self._p.palette(2)
616                    self._p.set_line(label="Total Fit")
617                    y = ma.masked_array(self.fitter.getfit(),
618                                          mask=invm)
619                    self._p.plot(self.x, y)
620        else:
621            self._p.palette(2)
622            self._p.set_line(label='Fit')
623            y = ma.masked_array(self.fitter.getfit(),mask=invm)
624            self._p.plot(self.x, y)
625        xlim=[min(self.x),max(self.x)]
626        self._p.axes.set_xlim(xlim)
627        self._p.set_axes('xlabel',xlab)
628        self._p.set_axes('ylabel',ylab)
629        self._p.set_axes('title',tlab)
630        self._p.release()
631        if (not rcParams['plotter.gui']):
632            self._p.save(filename)
633
634    @asaplog_post_dec
635    def auto_fit(self, insitu=None, plot=False):
636        """
637        Return a scan where the function is applied to all rows for
638        all Beams/IFs/Pols.
639
640        """
641        from asap import scantable
642        if not isinstance(self.data, scantable) :
643            msg = "Data is not a scantable"
644            raise TypeError(msg)
645        if insitu is None: insitu = rcParams['insitu']
646        if not insitu:
647            scan = self.data.copy()
648        else:
649            scan = self.data
650        rows = xrange(scan.nrow())
651        # Save parameters of baseline fits as a class attribute.
652        # NOTICE: This does not reflect changes in scantable!
653        if len(rows) > 0: self.blpars=[]
654        asaplog.push("Fitting:")
655        for r in rows:
656            out = " Scan[%d] Beam[%d] IF[%d] Pol[%d] Cycle[%d]" % (scan.getscan(r),
657                                                                   scan.getbeam(r),
658                                                                   scan.getif(r),
659                                                                   scan.getpol(r),
660                                                                   scan.getcycle(r))
661            asaplog.push(out, False)
662            self.x = scan._getabcissa(r)
663            self.y = scan._getspectrum(r)
664            #self.mask = mask_and(self.mask, scan._getmask(r))
665            if len(self.x) == len(self.mask):
666                self.mask = mask_and(self.mask, self.data._getmask(row))
667            else:
668                asaplog.push('lengths of data and mask are not the same. preset mask will be ignored')
669                asaplog.post('WARN','asapfit.fit')
670                self.mask=self.data._getmask(row)
671            self.data = None
672            self.fit()
673            x = self.get_parameters()
674            fpar = self.get_parameters()
675            if plot:
676                self.plot(residual=True)
677                x = raw_input("Accept fit ([y]/n): ")
678                if x.upper() == 'N':
679                    self.blpars.append(None)
680                    continue
681            scan._setspectrum(self.fitter.getresidual(), r)
682            self.blpars.append(fpar)
683        if plot:
684            self._p.quit()
685            del self._p
686            self._p = None
687        return scan
Note: See TracBrowser for help on using the repository browser.