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

Last change on this file since 1649 was 1649, checked in by TakTsutsumi, 15 years ago

New Development: No

JIRA Issue: No (regression test failure)

Ready to Release: Yes

Interface Changes: No

What Interface Changed: Please list interface changes

Test Programs: List test programs

Put in Release Notes: No

Module(s): Module Names change impacts.

Description: fixed a bug in scantable.poly_baseline()


  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 82.9 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        if not insitu:
1521            workscan = self.copy()
1522        else:
1523            workscan = self
1524        varlist = vars()
1525        if mask is None:
1526            mask = [True for i in xrange(self.nchan(-1))]
1527       
1528        from asap.asapfitter import fitter
1529        try:
1530            f = fitter()
1531            if uselin:
1532                f.set_function(lpoly=order)
1533            else:
1534                f.set_function(poly=order)
1535
1536            rows = range(self.nrow())
1537            if len(rows) > 0:
1538                self.blpars = []
1539           
1540            for r in rows:
1541                # take into account flagtra info (CAS-1434)
1542                flagtra = self._getmask(r)
1543                actualmask = mask[:]
1544                if len(actualmask) == 0:
1545                    actualmask = list(flagtra[:])
1546                else:
1547                    if len(actualmask) != len(flagtra):
1548                        raise RuntimeError, "Mask and flagtra have different length"
1549                    else:
1550                        for i in range(0, len(actualmask)):
1551                            actualmask[i] = actualmask[i] and flagtra[i]
1552                f.set_scan(self, actualmask)
1553                f.x = self._getabcissa(r)
1554                f.y = self._getspectrum(r)
1555                f.data = None
1556                f.fit()
1557                workscan._setspectrum(f.fitter.getresidual(), r)
1558                fpar = f.get_parameters()
1559                self.blpars.append(fpar)
1560               
1561            #f.set_scan(self, mask)
1562            #s = f.auto_fit(insitu, plot=plot)
1563            ## Save parameters of baseline fits as a class attribute.
1564            ## NOTICE: It does not reflect changes in scantable!
1565            #self.blpars = f.blpars
1566            workscan._add_history("poly_baseline", varlist)
1567            print_log()
1568            if insitu: self._assign(workscan)
1569            else: return workscan
1570        except RuntimeError:
1571            msg = "The fit failed, possibly because it didn't converge."
1572            if rcParams['verbose']:
1573                #print msg
1574                print_log()
1575                asaplog.push( msg.message )
1576                print_log( 'ERROR' )
1577                return
1578            else:
1579                raise RuntimeError(msg)
1580
1581
1582    def auto_poly_baseline(self, mask=[], edge=(0, 0), order=0,
1583                           threshold=3, chan_avg_limit=1, plot=False,
1584                           insitu=None):
1585        """
1586        Return a scan which has been baselined (all rows) by a polynomial.
1587        Spectral lines are detected first using linefinder and masked out
1588        to avoid them affecting the baseline solution.
1589
1590        Parameters:
1591            mask:       an optional mask retreived from scantable
1592            edge:       an optional number of channel to drop at
1593                        the edge of spectrum. If only one value is
1594                        specified, the same number will be dropped from
1595                        both sides of the spectrum. Default is to keep
1596                        all channels. Nested tuples represent individual
1597                        edge selection for different IFs (a number of spectral
1598                        channels can be different)
1599            order:      the order of the polynomial (default is 0)
1600            threshold:  the threshold used by line finder. It is better to
1601                        keep it large as only strong lines affect the
1602                        baseline solution.
1603            chan_avg_limit:
1604                        a maximum number of consequtive spectral channels to
1605                        average during the search of weak and broad lines.
1606                        The default is no averaging (and no search for weak
1607                        lines). If such lines can affect the fitted baseline
1608                        (e.g. a high order polynomial is fitted), increase this
1609                        parameter (usually values up to 8 are reasonable). Most
1610                        users of this method should find the default value
1611                        sufficient.
1612            plot:       plot the fit and the residual. In this each
1613                        indivual fit has to be approved, by typing 'y'
1614                        or 'n'
1615            insitu:     if False a new scantable is returned.
1616                        Otherwise, the scaling is done in-situ
1617                        The default is taken from .asaprc (False)
1618
1619        Example:
1620            scan2=scan.auto_poly_baseline(order=7)
1621        """
1622        if insitu is None: insitu = rcParams['insitu']
1623        varlist = vars()
1624        from asap.asapfitter import fitter
1625        from asap.asaplinefind import linefinder
1626        from asap import _is_sequence_or_number as _is_valid
1627
1628        # check whether edge is set up for each IF individually
1629        individualedge = False;
1630        if len(edge) > 1:
1631            if isinstance(edge[0], list) or isinstance(edge[0], tuple):
1632                individualedge = True;
1633
1634        if not _is_valid(edge, int) and not individualedge:
1635            raise ValueError, "Parameter 'edge' has to be an integer or a \
1636            pair of integers specified as a tuple. Nested tuples are allowed \
1637            to make individual selection for different IFs."
1638
1639        curedge = (0, 0)
1640        if individualedge:
1641            for edgepar in edge:
1642                if not _is_valid(edgepar, int):
1643                    raise ValueError, "Each element of the 'edge' tuple has \
1644                                       to be a pair of integers or an integer."
1645        else:
1646            curedge = edge;
1647
1648        # setup fitter
1649        f = fitter()
1650        f.set_function(poly=order)
1651
1652        # setup line finder
1653        fl = linefinder()
1654        fl.set_options(threshold=threshold,avg_limit=chan_avg_limit)
1655
1656        if not insitu:
1657            workscan = self.copy()
1658        else:
1659            workscan = self
1660
1661        fl.set_scan(workscan)
1662
1663        rows = range(workscan.nrow())
1664        # Save parameters of baseline fits & masklists as a class attribute.
1665        # NOTICE: It does not reflect changes in scantable!
1666        if len(rows) > 0:
1667            self.blpars=[]
1668            self.masklists=[]
1669        asaplog.push("Processing:")
1670        for r in rows:
1671            msg = " Scan[%d] Beam[%d] IF[%d] Pol[%d] Cycle[%d]" % \
1672                (workscan.getscan(r), workscan.getbeam(r), workscan.getif(r), \
1673                 workscan.getpol(r), workscan.getcycle(r))
1674            asaplog.push(msg, False)
1675
1676            # figure out edge parameter
1677            if individualedge:
1678                if len(edge) >= workscan.getif(r):
1679                    raise RuntimeError, "Number of edge elements appear to " \
1680                                        "be less than the number of IFs"
1681                    curedge = edge[workscan.getif(r)]
1682
1683            # take into account flagtra info (CAS-1434)
1684            flagtra = workscan._getmask(r)
1685            actualmask = mask[:]
1686            if len(actualmask) == 0:
1687                actualmask = list(flagtra[:])
1688            else:
1689                if len(actualmask) != len(flagtra):
1690                    raise RuntimeError, "Mask and flagtra have different length"
1691                else:
1692                    for i in range(0, len(actualmask)):
1693                        actualmask[i] = actualmask[i] and flagtra[i]
1694
1695            # setup line finder
1696            fl.find_lines(r, actualmask, curedge)
1697            outmask=fl.get_mask()
1698            f.set_scan(workscan, fl.get_mask())
1699            f.x = workscan._getabcissa(r)
1700            f.y = workscan._getspectrum(r)
1701            f.data = None
1702            f.fit()
1703           
1704            # Show mask list
1705            masklist=workscan.get_masklist(fl.get_mask(),row=r)
1706            msg = "mask range: "+str(masklist)
1707            asaplog.push(msg, False)
1708
1709            fpar = f.get_parameters()
1710            if plot:
1711                f.plot(residual=True)
1712                x = raw_input("Accept fit ( [y]/n ): ")
1713                if x.upper() == 'N':
1714                    self.blpars.append(None)
1715                    self.masklists.append(None)
1716                    continue
1717            workscan._setspectrum(f.fitter.getresidual(), r)
1718            self.blpars.append(fpar)
1719            self.masklists.append(masklist)
1720        if plot:
1721            f._p.unmap()
1722            f._p = None
1723        workscan._add_history("auto_poly_baseline", varlist)
1724        if insitu:
1725            self._assign(workscan)
1726        else:
1727            return workscan
1728
1729    def rotate_linpolphase(self, angle):
1730        """
1731        Rotate the phase of the complex polarization O=Q+iU correlation.
1732        This is always done in situ in the raw data.  So if you call this
1733        function more than once then each call rotates the phase further.
1734        Parameters:
1735            angle:   The angle (degrees) to rotate (add) by.
1736        Examples:
1737            scan.rotate_linpolphase(2.3)
1738        """
1739        varlist = vars()
1740        self._math._rotate_linpolphase(self, angle)
1741        self._add_history("rotate_linpolphase", varlist)
1742        print_log()
1743        return
1744
1745
1746    def rotate_xyphase(self, angle):
1747        """
1748        Rotate the phase of the XY correlation.  This is always done in situ
1749        in the data.  So if you call this function more than once
1750        then each call rotates the phase further.
1751        Parameters:
1752            angle:   The angle (degrees) to rotate (add) by.
1753        Examples:
1754            scan.rotate_xyphase(2.3)
1755        """
1756        varlist = vars()
1757        self._math._rotate_xyphase(self, angle)
1758        self._add_history("rotate_xyphase", varlist)
1759        print_log()
1760        return
1761
1762    def swap_linears(self):
1763        """
1764        Swap the linear polarisations XX and YY, or better the first two
1765        polarisations as this also works for ciculars.
1766        """
1767        varlist = vars()
1768        self._math._swap_linears(self)
1769        self._add_history("swap_linears", varlist)
1770        print_log()
1771        return
1772
1773    def invert_phase(self):
1774        """
1775        Invert the phase of the complex polarisation
1776        """
1777        varlist = vars()
1778        self._math._invert_phase(self)
1779        self._add_history("invert_phase", varlist)
1780        print_log()
1781        return
1782
1783    def add(self, offset, insitu=None):
1784        """
1785        Return a scan where all spectra have the offset added
1786        Parameters:
1787            offset:      the offset
1788            insitu:      if False a new scantable is returned.
1789                         Otherwise, the scaling is done in-situ
1790                         The default is taken from .asaprc (False)
1791        """
1792        if insitu is None: insitu = rcParams['insitu']
1793        self._math._setinsitu(insitu)
1794        varlist = vars()
1795        s = scantable(self._math._unaryop(self, offset, "ADD", False))
1796        s._add_history("add", varlist)
1797        print_log()
1798        if insitu:
1799            self._assign(s)
1800        else:
1801            return s
1802
1803    def scale(self, factor, tsys=True, insitu=None):
1804        """
1805        Return a scan where all spectra are scaled by the give 'factor'
1806        Parameters:
1807            factor:      the scaling factor
1808            insitu:      if False a new scantable is returned.
1809                         Otherwise, the scaling is done in-situ
1810                         The default is taken from .asaprc (False)
1811            tsys:        if True (default) then apply the operation to Tsys
1812                         as well as the data
1813        """
1814        if insitu is None: insitu = rcParams['insitu']
1815        self._math._setinsitu(insitu)
1816        varlist = vars()
1817        s = scantable(self._math._unaryop(self, factor, "MUL", tsys))
1818        s._add_history("scale", varlist)
1819        print_log()
1820        if insitu:
1821            self._assign(s)
1822        else:
1823            return s
1824
1825    def set_sourcetype(self, match, matchtype="pattern",
1826                       sourcetype="reference"):
1827        """
1828        Set the type of the source to be an source or reference scan
1829        using the provided pattern:
1830        Parameters:
1831            match:          a Unix style pattern, regular expression or selector
1832            matchtype:      'pattern' (default) UNIX style pattern or
1833                            'regex' regular expression
1834            sourcetype:     the type of the source to use (source/reference)
1835        """
1836        varlist = vars()
1837        basesel = self.get_selection()
1838        stype = -1
1839        if sourcetype.lower().startswith("r"):
1840            stype = 1
1841        elif sourcetype.lower().startswith("s"):
1842            stype = 0
1843        else:
1844            raise ValueError("Illegal sourcetype use s(ource) or r(eference)")
1845        if matchtype.lower().startswith("p"):
1846            matchtype = "pattern"
1847        elif matchtype.lower().startswith("r"):
1848            matchtype = "regex"
1849        else:
1850            raise ValueError("Illegal matchtype, use p(attern) or r(egex)")
1851        sel = selector()
1852        if isinstance(match, selector):
1853            sel = match
1854        else:
1855            sel.set_query("SRCNAME == %s('%s')" % (matchtype, match))
1856        self.set_selection(basesel+sel)
1857        self._setsourcetype(stype)
1858        self.set_selection(basesel)
1859        s._add_history("set_sourcetype", varlist)
1860
1861    def auto_quotient(self, preserve=True, mode='paired', verify=False):
1862        """
1863        This function allows to build quotients automatically.
1864        It assumes the observation to have the same number of
1865        "ons" and "offs"
1866        Parameters:
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            mode:           the on/off detection mode
1872                            'paired' (default)
1873                            identifies 'off' scans by the
1874                            trailing '_R' (Mopra/Parkes) or
1875                            '_e'/'_w' (Tid) and matches
1876                            on/off pairs from the observing pattern
1877                            'time'
1878                            finds the closest off in time
1879
1880        """
1881        modes = ["time", "paired"]
1882        if not mode in modes:
1883            msg = "please provide valid mode. Valid modes are %s" % (modes)
1884            raise ValueError(msg)
1885        varlist = vars()
1886        s = None
1887        if mode.lower() == "paired":
1888            basesel = self.get_selection()
1889            sel = selector()+basesel
1890            sel.set_query("SRCTYPE==1")
1891            self.set_selection(sel)
1892            offs = self.copy()
1893            sel.set_query("SRCTYPE==0")
1894            self.set_selection(sel)
1895            ons = self.copy()
1896            s = scantable(self._math._quotient(ons, offs, preserve))
1897            self.set_selection(basesel)
1898        elif mode.lower() == "time":
1899            s = scantable(self._math._auto_quotient(self, mode, preserve))
1900        s._add_history("auto_quotient", varlist)
1901        print_log()
1902        return s
1903
1904    def mx_quotient(self, mask = None, weight='median', preserve=True):
1905        """
1906        Form a quotient using "off" beams when observing in "MX" mode.
1907        Parameters:
1908            mask:           an optional mask to be used when weight == 'stddev'
1909            weight:         How to average the off beams.  Default is 'median'.
1910            preserve:       you can preserve (default) the continuum or
1911                            remove it.  The equations used are
1912                            preserve: Output = Toff * (on/off) - Toff
1913                            remove:   Output = Toff * (on/off) - Ton
1914        """
1915        if mask is None: mask = ()
1916        varlist = vars()
1917        on = scantable(self._math._mx_extract(self, 'on'))
1918        preoff = scantable(self._math._mx_extract(self, 'off'))
1919        off = preoff.average_time(mask=mask, weight=weight, scanav=False)
1920        from asapmath  import quotient
1921        q = quotient(on, off, preserve)
1922        q._add_history("mx_quotient", varlist)
1923        print_log()
1924        return q
1925
1926    def freq_switch(self, insitu=None):
1927        """
1928        Apply frequency switching to the data.
1929        Parameters:
1930            insitu:      if False a new scantable is returned.
1931                         Otherwise, the swictching is done in-situ
1932                         The default is taken from .asaprc (False)
1933        Example:
1934            none
1935        """
1936        if insitu is None: insitu = rcParams['insitu']
1937        self._math._setinsitu(insitu)
1938        varlist = vars()
1939        s = scantable(self._math._freqswitch(self))
1940        s._add_history("freq_switch", varlist)
1941        print_log()
1942        if insitu: self._assign(s)
1943        else: return s
1944
1945    def recalc_azel(self):
1946        """
1947        Recalculate the azimuth and elevation for each position.
1948        Parameters:
1949            none
1950        Example:
1951        """
1952        varlist = vars()
1953        self._recalcazel()
1954        self._add_history("recalc_azel", varlist)
1955        print_log()
1956        return
1957
1958    def __add__(self, other):
1959        varlist = vars()
1960        s = None
1961        if isinstance(other, scantable):
1962            s = scantable(self._math._binaryop(self, other, "ADD"))
1963        elif isinstance(other, float):
1964            s = scantable(self._math._unaryop(self, other, "ADD", False))
1965        else:
1966            raise TypeError("Other input is not a scantable or float value")
1967        s._add_history("operator +", varlist)
1968        print_log()
1969        return s
1970
1971    def __sub__(self, other):
1972        """
1973        implicit on all axes and on Tsys
1974        """
1975        varlist = vars()
1976        s = None
1977        if isinstance(other, scantable):
1978            s = scantable(self._math._binaryop(self, other, "SUB"))
1979        elif isinstance(other, float):
1980            s = scantable(self._math._unaryop(self, other, "SUB", False))
1981        else:
1982            raise TypeError("Other input is not a scantable or float value")
1983        s._add_history("operator -", varlist)
1984        print_log()
1985        return s
1986
1987    def __mul__(self, other):
1988        """
1989        implicit on all axes and on Tsys
1990        """
1991        varlist = vars()
1992        s = None
1993        if isinstance(other, scantable):
1994            s = scantable(self._math._binaryop(self, other, "MUL"))
1995        elif isinstance(other, float):
1996            s = scantable(self._math._unaryop(self, other, "MUL", False))
1997        else:
1998            raise TypeError("Other input is not a scantable or float value")
1999        s._add_history("operator *", varlist)
2000        print_log()
2001        return s
2002
2003
2004    def __div__(self, other):
2005        """
2006        implicit on all axes and on Tsys
2007        """
2008        varlist = vars()
2009        s = None
2010        if isinstance(other, scantable):
2011            s = scantable(self._math._binaryop(self, other, "DIV"))
2012        elif isinstance(other, float):
2013            if other == 0.0:
2014                raise ZeroDivisionError("Dividing by zero is not recommended")
2015            s = scantable(self._math._unaryop(self, other, "DIV", False))
2016        else:
2017            raise TypeError("Other input is not a scantable or float value")
2018        s._add_history("operator /", varlist)
2019        print_log()
2020        return s
2021
2022    def get_fit(self, row=0):
2023        """
2024        Print or return the stored fits for a row in the scantable
2025        Parameters:
2026            row:    the row which the fit has been applied to.
2027        """
2028        if row > self.nrow():
2029            return
2030        from asap.asapfit import asapfit
2031        fit = asapfit(self._getfit(row))
2032        if rcParams['verbose']:
2033            #print fit
2034            asaplog.push( '%s' %(fit) )
2035            print_log()
2036            return
2037        else:
2038            return fit.as_dict()
2039
2040    def flag_nans(self):
2041        """
2042        Utility function to flag NaN values in the scantable.
2043        """
2044        import numpy
2045        basesel = self.get_selection()
2046        for i in range(self.nrow()):
2047            sel = selector()+basesel
2048            sel.set_scans(self.getscan(i))
2049            sel.set_beams(self.getbeam(i))
2050            sel.set_ifs(self.getif(i))
2051            sel.set_polarisations(self.getpol(i))
2052            self.set_selection(sel)
2053            nans = numpy.isnan(self._getspectrum(0))
2054        if numpy.any(nans):
2055            bnans = [ bool(v) for v in nans]
2056            self.flag(bnans)
2057        self.set_selection(basesel)
2058       
2059
2060    def _add_history(self, funcname, parameters):
2061        if not rcParams['scantable.history']:
2062            return
2063        # create date
2064        sep = "##"
2065        from datetime import datetime
2066        dstr = datetime.now().strftime('%Y/%m/%d %H:%M:%S')
2067        hist = dstr+sep
2068        hist += funcname+sep#cdate+sep
2069        if parameters.has_key('self'): del parameters['self']
2070        for k, v in parameters.iteritems():
2071            if type(v) is dict:
2072                for k2, v2 in v.iteritems():
2073                    hist += k2
2074                    hist += "="
2075                    if isinstance(v2, scantable):
2076                        hist += 'scantable'
2077                    elif k2 == 'mask':
2078                        if isinstance(v2, list) or isinstance(v2, tuple):
2079                            hist += str(self._zip_mask(v2))
2080                        else:
2081                            hist += str(v2)
2082                    else:
2083                        hist += str(v2)
2084            else:
2085                hist += k
2086                hist += "="
2087                if isinstance(v, scantable):
2088                    hist += 'scantable'
2089                elif k == 'mask':
2090                    if isinstance(v, list) or isinstance(v, tuple):
2091                        hist += str(self._zip_mask(v))
2092                    else:
2093                        hist += str(v)
2094                else:
2095                    hist += str(v)
2096            hist += sep
2097        hist = hist[:-2] # remove trailing '##'
2098        self._addhistory(hist)
2099
2100
2101    def _zip_mask(self, mask):
2102        mask = list(mask)
2103        i = 0
2104        segments = []
2105        while mask[i:].count(1):
2106            i += mask[i:].index(1)
2107            if mask[i:].count(0):
2108                j = i + mask[i:].index(0)
2109            else:
2110                j = len(mask)
2111            segments.append([i, j])
2112            i = j
2113        return segments
2114
2115    def _get_ordinate_label(self):
2116        fu = "("+self.get_fluxunit()+")"
2117        import re
2118        lbl = "Intensity"
2119        if re.match(".K.", fu):
2120            lbl = "Brightness Temperature "+ fu
2121        elif re.match(".Jy.", fu):
2122            lbl = "Flux density "+ fu
2123        return lbl
2124
2125    def _check_ifs(self):
2126        nchans = [self.nchan(i) for i in range(self.nif(-1))]
2127        nchans = filter(lambda t: t > 0, nchans)
2128        return (sum(nchans)/len(nchans) == nchans[0])
2129
2130    def _fill(self, names, unit, average, getpt):
2131        import os
2132        from asap._asap import stfiller
2133        first = True
2134        fullnames = []
2135        for name in names:
2136            name = os.path.expandvars(name)
2137            name = os.path.expanduser(name)
2138            if not os.path.exists(name):
2139                msg = "File '%s' does not exists" % (name)
2140                if rcParams['verbose']:
2141                    asaplog.push(msg)
2142                    #print asaplog.pop().strip()
2143                    print_log( 'ERROR' )
2144                    return
2145                raise IOError(msg)
2146            fullnames.append(name)
2147        if average:
2148            asaplog.push('Auto averaging integrations')
2149        stype = int(rcParams['scantable.storage'].lower() == 'disk')
2150        for name in fullnames:
2151            tbl = Scantable(stype)
2152            r = stfiller(tbl)
2153            rx = rcParams['scantable.reference']
2154            r._setreferenceexpr(rx)
2155            msg = "Importing %s..." % (name)
2156            asaplog.push(msg, False)
2157            print_log()
2158            r._open(name, -1, -1, getpt)
2159            r._read()
2160            if average:
2161                tbl = self._math._average((tbl, ), (), 'NONE', 'SCAN')
2162            if not first:
2163                tbl = self._math._merge([self, tbl])
2164            Scantable.__init__(self, tbl)
2165            r._close()
2166            del r, tbl
2167            first = False
2168        if unit is not None:
2169            self.set_fluxunit(unit)
2170        #self.set_freqframe(rcParams['scantable.freqframe'])
2171
2172    def __getitem__(self, key):
2173        if key < 0:
2174            key += self.nrow()
2175        if key >= self.nrow():
2176            raise IndexError("Row index out of range.")
2177        return self._getspectrum(key)
2178
2179    def __setitem__(self, key, value):
2180        if key < 0:
2181            key += self.nrow()
2182        if key >= self.nrow():
2183            raise IndexError("Row index out of range.")
2184        if not hasattr(value, "__len__") or \
2185                len(value) > self.nchan(self.getif(key)):
2186            raise ValueError("Spectrum length doesn't match.")
2187        return self._setspectrum(value, key)
2188
2189    def __len__(self):
2190        return self.nrow()
2191
2192    def __iter__(self):
2193        for i in range(len(self)):
2194            yield self[i]
Note: See TracBrowser for help on using the repository browser.