source: trunk/python/scantable.py @ 1070

Last change on this file since 1070 was 1070, checked in by mar637, 18 years ago

enhancement ticket #35. median scantable; also added get_column

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