source: branches/alma/python/scantable.py @ 1631

Last change on this file since 1631 was 1631, checked in by Takeshi Nakazato, 15 years ago

New Development: No

JIRA Issue: Yes CAS-1424

Ready to Release: Yes

Interface Changes: Yes

What Interface Changed: Added 'verify' parameter for asapmath.calps, asapmath.calnod, asapmath.calfs, and scantable.auto_quotient

Test Programs: do calibration using sdaverage with verify=True

Put in Release Notes: Yes

Module(s): task sdaverage and sdcal

Description: Describe your changes here...

I have added verify parameter to verify calibration result.
If verify=True, methods plot pre- and post-calibration spectra and asks user
to be acceptable calibration or not.
If not, calibration will not be applied.


  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 81.2 KB
Line 
1from asap._asap import Scantable
2from asap import rcParams
3from asap import print_log
4from asap import asaplog
5from asap import selector
6from asap import linecatalog
7from asap import _n_bools, mask_not, mask_and, mask_or
8
9class scantable(Scantable):
10    """
11        The ASAP container for scans
12    """
13
14    def __init__(self, filename, average=None, unit=None, getpt=None):
15        """
16        Create a scantable from a saved one or make a reference
17        Parameters:
18            filename:    the name of an asap table on disk
19                         or
20                         the name of a rpfits/sdfits/ms file
21                         (integrations within scans are auto averaged
22                         and the whole file is read)
23                         or
24                         [advanced] a reference to an existing
25                         scantable
26            average:     average all integrations withinb a scan on read.
27                         The default (True) is taken from .asaprc.
28            unit:         brightness unit; must be consistent with K or Jy.
29                         Over-rides the default selected by the reader
30                         (input rpfits/sdfits/ms) or replaces the value
31                         in existing scantables
32            getpt:       for MeasurementSet input data only:
33                         If True, all pointing data are filled.
34                         The deafult is False, which makes time to load
35                         the MS data faster in some cases.
36        """
37        if average is None:
38            average = rcParams['scantable.autoaverage']
39        if getpt is None:
40            getpt = False
41        varlist = vars()
42        from asap._asap import stmath
43        self._math = stmath()
44        if isinstance(filename, Scantable):
45            Scantable.__init__(self, filename)
46        else:
47            if isinstance(filename, str):# or \
48#                (isinstance(filename, list) or isinstance(filename, tuple)) \
49#                  and isinstance(filename[-1], str):
50                import os.path
51                filename = os.path.expandvars(filename)
52                filename = os.path.expanduser(filename)
53                if not os.path.exists(filename):
54                    s = "File '%s' not found." % (filename)
55                    if rcParams['verbose']:
56                        asaplog.push(s)
57                        #print asaplog.pop().strip()
58                        print_log('ERROR')
59                        return
60                    raise IOError(s)
61                if os.path.isdir(filename) \
62                    and not os.path.exists(filename+'/table.f1'):
63                    # crude check if asap table
64                    if os.path.exists(filename+'/table.info'):
65                        ondisk = rcParams['scantable.storage'] == 'disk'
66                        Scantable.__init__(self, filename, ondisk)
67                        if unit is not None:
68                            self.set_fluxunit(unit)
69                        # do not reset to the default freqframe
70                        #self.set_freqframe(rcParams['scantable.freqframe'])
71                    else:
72                        msg = "The given file '%s'is not a valid " \
73                              "asap table." % (filename)
74                        if rcParams['verbose']:
75                            #print msg
76                            asaplog.push( msg )
77                            print_log( 'ERROR' )
78                            return
79                        else:
80                            raise IOError(msg)
81                else:
82                    self._fill([filename], unit, average, getpt)
83            elif (isinstance(filename, list) or isinstance(filename, tuple)) \
84                  and isinstance(filename[-1], str):
85                self._fill(filename, unit, average, getpt)
86        self._add_history("scantable", varlist)
87        print_log()
88
89    def save(self, name=None, format=None, overwrite=False):
90        """
91        Store the scantable on disk. This can be an asap (aips++) Table,
92        SDFITS or MS2 format.
93        Parameters:
94            name:        the name of the outputfile. For format "ASCII"
95                         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                                       'ASCII' (saves as ascii text file)
101                                       'MS2' (saves as an aips++
102                                              MeasurementSet V2)
103                                       'FITS' (save as image FITS - not
104                                               readable by class)
105                                       'CLASS' (save as FITS readable by CLASS)
106            overwrite:   If the file should be overwritten if it exists.
107                         The default False is to return with warning
108                         without writing the output. USE WITH CARE.
109        Example:
110            scan.save('myscan.asap')
111            scan.save('myscan.sdfits', 'SDFITS')
112        """
113        from os import path
114        if format is None: format = rcParams['scantable.save']
115        suffix = '.'+format.lower()
116        if name is None or name == "":
117            name = 'scantable'+suffix
118            msg = "No filename given. Using default name %s..." % name
119            asaplog.push(msg)
120        name = path.expandvars(name)
121        if path.isfile(name) or path.isdir(name):
122            if not overwrite:
123                msg = "File %s exists." % name
124                if rcParams['verbose']:
125                    #print msg
126                    asaplog.push( msg )
127                    print_log( 'ERROR' )
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 stwriter as stw
136            writer = stw(format2)
137            writer.write(self, name)
138        print_log()
139        return
140
141    def copy(self):
142        """
143        Return a copy of this scantable.
144        Note:
145            This makes a full (deep) copy. scan2 = scan1 makes a reference.
146        Parameters:
147            none
148        Example:
149            copiedscan = scan.copy()
150        """
151        sd = scantable(Scantable._copy(self))
152        return sd
153
154    def drop_scan(self, scanid=None):
155        """
156        Return a new scantable where the specified scan number(s) has(have)
157        been dropped.
158        Parameters:
159            scanid:    a (list of) scan number(s)
160        """
161        from asap import _is_sequence_or_number as _is_valid
162        from asap import _to_list
163        from asap import unique
164        if not _is_valid(scanid):
165            if rcParams['verbose']:
166                #print "Please specify a scanno to drop from the scantable"
167                asaplog.push( 'Please specify a scanno to drop from the scantable' )
168                print_log( 'ERROR' )
169                return
170            else:
171                raise RuntimeError("No scan given")
172        try:
173            scanid = _to_list(scanid)
174            allscans = unique([ self.getscan(i) for i in range(self.nrow())])
175            for sid in scanid: allscans.remove(sid)
176            if len(allscans) == 0:
177                raise ValueError("Can't remove all scans")
178        except ValueError:
179            if rcParams['verbose']:
180                #print "Couldn't find any match."
181                print_log()
182                asaplog.push( "Couldn't find any match." )
183                print_log( 'ERROR' )
184                return
185            else: raise
186        try:
187            bsel = self.get_selection()
188            sel = selector()
189            sel.set_scans(allscans)
190            self.set_selection(bsel+sel)
191            scopy = self._copy()
192            self.set_selection(bsel)
193            return scantable(scopy)
194        except RuntimeError:
195            if rcParams['verbose']:
196                #print "Couldn't find any match."
197                print_log()
198                asaplog.push( "Couldn't find any match." )
199                print_log( 'ERROR' )
200            else:
201                raise
202
203
204    def get_scan(self, scanid=None):
205        """
206        Return a specific scan (by scanno) or collection of scans (by
207        source name) in a new scantable.
208        Note:
209            See scantable.drop_scan() for the inverse operation.
210        Parameters:
211            scanid:    a (list of) scanno or a source name, unix-style
212                       patterns are accepted for source name matching, e.g.
213                       '*_R' gets all 'ref scans
214        Example:
215            # get all scans containing the source '323p459'
216            newscan = scan.get_scan('323p459')
217            # get all 'off' scans
218            refscans = scan.get_scan('*_R')
219            # get a susbset of scans by scanno (as listed in scan.summary())
220            newscan = scan.get_scan([0, 2, 7, 10])
221        """
222        if scanid is None:
223            if rcParams['verbose']:
224                #print "Please specify a scan no or name to " \
225                #      "retrieve from the scantable"
226                asaplog.push( 'Please specify a scan no or name to retrieve from the scantable' )
227                print_log( 'ERROR' )
228                return
229            else:
230                raise RuntimeError("No scan given")
231
232        try:
233            bsel = self.get_selection()
234            sel = selector()
235            if type(scanid) is str:
236                sel.set_name(scanid)
237                self.set_selection(bsel+sel)
238                scopy = self._copy()
239                self.set_selection(bsel)
240                return scantable(scopy)
241            elif type(scanid) is int:
242                sel.set_scans([scanid])
243                self.set_selection(bsel+sel)
244                scopy = self._copy()
245                self.set_selection(bsel)
246                return scantable(scopy)
247            elif type(scanid) is list:
248                sel.set_scans(scanid)
249                self.set_selection(sel)
250                scopy = self._copy()
251                self.set_selection(bsel)
252                return scantable(scopy)
253            else:
254                msg = "Illegal scanid type, use 'int' or 'list' if ints."
255                if rcParams['verbose']:
256                    #print msg
257                    asaplog.push( msg )
258                    print_log( 'ERROR' )
259                else:
260                    raise TypeError(msg)
261        except RuntimeError:
262            if rcParams['verbose']:
263                #print "Couldn't find any match."
264                print_log()
265                asaplog.push( "Couldn't find any match." )
266                print_log( 'ERROR' )
267            else: raise
268
269    def __str__(self):
270        return Scantable._summary(self, True)
271
272    def summary(self, filename=None):
273        """
274        Print a summary of the contents of this scantable.
275        Parameters:
276            filename:    the name of a file to write the putput to
277                         Default - no file output
278            verbose:     print extra info such as the frequency table
279                         The default (False) is taken from .asaprc
280        """
281        info = Scantable._summary(self, True)
282        #if verbose is None: verbose = rcParams['scantable.verbosesummary']
283        if filename is not None:
284            if filename is "":
285                filename = 'scantable_summary.txt'
286            from os.path import expandvars, isdir
287            filename = expandvars(filename)
288            if not isdir(filename):
289                data = open(filename, 'w')
290                data.write(info)
291                data.close()
292            else:
293                msg = "Illegal file name '%s'." % (filename)
294                if rcParams['verbose']:
295                    #print msg
296                    asaplog.push( msg )
297                    print_log( 'ERROR' )
298                else:
299                    raise IOError(msg)
300        if rcParams['verbose']:
301            try:
302                from IPython.genutils import page as pager
303            except ImportError:
304                from pydoc import pager
305            pager(info)
306        else:
307            return info
308
309    def get_spectrum(self, rowno):
310        """Return the spectrum for the current row in the scantable as a list.
311        Parameters:
312             rowno:   the row number to retrieve the spectrum from       
313        """
314        return self._getspectrum(rowno)
315
316    def get_mask(self, rowno):
317        """Return the mask for the current row in the scantable as a list.
318        Parameters:
319             rowno:   the row number to retrieve the mask from       
320        """
321        return self._getmask(rowno)
322
323    def set_spectrum(self, spec, rowno):
324        """Return the spectrum for the current row in the scantable as a list.
325        Parameters:
326             spec:   the spectrum
327             rowno:    the row number to set the spectrum for       
328        """
329        assert(len(spec) == self.nchan())
330        return self._setspectrum(spec, rowno)
331
332    def get_selection(self):
333        """
334        Get the selection object currently set on this scantable.
335        Parameters:
336            none
337        Example:
338            sel = scan.get_selection()
339            sel.set_ifs(0)              # select IF 0
340            scan.set_selection(sel)     # apply modified selection
341        """
342        return selector(self._getselection())
343
344    def set_selection(self, selection=selector()):
345        """
346        Select a subset of the data. All following operations on this scantable
347        are only applied to thi selection.
348        Parameters:
349            selection:    a selector object (default unset the selection)
350        Examples:
351            sel = selector()         # create a selection object
352            self.set_scans([0, 3])    # select SCANNO 0 and 3
353            scan.set_selection(sel)  # set the selection
354            scan.summary()           # will only print summary of scanno 0 an 3
355            scan.set_selection()     # unset the selection
356        """
357        self._setselection(selection)
358
359    def get_row(self, row=0, insitu=None):
360        """
361        Select a row in the scantable.
362        Return a scantable with single row.
363        Parameters:
364            row: row no of integration, default is 0.
365            insitu: if False a new scantable is returned.
366                    Otherwise, the scaling is done in-situ
367                    The default is taken from .asaprc (False)
368        """
369        if insitu is None: insitu = rcParams['insitu']
370        if not insitu:
371            workscan = self.copy()
372        else:
373            workscan = self
374        # Select a row
375        sel=selector()
376        sel.set_scans([workscan.getscan(row)])
377        sel.set_cycles([workscan.getcycle(row)])
378        sel.set_beams([workscan.getbeam(row)])
379        sel.set_ifs([workscan.getif(row)])
380        sel.set_polarisations([workscan.getpol(row)])
381        sel.set_name(workscan._getsourcename(row))
382        workscan.set_selection(sel)
383        if not workscan.nrow() == 1:
384            msg = "Cloud not identify single row. %d rows selected."%(workscan.nrow())
385            raise RuntimeError(msg)
386        del sel
387        if insitu:
388            self._assign(workscan)
389        else:
390            return workscan
391
392    #def stats(self, stat='stddev', mask=None):
393    def stats(self, stat='stddev', mask=None, form='3.3f'):
394        """
395        Determine the specified statistic of the current beam/if/pol
396        Takes a 'mask' as an optional parameter to specify which
397        channels should be excluded.
398        Parameters:
399            stat:    'min', 'max', 'min_abc', 'max_abc', 'sumsq', 'sum',
400                     'mean', 'var', 'stddev', 'avdev', 'rms', 'median'
401            mask:    an optional mask specifying where the statistic
402                     should be determined.
403            form:    format string to print statistic values
404        Example:
405            scan.set_unit('channel')
406            msk = scan.create_mask([100, 200], [500, 600])
407            scan.stats(stat='mean', mask=m)
408        """
409        if mask == None:
410            mask = []
411        axes = ['Beam', 'IF', 'Pol', 'Time']
412        if not self._check_ifs():
413            raise ValueError("Cannot apply mask as the IFs have different "
414                             "number of channels. Please use setselection() "
415                             "to select individual IFs")
416        rtnabc = False
417        if stat.lower().endswith('_abc'): rtnabc = True
418        getchan = False
419        if stat.lower().startswith('min') or stat.lower().startswith('max'):
420            chan = self._math._minmaxchan(self, mask, stat)
421            getchan = True
422            statvals = []
423        if not rtnabc: statvals = self._math._stats(self, mask, stat)
424
425        out = ''
426        axes = []
427        for i in range(self.nrow()):
428            axis = []
429            axis.append(self.getscan(i))
430            axis.append(self.getbeam(i))
431            axis.append(self.getif(i))
432            axis.append(self.getpol(i))
433            axis.append(self.getcycle(i))
434            axes.append(axis)
435            tm = self._gettime(i)
436            src = self._getsourcename(i)
437            refstr = ''
438            statunit= ''
439            if getchan:
440                qx, qy = self.chan2data(rowno=i, chan=chan[i])
441                if rtnabc:
442                    statvals.append(qx['value'])
443                    #refstr = '(value: %3.3f' % (qy['value'])+' ['+qy['unit']+'])'
444                    refstr = ('(value: %'+form) % (qy['value'])+' ['+qy['unit']+'])'
445                    statunit= '['+qx['unit']+']'
446                else:
447                    #refstr = '(@ %3.3f' % (qx['value'])+' ['+qx['unit']+'])'
448                    refstr = ('(@ %'+form) % (qx['value'])+' ['+qx['unit']+'])'
449                    #statunit= ' ['+qy['unit']+']'
450            out += 'Scan[%d] (%s) ' % (axis[0], src)
451            out += 'Time[%s]:\n' % (tm)
452            if self.nbeam(-1) > 1: out +=  ' Beam[%d] ' % (axis[1])
453            if self.nif(-1) > 1: out +=  ' IF[%d] ' % (axis[2])
454            if self.npol(-1) > 1: out +=  ' Pol[%d] ' % (axis[3])
455            #out += '= %3.3f   ' % (statvals[i]) +refstr+'\n'
456            out += ('= %'+form) % (statvals[i]) +'   '+refstr+'\n'
457            out +=  "--------------------------------------------------\n"
458
459        if rcParams['verbose']:
460            import os
461            if os.environ.has_key( 'USER' ):
462                usr=os.environ['USER']
463            else:
464                import commands
465                usr=commands.getoutput( 'whoami' )
466            tmpfile='/tmp/tmp_'+usr+'_casapy_asap_scantable_stats'
467            f=open(tmpfile,'w')
468            print >> f, "--------------------------------------------------"
469            print >> f, " ", stat, statunit
470            print >> f, "--------------------------------------------------"
471            print >> f, out
472            f.close()
473            f=open(tmpfile,'r')
474            x=f.readlines()
475            f.close()
476            for xx in x:
477                asaplog.push( xx )
478            print_log()
479        #else:
480            #retval = { 'axesnames': ['scanno', 'beamno', 'ifno', 'polno', 'cycleno'],
481            #           'axes' : axes,
482            #           'data': statvals}
483        return statvals
484
485    def chan2data(self, rowno=0, chan=0):
486        """
487        Returns channel/frequency/velocity and spectral value
488        at an arbitrary row and channel in the scantable.
489        Parameters:
490            rowno:   a row number in the scantable. Default is the
491                     first row, i.e. rowno=0
492            chan:    a channel in the scantable. Default is the first
493                     channel, i.e. pos=0
494        """
495        if isinstance(rowno, int) and isinstance(chan, int):
496            qx = {'unit': self.get_unit(),
497                  'value': self._getabcissa(rowno)[chan]}
498            qy = {'unit': self.get_fluxunit(),
499                  'value': self._getspectrum(rowno)[chan]}
500            return qx, qy
501
502    def stddev(self, mask=None):
503        """
504        Determine the standard deviation of the current beam/if/pol
505        Takes a 'mask' as an optional parameter to specify which
506        channels should be excluded.
507        Parameters:
508            mask:    an optional mask specifying where the standard
509                     deviation should be determined.
510
511        Example:
512            scan.set_unit('channel')
513            msk = scan.create_mask([100, 200], [500, 600])
514            scan.stddev(mask=m)
515        """
516        return self.stats(stat='stddev', mask=mask);
517
518
519    def get_column_names(self):
520        """
521        Return a  list of column names, which can be used for selection.
522        """
523        return list(Scantable.get_column_names(self))
524
525    def get_tsys(self):
526        """
527        Return the System temperatures.
528        Returns:
529            a list of Tsys values for the current selection
530        """
531
532        return self._row_callback(self._gettsys, "Tsys")
533
534    def _row_callback(self, callback, label):
535        axes = []
536        axesnames = ['scanno', 'beamno', 'ifno', 'polno', 'cycleno']
537        out = ""
538        outvec = []
539        for i in range(self.nrow()):
540            axis = []
541            axis.append(self.getscan(i))
542            axis.append(self.getbeam(i))
543            axis.append(self.getif(i))
544            axis.append(self.getpol(i))
545            axis.append(self.getcycle(i))
546            axes.append(axis)
547            tm = self._gettime(i)
548            src = self._getsourcename(i)
549            out += 'Scan[%d] (%s) ' % (axis[0], src)
550            out += 'Time[%s]:\n' % (tm)
551            if self.nbeam(-1) > 1: out +=  ' Beam[%d] ' % (axis[1])
552            if self.nif(-1) > 1: out +=  ' IF[%d] ' % (axis[2])
553            if self.npol(-1) > 1: out +=  ' Pol[%d] ' % (axis[3])
554            outvec.append(callback(i))
555            out += '= %3.3f\n' % (outvec[i])
556            out +=  "--------------------------------------------------\n"
557        if rcParams['verbose']:
558            asaplog.push("--------------------------------------------------")
559            asaplog.push(" %s" % (label))
560            asaplog.push("--------------------------------------------------")
561            asaplog.push(out)
562            print_log()
563        # disabled because the vector seems more useful
564        #retval = {'axesnames': axesnames, 'axes': axes, 'data': outvec}
565        return outvec
566
567    def _get_column(self, callback, row=-1):
568        """
569        """
570        if row == -1:
571            return [callback(i) for i in range(self.nrow())]
572        else:
573            if  0 <= row < self.nrow():
574                return callback(row)
575
576
577    def get_time(self, row=-1, asdatetime=False):
578        """
579        Get a list of time stamps for the observations.
580        Return a datetime object for each integration time stamp in the scantable.
581        Parameters:
582            row:          row no of integration. Default -1 return all rows
583            asdatetime:   return values as datetime objects rather than strings
584        Example:
585            none
586        """
587        from time import strptime
588        from datetime import datetime
589        times = self._get_column(self._gettime, row)
590        if not asdatetime:
591            return times
592        format = "%Y/%m/%d/%H:%M:%S"
593        if isinstance(times, list):
594            return [datetime(*strptime(i, format)[:6]) for i in times]
595        else:
596            return datetime(*strptime(times, format)[:6])
597
598
599    def get_inttime(self, row=-1):
600        """
601        Get a list of integration times for the observations.
602        Return a time in seconds for each integration in the scantable.
603        Parameters:
604            row:    row no of integration. Default -1 return all rows.
605        Example:
606            none
607        """
608        return self._get_column(self._getinttime, row)       
609       
610
611    def get_sourcename(self, row=-1):
612        """
613        Get a list source names for the observations.
614        Return a string for each integration in the scantable.
615        Parameters:
616            row:    row no of integration. Default -1 return all rows.
617        Example:
618            none
619        """
620        return self._get_column(self._getsourcename, row)
621
622    def get_elevation(self, row=-1):
623        """
624        Get a list of elevations for the observations.
625        Return a float for each integration in the scantable.
626        Parameters:
627            row:    row no of integration. Default -1 return all rows.
628        Example:
629            none
630        """
631        return self._get_column(self._getelevation, row)
632
633    def get_azimuth(self, row=-1):
634        """
635        Get a list of azimuths for the observations.
636        Return a float for each integration in the scantable.
637        Parameters:
638            row:    row no of integration. Default -1 return all rows.
639        Example:
640            none
641        """
642        return self._get_column(self._getazimuth, row)
643
644    def get_parangle(self, row=-1):
645        """
646        Get a list of parallactic angles for the observations.
647        Return a float for each integration in the scantable.
648        Parameters:
649            row:    row no of integration. Default -1 return all rows.
650        Example:
651            none
652        """
653        return self._get_column(self._getparangle, row)
654
655    def get_direction(self, row=-1):
656        """
657        Get a list of Positions on the sky (direction) for the observations.
658        Return a float for each integration in the scantable.
659        Parameters:
660            row:    row no of integration. Default -1 return all rows
661        Example:
662            none
663        """
664        return self._get_column(self._getdirection, row)
665
666    def get_directionval(self, row=-1):
667        """
668        Get a list of Positions on the sky (direction) for the observations.
669        Return a float for each integration in the scantable.
670        Parameters:
671            row:    row no of integration. Default -1 return all rows
672        Example:
673            none
674        """
675        return self._get_column(self._getdirectionvec, row)
676
677    def set_unit(self, unit='channel'):
678        """
679        Set the unit for all following operations on this scantable
680        Parameters:
681            unit:    optional unit, default is 'channel'
682                     one of '*Hz', 'km/s', 'channel', ''
683        """
684        varlist = vars()
685        if unit in ['', 'pixel', 'channel']:
686            unit = ''
687        inf = list(self._getcoordinfo())
688        inf[0] = unit
689        self._setcoordinfo(inf)
690        self._add_history("set_unit", varlist)
691
692    def set_instrument(self, instr):
693        """
694        Set the instrument for subsequent processing.
695        Parameters:
696            instr:    Select from 'ATPKSMB', 'ATPKSHOH', 'ATMOPRA',
697                      'DSS-43' (Tid), 'CEDUNA', and 'HOBART'
698        """
699        self._setInstrument(instr)
700        self._add_history("set_instument", vars())
701        print_log()
702
703    def set_feedtype(self, feedtype):
704        """
705        Overwrite the feed type, which might not be set correctly.
706        Parameters:
707            feedtype:     'linear' or 'circular'
708        """
709        self._setfeedtype(feedtype)
710        self._add_history("set_feedtype", vars())
711        print_log()
712
713    def set_doppler(self, doppler='RADIO'):
714        """
715        Set the doppler for all following operations on this scantable.
716        Parameters:
717            doppler:    One of 'RADIO', 'OPTICAL', 'Z', 'BETA', 'GAMMA'
718        """
719        varlist = vars()
720        inf = list(self._getcoordinfo())
721        inf[2] = doppler
722        self._setcoordinfo(inf)
723        self._add_history("set_doppler", vars())
724        print_log()
725
726    def set_freqframe(self, frame=None):
727        """
728        Set the frame type of the Spectral Axis.
729        Parameters:
730            frame:   an optional frame type, default 'LSRK'. Valid frames are:
731                     'REST', 'TOPO', 'LSRD', 'LSRK', 'BARY',
732                     'GEO', 'GALACTO', 'LGROUP', 'CMB'
733        Examples:
734            scan.set_freqframe('BARY')
735        """
736        if frame is None: frame = rcParams['scantable.freqframe']
737        varlist = vars()
738        valid = ['REST', 'TOPO', 'LSRD', 'LSRK', 'BARY', \
739                   'GEO', 'GALACTO', 'LGROUP', 'CMB']
740
741        if frame in valid:
742            inf = list(self._getcoordinfo())
743            inf[1] = frame
744            self._setcoordinfo(inf)
745            self._add_history("set_freqframe", varlist)
746        else:
747            msg  = "Please specify a valid freq type. Valid types are:\n", valid
748            if rcParams['verbose']:
749                #print msg
750                asaplog.push( msg )
751                print_log( 'ERROR' )
752            else:
753                raise TypeError(msg)
754        print_log()
755
756    def set_dirframe(self, frame=""):
757        """
758        Set the frame type of the Direction on the sky.
759        Parameters:
760            frame:   an optional frame type, default ''. Valid frames are:
761                     'J2000', 'B1950', 'GALACTIC'
762        Examples:
763            scan.set_dirframe('GALACTIC')
764        """
765        varlist = vars()
766        try:
767            Scantable.set_dirframe(self, frame)
768        except RuntimeError, msg:
769            if rcParams['verbose']:
770                #print msg
771                print_log()
772                asaplog.push( msg.message )
773                print_log( 'ERROR' )
774            else:
775                raise
776        self._add_history("set_dirframe", varlist)
777
778    def get_unit(self):
779        """
780        Get the default unit set in this scantable
781        Returns:
782            A unit string
783        """
784        inf = self._getcoordinfo()
785        unit = inf[0]
786        if unit == '': unit = 'channel'
787        return unit
788
789    def get_abcissa(self, rowno=0):
790        """
791        Get the abcissa in the current coordinate setup for the currently
792        selected Beam/IF/Pol
793        Parameters:
794            rowno:    an optional row number in the scantable. Default is the
795                      first row, i.e. rowno=0
796        Returns:
797            The abcissa values and the format string (as a dictionary)
798        """
799        abc = self._getabcissa(rowno)
800        lbl = self._getabcissalabel(rowno)
801        print_log()
802        return abc, lbl
803
804    def flag(self, mask=None, unflag=False):
805        """
806        Flag the selected data using an optional channel mask.
807        Parameters:
808            mask:   an optional channel mask, created with create_mask. Default
809                    (no mask) is all channels.
810            unflag:    if True, unflag the data
811        """
812        varlist = vars()
813        if mask is None:
814            mask = []
815        try:
816            self._flag(mask, unflag)
817        except RuntimeError, msg:
818            if rcParams['verbose']:
819                #print msg
820                print_log()
821                asaplog.push( msg.message )
822                print_log( 'ERROR' )
823                return
824            else: raise
825        self._add_history("flag", varlist)
826
827    def lag_flag(self, frequency, width=0.0, unit="GHz", insitu=None):
828        """
829        Flag the data in 'lag' space by providing a frequency to remove.
830        Flagged data in the scantable gets set to 0.0 before the fft.
831        No taper is applied.
832        Parameters:
833            frequency:    the frequency (really a period within the bandwidth)
834                          to remove
835            width:        the width of the frequency to remove, to remove a
836                          range of frequencies around the centre.
837            unit:         the frequency unit (default "GHz")
838        Notes:
839            It is recommended to flag edges of the band or strong
840            signals beforehand.
841        """
842        if insitu is None: insitu = rcParams['insitu']
843        self._math._setinsitu(insitu)
844        varlist = vars()
845        base = { "GHz": 1000000000., "MHz": 1000000., "kHz": 1000., "Hz": 1. }
846        if not base.has_key(unit):
847            raise ValueError("%s is not a valid unit." % unit)
848        try:
849            s = scantable(self._math._lag_flag(self, frequency*base[unit],
850                                               width*base[unit]))
851        except RuntimeError, msg:
852            if rcParams['verbose']:
853                #print msg
854                print_log()
855                asaplog.push( msg.message )
856                print_log( 'ERROR' )
857                return
858            else: raise
859        s._add_history("lag_flag", varlist)
860        print_log()
861        if insitu:
862            self._assign(s)
863        else:
864            return s
865
866
867    def create_mask(self, *args, **kwargs):
868        """
869        Compute and return a mask based on [min, max] windows.
870        The specified windows are to be INCLUDED, when the mask is
871        applied.
872        Parameters:
873            [min, max], [min2, max2], ...
874                Pairs of start/end points (inclusive)specifying the regions
875                to be masked
876            invert:     optional argument. If specified as True,
877                        return an inverted mask, i.e. the regions
878                        specified are EXCLUDED
879            row:        create the mask using the specified row for
880                        unit conversions, default is row=0
881                        only necessary if frequency varies over rows.
882        Example:
883            scan.set_unit('channel')
884            a)
885            msk = scan.create_mask([400, 500], [800, 900])
886            # masks everything outside 400 and 500
887            # and 800 and 900 in the unit 'channel'
888
889            b)
890            msk = scan.create_mask([400, 500], [800, 900], invert=True)
891            # masks the regions between 400 and 500
892            # and 800 and 900 in the unit 'channel'
893            c)
894            mask only channel 400
895            msk =  scan.create_mask([400, 400])
896        """
897        row = 0
898        if kwargs.has_key("row"):
899            row = kwargs.get("row")
900        data = self._getabcissa(row)
901        u = self._getcoordinfo()[0]
902        if rcParams['verbose']:
903            if u == "": u = "channel"
904            msg = "The current mask window unit is %s" % u
905            i = self._check_ifs()
906            if not i:
907                msg += "\nThis mask is only valid for IF=%d" % (self.getif(i))
908            asaplog.push(msg)
909        n = self.nchan()
910        msk = _n_bools(n, False)
911        # test if args is a 'list' or a 'normal *args - UGLY!!!
912
913        ws = (isinstance(args[-1][-1], int) or isinstance(args[-1][-1], float)) \
914             and args or args[0]
915        for window in ws:
916            if (len(window) != 2 or window[0] > window[1] ):
917                raise TypeError("A window needs to be defined as [min, max]")
918            for i in range(n):
919                if data[i] >= window[0] and data[i] <= window[1]:
920                    msk[i] = True
921        if kwargs.has_key('invert'):
922            if kwargs.get('invert'):
923                msk = mask_not(msk)
924        print_log()
925        return msk
926
927    def get_masklist(self, mask=None, row=0):
928        """
929        Compute and return a list of mask windows, [min, max].
930        Parameters:
931            mask:       channel mask, created with create_mask.
932            row:        calcutate the masklist using the specified row
933                        for unit conversions, default is row=0
934                        only necessary if frequency varies over rows.
935        Returns:
936            [min, max], [min2, max2], ...
937                Pairs of start/end points (inclusive)specifying
938                the masked regions
939        """
940        if not (isinstance(mask,list) or isinstance(mask, tuple)):
941            raise TypeError("The mask should be list or tuple.")
942        if len(mask) < 2:
943            raise TypeError("The mask elements should be > 1")
944        if self.nchan() != len(mask):
945            msg = "Number of channels in scantable != number of mask elements"
946            raise TypeError(msg)
947        data = self._getabcissa(row)
948        u = self._getcoordinfo()[0]
949        if rcParams['verbose']:
950            if u == "": u = "channel"
951            msg = "The current mask window unit is %s" % u
952            i = self._check_ifs()
953            if not i:
954                msg += "\nThis mask is only valid for IF=%d" % (self.getif(i))
955            asaplog.push(msg)
956        masklist=[]
957        ist, ien = None, None
958        ist, ien=self.get_mask_indices(mask)
959        if ist is not None and ien is not None:
960            for i in xrange(len(ist)):
961                range=[data[ist[i]],data[ien[i]]]
962                range.sort()
963                masklist.append([range[0],range[1]])
964        return masklist
965
966    def get_mask_indices(self, mask=None):
967        """
968        Compute and Return lists of mask start indices and mask end indices.
969         Parameters:
970            mask:       channel mask, created with create_mask.
971        Returns:
972            List of mask start indices and that of mask end indices,
973            i.e., [istart1,istart2,....], [iend1,iend2,....].
974        """
975        if not (isinstance(mask,list) or isinstance(mask, tuple)):
976            raise TypeError("The mask should be list or tuple.")
977        if len(mask) < 2:
978            raise TypeError("The mask elements should be > 1")
979        istart=[]
980        iend=[]
981        if mask[0]: istart.append(0)
982        for i in range(len(mask)-1):
983            if not mask[i] and mask[i+1]:
984                istart.append(i+1)
985            elif mask[i] and not mask[i+1]:
986                iend.append(i)
987        if mask[len(mask)-1]: iend.append(len(mask)-1)
988        if len(istart) != len(iend):
989            raise RuntimeError("Numbers of mask start != mask end.")
990        for i in range(len(istart)):
991            if istart[i] > iend[i]:
992                raise RuntimeError("Mask start index > mask end index")
993                break
994        return istart,iend
995
996#    def get_restfreqs(self):
997#        """
998#        Get the restfrequency(s) stored in this scantable.
999#        The return value(s) are always of unit 'Hz'
1000#        Parameters:
1001#            none
1002#        Returns:
1003#            a list of doubles
1004#        """
1005#        return list(self._getrestfreqs())
1006
1007    def get_restfreqs(self, ids=None):
1008        """
1009        Get the restfrequency(s) stored in this scantable.
1010        The return value(s) are always of unit 'Hz'
1011        Parameters:
1012            ids: (optional) a list of MOLECULE_ID for that restfrequency(s) to
1013                 be retrieved
1014        Returns:
1015            dictionary containing ids and a list of doubles for each id
1016        """
1017        if ids is None:
1018            rfreqs={}
1019            idlist = self.getmolnos()
1020            for i in idlist:
1021                rfreqs[i]=list(self._getrestfreqs(i))
1022            return rfreqs
1023        else:
1024            if type(ids)==list or type(ids)==tuple:
1025                rfreqs={}
1026                for i in ids:
1027                    rfreqs[i]=list(self._getrestfreqs(i))
1028                return rfreqs
1029            else:
1030                return list(self._getrestfreqs(ids))
1031            #return list(self._getrestfreqs(ids))
1032
1033    def set_restfreqs(self, freqs=None, unit='Hz'):
1034        """
1035        ********NEED TO BE UPDATED begin************
1036        Set or replace the restfrequency specified and
1037        If the 'freqs' argument holds a scalar,
1038        then that rest frequency will be applied to all the selected
1039        data.  If the 'freqs' argument holds
1040        a vector, then it MUST be of equal or smaller length than
1041        the number of IFs (and the available restfrequencies will be
1042        replaced by this vector).  In this case, *all* data have
1043        the restfrequency set per IF according
1044        to the corresponding value you give in the 'freqs' vector.
1045        E.g. 'freqs=[1e9, 2e9]'  would mean IF 0 gets restfreq 1e9 and
1046        IF 1 gets restfreq 2e9.
1047        ********NEED TO BE UPDATED end************
1048        You can also specify the frequencies via a linecatalog.
1049
1050        Parameters:
1051            freqs:   list of rest frequency values or string idenitfiers
1052            unit:    unit for rest frequency (default 'Hz')
1053
1054        Example:
1055            # set the given restfrequency for the all currently selected IFs
1056            scan.set_restfreqs(freqs=1.4e9)
1057            # set multiple restfrequencies to all the selected data
1058            scan.set_restfreqs(freqs=[1.4e9, 1.41e9, 1.42e9])
1059            # If the number of IFs in the data is >= 2 the IF0 gets the first
1060            # value IF1 the second... NOTE that freqs needs to be
1061            # specified in list of list (e.g. [[],[],...] ).
1062            scan.set_restfreqs(freqs=[[1.4e9],[1.67e9]])
1063            #set the given restfrequency for the whole table (by name)
1064            scan.set_restfreqs(freqs="OH1667")
1065
1066        Note:
1067            To do more sophisticate Restfrequency setting, e.g. on a
1068            source and IF basis, use scantable.set_selection() before using
1069            this function.
1070            # provide your scantable is call scan
1071            selection = selector()
1072            selection.set_name("ORION*")
1073            selection.set_ifs([1])
1074            scan.set_selection(selection)
1075            scan.set_restfreqs(freqs=86.6e9)
1076
1077        """
1078        varlist = vars()
1079        from asap import linecatalog
1080        # simple  value
1081        if isinstance(freqs, int) or isinstance(freqs, float):
1082            # TT mod
1083            #self._setrestfreqs(freqs, "",unit)
1084            self._setrestfreqs([freqs], [""],unit)
1085        # list of values
1086        elif isinstance(freqs, list) or isinstance(freqs, tuple):
1087            # list values are scalars
1088            if isinstance(freqs[-1], int) or isinstance(freqs[-1], float):
1089                self._setrestfreqs(freqs, [""],unit)
1090            # list values are tuples, (value, name)
1091            elif isinstance(freqs[-1], dict):
1092                #sel = selector()
1093                #savesel = self._getselection()
1094                #iflist = self.getifnos()
1095                #for i in xrange(len(freqs)):
1096                #    sel.set_ifs(iflist[i])
1097                #    self._setselection(sel)
1098                #    self._setrestfreqs(freqs[i], "",unit)
1099                #self._setselection(savesel)
1100                self._setrestfreqs(freqs["value"],
1101                                   freqs["name"], "MHz")
1102            elif isinstance(freqs[-1], list) or isinstance(freqs[-1], tuple):
1103                sel = selector()
1104                savesel = self._getselection()
1105                iflist = self.getifnos()
1106                if len(freqs)>len(iflist):
1107                    raise ValueError("number of elements in list of list exeeds the current IF selections")
1108                for i in xrange(len(freqs)):
1109                    sel.set_ifs(iflist[i])
1110                    self._setselection(sel)
1111                    self._setrestfreqs(freqs[i]["value"],
1112                                       freqs[i]["name"], "MHz")
1113                self._setselection(savesel)
1114        # freqs are to be taken from a linecatalog
1115        elif isinstance(freqs, linecatalog):
1116            sel = selector()
1117            savesel = self._getselection()
1118            for i in xrange(freqs.nrow()):
1119                sel.set_ifs(iflist[i])
1120                self._setselection(sel)
1121                self._setrestfreqs(freqs.get_frequency(i),
1122                                   freqs.get_name(i), "MHz")
1123                # ensure that we are not iterating past nIF
1124                if i == self.nif()-1: break
1125            self._setselection(savesel)
1126        else:
1127            return
1128        self._add_history("set_restfreqs", varlist)
1129
1130    def shift_refpix(self, delta):
1131        """
1132        Shift the reference pixel of the Spectra Coordinate by an
1133        integer amount.
1134        Parameters:
1135            delta:   the amount to shift by
1136        Note:
1137            Be careful using this with broadband data.
1138        """
1139        Scantable.shift(self, delta)
1140
1141    def history(self, filename=None):
1142        """
1143        Print the history. Optionally to a file.
1144        Parameters:
1145            filename:    The name  of the file to save the history to.
1146        """
1147        hist = list(self._gethistory())
1148        out = "-"*80
1149        for h in hist:
1150            if h.startswith("---"):
1151                out += "\n"+h
1152            else:
1153                items = h.split("##")
1154                date = items[0]
1155                func = items[1]
1156                items = items[2:]
1157                out += "\n"+date+"\n"
1158                out += "Function: %s\n  Parameters:" % (func)
1159                for i in items:
1160                    s = i.split("=")
1161                    out += "\n   %s = %s" % (s[0], s[1])
1162                out += "\n"+"-"*80
1163        if filename is not None:
1164            if filename is "":
1165                filename = 'scantable_history.txt'
1166            import os
1167            filename = os.path.expandvars(os.path.expanduser(filename))
1168            if not os.path.isdir(filename):
1169                data = open(filename, 'w')
1170                data.write(out)
1171                data.close()
1172            else:
1173                msg = "Illegal file name '%s'." % (filename)
1174                if rcParams['verbose']:
1175                    #print msg
1176                    asaplog.push( msg )
1177                    print_log( 'ERROR' )
1178                else:
1179                    raise IOError(msg)
1180        if rcParams['verbose']:
1181            try:
1182                from IPython.genutils import page as pager
1183            except ImportError:
1184                from pydoc import pager
1185            pager(out)
1186        else:
1187            return out
1188        return
1189    #
1190    # Maths business
1191    #
1192
1193    def average_time(self, mask=None, scanav=False, weight='tint', align=False):
1194        """
1195        Return the (time) weighted average of a scan.
1196        Note:
1197            in channels only - align if necessary
1198        Parameters:
1199            mask:     an optional mask (only used for 'var' and 'tsys'
1200                      weighting)
1201            scanav:   True averages each scan separately
1202                      False (default) averages all scans together,
1203            weight:   Weighting scheme.
1204                      'none'     (mean no weight)
1205                      'var'      (1/var(spec) weighted)
1206                      'tsys'     (1/Tsys**2 weighted)
1207                      'tint'     (integration time weighted)
1208                      'tintsys'  (Tint/Tsys**2)
1209                      'median'   ( median averaging)
1210                      The default is 'tint'
1211            align:    align the spectra in velocity before averaging. It takes
1212                      the time of the first spectrum as reference time.
1213        Example:
1214            # time average the scantable without using a mask
1215            newscan = scan.average_time()
1216        """
1217        varlist = vars()
1218        if weight is None: weight = 'TINT'
1219        if mask is None: mask = ()
1220        if scanav: scanav = "SCAN"
1221        else: scanav = "NONE"
1222        scan = (self, )
1223        try:
1224            if align:
1225                scan = (self.freq_align(insitu=False), )
1226            s = None
1227            if weight.upper() == 'MEDIAN':
1228                s = scantable(self._math._averagechannel(scan[0], 'MEDIAN',
1229                                                         scanav))
1230            else:
1231                s = scantable(self._math._average(scan, mask, weight.upper(),
1232                              scanav))
1233        except RuntimeError, msg:
1234            if rcParams['verbose']:
1235                #print msg
1236                print_log()
1237                asaplog.push( msg.message )
1238                print_log( 'ERROR' )
1239                return
1240            else: raise
1241        s._add_history("average_time", varlist)
1242        print_log()
1243        return s
1244
1245    def convert_flux(self, jyperk=None, eta=None, d=None, insitu=None):
1246        """
1247        Return a scan where all spectra are converted to either
1248        Jansky or Kelvin depending upon the flux units of the scan table.
1249        By default the function tries to look the values up internally.
1250        If it can't find them (or if you want to over-ride), you must
1251        specify EITHER jyperk OR eta (and D which it will try to look up
1252        also if you don't set it). jyperk takes precedence if you set both.
1253        Parameters:
1254            jyperk:      the Jy / K conversion factor
1255            eta:         the aperture efficiency
1256            d:           the geomtric diameter (metres)
1257            insitu:      if False a new scantable is returned.
1258                         Otherwise, the scaling is done in-situ
1259                         The default is taken from .asaprc (False)
1260        """
1261        if insitu is None: insitu = rcParams['insitu']
1262        self._math._setinsitu(insitu)
1263        varlist = vars()
1264        if jyperk is None: jyperk = -1.0
1265        if d is None: d = -1.0
1266        if eta is None: eta = -1.0
1267        s = scantable(self._math._convertflux(self, d, eta, jyperk))
1268        s._add_history("convert_flux", varlist)
1269        print_log()
1270        if insitu: self._assign(s)
1271        else: return s
1272
1273    def gain_el(self, poly=None, filename="", method="linear", insitu=None):
1274        """
1275        Return a scan after applying a gain-elevation correction.
1276        The correction can be made via either a polynomial or a
1277        table-based interpolation (and extrapolation if necessary).
1278        You specify polynomial coefficients, an ascii table or neither.
1279        If you specify neither, then a polynomial correction will be made
1280        with built in coefficients known for certain telescopes (an error
1281        will occur if the instrument is not known).
1282        The data and Tsys are *divided* by the scaling factors.
1283        Parameters:
1284            poly:        Polynomial coefficients (default None) to compute a
1285                         gain-elevation correction as a function of
1286                         elevation (in degrees).
1287            filename:    The name of an ascii file holding correction factors.
1288                         The first row of the ascii file must give the column
1289                         names and these MUST include columns
1290                         "ELEVATION" (degrees) and "FACTOR" (multiply data
1291                         by this) somewhere.
1292                         The second row must give the data type of the
1293                         column. Use 'R' for Real and 'I' for Integer.
1294                         An example file would be
1295                         (actual factors are arbitrary) :
1296
1297                         TIME ELEVATION FACTOR
1298                         R R R
1299                         0.1 0 0.8
1300                         0.2 20 0.85
1301                         0.3 40 0.9
1302                         0.4 60 0.85
1303                         0.5 80 0.8
1304                         0.6 90 0.75
1305            method:      Interpolation method when correcting from a table.
1306                         Values are  "nearest", "linear" (default), "cubic"
1307                         and "spline"
1308            insitu:      if False a new scantable is returned.
1309                         Otherwise, the scaling is done in-situ
1310                         The default is taken from .asaprc (False)
1311        """
1312
1313        if insitu is None: insitu = rcParams['insitu']
1314        self._math._setinsitu(insitu)
1315        varlist = vars()
1316        if poly is None:
1317            poly = ()
1318        from os.path import expandvars
1319        filename = expandvars(filename)
1320        s = scantable(self._math._gainel(self, poly, filename, method))
1321        s._add_history("gain_el", varlist)
1322        print_log()
1323        if insitu: self._assign(s)
1324        else: return s
1325
1326    def freq_align(self, reftime=None, method='cubic', insitu=None):
1327        """
1328        Return a scan where all rows have been aligned in frequency/velocity.
1329        The alignment frequency frame (e.g. LSRK) is that set by function
1330        set_freqframe.
1331        Parameters:
1332            reftime:     reference time to align at. By default, the time of
1333                         the first row of data is used.
1334            method:      Interpolation method for regridding the spectra.
1335                         Choose from "nearest", "linear", "cubic" (default)
1336                         and "spline"
1337            insitu:      if False a new scantable is returned.
1338                         Otherwise, the scaling is done in-situ
1339                         The default is taken from .asaprc (False)
1340        """
1341        if insitu is None: insitu = rcParams["insitu"]
1342        self._math._setinsitu(insitu)
1343        varlist = vars()
1344        if reftime is None: reftime = ""
1345        s = scantable(self._math._freq_align(self, reftime, method))
1346        s._add_history("freq_align", varlist)
1347        print_log()
1348        if insitu: self._assign(s)
1349        else: return s
1350
1351    def opacity(self, tau, insitu=None):
1352        """
1353        Apply an opacity correction. The data
1354        and Tsys are multiplied by the correction factor.
1355        Parameters:
1356            tau:         Opacity from which the correction factor is
1357                         exp(tau*ZD)
1358                         where ZD is the zenith-distance
1359            insitu:      if False a new scantable is returned.
1360                         Otherwise, the scaling is done in-situ
1361                         The default is taken from .asaprc (False)
1362        """
1363        if insitu is None: insitu = rcParams['insitu']
1364        self._math._setinsitu(insitu)
1365        varlist = vars()
1366        s = scantable(self._math._opacity(self, tau))
1367        s._add_history("opacity", varlist)
1368        print_log()
1369        if insitu: self._assign(s)
1370        else: return s
1371
1372    def bin(self, width=5, insitu=None):
1373        """
1374        Return a scan where all spectra have been binned up.
1375        Parameters:
1376            width:       The bin width (default=5) in pixels
1377            insitu:      if False a new scantable is returned.
1378                         Otherwise, the scaling is done in-situ
1379                         The default is taken from .asaprc (False)
1380        """
1381        if insitu is None: insitu = rcParams['insitu']
1382        self._math._setinsitu(insitu)
1383        varlist = vars()
1384        s = scantable(self._math._bin(self, width))
1385        s._add_history("bin", varlist)
1386        print_log()
1387        if insitu: self._assign(s)
1388        else: return s
1389
1390
1391    def resample(self, width=5, method='cubic', insitu=None):
1392        """
1393        Return a scan where all spectra have been binned up.
1394       
1395        Parameters:
1396            width:       The bin width (default=5) in pixels
1397            method:      Interpolation method when correcting from a table.
1398                         Values are  "nearest", "linear", "cubic" (default)
1399                         and "spline"
1400            insitu:      if False a new scantable is returned.
1401                         Otherwise, the scaling is done in-situ
1402                         The default is taken from .asaprc (False)
1403        """
1404        if insitu is None: insitu = rcParams['insitu']
1405        self._math._setinsitu(insitu)
1406        varlist = vars()
1407        s = scantable(self._math._resample(self, method, width))
1408        s._add_history("resample", varlist)
1409        print_log()
1410        if insitu: self._assign(s)
1411        else: return s
1412
1413
1414    def average_pol(self, mask=None, weight='none'):
1415        """
1416        Average the Polarisations together.
1417        Parameters:
1418            mask:        An optional mask defining the region, where the
1419                         averaging will be applied. The output will have all
1420                         specified points masked.
1421            weight:      Weighting scheme. 'none' (default), 'var' (1/var(spec)
1422                         weighted), or 'tsys' (1/Tsys**2 weighted)
1423        """
1424        varlist = vars()
1425        if mask is None:
1426            mask = ()
1427        s = scantable(self._math._averagepol(self, mask, weight.upper()))
1428        s._add_history("average_pol", varlist)
1429        print_log()
1430        return s
1431
1432    def average_beam(self, mask=None, weight='none'):
1433        """
1434        Average the Beams together.
1435        Parameters:
1436            mask:        An optional mask defining the region, where the
1437                         averaging will be applied. The output will have all
1438                         specified points masked.
1439            weight:      Weighting scheme. 'none' (default), 'var' (1/var(spec)
1440                         weighted), or 'tsys' (1/Tsys**2 weighted)
1441        """
1442        varlist = vars()
1443        if mask is None:
1444            mask = ()
1445        s = scantable(self._math._averagebeams(self, mask, weight.upper()))
1446        s._add_history("average_beam", varlist)
1447        print_log()
1448        return s
1449
1450    def convert_pol(self, poltype=None):
1451        """
1452        Convert the data to a different polarisation type.
1453        Parameters:
1454            poltype:    The new polarisation type. Valid types are:
1455                        "linear", "stokes" and "circular"
1456        """
1457        varlist = vars()
1458        try:
1459            s = scantable(self._math._convertpol(self, poltype))
1460        except RuntimeError, msg:
1461            if rcParams['verbose']:
1462                #print msg
1463                print_log()
1464                asaplog.push( msg.message )
1465                print_log( 'ERROR' )
1466                return
1467            else:
1468                raise
1469        s._add_history("convert_pol", varlist)
1470        print_log()
1471        return s
1472
1473    def smooth(self, kernel="hanning", width=5.0, insitu=None):
1474        """
1475        Smooth the spectrum by the specified kernel (conserving flux).
1476        Parameters:
1477            kernel:     The type of smoothing kernel. Select from
1478                        'hanning' (default), 'gaussian', 'boxcar' and
1479                        'rmedian'
1480            width:      The width of the kernel in pixels. For hanning this is
1481                        ignored otherwise it defauls to 5 pixels.
1482                        For 'gaussian' it is the Full Width Half
1483                        Maximum. For 'boxcar' it is the full width.
1484                        For 'rmedian' it is the half width.
1485            insitu:     if False a new scantable is returned.
1486                        Otherwise, the scaling is done in-situ
1487                        The default is taken from .asaprc (False)
1488        Example:
1489             none
1490        """
1491        if insitu is None: insitu = rcParams['insitu']
1492        self._math._setinsitu(insitu)
1493        varlist = vars()
1494        s = scantable(self._math._smooth(self, kernel.lower(), width))
1495        s._add_history("smooth", varlist)
1496        print_log()
1497        if insitu: self._assign(s)
1498        else: return s
1499
1500
1501    def poly_baseline(self, mask=None, order=0, plot=False, uselin=False, insitu=None):
1502        """
1503        Return a scan which has been baselined (all rows) by a polynomial.
1504        Parameters:
1505            mask:       an optional mask
1506            order:      the order of the polynomial (default is 0)
1507            plot:       plot the fit and the residual. In this each
1508                        indivual fit has to be approved, by typing 'y'
1509                        or 'n'
1510            uselin:     use linear polynomial fit
1511            insitu:     if False a new scantable is returned.
1512                        Otherwise, the scaling is done in-situ
1513                        The default is taken from .asaprc (False)
1514        Example:
1515            # return a scan baselined by a third order polynomial,
1516            # not using a mask
1517            bscan = scan.poly_baseline(order=3)
1518        """
1519        if insitu is None: insitu = rcParams['insitu']
1520        varlist = vars()
1521        if mask is None:
1522            mask = [True for i in xrange(self.nchan(-1))]
1523        from asap.asapfitter import fitter
1524        try:
1525            f = fitter()
1526            f.set_scan(self, mask)
1527            if uselin:
1528                f.set_function(lpoly=order)
1529            else:
1530                f.set_function(poly=order)
1531            s = f.auto_fit(insitu, plot=plot)
1532            # Save parameters of baseline fits as a class attribute.
1533            # NOTICE: It does not reflect changes in scantable!
1534            self.blpars = f.blpars
1535            s._add_history("poly_baseline", varlist)
1536            print_log()
1537            if insitu: self._assign(s)
1538            else: return s
1539        except RuntimeError:
1540            msg = "The fit failed, possibly because it didn't converge."
1541            if rcParams['verbose']:
1542                #print msg
1543                print_log()
1544                asaplog.push( msg.message )
1545                print_log( 'ERROR' )
1546                return
1547            else:
1548                raise RuntimeError(msg)
1549
1550
1551    def auto_poly_baseline(self, mask=[], edge=(0, 0), order=0,
1552                           threshold=3, chan_avg_limit=1, plot=False,
1553                           insitu=None):
1554        """
1555        Return a scan which has been baselined (all rows) by a polynomial.
1556        Spectral lines are detected first using linefinder and masked out
1557        to avoid them affecting the baseline solution.
1558
1559        Parameters:
1560            mask:       an optional mask retreived from scantable
1561            edge:       an optional number of channel to drop at
1562                        the edge of spectrum. If only one value is
1563                        specified, the same number will be dropped from
1564                        both sides of the spectrum. Default is to keep
1565                        all channels. Nested tuples represent individual
1566                        edge selection for different IFs (a number of spectral
1567                        channels can be different)
1568            order:      the order of the polynomial (default is 0)
1569            threshold:  the threshold used by line finder. It is better to
1570                        keep it large as only strong lines affect the
1571                        baseline solution.
1572            chan_avg_limit:
1573                        a maximum number of consequtive spectral channels to
1574                        average during the search of weak and broad lines.
1575                        The default is no averaging (and no search for weak
1576                        lines). If such lines can affect the fitted baseline
1577                        (e.g. a high order polynomial is fitted), increase this
1578                        parameter (usually values up to 8 are reasonable). Most
1579                        users of this method should find the default value
1580                        sufficient.
1581            plot:       plot the fit and the residual. In this each
1582                        indivual fit has to be approved, by typing 'y'
1583                        or 'n'
1584            insitu:     if False a new scantable is returned.
1585                        Otherwise, the scaling is done in-situ
1586                        The default is taken from .asaprc (False)
1587
1588        Example:
1589            scan2=scan.auto_poly_baseline(order=7)
1590        """
1591        if insitu is None: insitu = rcParams['insitu']
1592        varlist = vars()
1593        from asap.asapfitter import fitter
1594        from asap.asaplinefind import linefinder
1595        from asap import _is_sequence_or_number as _is_valid
1596
1597        # check whether edge is set up for each IF individually
1598        individualedge = False;
1599        if len(edge) > 1:
1600            if isinstance(edge[0], list) or isinstance(edge[0], tuple):
1601                individualedge = True;
1602
1603        if not _is_valid(edge, int) and not individualedge:
1604            raise ValueError, "Parameter 'edge' has to be an integer or a \
1605            pair of integers specified as a tuple. Nested tuples are allowed \
1606            to make individual selection for different IFs."
1607
1608        curedge = (0, 0)
1609        if individualedge:
1610            for edgepar in edge:
1611                if not _is_valid(edgepar, int):
1612                    raise ValueError, "Each element of the 'edge' tuple has \
1613                                       to be a pair of integers or an integer."
1614        else:
1615            curedge = edge;
1616
1617        # setup fitter
1618        f = fitter()
1619        f.set_function(poly=order)
1620
1621        # setup line finder
1622        fl = linefinder()
1623        fl.set_options(threshold=threshold,avg_limit=chan_avg_limit)
1624
1625        if not insitu:
1626            workscan = self.copy()
1627        else:
1628            workscan = self
1629
1630        fl.set_scan(workscan)
1631
1632        rows = range(workscan.nrow())
1633        # Save parameters of baseline fits & masklists as a class attribute.
1634        # NOTICE: It does not reflect changes in scantable!
1635        if len(rows) > 0:
1636            self.blpars=[]
1637            self.masklists=[]
1638        asaplog.push("Processing:")
1639        for r in rows:
1640            msg = " Scan[%d] Beam[%d] IF[%d] Pol[%d] Cycle[%d]" % \
1641                (workscan.getscan(r), workscan.getbeam(r), workscan.getif(r), \
1642                 workscan.getpol(r), workscan.getcycle(r))
1643            asaplog.push(msg, False)
1644
1645            # figure out edge parameter
1646            if individualedge:
1647                if len(edge) >= workscan.getif(r):
1648                    raise RuntimeError, "Number of edge elements appear to " \
1649                                        "be less than the number of IFs"
1650                    curedge = edge[workscan.getif(r)]
1651
1652            # setup line finder
1653            fl.find_lines(r, mask, curedge)
1654            outmask=fl.get_mask()
1655            f.set_scan(workscan, fl.get_mask())
1656            f.x = workscan._getabcissa(r)
1657            f.y = workscan._getspectrum(r)
1658            f.data = None
1659            f.fit()
1660           
1661            # Show mask list
1662            masklist=workscan.get_masklist(fl.get_mask(),row=r)
1663            msg = "mask range: "+str(masklist)
1664            asaplog.push(msg, False)
1665
1666            fpar = f.get_parameters()
1667            if plot:
1668                f.plot(residual=True)
1669                x = raw_input("Accept fit ( [y]/n ): ")
1670                if x.upper() == 'N':
1671                    self.blpars.append(None)
1672                    self.masklists.append(None)
1673                    continue
1674            workscan._setspectrum(f.fitter.getresidual(), r)
1675            self.blpars.append(fpar)
1676            self.masklists.append(masklist)
1677        if plot:
1678            f._p.unmap()
1679            f._p = None
1680        workscan._add_history("auto_poly_baseline", varlist)
1681        if insitu:
1682            self._assign(workscan)
1683        else:
1684            return workscan
1685
1686    def rotate_linpolphase(self, angle):
1687        """
1688        Rotate the phase of the complex polarization O=Q+iU correlation.
1689        This is always done in situ in the raw data.  So if you call this
1690        function more than once then each call rotates the phase further.
1691        Parameters:
1692            angle:   The angle (degrees) to rotate (add) by.
1693        Examples:
1694            scan.rotate_linpolphase(2.3)
1695        """
1696        varlist = vars()
1697        self._math._rotate_linpolphase(self, angle)
1698        self._add_history("rotate_linpolphase", varlist)
1699        print_log()
1700        return
1701
1702
1703    def rotate_xyphase(self, angle):
1704        """
1705        Rotate the phase of the XY correlation.  This is always done in situ
1706        in the data.  So if you call this function more than once
1707        then each call rotates the phase further.
1708        Parameters:
1709            angle:   The angle (degrees) to rotate (add) by.
1710        Examples:
1711            scan.rotate_xyphase(2.3)
1712        """
1713        varlist = vars()
1714        self._math._rotate_xyphase(self, angle)
1715        self._add_history("rotate_xyphase", varlist)
1716        print_log()
1717        return
1718
1719    def swap_linears(self):
1720        """
1721        Swap the linear polarisations XX and YY, or better the first two
1722        polarisations as this also works for ciculars.
1723        """
1724        varlist = vars()
1725        self._math._swap_linears(self)
1726        self._add_history("swap_linears", varlist)
1727        print_log()
1728        return
1729
1730    def invert_phase(self):
1731        """
1732        Invert the phase of the complex polarisation
1733        """
1734        varlist = vars()
1735        self._math._invert_phase(self)
1736        self._add_history("invert_phase", varlist)
1737        print_log()
1738        return
1739
1740    def add(self, offset, insitu=None):
1741        """
1742        Return a scan where all spectra have the offset added
1743        Parameters:
1744            offset:      the offset
1745            insitu:      if False a new scantable is returned.
1746                         Otherwise, the scaling is done in-situ
1747                         The default is taken from .asaprc (False)
1748        """
1749        if insitu is None: insitu = rcParams['insitu']
1750        self._math._setinsitu(insitu)
1751        varlist = vars()
1752        s = scantable(self._math._unaryop(self, offset, "ADD", False))
1753        s._add_history("add", varlist)
1754        print_log()
1755        if insitu:
1756            self._assign(s)
1757        else:
1758            return s
1759
1760    def scale(self, factor, tsys=True, insitu=None):
1761        """
1762        Return a scan where all spectra are scaled by the give 'factor'
1763        Parameters:
1764            factor:      the scaling factor
1765            insitu:      if False a new scantable is returned.
1766                         Otherwise, the scaling is done in-situ
1767                         The default is taken from .asaprc (False)
1768            tsys:        if True (default) then apply the operation to Tsys
1769                         as well as the data
1770        """
1771        if insitu is None: insitu = rcParams['insitu']
1772        self._math._setinsitu(insitu)
1773        varlist = vars()
1774        s = scantable(self._math._unaryop(self, factor, "MUL", tsys))
1775        s._add_history("scale", varlist)
1776        print_log()
1777        if insitu:
1778            self._assign(s)
1779        else:
1780            return s
1781
1782    def set_sourcetype(self, match, matchtype="pattern",
1783                       sourcetype="reference"):
1784        """
1785        Set the type of the source to be an source or reference scan
1786        using the provided pattern:
1787        Parameters:
1788            match:          a Unix style pattern, regular expression or selector
1789            matchtype:      'pattern' (default) UNIX style pattern or
1790                            'regex' regular expression
1791            sourcetype:     the type of the source to use (source/reference)
1792        """
1793        varlist = vars()
1794        basesel = self.get_selection()
1795        stype = -1
1796        if sourcetype.lower().startswith("r"):
1797            stype = 1
1798        elif sourcetype.lower().startswith("s"):
1799            stype = 0
1800        else:
1801            raise ValueError("Illegal sourcetype use s(ource) or r(eference)")
1802        if matchtype.lower().startswith("p"):
1803            matchtype = "pattern"
1804        elif matchtype.lower().startswith("r"):
1805            matchtype = "regex"
1806        else:
1807            raise ValueError("Illegal matchtype, use p(attern) or r(egex)")
1808        sel = selector()
1809        if isinstance(match, selector):
1810            sel = match
1811        else:
1812            sel.set_query("SRCNAME == %s('%s')" % (matchtype, match))
1813        self.set_selection(basesel+sel)
1814        self._setsourcetype(stype)
1815        self.set_selection(basesel)
1816        s._add_history("set_sourcetype", varlist)
1817
1818    def auto_quotient(self, preserve=True, mode='paired', verify=False):
1819        """
1820        This function allows to build quotients automatically.
1821        It assumes the observation to have the same number of
1822        "ons" and "offs"
1823        Parameters:
1824            preserve:       you can preserve (default) the continuum or
1825                            remove it.  The equations used are
1826                            preserve: Output = Toff * (on/off) - Toff
1827                            remove:   Output = Toff * (on/off) - Ton
1828            mode:           the on/off detection mode
1829                            'paired' (default)
1830                            identifies 'off' scans by the
1831                            trailing '_R' (Mopra/Parkes) or
1832                            '_e'/'_w' (Tid) and matches
1833                            on/off pairs from the observing pattern
1834                            'time'
1835                            finds the closest off in time
1836
1837        """
1838        modes = ["time", "paired"]
1839        if not mode in modes:
1840            msg = "please provide valid mode. Valid modes are %s" % (modes)
1841            raise ValueError(msg)
1842        varlist = vars()
1843        s = None
1844        if mode.lower() == "paired":
1845            basesel = self.get_selection()
1846            sel = selector()+basesel
1847            sel.set_query("SRCTYPE==1")
1848            self.set_selection(sel)
1849            offs = self.copy()
1850            sel.set_query("SRCTYPE==0")
1851            self.set_selection(sel)
1852            ons = self.copy()
1853            s = scantable(self._math._quotient(ons, offs, preserve))
1854            self.set_selection(basesel)
1855        elif mode.lower() == "time":
1856            s = scantable(self._math._auto_quotient(self, mode, preserve))
1857        s._add_history("auto_quotient", varlist)
1858        print_log()
1859        return s
1860
1861    def mx_quotient(self, mask = None, weight='median', preserve=True):
1862        """
1863        Form a quotient using "off" beams when observing in "MX" mode.
1864        Parameters:
1865            mask:           an optional mask to be used when weight == 'stddev'
1866            weight:         How to average the off beams.  Default is 'median'.
1867            preserve:       you can preserve (default) the continuum or
1868                            remove it.  The equations used are
1869                            preserve: Output = Toff * (on/off) - Toff
1870                            remove:   Output = Toff * (on/off) - Ton
1871        """
1872        if mask is None: mask = ()
1873        varlist = vars()
1874        on = scantable(self._math._mx_extract(self, 'on'))
1875        preoff = scantable(self._math._mx_extract(self, 'off'))
1876        off = preoff.average_time(mask=mask, weight=weight, scanav=False)
1877        from asapmath  import quotient
1878        q = quotient(on, off, preserve)
1879        q._add_history("mx_quotient", varlist)
1880        print_log()
1881        return q
1882
1883    def freq_switch(self, insitu=None):
1884        """
1885        Apply frequency switching to the data.
1886        Parameters:
1887            insitu:      if False a new scantable is returned.
1888                         Otherwise, the swictching is done in-situ
1889                         The default is taken from .asaprc (False)
1890        Example:
1891            none
1892        """
1893        if insitu is None: insitu = rcParams['insitu']
1894        self._math._setinsitu(insitu)
1895        varlist = vars()
1896        s = scantable(self._math._freqswitch(self))
1897        s._add_history("freq_switch", varlist)
1898        print_log()
1899        if insitu: self._assign(s)
1900        else: return s
1901
1902    def recalc_azel(self):
1903        """
1904        Recalculate the azimuth and elevation for each position.
1905        Parameters:
1906            none
1907        Example:
1908        """
1909        varlist = vars()
1910        self._recalcazel()
1911        self._add_history("recalc_azel", varlist)
1912        print_log()
1913        return
1914
1915    def __add__(self, other):
1916        varlist = vars()
1917        s = None
1918        if isinstance(other, scantable):
1919            s = scantable(self._math._binaryop(self, other, "ADD"))
1920        elif isinstance(other, float):
1921            s = scantable(self._math._unaryop(self, other, "ADD", False))
1922        else:
1923            raise TypeError("Other input is not a scantable or float value")
1924        s._add_history("operator +", varlist)
1925        print_log()
1926        return s
1927
1928    def __sub__(self, other):
1929        """
1930        implicit on all axes and on Tsys
1931        """
1932        varlist = vars()
1933        s = None
1934        if isinstance(other, scantable):
1935            s = scantable(self._math._binaryop(self, other, "SUB"))
1936        elif isinstance(other, float):
1937            s = scantable(self._math._unaryop(self, other, "SUB", False))
1938        else:
1939            raise TypeError("Other input is not a scantable or float value")
1940        s._add_history("operator -", varlist)
1941        print_log()
1942        return s
1943
1944    def __mul__(self, other):
1945        """
1946        implicit on all axes and on Tsys
1947        """
1948        varlist = vars()
1949        s = None
1950        if isinstance(other, scantable):
1951            s = scantable(self._math._binaryop(self, other, "MUL"))
1952        elif isinstance(other, float):
1953            s = scantable(self._math._unaryop(self, other, "MUL", False))
1954        else:
1955            raise TypeError("Other input is not a scantable or float value")
1956        s._add_history("operator *", varlist)
1957        print_log()
1958        return s
1959
1960
1961    def __div__(self, other):
1962        """
1963        implicit on all axes and on Tsys
1964        """
1965        varlist = vars()
1966        s = None
1967        if isinstance(other, scantable):
1968            s = scantable(self._math._binaryop(self, other, "DIV"))
1969        elif isinstance(other, float):
1970            if other == 0.0:
1971                raise ZeroDivisionError("Dividing by zero is not recommended")
1972            s = scantable(self._math._unaryop(self, other, "DIV", False))
1973        else:
1974            raise TypeError("Other input is not a scantable or float value")
1975        s._add_history("operator /", varlist)
1976        print_log()
1977        return s
1978
1979    def get_fit(self, row=0):
1980        """
1981        Print or return the stored fits for a row in the scantable
1982        Parameters:
1983            row:    the row which the fit has been applied to.
1984        """
1985        if row > self.nrow():
1986            return
1987        from asap.asapfit import asapfit
1988        fit = asapfit(self._getfit(row))
1989        if rcParams['verbose']:
1990            #print fit
1991            asaplog.push( '%s' %(fit) )
1992            print_log()
1993            return
1994        else:
1995            return fit.as_dict()
1996
1997    def flag_nans(self):
1998        """
1999        Utility function to flag NaN values in the scantable.
2000        """
2001        import numpy
2002        basesel = self.get_selection()
2003        for i in range(self.nrow()):
2004            sel = selector()+basesel
2005            sel.set_scans(self.getscan(i))
2006            sel.set_beams(self.getbeam(i))
2007            sel.set_ifs(self.getif(i))
2008            sel.set_polarisations(self.getpol(i))
2009            self.set_selection(sel)
2010            nans = numpy.isnan(self._getspectrum(0))
2011        if numpy.any(nans):
2012            bnans = [ bool(v) for v in nans]
2013            self.flag(bnans)
2014        self.set_selection(basesel)
2015       
2016
2017    def _add_history(self, funcname, parameters):
2018        if not rcParams['scantable.history']:
2019            return
2020        # create date
2021        sep = "##"
2022        from datetime import datetime
2023        dstr = datetime.now().strftime('%Y/%m/%d %H:%M:%S')
2024        hist = dstr+sep
2025        hist += funcname+sep#cdate+sep
2026        if parameters.has_key('self'): del parameters['self']
2027        for k, v in parameters.iteritems():
2028            if type(v) is dict:
2029                for k2, v2 in v.iteritems():
2030                    hist += k2
2031                    hist += "="
2032                    if isinstance(v2, scantable):
2033                        hist += 'scantable'
2034                    elif k2 == 'mask':
2035                        if isinstance(v2, list) or isinstance(v2, tuple):
2036                            hist += str(self._zip_mask(v2))
2037                        else:
2038                            hist += str(v2)
2039                    else:
2040                        hist += str(v2)
2041            else:
2042                hist += k
2043                hist += "="
2044                if isinstance(v, scantable):
2045                    hist += 'scantable'
2046                elif k == 'mask':
2047                    if isinstance(v, list) or isinstance(v, tuple):
2048                        hist += str(self._zip_mask(v))
2049                    else:
2050                        hist += str(v)
2051                else:
2052                    hist += str(v)
2053            hist += sep
2054        hist = hist[:-2] # remove trailing '##'
2055        self._addhistory(hist)
2056
2057
2058    def _zip_mask(self, mask):
2059        mask = list(mask)
2060        i = 0
2061        segments = []
2062        while mask[i:].count(1):
2063            i += mask[i:].index(1)
2064            if mask[i:].count(0):
2065                j = i + mask[i:].index(0)
2066            else:
2067                j = len(mask)
2068            segments.append([i, j])
2069            i = j
2070        return segments
2071
2072    def _get_ordinate_label(self):
2073        fu = "("+self.get_fluxunit()+")"
2074        import re
2075        lbl = "Intensity"
2076        if re.match(".K.", fu):
2077            lbl = "Brightness Temperature "+ fu
2078        elif re.match(".Jy.", fu):
2079            lbl = "Flux density "+ fu
2080        return lbl
2081
2082    def _check_ifs(self):
2083        nchans = [self.nchan(i) for i in range(self.nif(-1))]
2084        nchans = filter(lambda t: t > 0, nchans)
2085        return (sum(nchans)/len(nchans) == nchans[0])
2086
2087    def _fill(self, names, unit, average, getpt):
2088        import os
2089        from asap._asap import stfiller
2090        first = True
2091        fullnames = []
2092        for name in names:
2093            name = os.path.expandvars(name)
2094            name = os.path.expanduser(name)
2095            if not os.path.exists(name):
2096                msg = "File '%s' does not exists" % (name)
2097                if rcParams['verbose']:
2098                    asaplog.push(msg)
2099                    #print asaplog.pop().strip()
2100                    print_log( 'ERROR' )
2101                    return
2102                raise IOError(msg)
2103            fullnames.append(name)
2104        if average:
2105            asaplog.push('Auto averaging integrations')
2106        stype = int(rcParams['scantable.storage'].lower() == 'disk')
2107        for name in fullnames:
2108            tbl = Scantable(stype)
2109            r = stfiller(tbl)
2110            rx = rcParams['scantable.reference']
2111            r._setreferenceexpr(rx)
2112            msg = "Importing %s..." % (name)
2113            asaplog.push(msg, False)
2114            print_log()
2115            r._open(name, -1, -1, getpt)
2116            r._read()
2117            if average:
2118                tbl = self._math._average((tbl, ), (), 'NONE', 'SCAN')
2119            if not first:
2120                tbl = self._math._merge([self, tbl])
2121            Scantable.__init__(self, tbl)
2122            r._close()
2123            del r, tbl
2124            first = False
2125        if unit is not None:
2126            self.set_fluxunit(unit)
2127        #self.set_freqframe(rcParams['scantable.freqframe'])
2128
2129    def __getitem__(self, key):
2130        if key < 0:
2131            key += self.nrow()
2132        if key >= self.nrow():
2133            raise IndexError("Row index out of range.")
2134        return self._getspectrum(key)
2135
2136    def __setitem__(self, key, value):
2137        if key < 0:
2138            key += self.nrow()
2139        if key >= self.nrow():
2140            raise IndexError("Row index out of range.")
2141        if not hasattr(value, "__len__") or \
2142                len(value) > self.nchan(self.getif(key)):
2143            raise ValueError("Spectrum length doesn't match.")
2144        return self._setspectrum(value, key)
2145
2146    def __len__(self):
2147        return self.nrow()
2148
2149    def __iter__(self):
2150        for i in range(len(self)):
2151            yield self[i]
Note: See TracBrowser for help on using the repository browser.