source: trunk/python/scantable.py @ 1005

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

added doc for get/set_selection. added default argument to set_selection

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