source: trunk/python/scantable.py @ 1061

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

Added feature Ticket #42; The user can now plot the fits adn reject them.

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