source: trunk/python/scantable.py @ 718

Last change on this file since 718 was 718, checked in by mar637, 19 years ago

more asaplog migration

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 58.5 KB
Line 
1from asap._asap import sdtable
2from asap import rcParams
3from asap import print_log
4from numarray import ones,zeros
5import sys
6
7class scantable(sdtable):
8    """
9        The ASAP container for scans
10    """
11
12    def __init__(self, filename, average=None, unit=None):
13        """
14        Create a scantable from a saved one or make a reference
15        Parameters:
16            filename:    the name of an asap table on disk
17                         or
18                         the name of a rpfits/sdfits/ms file
19                         (integrations within scans are auto averaged
20                         and the whole file is read)
21                         or
22                         [advanced] a reference to an existing
23                         scantable
24            average:     average all integrations withinb a scan on read.
25                         The default (True) is taken from .asaprc.
26            unit:         brightness unit; must be consistent with K or Jy.
27                         Over-rides the default selected by the reader
28                         (input rpfits/sdfits/ms) or replaces the value
29                         in existing scantables
30        """
31        if average is None or type(average) is not bool:
32            average = rcParams['scantable.autoaverage']
33
34        varlist = vars()
35        self._p = None
36        from asap import asaplog
37        if isinstance(filename,sdtable):
38            sdtable.__init__(self, filename)
39            if unit is not None:
40                self.set_fluxunit(unit)
41        else:
42            import os.path
43            if not os.path.exists(filename):
44                s = "File '%s' not found." % (filename)
45                if rcParams['verbose']:
46                    asaplog.push(s)
47                    print asaplog.pop().strip()
48                    return
49                raise IOError(s)
50            filename = os.path.expandvars(filename)
51            if os.path.isdir(filename):
52                # crude check if asap table
53                if os.path.exists(filename+'/table.info'):
54                    sdtable.__init__(self, filename)
55                    if unit is not None:
56                        self.set_fluxunit(unit)
57                else:
58                    msg = "The given file '%s'is not a valid asap table." % (filename)
59                    if rcParams['verbose']:
60                        print msg
61                        return
62                    else:
63                        raise IOError(msg)
64            else:
65                from asap._asap import sdreader
66                ifSel = -1
67                beamSel = -1
68                r = sdreader()
69                r._open(filename,ifSel,beamSel)
70                asaplog.push('Importing data...')
71                r._read([-1])
72                tbl = r._getdata()
73                if unit is not None:
74                    tbl.set_fluxunit(unit)
75                if average:
76                    from asap._asap import average as _av
77                    asaplog.push('Auto averaging integrations...')
78                    tbl2 = _av((tbl,),(),True,'none')
79                    sdtable.__init__(self,tbl2)
80                    del tbl2
81                else:
82                    sdtable.__init__(self,tbl)
83                del r,tbl
84                self._add_history("scantable", varlist)
85        print_log()
86
87    def save(self, name=None, format=None, stokes=False, overwrite=False):
88        """
89        Store the scantable on disk. This can be an asap (aips++) Table, SDFITS,
90        Image FITS or MS2 format.
91        Parameters:
92            name:        the name of the outputfile. For format="FITS" this
93                         is the directory file name into which all the files
94                         will be written (default is 'asap_FITS'). For format
95                         "ASCII" this is the root file name (data in 'name'.txt
96                         and header in 'name'_header.txt)
97            format:      an optional file format. Default is ASAP.
98                         Allowed are - 'ASAP' (save as ASAP [aips++] Table),
99                                       'SDFITS' (save as SDFITS file)
100                                       'FITS' (saves each row as a FITS Image)
101                                       'ASCII' (saves as ascii text file)
102                                       'MS2' (saves as an aips++
103                                              MeasurementSet V2)
104            stokes:      Convert to Stokes parameters (only available
105                         currently with FITS and ASCII formats.
106                         Default is False.
107            overwrite:   If the file should be overwritten if it exists.
108                         The default False is to return with warning
109                         without writing the output. USE WITH CARE.
110        Example:
111            scan.save('myscan.asap')
112            scan.save('myscan.sdfits','SDFITS')
113        """
114        from os import path
115        if format is None: format = rcParams['scantable.save']
116        suffix = '.'+format.lower()
117        if name is None or name =="":
118            name = 'scantable'+suffix
119            from asap import asaplog
120            msg = "No filename given. Using default name %s..." % name
121            asaplog.push(msg)
122        name = path.expandvars(name)
123        if path.isfile(name) or path.isdir(name):
124            if not overwrite:
125                msg = "File %s exists." % name
126                if rcParams['verbose']:
127                    print msg
128                    return
129                else:
130                    raise IOError(msg)
131        format2 = format.upper()
132        if format2 == 'ASAP':
133            self._save(name)
134        else:
135            from asap._asap import sdwriter as _sw
136            w = _sw(format2)
137            w.write(self, name, stokes)
138
139        print_log()
140        return
141
142    def copy(self):
143        """
144        Return a copy of this scantable.
145        Parameters:
146            none
147        Example:
148            copiedscan = scan.copy()
149        """
150        sd = scantable(sdtable._copy(self))
151        return sd
152
153    def get_scan(self, scanid=None):
154        """
155        Return a specific scan (by scanno) or collection of scans (by
156        source name) in a new scantable.
157        Parameters:
158            scanid:    a (list of) scanno or a source name, unix-style
159                       patterns are accepted for source name matching, e.g.
160                       '*_R' gets all 'ref scans
161        Example:
162            # get all scans containing the source '323p459'
163            newscan = scan.get_scan('323p459')
164            # get all 'off' scans
165            refscans = scan.get_scan('*_R')
166            # get a susbset of scans by scanno (as listed in scan.summary())
167            newscan = scan.get_scan([0,2,7,10])
168        """
169        if scanid is None:
170            if rcParams['verbose']:
171                print "Please specify a scan no or name to retrieve from the scantable"
172                return
173            else:
174                raise RuntimeError("No scan given")
175
176        try:
177            if type(scanid) is str:
178                s = sdtable._getsource(self,scanid)
179                return scantable(s)
180            elif type(scanid) is int:
181                s = sdtable._getscan(self,[scanid])
182                return scantable(s)
183            elif type(scanid) is list:
184                s = sdtable._getscan(self,scanid)
185                return scantable(s)
186            else:
187                msg = "Illegal scanid type, use 'int' or 'list' if ints."
188                if rcParams['verbose']:
189                    print msg
190                else:
191                    raise TypeError(msg)
192        except RuntimeError:
193            if rcParams['verbose']: print "Couldn't find any match."
194            else: raise
195
196    def __str__(self):
197        return sdtable._summary(self,True)
198
199    def summary(self,filename=None, verbose=None):
200        """
201        Print a summary of the contents of this scantable.
202        Parameters:
203            filename:    the name of a file to write the putput to
204                         Default - no file output
205            verbose:     print extra info such as the frequency table
206                         The default (False) is taken from .asaprc
207        """
208        info = sdtable._summary(self, verbose)
209        if verbose is None: verbose = rcParams['scantable.verbosesummary']
210        if filename is not None:
211            if filename is "":
212                filename = 'scantable_summary.txt'
213            from os.path import expandvars, isdir
214            filename = expandvars(filename)
215            if not isdir(filename):
216                data = open(filename, 'w')
217                data.write(info)
218                data.close()
219            else:
220                msg = "Illegal file name '%s'." % (filename)
221                if rcParams['verbose']:
222                    print msg
223                else:
224                    raise IOError(msg)
225        if rcParams['verbose']:
226            print info
227        else:
228            return info
229
230    def set_cursor(self, beam=0, IF=0, pol=0):
231        """
232        Set the spectrum for individual operations.
233        Parameters:
234            beam, IF, pol:    a number
235        Example:
236            scan.set_cursor(0,0,1)
237            pol1sig = scan.stats(all=False) # returns std dev for beam=0
238                                            # if=0, pol=1
239        """
240        varlist = vars()
241        self.setbeam(beam)
242        self.setpol(pol)
243        self.setif(IF)
244        self._add_history("set_cursor",varlist)
245        return
246
247    def get_cursor(self):
248        """
249        Return/print a the current 'cursor' into the Beam/IF/Pol cube.
250        Parameters:
251            none
252        Returns:
253            a list of values (currentBeam,currentIF,currentPol)
254        Example:
255            none
256        """
257        i = self.getbeam()
258        j = self.getif()
259        k = self.getpol()
260        if rcParams['verbose']:
261            print "--------------------------------------------------"
262            print " Cursor position"
263            print "--------------------------------------------------"
264            out = 'Beam=%d IF=%d Pol=%d ' % (i,j,k)
265            print out
266        else:
267            return i,j,k
268
269    def stats(self, stat='stddev', mask=None, allaxes=None):
270        """
271        Determine the specified statistic of the current beam/if/pol
272        Takes a 'mask' as an optional parameter to specify which
273        channels should be excluded.
274        Parameters:
275            stat:    'min', 'max', 'sumsq', 'sum', 'mean'
276                     'var', 'stddev', 'avdev', 'rms', 'median'
277            mask:    an optional mask specifying where the statistic
278                     should be determined.
279            allaxes: if True apply to all spectra. Otherwise
280                     apply only to the selected (beam/pol/if)spectra only.
281                     The default is taken from .asaprc (True if none)
282        Example:
283            scan.set_unit('channel')
284            msk = scan.create_mask([100,200],[500,600])
285            scan.stats(stat='mean', mask=m)
286        """
287        if allaxes is None: allaxes = rcParams['scantable.allaxes']
288        from asap._asap import stats as _stats
289        from numarray import array,zeros,Float
290        if mask == None:
291            mask = ones(self.nchan())
292        axes = ['Beam','IF','Pol','Time']
293
294        beamSel,IFSel,polSel = (self.getbeam(),self.getif(),self.getpol())
295        if allaxes:
296            n = self.nbeam()*self.nif()*self.npol()*self.nrow()
297            shp = [self.nbeam(),self.nif(),self.npol(),self.nrow()]
298            arr = array(zeros(n),shape=shp,type=Float)
299
300            for i in range(self.nbeam()):
301                self.setbeam(i)
302                for j in range(self.nif()):
303                    self.setif(j)
304                    for k in range(self.npol()):
305                        self.setpol(k)
306                        arr[i,j,k,:] = _stats(self,mask,stat,-1)
307            retval = {'axes': axes, 'data': arr, 'cursor':None}
308            tm = [self._gettime(val) for val in range(self.nrow())]
309            if rcParams['verbose']:
310                self._print_values(retval,stat,tm)
311            self.setbeam(beamSel)
312            self.setif(IFSel)
313            self.setpol(polSel)
314            return retval
315
316        else:
317            statval = _stats(self,mask,stat,-1)
318            out = ''
319            for l in range(self.nrow()):
320                tm = self._gettime(l)
321                out += 'Time[%s]:\n' % (tm)
322                if self.nbeam() > 1: out +=  ' Beam[%d] ' % (beamSel)
323                if self.nif() > 1: out +=  ' IF[%d] ' % (IFSel)
324                if self.npol() > 1: out +=  ' Pol[%d] ' % (polSel)
325                out += '= %3.3f\n' % (statval[l])
326                out +=  "--------------------------------------------------\n"
327
328            if rcParams['verbose']:
329                print "--------------------------------------------------"
330                print " ",stat
331                print "--------------------------------------------------"
332                print out
333            retval = {'axes': axes, 'data': array(statval), 'cursor':(i,j,k)}
334            return retval
335
336    def stddev(self,mask=None, allaxes=None):
337        """
338        Determine the standard deviation of the current beam/if/pol
339        Takes a 'mask' as an optional parameter to specify which
340        channels should be excluded.
341        Parameters:
342            mask:    an optional mask specifying where the standard
343                     deviation should be determined.
344            allaxes: optional flag to show all or a cursor selected
345                     spectrum of Beam/IF/Pol. Default is all or taken
346                     from .asaprc
347
348        Example:
349            scan.set_unit('channel')
350            msk = scan.create_mask([100,200],[500,600])
351            scan.stddev(mask=m)
352        """
353        if allaxes is None: allaxes = rcParams['scantable.allaxes']
354        return self.stats(stat='stddev',mask=mask, allaxes=allaxes);
355
356    def get_tsys(self, allaxes=None):
357        """
358        Return the System temperatures.
359        Parameters:
360           allaxes:     if True apply to all spectra. Otherwise
361                        apply only to the selected (beam/pol/if)spectra only.
362                        The default is taken from .asaprc (True if none)
363        Returns:
364            a list of Tsys values.
365        """
366        if allaxes is None: allaxes = rcParams['scantable.allaxes']
367        from numarray import array,zeros,Float
368        axes = ['Beam','IF','Pol','Time']
369
370        if allaxes:
371            n = self.nbeam()*self.nif()*self.npol()*self.nrow()
372            shp = [self.nbeam(),self.nif(),self.npol(),self.nrow()]
373            arr = array(zeros(n),shape=shp,type=Float)
374
375            for i in range(self.nbeam()):
376                self.setbeam(i)
377                for j in range(self.nif()):
378                    self.setif(j)
379                    for k in range(self.npol()):
380                        self.setpol(k)
381                        arr[i,j,k,:] = self._gettsys()
382            retval = {'axes': axes, 'data': arr, 'cursor':None}
383            tm = [self._gettime(val) for val in range(self.nrow())]
384            if rcParams['verbose']:
385                self._print_values(retval,'Tsys',tm)
386            return retval
387
388        else:
389            i,j,k = (self.getbeam(),self.getif(),self.getpol())
390            statval = self._gettsys()
391            out = ''
392            for l in range(self.nrow()):
393                tm = self._gettime(l)
394                out += 'Time[%s]:\n' % (tm)
395                if self.nbeam() > 1: out +=  ' Beam[%d] ' % (i)
396                if self.nif() > 1: out +=  ' IF[%d] ' % (j)
397                if self.npol() > 1: out +=  ' Pol[%d] ' % (k)
398                out += '= %3.3f\n' % (statval[l])
399                out +=  "--------------------------------------------------\n"
400
401            if rcParams['verbose']:
402                print "--------------------------------------------------"
403                print " TSys"
404                print "--------------------------------------------------"
405                print out
406            retval = {'axes': axes, 'data': array(statval), 'cursor':(i,j,k)}
407            return retval
408
409    def get_time(self, row=-1):
410        """
411        Get a list of time stamps for the observations.
412        Return a string for each integration in the scantable.
413        Parameters:
414            row:    row no of integration. Default -1 return all rows
415        Example:
416            none
417        """
418        out = []
419        if row == -1:
420            for i in range(self.nrow()):
421                out.append(self._gettime(i))
422            return out
423        else:
424            if row < self.nrow():
425                return self._gettime(row)
426
427    def get_sourcename(self, row=-1):
428        """
429        Get a list source anmes for the observations.
430        Return a string for each integration in the scantable.
431        Parameters:
432            row:    row no of integration. Default -1 return all rows
433        Example:
434            none
435        """
436        out = []
437        if row == -1:
438            return [self._getsourcename(i) for i in range(self.nrow())]
439        else:
440            if  0 <= row < self.nrow():
441                return self._getsourcename(row)
442
443    def set_unit(self, unit='channel'):
444        """
445        Set the unit for all following operations on this scantable
446        Parameters:
447            unit:    optional unit, default is 'channel'
448                     one of '*Hz','km/s','channel', ''
449        """
450        varlist = vars()
451        if unit in ['','pixel', 'channel']:
452            unit = ''
453        inf = list(self._getcoordinfo())
454        inf[0] = unit
455        self._setcoordinfo(inf)
456        if self._p: self.plot()
457        self._add_history("set_unit",varlist)
458
459    def set_instrument(self, instr):
460        """
461        Set the instrument for subsequent processing
462        Parameters:
463            instr:    Select from 'ATPKSMB', 'ATPKSHOH', 'ATMOPRA',
464                      'DSS-43' (Tid), 'CEDUNA', and 'HOBART'
465        """
466        self._setInstrument(instr)
467        self._add_history("set_instument",vars())
468        print_log()
469
470    def set_doppler(self, doppler='RADIO'):
471        """
472        Set the doppler for all following operations on this scantable.
473        Parameters:
474            doppler:    One of 'RADIO', 'OPTICAL', 'Z', 'BETA', 'GAMMA'
475        """
476        varlist = vars()
477        inf = list(self._getcoordinfo())
478        inf[2] = doppler
479        self._setcoordinfo(inf)
480        if self._p: self.plot()
481        self._add_history("set_doppler",vars())
482        print_log()
483
484    def set_freqframe(self, frame=None):
485        """
486        Set the frame type of the Spectral Axis.
487        Parameters:
488            frame:   an optional frame type, default 'LSRK'. Valid frames are:
489                     'REST','TOPO','LSRD','LSRK','BARY',
490                     'GEO','GALACTO','LGROUP','CMB'
491        Examples:
492            scan.set_freqframe('BARY')
493        """
494        if frame is None: frame = rcParams['scantable.freqframe']
495        varlist = vars()
496        valid = ['REST','TOPO','LSRD','LSRK','BARY', \
497                   'GEO','GALACTO','LGROUP','CMB']
498
499        if frame in valid:
500            inf = list(self._getcoordinfo())
501            inf[1] = frame
502            self._setcoordinfo(inf)
503            self._add_history("set_freqframe",varlist)
504        else:
505            msg  = "Please specify a valid freq type. Valid types are:\n",valid
506            if rcParams['verbose']:
507                print msg
508            else:
509                raise TypeError(msg)
510        print_log()
511
512    def get_unit(self):
513        """
514        Get the default unit set in this scantable
515        Parameters:
516        Returns:
517            A unit string
518        """
519        inf = self._getcoordinfo()
520        unit = inf[0]
521        if unit == '': unit = 'channel'
522        return unit
523
524    def get_abcissa(self, rowno=0):
525        """
526        Get the abcissa in the current coordinate setup for the currently
527        selected Beam/IF/Pol
528        Parameters:
529            rowno:    an optional row number in the scantable. Default is the
530                      first row, i.e. rowno=0
531        Returns:
532            The abcissa values and it's format string (as a dictionary)
533        """
534        abc = self._getabcissa(rowno)
535        lbl = self._getabcissalabel(rowno)
536        print_log()
537        return abc, lbl
538
539    def create_mask(self, *args, **kwargs):
540        """
541        Compute and return a mask based on [min,max] windows.
542        The specified windows are to be INCLUDED, when the mask is
543        applied.
544        Parameters:
545            [min,max],[min2,max2],...
546                Pairs of start/end points specifying the regions
547                to be masked
548            invert:     optional argument. If specified as True,
549                        return an inverted mask, i.e. the regions
550                        specified are EXCLUDED
551            row:        create the mask using the specified row for
552                        unit conversions, default is row=0
553                        only necessary if frequency varies over rows.
554        Example:
555            scan.set_unit('channel')
556
557            a)
558            msk = scan.set_mask([400,500],[800,900])
559            # masks everything outside 400 and 500
560            # and 800 and 900 in the unit 'channel'
561
562            b)
563            msk = scan.set_mask([400,500],[800,900], invert=True)
564            # masks the regions between 400 and 500
565            # and 800 and 900 in the unit 'channel'
566
567        """
568        row = 0
569        if kwargs.has_key("row"):
570            row = kwargs.get("row")
571        data = self._getabcissa(row)
572        u = self._getcoordinfo()[0]
573        if rcParams['verbose']:
574            if u == "": u = "channel"
575            from asap import asaplog
576            msg = "The current mask window unit is %s" % u
577            asaplog.push(msg)
578        n = self.nchan()
579        msk = zeros(n)
580        # test if args is a 'list' or a 'normal *args - UGLY!!!
581
582        ws = (isinstance(args[-1][-1],int) or isinstance(args[-1][-1],float)) and args or args[0]
583        for window in ws:
584            if (len(window) != 2 or window[0] > window[1] ):
585                raise TypeError("A window needs to be defined as [min,max]")
586            for i in range(n):
587                if data[i] >= window[0] and data[i] < window[1]:
588                    msk[i] = 1
589        if kwargs.has_key('invert'):
590            if kwargs.get('invert'):
591                from numarray import logical_not
592                msk = logical_not(msk)
593        print_log()
594        return msk
595
596    def get_restfreqs(self):
597        """
598        Get the restfrequency(s) stored in this scantable.
599        The return value(s) are always of unit 'Hz'
600        Parameters:
601            none
602        Returns:
603            a list of doubles
604        """
605        return list(self._getrestfreqs())
606
607    def lines(self):
608        """
609        Print the list of known spectral lines
610        """
611        l = sdtable._lines(self)
612        if rcParams['verbose']:
613            print l
614        else:
615            return l
616
617    def set_restfreqs(self, freqs=None, unit='Hz', lines=None, source=None,
618                      theif=None):
619        """
620        Select the restfrequency for the specified source and IF OR
621        replace for all IFs.  If the 'freqs' argument holds a scalar,
622        then that rest frequency will be applied to the selected
623        data (and added to the list of available rest frequencies).
624        In this way, you can set a rest frequency for each
625        source and IF combination.   If the 'freqs' argument holds
626        a vector, then it MUST be of length the number of IFs
627        (and the available restfrequencies will be replaced by
628        this vector).  In this case, *all* data ('source' and
629        'theif' are ignored) have the restfrequency set per IF according
630        to the corresponding value you give in the 'freqs' vector.
631        E.g. 'freqs=[1e9,2e9]'  would mean IF 0 gets restfreq 1e9 and
632        IF 1 gets restfreq 2e9.
633
634        You can also specify the frequencies via known line names
635        in the argument 'lines'.  Use 'freqs' or 'lines'.  'freqs'
636        takes precedence. See the list of known names via function
637        scantable.lines()
638        Parameters:
639            freqs:   list of rest frequencies
640            unit:    unit for rest frequency (default 'Hz')
641            lines:   list of known spectral lines names (alternative to freqs).
642                     See possible list via scantable.lines()
643            source:  Source name (blank means all)
644            theif:   IF (-1 means all)
645        Example:
646            scan.set_restfreqs(freqs=1.4e9, source='NGC253', theif=2)
647            scan.set_restfreqs(freqs=[1.4e9,1.67e9])
648        """
649        varlist = vars()
650        if source is None:
651            source = ""
652        if theif is None:
653            theif = -1
654        t = type(freqs)
655        if t is int or t is float:
656           freqs = [freqs]
657        if freqs is None:
658           freqs = []
659        t = type(lines)
660        if t is str:
661           lines = [lines]
662        if lines is None:
663           lines = []
664        sdtable._setrestfreqs(self, freqs, unit, lines, source, theif)
665        self._add_history("set_restfreqs", varlist)
666
667
668
669    def flag_spectrum(self, thebeam, theif, thepol):
670        """
671        This flags a selected spectrum in the scan 'for good'.
672        USE WITH CARE - not reversible.
673        Use masks for non-permanent exclusion of channels.
674        Parameters:
675            thebeam,theif,thepol:    all have to be explicitly
676                                     specified
677        Example:
678            scan.flag_spectrum(0,0,1)
679            flags the spectrum for Beam=0, IF=0, Pol=1
680        """
681        if (thebeam < self.nbeam() and
682            theif < self.nif() and
683            thepol < self.npol()):
684            sdtable.setbeam(self, thebeam)
685            sdtable.setif(self, theif)
686            sdtable.setpol(self, thepol)
687            sdtable._flag(self)
688            self._add_history("flag_spectrum", vars())
689        else:
690            print "Please specify a valid (Beam/IF/Pol)"
691        return
692
693    def _print_values(self, dat, label='', timestamps=[]):
694        d = dat['data']
695        a = dat['axes']
696        shp = d.getshape()
697        out = ''
698        for i in range(shp[3]):
699            out += '%s [%s]:\n' % (a[3],timestamps[i])
700            t = d[:,:,:,i]
701            for j in range(shp[0]):
702                if shp[0] > 1: out +=  ' %s[%d] ' % (a[0],j)
703                for k in range(shp[1]):
704                    if shp[1] > 1: out +=  ' %s[%d] ' % (a[1],k)
705                    for l in range(shp[2]):
706                        if shp[2] > 1: out +=  ' %s[%d] ' % (a[2],l)
707                        out += '= %3.3f\n' % (t[j,k,l])
708            out += "-"*80
709            out += "\n"
710        print "-"*80
711        print " ", label
712        print "-"*80
713        print out
714
715    def history(self):
716        hist = list(self._gethistory())
717        print "-"*80
718        for h in hist:
719            if h.startswith("---"):
720                print h
721            else:
722                items = h.split("##")
723                date = items[0]
724                func = items[1]
725                items = items[2:]
726                print date
727                print "Function: %s\n  Parameters:" % (func)
728                for i in items:
729                    s = i.split("=")
730                    print "   %s = %s" % (s[0],s[1])
731                print "-"*80
732        return
733
734    #
735    # Maths business
736    #
737
738    def average_time(self, mask=None, scanav=False, weight='tint'):
739        """
740        Return the (time) average of a scan, or apply it 'insitu'.
741        Note:
742            in channels only
743            The cursor of the output scan is set to 0.
744        Parameters:
745            one scan or comma separated  scans
746            mask:     an optional mask (only used for 'var' and 'tsys'
747                      weighting)
748            scanav:   True averages each scan separately
749                      False (default) averages all scans together,
750            weight:   Weighting scheme. 'none', 'var' (1/var(spec)
751                      weighted), 'tsys' (1/Tsys**2 weighted), 'tint'
752                      (integration time weighted) or 'tintsys' (Tint/Tsys**2).
753                      The default is 'tint'
754        Example:
755            # time average the scantable without using a mask
756            newscan = scan.average_time()
757        """
758        varlist = vars()
759        if weight is None: weight = 'tint'
760        if mask is None: mask = ()
761        from asap._asap import average as _av
762        s = scantable(_av((self,), mask, scanav, weight))
763        s._add_history("average_time",varlist)
764        print_log()
765        return s
766
767    def convert_flux(self, jyperk=None, eta=None, d=None, insitu=None,
768                     allaxes=None):
769        """
770        Return a scan where all spectra are converted to either
771        Jansky or Kelvin depending upon the flux units of the scan table.
772        By default the function tries to look the values up internally.
773        If it can't find them (or if you want to over-ride), you must
774        specify EITHER jyperk OR eta (and D which it will try to look up
775        also if you don't set it). jyperk takes precedence if you set both.
776        Parameters:
777            jyperk:      the Jy / K conversion factor
778            eta:         the aperture efficiency
779            d:           the geomtric diameter (metres)
780            insitu:      if False a new scantable is returned.
781                         Otherwise, the scaling is done in-situ
782                         The default is taken from .asaprc (False)
783            allaxes:         if True apply to all spectra. Otherwise
784                         apply only to the selected (beam/pol/if)spectra only
785                         The default is taken from .asaprc (True if none)
786        """
787        if allaxes is None: allaxes = rcParams['scantable.allaxes']
788        if insitu is None: insitu = rcParams['insitu']
789        varlist = vars()
790        if jyperk is None: jyperk = -1.0
791        if d is None: d = -1.0
792        if eta is None: eta = -1.0
793        if not insitu:
794            from asap._asap import convertflux as _convert
795            s = scantable(_convert(self, d, eta, jyperk, allaxes))
796            s._add_history("convert_flux", varlist)
797            print_log()
798            return s
799        else:
800            from asap._asap import convertflux_insitu as _convert
801            _convert(self, d, eta, jyperk, allaxes)
802            self._add_history("convert_flux", varlist)
803            print_log()
804            return
805
806    def gain_el(self, poly=None, filename="", method="linear",
807                insitu=None, allaxes=None):
808        """
809        Return a scan after applying a gain-elevation correction.
810        The correction can be made via either a polynomial or a
811        table-based interpolation (and extrapolation if necessary).
812        You specify polynomial coefficients, an ascii table or neither.
813        If you specify neither, then a polynomial correction will be made
814        with built in coefficients known for certain telescopes (an error
815        will occur if the instrument is not known).
816        The data and Tsys are *divided* by the scaling factors.
817        Parameters:
818            poly:        Polynomial coefficients (default None) to compute a
819                         gain-elevation correction as a function of
820                         elevation (in degrees).
821            filename:    The name of an ascii file holding correction factors.
822                         The first row of the ascii file must give the column
823                         names and these MUST include columns
824                         "ELEVATION" (degrees) and "FACTOR" (multiply data
825                         by this) somewhere.
826                         The second row must give the data type of the
827                         column. Use 'R' for Real and 'I' for Integer.
828                         An example file would be
829                         (actual factors are arbitrary) :
830
831                         TIME ELEVATION FACTOR
832                         R R R
833                         0.1 0 0.8
834                         0.2 20 0.85
835                         0.3 40 0.9
836                         0.4 60 0.85
837                         0.5 80 0.8
838                         0.6 90 0.75
839            method:      Interpolation method when correcting from a table.
840                         Values are  "nearest", "linear" (default), "cubic"
841                         and "spline"
842            insitu:      if False a new scantable is returned.
843                         Otherwise, the scaling is done in-situ
844                         The default is taken from .asaprc (False)
845            allaxes:     If True apply to all spectra. Otherwise
846                         apply only to the selected (beam/pol/if) spectra only
847                         The default is taken from .asaprc (True if none)
848        """
849
850        if allaxes is None: allaxes = rcParams['scantable.allaxes']
851        if insitu is None: insitu = rcParams['insitu']
852        varlist = vars()
853        if poly is None:
854           poly = ()
855        from os.path import expandvars
856        filename = expandvars(filename)
857        if not insitu:
858            from asap._asap import gainel as _gainEl
859            s = scantable(_gainEl(self, poly, filename, method, allaxes))
860            s._add_history("gain_el", varlist)
861            print_log()
862            return s
863        else:
864            from asap._asap import gainel_insitu as _gainEl
865            _gainEl(self, poly, filename, method, allaxes)
866            self._add_history("gain_el", varlist)
867            print_log()
868            return
869
870    def freq_align(self, reftime=None, method='cubic', perif=False,
871                   insitu=None):
872        """
873        Return a scan where all rows have been aligned in frequency/velocity.
874        The alignment frequency frame (e.g. LSRK) is that set by function
875        set_freqframe.
876        Parameters:
877            reftime:     reference time to align at. By default, the time of
878                         the first row of data is used.
879            method:      Interpolation method for regridding the spectra.
880                         Choose from "nearest", "linear", "cubic" (default)
881                         and "spline"
882            perif:       Generate aligners per freqID (no doppler tracking) or
883                         per IF (scan-based doppler tracking)
884            insitu:      if False a new scantable is returned.
885                         Otherwise, the scaling is done in-situ
886                         The default is taken from .asaprc (False)
887        """
888        if insitu is None: insitu = rcParams['insitu']
889        varlist = vars()
890        if reftime is None: reftime = ''
891        perfreqid = not perif
892        if not insitu:
893            from asap._asap import freq_align as _align
894            s = scantable(_align(self, reftime, method, perfreqid))
895            s._add_history("freq_align", varlist)
896            print_log()
897            return s
898        else:
899            from asap._asap import freq_align_insitu as _align
900            _align(self, reftime, method, perfreqid)
901            self._add_history("freq_align", varlist)
902            print_log()
903            return
904
905    def opacity(self, tau, insitu=None, allaxes=None):
906        """
907        Apply an opacity correction. The data
908        and Tsys are multiplied by the correction factor.
909        Parameters:
910            tau:         Opacity from which the correction factor is
911                         exp(tau*ZD)
912                         where ZD is the zenith-distance
913            insitu:      if False a new scantable is returned.
914                         Otherwise, the scaling is done in-situ
915                         The default is taken from .asaprc (False)
916            allaxes:     if True apply to all spectra. Otherwise
917                         apply only to the selected (beam/pol/if)spectra only
918                         The default is taken from .asaprc (True if none)
919        """
920        if allaxes is None: allaxes = rcParams['scantable.allaxes']
921        if insitu is None: insitu = rcParams['insitu']
922        varlist = vars()
923        if not insitu:
924            from asap._asap import opacity as _opacity
925            s = scantable(_opacity(self, tau, allaxes))
926            s._add_history("opacity", varlist)
927            print_log()
928            return s
929        else:
930            from asap._asap import opacity_insitu as _opacity
931            _opacity(self, tau, allaxes)
932            self._add_history("opacity", varlist)
933            print_log()
934            return
935
936    def bin(self, width=5, insitu=None):
937        """
938        Return a scan where all spectra have been binned up.
939            width:       The bin width (default=5) in pixels
940            insitu:      if False a new scantable is returned.
941                         Otherwise, the scaling is done in-situ
942                         The default is taken from .asaprc (False)
943        """
944        if insitu is None: insitu = rcParams['insitu']
945        varlist = vars()
946        if not insitu:
947            from asap._asap import bin as _bin
948            s = scantable(_bin(self, width))
949            s._add_history("bin",varlist)
950            print_log()
951            return s
952        else:
953            from asap._asap import bin_insitu as _bin
954            _bin(self, width)
955            self._add_history("bin",varlist)
956            print_log()
957            return
958
959
960    def resample(self, width=5, method='cubic', insitu=None):
961        """
962        Return a scan where all spectra have been binned up
963            width:       The bin width (default=5) in pixels
964            method:      Interpolation method when correcting from a table.
965                         Values are  "nearest", "linear", "cubic" (default)
966                         and "spline"
967            insitu:      if False a new scantable is returned.
968                         Otherwise, the scaling is done in-situ
969                         The default is taken from .asaprc (False)
970        """
971        if insitu is None: insitu = rcParams['insitu']
972        varlist = vars()
973        if not insitu:
974            from asap._asap import resample as _resample
975            s = scantable(_resample(self, method, width))
976            s._add_history("resample",varlist)
977            print_log()
978            return s
979        else:
980            from asap._asap import resample_insitu as _resample
981            _resample(self, method, width)
982            self._add_history("resample",varlist)
983            print_log()
984            return
985
986    def average_pol(self, mask=None, weight='none', insitu=None):
987        """
988        Average the Polarisations together.
989        The polarisation cursor of the output scan is set to 0
990        Parameters:
991            mask:        An optional mask defining the region, where the
992                         averaging will be applied. The output will have all
993                         specified points masked.
994            weight:      Weighting scheme. 'none' (default), 'var' (1/var(spec)
995                         weighted), or 'tsys' (1/Tsys**2 weighted)
996            insitu:      if False a new scantable is returned.
997                         Otherwise, the scaling is done in-situ
998                         The default is taken from .asaprc (False)
999        """
1000        if insitu is None: insitu = rcParams['insitu']
1001        varlist = vars()
1002
1003        if mask is None:
1004            mask = ()
1005        if not insitu:
1006            from asap._asap import averagepol as _avpol
1007            s = scantable(_avpol(self, mask, weight))
1008            s._add_history("average_pol",varlist)
1009            print_log()
1010            return s
1011        else:
1012            from asap._asap import averagepol_insitu as _avpol
1013            _avpol(self, mask, weight)
1014            self._add_history("average_pol",varlist)
1015            print_log()
1016            return
1017
1018    def smooth(self, kernel="hanning", width=5.0, insitu=None, allaxes=None):
1019        """
1020        Smooth the spectrum by the specified kernel (conserving flux).
1021        Parameters:
1022            scan:       The input scan
1023            kernel:     The type of smoothing kernel. Select from
1024                        'hanning' (default), 'gaussian' and 'boxcar'.
1025                        The first three characters are sufficient.
1026            width:      The width of the kernel in pixels. For hanning this is
1027                        ignored otherwise it defauls to 5 pixels.
1028                        For 'gaussian' it is the Full Width Half
1029                        Maximum. For 'boxcar' it is the full width.
1030            insitu:     if False a new scantable is returned.
1031                        Otherwise, the scaling is done in-situ
1032                        The default is taken from .asaprc (False)
1033            allaxes:    If True (default) apply to all spectra. Otherwise
1034                        apply only to the selected (beam/pol/if)spectra only
1035                        The default is taken from .asaprc (True if none)
1036        Example:
1037             none
1038        """
1039        if allaxes is None: allaxes = rcParams['scantable.allaxes']
1040        if insitu is None: insitu = rcParams['insitu']
1041        varlist = vars()
1042        if not insitu:
1043            from asap._asap import smooth as _smooth
1044            s = scantable(_smooth(self,kernel,width,allaxes))
1045            s._add_history("smooth", varlist)
1046            print_log()
1047            return s
1048        else:
1049            from asap._asap import smooth_insitu as _smooth
1050            _smooth(self,kernel,width,allaxes)
1051            self._add_history("smooth", varlist)
1052            print_log()
1053            return
1054
1055    def poly_baseline(self, mask=None, order=0, insitu=None):
1056        """
1057        Return a scan which has been baselined (all rows) by a polynomial.
1058        Parameters:
1059            scan:    a scantable
1060            mask:    an optional mask
1061            order:   the order of the polynomial (default is 0)
1062            insitu:      if False a new scantable is returned.
1063                         Otherwise, the scaling is done in-situ
1064                         The default is taken from .asaprc (False)
1065        Example:
1066            # return a scan baselined by a third order polynomial,
1067            # not using a mask
1068            bscan = scan.poly_baseline(order=3)
1069        """
1070        if insitu is None: insitu = rcParams['insitu']
1071        varlist = vars()
1072        if mask is None:
1073            from numarray import ones
1074            mask = list(ones(self.nchan()))
1075        from asap.asapfitter import fitter
1076        f = fitter()
1077        f._verbose(True)
1078        f.set_scan(self, mask)
1079        f.set_function(poly=order)
1080        sf = f.auto_fit(insitu)
1081        if insitu:
1082            self._add_history("poly_baseline", varlist)
1083            print_log()
1084            return
1085        else:
1086            sf._add_history("poly_baseline", varlist)
1087            print_log()
1088            return sf
1089
1090    def auto_poly_baseline(self, mask=None, edge=(0,0), order=0,
1091                           threshold=3,insitu=None):
1092        """
1093        Return a scan which has been baselined (all rows) by a polynomial.
1094        Spectral lines are detected first using linefinder and masked out
1095        to avoid them affecting the baseline solution.
1096
1097        Parameters:
1098            mask:       an optional mask retreived from scantable
1099            edge:       an optional number of channel to drop at
1100                        the edge of spectrum. If only one value is
1101                        specified, the same number will be dropped from
1102                        both sides of the spectrum. Default is to keep
1103                        all channels
1104            order:      the order of the polynomial (default is 0)
1105            threshold:  the threshold used by line finder. It is better to
1106                        keep it large as only strong lines affect the
1107                        baseline solution.
1108            insitu:     if False a new scantable is returned.
1109                        Otherwise, the scaling is done in-situ
1110                        The default is taken from .asaprc (False)
1111
1112        Example:
1113            scan2=scan.auto_poly_baseline(order=7)
1114        """
1115        if insitu is None: insitu = rcParams['insitu']
1116        varlist = vars()
1117        from asap.asapfitter import fitter
1118        from asap.asaplinefind import linefinder
1119        from asap import _is_sequence_or_number as _is_valid
1120
1121        if not _is_valid(edge, int):
1122
1123            raise RuntimeError, "Parameter 'edge' has to be an integer or a \
1124            pair of integers specified as a tuple"
1125
1126        # setup fitter
1127        f = fitter()
1128        f._verbose(True)
1129        f.set_function(poly=order)
1130
1131        # setup line finder
1132        fl=linefinder()
1133        fl.set_options(threshold=threshold)
1134
1135        if not insitu:
1136            workscan=self.copy()
1137        else:
1138            workscan=self
1139
1140        sel=workscan.get_cursor()
1141        rows=range(workscan.nrow())
1142        from asap import asaplog
1143        for i in range(workscan.nbeam()):
1144            workscan.setbeam(i)
1145            for j in range(workscan.nif()):
1146                workscan.setif(j)
1147                for k in range(workscan.npol()):
1148                    workscan.setpol(k)
1149                    asaplog.push("Processing:")
1150                    msg = 'Beam[%d], IF[%d], Pol[%d]' % (i,j,k)
1151                    asaplog.push(msg)
1152                    for iRow in rows:
1153                       fl.set_scan(workscan,mask,edge)
1154                       fl.find_lines(iRow)
1155                       f.set_scan(workscan, fl.get_mask())
1156                       f.x=workscan._getabcissa(iRow)
1157                       f.y=workscan._getspectrum(iRow)
1158                       f.data=None
1159                       f.fit()
1160                       x=f.get_parameters()
1161                       workscan._setspectrum(f.fitter.getresidual(),iRow)
1162        workscan.set_cursor(sel[0],sel[1],sel[2])
1163        if not insitu:
1164            return workscan
1165
1166    def rotate_linpolphase(self, angle, allaxes=None):
1167        """
1168        Rotate the phase of the complex polarization O=Q+iU correlation.
1169        This is always done in situ in the raw data.  So if you call this
1170        function more than once then each call rotates the phase further.
1171        Parameters:
1172            angle:   The angle (degrees) to rotate (add) by.
1173            allaxes: If True apply to all spectra. Otherwise
1174                     apply only to the selected (beam/pol/if)spectra only.
1175                     The default is taken from .asaprc (True if none)
1176        Examples:
1177            scan.rotate_linpolphase(2.3)
1178    """
1179        if allaxes is None: allaxes = rcParams['scantable.allaxes']
1180        varlist = vars()
1181        from asap._asap import _rotate_linpolphase as _rotate
1182        _rotate(self, angle, allaxes)
1183        self._add_history("rotate_linpolphase", varlist)
1184        print_log()
1185        return
1186
1187
1188    def rotate_xyphase(self, angle, allaxes=None):
1189        """
1190        Rotate the phase of the XY correlation.  This is always done in situ
1191        in the data.  So if you call this function more than once
1192        then each call rotates the phase further.
1193        Parameters:
1194            angle:   The angle (degrees) to rotate (add) by.
1195            allaxes: If True apply to all spectra. Otherwise
1196                     apply only to the selected (beam/pol/if)spectra only.
1197                     The default is taken from .asaprc (True if none)
1198        Examples:
1199            scan.rotate_xyphase(2.3)
1200        """
1201        if allaxes is None: allaxes = rcParams['scantable.allaxes']
1202        varlist = vars()
1203        from asap._asap import _rotate_xyphase
1204        _rotate_xyphase(self, angle, allaxes)
1205        self._add_history("rotate_xyphase", varlist)
1206        print_log()
1207        return
1208
1209
1210    def add(self, offset, insitu=None, allaxes=None):
1211        """
1212        Return a scan where all spectra have the offset added
1213        Parameters:
1214            offset:      the offset
1215            insitu:      if False a new scantable is returned.
1216                         Otherwise, the scaling is done in-situ
1217                         The default is taken from .asaprc (False)
1218            allaxes:     if True apply to all spectra. Otherwise
1219                         apply only to the selected (beam/pol/if)spectra only
1220                         The default is taken from .asaprc (True if none)
1221        """
1222        if allaxes is None: allaxes = rcParams['scantable.allaxes']
1223        if insitu is None: insitu = rcParams['insitu']
1224        varlist = vars()
1225        if not insitu:
1226            from asap._asap import add as _add
1227            s = scantable(_add(self, offset, allaxes))
1228            s._add_history("add",varlist)
1229            print_log()
1230            return s
1231        else:
1232            from asap._asap import add_insitu as _add
1233            _add(self, offset, allaxes)
1234            self._add_history("add",varlist)
1235            print_log()
1236            return
1237
1238    def scale(self, factor, insitu=None, allaxes=None, tsys=True):
1239        """
1240        Return a scan where all spectra are scaled by the give 'factor'
1241        Parameters:
1242            factor:      the scaling factor
1243            insitu:      if False a new scantable is returned.
1244                         Otherwise, the scaling is done in-situ
1245                         The default is taken from .asaprc (False)
1246            allaxes:     if True apply to all spectra. Otherwise
1247                         apply only to the selected (beam/pol/if)spectra only.
1248                         The default is taken from .asaprc (True if none)
1249            tsys:        if True (default) then apply the operation to Tsys
1250                         as well as the data
1251        """
1252        if allaxes is None: allaxes = rcParams['scantable.allaxes']
1253        if insitu is None: insitu = rcParams['insitu']
1254        varlist = vars()
1255        if not insitu:
1256            from asap._asap import scale as _scale
1257            s = scantable(_scale(self, factor, allaxes, tsys))
1258            s._add_history("scale",varlist)
1259            print_log()
1260            return s
1261        else:
1262            from asap._asap import scale_insitu as _scale
1263            _scale(self, factor, allaxes, tsys)
1264            self._add_history("scale",varlist)
1265            print_log()
1266            return
1267
1268    def auto_quotient(self, mode='suffix', preserve=True):
1269        """
1270        This function allows to build quotients automatically.
1271        It assumes the observation to have the same numer of
1272        "ons" and "offs"
1273        It will support "closest off in time" in the future
1274        Parameters:
1275            mode:           the on/off detection mode; 'suffix' (default)
1276                            'suffix' identifies 'off' scans by the
1277                            trailing '_R' (Mopra/Parkes) or
1278                            '_e'/'_w' (Tid)
1279            preserve:       you can preserve (default) the continuum or
1280                            remove it.  The equations used are
1281                            preserve: Output = Toff * (on/off) - Toff
1282                            remove:   Output = Tref * (on/off) - Ton
1283        """
1284        modes = ["suffix","time"]
1285        if not mode in modes:
1286            print "please provide valid mode. Valid modes are %s" % (modes)
1287            return None
1288        from asap._asap import quotient as _quot
1289        if mode == "suffix":
1290            srcs = self.get_scan("*[^_ewR]")
1291            refs = self.get_scan("*[_ewR]")
1292            if isinstance(srcs,scantable) and isinstance(refs,scantable):
1293                ns,nr = srcs.nrow(),refs.nrow()
1294                if nr > ns:
1295                    refs = refs.get_scan(range(ns))
1296                print_log()
1297                return scantable(_quot(srcs,refs, preserve))
1298            else:
1299                msg = "Couldn't find any on/off pairs"
1300                if rcParams['verbose']:
1301                    print msg
1302                    return
1303                else:
1304                    raise RuntimeError()
1305        else:
1306            if rcParams['verbose']: print "not yet implemented"
1307            return None
1308
1309    def quotient(self, other, isreference=True, preserve=True):
1310        """
1311        Return the quotient of a 'source' (on) scan and a 'reference' (off)
1312        scan.
1313        The reference can have just one row, even if the signal has many.
1314        Otherwise they must have the same number of rows.
1315        The cursor of the output scan is set to 0
1316        Parameters:
1317            other:          the 'other' scan
1318            isreference:    if the 'other' scan is the reference (default)
1319                            or source
1320            preserve:       you can preserve (default) the continuum or
1321                            remove it.  The equations used are
1322                            preserve: Output = Toff * (on/off) - Toff
1323                            remove:   Output = Tref * (on/off) - Ton
1324        Example:
1325            # src is a scantable for an 'on' scan, ref for an 'off' scantable
1326            q1 = src.quotient(ref)
1327            q2 = ref.quotient(src, isreference=False)
1328            # gives the same result
1329        """
1330        from asap._asap import quotient as _quot
1331        try:
1332            s = None
1333            if isreference:
1334                s = scantable(_quot(self, other, preserve))
1335            else:
1336                s = scantable(_quot(other, self, preserve))
1337            print_log()
1338            return s
1339        except RuntimeError,e:
1340            if rcParams['verbose']:
1341                print e
1342                return
1343            else: raise
1344
1345    def freq_switch(self, insitu=None):
1346        """
1347        Apply frequency switching to the data.
1348        Parameters:
1349            insitu:      if False a new scantable is returned.
1350                         Otherwise, the swictching is done in-situ
1351                         The default is taken from .asaprc (False)
1352        Example:
1353            none
1354        """
1355        if insitu is None: insitu = rcParams['insitu']
1356        varlist = vars()
1357        try:
1358            if insitu:
1359                from asap._asap import _frequency_switch_insitu
1360                _frequency_switch_insitu(self)
1361                self._add_history("freq_switch", varlist)
1362                print_log()
1363                return
1364            else:
1365                from asap._asap import _frequency_switch
1366                sf = scantable(_frequency_switch(self))
1367                sf._add_history("freq_switch", varlist)
1368                print_log()
1369                return sf
1370        except RuntimeError,e:
1371            if rcParams['verbose']: print e
1372            else: raise
1373
1374    def __add__(self, other):
1375        varlist = vars()
1376        s = None
1377        if isinstance(other, scantable):
1378            from asap._asap import b_operate as _bop
1379            s = scantable(_bop(self, other, 'add', True))
1380        elif isinstance(other, float):
1381            from asap._asap import add as _add
1382            s = scantable(_add(self, other, True))
1383        else:
1384            raise TypeError("Other input is not a scantable or float value")
1385        s._add_history("operator +", varlist)
1386        print_log()
1387        return s
1388
1389
1390    def __sub__(self, other):
1391        """
1392        implicit on all axes and on Tsys
1393        """
1394        varlist = vars()
1395        s = None
1396        if isinstance(other, scantable):
1397            from asap._asap import b_operate as _bop
1398            s = scantable(_bop(self, other, 'sub', True))
1399        elif isinstance(other, float):
1400            from asap._asap import add as _add
1401            s = scantable(_add(self, -other, True))
1402        else:
1403            raise TypeError("Other input is not a scantable or float value")
1404        s._add_history("operator -", varlist)
1405        print_log()
1406        return s
1407
1408    def __mul__(self, other):
1409        """
1410        implicit on all axes and on Tsys
1411        """
1412        varlist = vars()
1413        s = None
1414        if isinstance(other, scantable):
1415            from asap._asap import b_operate as _bop
1416            s = scantable(_bop(self, other, 'mul', True))
1417        elif isinstance(other, float):
1418            if other == 0.0:
1419                raise ZeroDivisionError("Dividing by zero is not recommended")
1420            from asap._asap import scale as _sca
1421            s = scantable(_sca(self, other, True))
1422        else:
1423            raise TypeError("Other input is not a scantable or float value")
1424        s._add_history("operator *", varlist)
1425        print_log()
1426        return s
1427
1428
1429    def __div__(self, other):
1430        """
1431        implicit on all axes and on Tsys
1432        """
1433        varlist = vars()
1434        s = None
1435        if isinstance(other, scantable):
1436            from asap._asap import b_operate as _bop
1437            s = scantable(_bop(self, other, 'div', True))
1438        elif isinstance(other, float):
1439            if other == 0.0:
1440                raise ZeroDivisionError("Dividing by zero is not recommended")
1441            from asap._asap import scale as _sca
1442            s = scantable(_sca(self, 1.0/other, True))
1443        else:
1444            raise TypeError("Other input is not a scantable or float value")
1445        s._add_history("operator /", varlist)
1446        print_log()
1447        return s
1448
1449    def get_fit(self, row=0):
1450        """
1451        Print or return the stored fits for a row in the scantable
1452        Parameters:
1453            row:    the row which the fit has been applied to.
1454        """
1455        if row > self.nrow():
1456            return
1457        from asap import asapfit
1458        fit = asapfit(self._getfit(row))
1459        if rcParams['verbose']:
1460            print fit
1461            return
1462        else:
1463            return fit.as_dict()
1464
1465    def _add_history(self, funcname, parameters):
1466        # create date
1467        sep = "##"
1468        from datetime import datetime
1469        dstr = datetime.now().strftime('%Y/%m/%d %H:%M:%S')
1470        hist = dstr+sep
1471        hist += funcname+sep#cdate+sep
1472        if parameters.has_key('self'): del parameters['self']
1473        for k,v in parameters.iteritems():
1474            if type(v) is dict:
1475                for k2,v2 in v.iteritems():
1476                    hist += k2
1477                    hist += "="
1478                    if isinstance(v2,scantable):
1479                        hist += 'scantable'
1480                    elif k2 == 'mask':
1481                        if isinstance(v2,list) or isinstance(v2,tuple):
1482                            hist += str(self._zip_mask(v2))
1483                        else:
1484                            hist += str(v2)
1485                    else:
1486                        hist += str(v2)
1487            else:
1488                hist += k
1489                hist += "="
1490                if isinstance(v,scantable):
1491                    hist += 'scantable'
1492                elif k == 'mask':
1493                    if isinstance(v,list) or isinstance(v,tuple):
1494                        hist += str(self._zip_mask(v))
1495                    else:
1496                        hist += str(v)
1497                else:
1498                    hist += str(v)
1499            hist += sep
1500        hist = hist[:-2] # remove trailing '##'
1501        self._addhistory(hist)
1502
1503
1504    def _zip_mask(self, mask):
1505        mask = list(mask)
1506        i = 0
1507        segments = []
1508        while mask[i:].count(1):
1509            i += mask[i:].index(1)
1510            if mask[i:].count(0):
1511                j = i + mask[i:].index(0)
1512            else:
1513                j = len(mask)
1514            segments.append([i,j])
1515            i = j
1516        return segments
1517
1518    def _get_ordinate_label(self):
1519        fu = "("+self.get_fluxunit()+")"
1520        import re
1521        lbl = "Intensity"
1522        if re.match(".K.",fu):
1523            lbl = "Brightness Temperature "+ fu
1524        elif re.match(".Jy.",fu):
1525            lbl = "Flux density "+ fu
1526        return lbl
1527
Note: See TracBrowser for help on using the repository browser.