source: trunk/python/scantable.py@ 1915

Last change on this file since 1915 was 1909, checked in by WataruKawasaki, 14 years ago

New Development: No

JIRA Issue: Yes CAS-1937

Ready to Release: Yes

Interface Changes: No

What Interface Changed:

Test Programs:

Put in Release Notes: No

Module(s): sdbaseline

Description: Removing an obsolete function print_log().


  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 92.2 KB
RevLine 
[1846]1"""This module defines the scantable class."""
2
[1697]3import os
[1691]4try:
5 from functools import wraps as wraps_dec
6except ImportError:
7 from asap.compatibility import wraps as wraps_dec
8
[1824]9from asap.env import is_casapy
[876]10from asap._asap import Scantable
[1843]11from asap._asap import filler
[1824]12from asap.parameters import rcParams
[1862]13from asap.logging import asaplog, asaplog_post_dec
[1824]14from asap.selector import selector
15from asap.linecatalog import linecatalog
[1600]16from asap.coordinate import coordinate
[1859]17from asap.utils import _n_bools, mask_not, mask_and, mask_or, page
[1907]18from asap.asapfitter import fitter
[102]19
[1689]20
21def preserve_selection(func):
[1691]22 @wraps_dec(func)
[1689]23 def wrap(obj, *args, **kw):
24 basesel = obj.get_selection()
[1857]25 try:
26 val = func(obj, *args, **kw)
27 finally:
28 obj.set_selection(basesel)
[1689]29 return val
30 return wrap
31
[1846]32def is_scantable(filename):
33 """Is the given file a scantable?
[1689]34
[1846]35 Parameters:
36
37 filename: the name of the file/directory to test
38
39 """
[1883]40 if ( os.path.isdir(filename)
41 and os.path.exists(filename+'/table.info')
42 and os.path.exists(filename+'/table.dat') ):
43 f=open(filename+'/table.info')
44 l=f.readline()
45 f.close()
46 #if ( l.find('Scantable') != -1 ):
47 if ( l.find('Measurement Set') == -1 ):
48 return True
49 else:
50 return False
51 else:
52 return False
53## return (os.path.isdir(filename)
54## and not os.path.exists(filename+'/table.f1')
55## and os.path.exists(filename+'/table.info'))
[1697]56
[1883]57def is_ms(filename):
58 """Is the given file a MeasurementSet?
[1697]59
[1883]60 Parameters:
61
62 filename: the name of the file/directory to test
63
64 """
65 if ( os.path.isdir(filename)
66 and os.path.exists(filename+'/table.info')
67 and os.path.exists(filename+'/table.dat') ):
68 f=open(filename+'/table.info')
69 l=f.readline()
70 f.close()
71 if ( l.find('Measurement Set') != -1 ):
72 return True
73 else:
74 return False
75 else:
76 return False
77
[876]78class scantable(Scantable):
[1846]79 """\
80 The ASAP container for scans (single-dish data).
[102]81 """
[1819]82
[1862]83 @asaplog_post_dec
[1824]84 def __init__(self, filename, average=None, unit=None, getpt=None,
85 antenna=None, parallactify=None):
[1846]86 """\
[102]87 Create a scantable from a saved one or make a reference
[1846]88
[102]89 Parameters:
[1846]90
91 filename: the name of an asap table on disk
92 or
93 the name of a rpfits/sdfits/ms file
94 (integrations within scans are auto averaged
95 and the whole file is read) or
96 [advanced] a reference to an existing scantable
97
98 average: average all integrations withinb a scan on read.
99 The default (True) is taken from .asaprc.
100
[484]101 unit: brightness unit; must be consistent with K or Jy.
[1846]102 Over-rides the default selected by the filler
103 (input rpfits/sdfits/ms) or replaces the value
104 in existing scantables
105
106 getpt: for MeasurementSet input data only:
107 If True, all pointing data are filled.
108 The deafult is False, which makes time to load
109 the MS data faster in some cases.
110
111 antenna: Antenna selection. integer (id) or string (name or id).
112
113 parallactify: Indicate that the data had been parallatified. Default
114 is taken from rc file.
115
[710]116 """
[976]117 if average is None:
[710]118 average = rcParams['scantable.autoaverage']
[1819]119 if getpt is None:
120 getpt = True
[1843]121 if antenna is not None:
122 asaplog.push("Antenna selection currently unsupported."
[1883]123 "Using ''")
[1861]124 asaplog.post('WARN')
[1819]125 if antenna is None:
126 antenna = ''
127 elif type(antenna) == int:
[1843]128 antenna = '%s' % antenna
[1819]129 elif type(antenna) == list:
130 tmpstr = ''
131 for i in range( len(antenna) ):
132 if type(antenna[i]) == int:
133 tmpstr = tmpstr + ('%s,'%(antenna[i]))
134 elif type(antenna[i]) == str:
135 tmpstr=tmpstr+antenna[i]+','
136 else:
[1859]137 raise TypeError('Bad antenna selection.')
[1819]138 antenna = tmpstr.rstrip(',')
[1593]139 parallactify = parallactify or rcParams['scantable.parallactify']
[1259]140 varlist = vars()
[876]141 from asap._asap import stmath
[1819]142 self._math = stmath( rcParams['insitu'] )
[876]143 if isinstance(filename, Scantable):
144 Scantable.__init__(self, filename)
[181]145 else:
[1697]146 if isinstance(filename, str):
[976]147 filename = os.path.expandvars(filename)
148 filename = os.path.expanduser(filename)
149 if not os.path.exists(filename):
150 s = "File '%s' not found." % (filename)
151 raise IOError(s)
[1697]152 if is_scantable(filename):
153 ondisk = rcParams['scantable.storage'] == 'disk'
154 Scantable.__init__(self, filename, ondisk)
155 if unit is not None:
156 self.set_fluxunit(unit)
[1819]157 # do not reset to the default freqframe
158 #self.set_freqframe(rcParams['scantable.freqframe'])
[1883]159 #elif os.path.isdir(filename) \
160 # and not os.path.exists(filename+'/table.f1'):
161 elif is_ms(filename):
162 self._fill([filename], unit, average, getpt, antenna)
[1893]163 elif os.path.isfile(filename):
164 self._fill([filename], unit, average, getpt, antenna)
[1883]165 else:
[1819]166 msg = "The given file '%s'is not a valid " \
167 "asap table." % (filename)
[1859]168 raise IOError(msg)
[1118]169 elif (isinstance(filename, list) or isinstance(filename, tuple)) \
[976]170 and isinstance(filename[-1], str):
[1819]171 self._fill(filename, unit, average, getpt, antenna)
[1586]172 self.parallactify(parallactify)
[1259]173 self._add_history("scantable", varlist)
[102]174
[1862]175 @asaplog_post_dec
[876]176 def save(self, name=None, format=None, overwrite=False):
[1846]177 """\
[1280]178 Store the scantable on disk. This can be an asap (aips++) Table,
179 SDFITS or MS2 format.
[1846]180
[116]181 Parameters:
[1846]182
[1093]183 name: the name of the outputfile. For format "ASCII"
184 this is the root file name (data in 'name'.txt
[497]185 and header in 'name'_header.txt)
[1855]186
[116]187 format: an optional file format. Default is ASAP.
[1855]188 Allowed are:
189
190 * 'ASAP' (save as ASAP [aips++] Table),
191 * 'SDFITS' (save as SDFITS file)
192 * 'ASCII' (saves as ascii text file)
193 * 'MS2' (saves as an casacore MeasurementSet V2)
194 * 'FITS' (save as image FITS - not readable by class)
195 * 'CLASS' (save as FITS readable by CLASS)
196
[411]197 overwrite: If the file should be overwritten if it exists.
[256]198 The default False is to return with warning
[411]199 without writing the output. USE WITH CARE.
[1855]200
[1846]201 Example::
202
[116]203 scan.save('myscan.asap')
[1118]204 scan.save('myscan.sdfits', 'SDFITS')
[1846]205
[116]206 """
[411]207 from os import path
[1593]208 format = format or rcParams['scantable.save']
[256]209 suffix = '.'+format.lower()
[1118]210 if name is None or name == "":
[256]211 name = 'scantable'+suffix
[718]212 msg = "No filename given. Using default name %s..." % name
213 asaplog.push(msg)
[411]214 name = path.expandvars(name)
[256]215 if path.isfile(name) or path.isdir(name):
216 if not overwrite:
[718]217 msg = "File %s exists." % name
[1859]218 raise IOError(msg)
[451]219 format2 = format.upper()
220 if format2 == 'ASAP':
[116]221 self._save(name)
222 else:
[989]223 from asap._asap import stwriter as stw
[1118]224 writer = stw(format2)
225 writer.write(self, name)
[116]226 return
227
[102]228 def copy(self):
[1846]229 """Return a copy of this scantable.
230
231 *Note*:
232
[1348]233 This makes a full (deep) copy. scan2 = scan1 makes a reference.
[1846]234
235 Example::
236
[102]237 copiedscan = scan.copy()
[1846]238
[102]239 """
[876]240 sd = scantable(Scantable._copy(self))
[113]241 return sd
242
[1093]243 def drop_scan(self, scanid=None):
[1846]244 """\
[1093]245 Return a new scantable where the specified scan number(s) has(have)
246 been dropped.
[1846]247
[1093]248 Parameters:
[1846]249
[1093]250 scanid: a (list of) scan number(s)
[1846]251
[1093]252 """
253 from asap import _is_sequence_or_number as _is_valid
254 from asap import _to_list
255 from asap import unique
256 if not _is_valid(scanid):
[1859]257 raise RuntimeError( 'Please specify a scanno to drop from the scantable' )
258 scanid = _to_list(scanid)
259 allscans = unique([ self.getscan(i) for i in range(self.nrow())])
260 for sid in scanid: allscans.remove(sid)
261 if len(allscans) == 0:
262 raise ValueError("Can't remove all scans")
263 sel = selector(scans=allscans)
264 return self._select_copy(sel)
[1093]265
[1594]266 def _select_copy(self, selection):
267 orig = self.get_selection()
268 self.set_selection(orig+selection)
269 cp = self.copy()
270 self.set_selection(orig)
271 return cp
272
[102]273 def get_scan(self, scanid=None):
[1855]274 """\
[102]275 Return a specific scan (by scanno) or collection of scans (by
276 source name) in a new scantable.
[1846]277
278 *Note*:
279
[1348]280 See scantable.drop_scan() for the inverse operation.
[1846]281
[102]282 Parameters:
[1846]283
[513]284 scanid: a (list of) scanno or a source name, unix-style
285 patterns are accepted for source name matching, e.g.
286 '*_R' gets all 'ref scans
[1846]287
288 Example::
289
[513]290 # get all scans containing the source '323p459'
291 newscan = scan.get_scan('323p459')
292 # get all 'off' scans
293 refscans = scan.get_scan('*_R')
294 # get a susbset of scans by scanno (as listed in scan.summary())
[1118]295 newscan = scan.get_scan([0, 2, 7, 10])
[1846]296
[102]297 """
298 if scanid is None:
[1859]299 raise RuntimeError( 'Please specify a scan no or name to '
300 'retrieve from the scantable' )
[102]301 try:
[946]302 bsel = self.get_selection()
303 sel = selector()
[102]304 if type(scanid) is str:
[946]305 sel.set_name(scanid)
[1594]306 return self._select_copy(sel)
[102]307 elif type(scanid) is int:
[946]308 sel.set_scans([scanid])
[1594]309 return self._select_copy(sel)
[381]310 elif type(scanid) is list:
[946]311 sel.set_scans(scanid)
[1594]312 return self._select_copy(sel)
[381]313 else:
[718]314 msg = "Illegal scanid type, use 'int' or 'list' if ints."
[1859]315 raise TypeError(msg)
[102]316 except RuntimeError:
[1859]317 raise
[102]318
319 def __str__(self):
[1118]320 return Scantable._summary(self, True)
[102]321
[976]322 def summary(self, filename=None):
[1846]323 """\
[102]324 Print a summary of the contents of this scantable.
[1846]325
[102]326 Parameters:
[1846]327
[102]328 filename: the name of a file to write the putput to
329 Default - no file output
[1846]330
[102]331 """
[976]332 info = Scantable._summary(self, True)
[102]333 if filename is not None:
[256]334 if filename is "":
335 filename = 'scantable_summary.txt'
[415]336 from os.path import expandvars, isdir
[411]337 filename = expandvars(filename)
[415]338 if not isdir(filename):
[413]339 data = open(filename, 'w')
340 data.write(info)
341 data.close()
342 else:
[718]343 msg = "Illegal file name '%s'." % (filename)
[1859]344 raise IOError(msg)
345 return page(info)
[710]346
[1512]347 def get_spectrum(self, rowno):
[1471]348 """Return the spectrum for the current row in the scantable as a list.
[1846]349
[1471]350 Parameters:
[1846]351
[1573]352 rowno: the row number to retrieve the spectrum from
[1846]353
[1471]354 """
355 return self._getspectrum(rowno)
[946]356
[1471]357 def get_mask(self, rowno):
358 """Return the mask for the current row in the scantable as a list.
[1846]359
[1471]360 Parameters:
[1846]361
[1573]362 rowno: the row number to retrieve the mask from
[1846]363
[1471]364 """
365 return self._getmask(rowno)
366
367 def set_spectrum(self, spec, rowno):
368 """Return the spectrum for the current row in the scantable as a list.
[1846]369
[1471]370 Parameters:
[1846]371
[1855]372 spec: the new spectrum
[1846]373
[1855]374 rowno: the row number to set the spectrum for
375
[1471]376 """
377 assert(len(spec) == self.nchan())
378 return self._setspectrum(spec, rowno)
379
[1600]380 def get_coordinate(self, rowno):
381 """Return the (spectral) coordinate for a a given 'rowno'.
[1846]382
383 *Note*:
384
[1600]385 * This coordinate is only valid until a scantable method modifies
386 the frequency axis.
387 * This coordinate does contain the original frequency set-up
388 NOT the new frame. The conversions however are done using the user
389 specified frame (e.g. LSRK/TOPO). To get the 'real' coordinate,
390 use scantable.freq_align first. Without it there is no closure,
[1846]391 i.e.::
[1600]392
[1846]393 c = myscan.get_coordinate(0)
394 c.to_frequency(c.get_reference_pixel()) != c.get_reference_value()
395
[1600]396 Parameters:
[1846]397
[1600]398 rowno: the row number for the spectral coordinate
399
400 """
401 return coordinate(Scantable.get_coordinate(self, rowno))
402
[946]403 def get_selection(self):
[1846]404 """\
[1005]405 Get the selection object currently set on this scantable.
[1846]406
407 Example::
408
[1005]409 sel = scan.get_selection()
410 sel.set_ifs(0) # select IF 0
411 scan.set_selection(sel) # apply modified selection
[1846]412
[946]413 """
414 return selector(self._getselection())
415
[1576]416 def set_selection(self, selection=None, **kw):
[1846]417 """\
[1005]418 Select a subset of the data. All following operations on this scantable
419 are only applied to thi selection.
[1846]420
[1005]421 Parameters:
[1697]422
[1846]423 selection: a selector object (default unset the selection), or
424 any combination of "pols", "ifs", "beams", "scans",
425 "cycles", "name", "query"
[1697]426
[1846]427 Examples::
[1697]428
[1005]429 sel = selector() # create a selection object
[1118]430 self.set_scans([0, 3]) # select SCANNO 0 and 3
[1005]431 scan.set_selection(sel) # set the selection
432 scan.summary() # will only print summary of scanno 0 an 3
433 scan.set_selection() # unset the selection
[1697]434 # or the equivalent
435 scan.set_selection(scans=[0,3])
436 scan.summary() # will only print summary of scanno 0 an 3
437 scan.set_selection() # unset the selection
[1846]438
[946]439 """
[1576]440 if selection is None:
441 # reset
442 if len(kw) == 0:
443 selection = selector()
444 else:
445 # try keywords
446 for k in kw:
447 if k not in selector.fields:
448 raise KeyError("Invalid selection key '%s', valid keys are %s" % (k, selector.fields))
449 selection = selector(**kw)
[946]450 self._setselection(selection)
451
[1819]452 def get_row(self, row=0, insitu=None):
[1846]453 """\
[1819]454 Select a row in the scantable.
455 Return a scantable with single row.
[1846]456
[1819]457 Parameters:
[1846]458
459 row: row no of integration, default is 0.
460 insitu: if False a new scantable is returned. Otherwise, the
461 scaling is done in-situ. The default is taken from .asaprc
462 (False)
463
[1819]464 """
465 if insitu is None: insitu = rcParams['insitu']
466 if not insitu:
467 workscan = self.copy()
468 else:
469 workscan = self
470 # Select a row
471 sel=selector()
472 sel.set_scans([workscan.getscan(row)])
473 sel.set_cycles([workscan.getcycle(row)])
474 sel.set_beams([workscan.getbeam(row)])
475 sel.set_ifs([workscan.getif(row)])
476 sel.set_polarisations([workscan.getpol(row)])
477 sel.set_name(workscan._getsourcename(row))
478 workscan.set_selection(sel)
479 if not workscan.nrow() == 1:
480 msg = "Cloud not identify single row. %d rows selected."%(workscan.nrow())
481 raise RuntimeError(msg)
482 del sel
483 if insitu:
484 self._assign(workscan)
485 else:
486 return workscan
487
[1862]488 @asaplog_post_dec
[1907]489 def stats(self, stat='stddev', mask=None, form='3.3f', row=None):
[1846]490 """\
[135]491 Determine the specified statistic of the current beam/if/pol
[102]492 Takes a 'mask' as an optional parameter to specify which
493 channels should be excluded.
[1846]494
[102]495 Parameters:
[1846]496
[1819]497 stat: 'min', 'max', 'min_abc', 'max_abc', 'sumsq', 'sum',
498 'mean', 'var', 'stddev', 'avdev', 'rms', 'median'
[1855]499
[135]500 mask: an optional mask specifying where the statistic
[102]501 should be determined.
[1855]502
[1819]503 form: format string to print statistic values
[1846]504
[1907]505 row: row number of spectrum to process.
506 (default is None: for all rows)
[1846]507
[1907]508 Example:
[113]509 scan.set_unit('channel')
[1118]510 msk = scan.create_mask([100, 200], [500, 600])
[135]511 scan.stats(stat='mean', mask=m)
[1846]512
[102]513 """
[1593]514 mask = mask or []
[876]515 if not self._check_ifs():
[1118]516 raise ValueError("Cannot apply mask as the IFs have different "
517 "number of channels. Please use setselection() "
518 "to select individual IFs")
[1819]519 rtnabc = False
520 if stat.lower().endswith('_abc'): rtnabc = True
521 getchan = False
522 if stat.lower().startswith('min') or stat.lower().startswith('max'):
523 chan = self._math._minmaxchan(self, mask, stat)
524 getchan = True
525 statvals = []
[1907]526 if not rtnabc:
527 if row == None:
528 statvals = self._math._stats(self, mask, stat)
529 else:
530 statvals = self._math._statsrow(self, mask, stat, int(row))
[256]531
[1819]532 #def cb(i):
533 # return statvals[i]
[256]534
[1819]535 #return self._row_callback(cb, stat)
[102]536
[1819]537 label=stat
538 #callback=cb
539 out = ""
540 #outvec = []
541 sep = '-'*50
[1907]542
543 if row == None:
544 rows = xrange(self.nrow())
545 elif isinstance(row, int):
546 rows = [ row ]
547
548 for i in rows:
[1819]549 refstr = ''
550 statunit= ''
551 if getchan:
552 qx, qy = self.chan2data(rowno=i, chan=chan[i])
553 if rtnabc:
554 statvals.append(qx['value'])
555 refstr = ('(value: %'+form) % (qy['value'])+' ['+qy['unit']+'])'
556 statunit= '['+qx['unit']+']'
557 else:
558 refstr = ('(@ %'+form) % (qx['value'])+' ['+qx['unit']+'])'
559
560 tm = self._gettime(i)
561 src = self._getsourcename(i)
562 out += 'Scan[%d] (%s) ' % (self.getscan(i), src)
563 out += 'Time[%s]:\n' % (tm)
[1907]564 if self.nbeam(-1) > 1: out += ' Beam[%d] ' % (self.getbeam(i))
565 if self.nif(-1) > 1: out += ' IF[%d] ' % (self.getif(i))
566 if self.npol(-1) > 1: out += ' Pol[%d] ' % (self.getpol(i))
[1819]567 #outvec.append(callback(i))
[1907]568 if len(rows) > 1:
569 # out += ('= %'+form) % (outvec[i]) +' '+refstr+'\n'
570 out += ('= %'+form) % (statvals[i]) +' '+refstr+'\n'
571 else:
572 # out += ('= %'+form) % (outvec[0]) +' '+refstr+'\n'
573 out += ('= %'+form) % (statvals[0]) +' '+refstr+'\n'
[1819]574 out += sep+"\n"
575
[1859]576 import os
577 if os.environ.has_key( 'USER' ):
578 usr = os.environ['USER']
579 else:
580 import commands
581 usr = commands.getoutput( 'whoami' )
582 tmpfile = '/tmp/tmp_'+usr+'_casapy_asap_scantable_stats'
583 f = open(tmpfile,'w')
584 print >> f, sep
585 print >> f, ' %s %s' % (label, statunit)
586 print >> f, sep
587 print >> f, out
588 f.close()
589 f = open(tmpfile,'r')
590 x = f.readlines()
591 f.close()
592 asaplog.push(''.join(x), False)
593
[1819]594 return statvals
595
596 def chan2data(self, rowno=0, chan=0):
[1846]597 """\
[1819]598 Returns channel/frequency/velocity and spectral value
599 at an arbitrary row and channel in the scantable.
[1846]600
[1819]601 Parameters:
[1846]602
[1819]603 rowno: a row number in the scantable. Default is the
604 first row, i.e. rowno=0
[1855]605
[1819]606 chan: a channel in the scantable. Default is the first
607 channel, i.e. pos=0
[1846]608
[1819]609 """
610 if isinstance(rowno, int) and isinstance(chan, int):
611 qx = {'unit': self.get_unit(),
612 'value': self._getabcissa(rowno)[chan]}
613 qy = {'unit': self.get_fluxunit(),
614 'value': self._getspectrum(rowno)[chan]}
615 return qx, qy
616
[1118]617 def stddev(self, mask=None):
[1846]618 """\
[135]619 Determine the standard deviation of the current beam/if/pol
620 Takes a 'mask' as an optional parameter to specify which
621 channels should be excluded.
[1846]622
[135]623 Parameters:
[1846]624
[135]625 mask: an optional mask specifying where the standard
626 deviation should be determined.
627
[1846]628 Example::
629
[135]630 scan.set_unit('channel')
[1118]631 msk = scan.create_mask([100, 200], [500, 600])
[135]632 scan.stddev(mask=m)
[1846]633
[135]634 """
[1118]635 return self.stats(stat='stddev', mask=mask);
[135]636
[1003]637
[1259]638 def get_column_names(self):
[1846]639 """\
[1003]640 Return a list of column names, which can be used for selection.
641 """
[1259]642 return list(Scantable.get_column_names(self))
[1003]643
[1730]644 def get_tsys(self, row=-1):
[1846]645 """\
[113]646 Return the System temperatures.
[1846]647
648 Parameters:
649
650 row: the rowno to get the information for. (default all rows)
651
[113]652 Returns:
[1846]653
[876]654 a list of Tsys values for the current selection
[1846]655
[113]656 """
[1730]657 if row > -1:
658 return self._get_column(self._gettsys, row)
[876]659 return self._row_callback(self._gettsys, "Tsys")
[256]660
[1730]661
662 def get_weather(self, row=-1):
[1846]663 """\
664 Return the weather informations.
665
666 Parameters:
667
668 row: the rowno to get the information for. (default all rows)
669
670 Returns:
671
672 a dict or list of of dicts of values for the current selection
673
674 """
675
[1730]676 values = self._get_column(self._get_weather, row)
677 if row > -1:
678 return {'temperature': values[0],
679 'pressure': values[1], 'humidity' : values[2],
680 'windspeed' : values[3], 'windaz' : values[4]
681 }
682 else:
683 out = []
684 for r in values:
685
686 out.append({'temperature': r[0],
687 'pressure': r[1], 'humidity' : r[2],
688 'windspeed' : r[3], 'windaz' : r[4]
689 })
690 return out
691
[876]692 def _row_callback(self, callback, label):
693 out = ""
[1118]694 outvec = []
[1590]695 sep = '-'*50
[876]696 for i in range(self.nrow()):
697 tm = self._gettime(i)
698 src = self._getsourcename(i)
[1590]699 out += 'Scan[%d] (%s) ' % (self.getscan(i), src)
[876]700 out += 'Time[%s]:\n' % (tm)
[1590]701 if self.nbeam(-1) > 1:
702 out += ' Beam[%d] ' % (self.getbeam(i))
703 if self.nif(-1) > 1: out += ' IF[%d] ' % (self.getif(i))
704 if self.npol(-1) > 1: out += ' Pol[%d] ' % (self.getpol(i))
[876]705 outvec.append(callback(i))
706 out += '= %3.3f\n' % (outvec[i])
[1590]707 out += sep+'\n'
[1859]708
709 asaplog.push(sep)
710 asaplog.push(" %s" % (label))
711 asaplog.push(sep)
712 asaplog.push(out)
[1861]713 asaplog.post()
[1175]714 return outvec
[256]715
[1070]716 def _get_column(self, callback, row=-1):
717 """
718 """
719 if row == -1:
720 return [callback(i) for i in range(self.nrow())]
721 else:
[1819]722 if 0 <= row < self.nrow():
[1070]723 return callback(row)
[256]724
[1070]725
[1348]726 def get_time(self, row=-1, asdatetime=False):
[1846]727 """\
[113]728 Get a list of time stamps for the observations.
[1348]729 Return a datetime object for each integration time stamp in the scantable.
[1846]730
[113]731 Parameters:
[1846]732
[1348]733 row: row no of integration. Default -1 return all rows
[1855]734
[1348]735 asdatetime: return values as datetime objects rather than strings
[1846]736
[113]737 """
[1175]738 from time import strptime
739 from datetime import datetime
[1392]740 times = self._get_column(self._gettime, row)
[1348]741 if not asdatetime:
[1392]742 return times
[1175]743 format = "%Y/%m/%d/%H:%M:%S"
744 if isinstance(times, list):
745 return [datetime(*strptime(i, format)[:6]) for i in times]
746 else:
747 return datetime(*strptime(times, format)[:6])
[102]748
[1348]749
750 def get_inttime(self, row=-1):
[1846]751 """\
[1348]752 Get a list of integration times for the observations.
753 Return a time in seconds for each integration in the scantable.
[1846]754
[1348]755 Parameters:
[1846]756
[1348]757 row: row no of integration. Default -1 return all rows.
[1846]758
[1348]759 """
[1573]760 return self._get_column(self._getinttime, row)
[1348]761
[1573]762
[714]763 def get_sourcename(self, row=-1):
[1846]764 """\
[794]765 Get a list source names for the observations.
[714]766 Return a string for each integration in the scantable.
767 Parameters:
[1846]768
[1348]769 row: row no of integration. Default -1 return all rows.
[1846]770
[714]771 """
[1070]772 return self._get_column(self._getsourcename, row)
[714]773
[794]774 def get_elevation(self, row=-1):
[1846]775 """\
[794]776 Get a list of elevations for the observations.
777 Return a float for each integration in the scantable.
[1846]778
[794]779 Parameters:
[1846]780
[1348]781 row: row no of integration. Default -1 return all rows.
[1846]782
[794]783 """
[1070]784 return self._get_column(self._getelevation, row)
[794]785
786 def get_azimuth(self, row=-1):
[1846]787 """\
[794]788 Get a list of azimuths for the observations.
789 Return a float for each integration in the scantable.
[1846]790
[794]791 Parameters:
[1348]792 row: row no of integration. Default -1 return all rows.
[1846]793
[794]794 """
[1070]795 return self._get_column(self._getazimuth, row)
[794]796
797 def get_parangle(self, row=-1):
[1846]798 """\
[794]799 Get a list of parallactic angles for the observations.
800 Return a float for each integration in the scantable.
[1846]801
[794]802 Parameters:
[1846]803
[1348]804 row: row no of integration. Default -1 return all rows.
[1846]805
[794]806 """
[1070]807 return self._get_column(self._getparangle, row)
[794]808
[1070]809 def get_direction(self, row=-1):
810 """
811 Get a list of Positions on the sky (direction) for the observations.
[1594]812 Return a string for each integration in the scantable.
[1855]813
[1070]814 Parameters:
[1855]815
[1070]816 row: row no of integration. Default -1 return all rows
[1855]817
[1070]818 """
819 return self._get_column(self._getdirection, row)
820
[1391]821 def get_directionval(self, row=-1):
[1846]822 """\
[1391]823 Get a list of Positions on the sky (direction) for the observations.
824 Return a float for each integration in the scantable.
[1846]825
[1391]826 Parameters:
[1846]827
[1391]828 row: row no of integration. Default -1 return all rows
[1846]829
[1391]830 """
831 return self._get_column(self._getdirectionvec, row)
832
[1862]833 @asaplog_post_dec
[102]834 def set_unit(self, unit='channel'):
[1846]835 """\
[102]836 Set the unit for all following operations on this scantable
[1846]837
[102]838 Parameters:
[1846]839
840 unit: optional unit, default is 'channel'. Use one of '*Hz',
841 'km/s', 'channel' or equivalent ''
842
[102]843 """
[484]844 varlist = vars()
[1118]845 if unit in ['', 'pixel', 'channel']:
[113]846 unit = ''
847 inf = list(self._getcoordinfo())
848 inf[0] = unit
849 self._setcoordinfo(inf)
[1118]850 self._add_history("set_unit", varlist)
[113]851
[1862]852 @asaplog_post_dec
[484]853 def set_instrument(self, instr):
[1846]854 """\
[1348]855 Set the instrument for subsequent processing.
[1846]856
[358]857 Parameters:
[1846]858
[710]859 instr: Select from 'ATPKSMB', 'ATPKSHOH', 'ATMOPRA',
[407]860 'DSS-43' (Tid), 'CEDUNA', and 'HOBART'
[1846]861
[358]862 """
863 self._setInstrument(instr)
[1118]864 self._add_history("set_instument", vars())
[358]865
[1862]866 @asaplog_post_dec
[1190]867 def set_feedtype(self, feedtype):
[1846]868 """\
[1190]869 Overwrite the feed type, which might not be set correctly.
[1846]870
[1190]871 Parameters:
[1846]872
[1190]873 feedtype: 'linear' or 'circular'
[1846]874
[1190]875 """
876 self._setfeedtype(feedtype)
877 self._add_history("set_feedtype", vars())
878
[1862]879 @asaplog_post_dec
[276]880 def set_doppler(self, doppler='RADIO'):
[1846]881 """\
[276]882 Set the doppler for all following operations on this scantable.
[1846]883
[276]884 Parameters:
[1846]885
[276]886 doppler: One of 'RADIO', 'OPTICAL', 'Z', 'BETA', 'GAMMA'
[1846]887
[276]888 """
[484]889 varlist = vars()
[276]890 inf = list(self._getcoordinfo())
891 inf[2] = doppler
892 self._setcoordinfo(inf)
[1118]893 self._add_history("set_doppler", vars())
[710]894
[1862]895 @asaplog_post_dec
[226]896 def set_freqframe(self, frame=None):
[1846]897 """\
[113]898 Set the frame type of the Spectral Axis.
[1846]899
[113]900 Parameters:
[1846]901
[591]902 frame: an optional frame type, default 'LSRK'. Valid frames are:
[1819]903 'TOPO', 'LSRD', 'LSRK', 'BARY',
[1118]904 'GEO', 'GALACTO', 'LGROUP', 'CMB'
[1846]905
906 Example::
907
[113]908 scan.set_freqframe('BARY')
[1846]909
[113]910 """
[1593]911 frame = frame or rcParams['scantable.freqframe']
[484]912 varlist = vars()
[1819]913 # "REST" is not implemented in casacore
914 #valid = ['REST', 'TOPO', 'LSRD', 'LSRK', 'BARY', \
915 # 'GEO', 'GALACTO', 'LGROUP', 'CMB']
916 valid = ['TOPO', 'LSRD', 'LSRK', 'BARY', \
[1118]917 'GEO', 'GALACTO', 'LGROUP', 'CMB']
[591]918
[989]919 if frame in valid:
[113]920 inf = list(self._getcoordinfo())
921 inf[1] = frame
922 self._setcoordinfo(inf)
[1118]923 self._add_history("set_freqframe", varlist)
[102]924 else:
[1118]925 msg = "Please specify a valid freq type. Valid types are:\n", valid
[1859]926 raise TypeError(msg)
[710]927
[1862]928 @asaplog_post_dec
[989]929 def set_dirframe(self, frame=""):
[1846]930 """\
[989]931 Set the frame type of the Direction on the sky.
[1846]932
[989]933 Parameters:
[1846]934
[989]935 frame: an optional frame type, default ''. Valid frames are:
936 'J2000', 'B1950', 'GALACTIC'
[1846]937
938 Example:
939
[989]940 scan.set_dirframe('GALACTIC')
[1846]941
[989]942 """
943 varlist = vars()
[1859]944 Scantable.set_dirframe(self, frame)
[1118]945 self._add_history("set_dirframe", varlist)
[989]946
[113]947 def get_unit(self):
[1846]948 """\
[113]949 Get the default unit set in this scantable
[1846]950
[113]951 Returns:
[1846]952
[113]953 A unit string
[1846]954
[113]955 """
956 inf = self._getcoordinfo()
957 unit = inf[0]
958 if unit == '': unit = 'channel'
959 return unit
[102]960
[1862]961 @asaplog_post_dec
[158]962 def get_abcissa(self, rowno=0):
[1846]963 """\
[158]964 Get the abcissa in the current coordinate setup for the currently
[113]965 selected Beam/IF/Pol
[1846]966
[113]967 Parameters:
[1846]968
[226]969 rowno: an optional row number in the scantable. Default is the
970 first row, i.e. rowno=0
[1846]971
[113]972 Returns:
[1846]973
[1348]974 The abcissa values and the format string (as a dictionary)
[1846]975
[113]976 """
[256]977 abc = self._getabcissa(rowno)
[710]978 lbl = self._getabcissalabel(rowno)
[158]979 return abc, lbl
[113]980
[1862]981 @asaplog_post_dec
[1819]982 def flag(self, mask=None, unflag=False):
[1846]983 """\
[1001]984 Flag the selected data using an optional channel mask.
[1846]985
[1001]986 Parameters:
[1846]987
[1001]988 mask: an optional channel mask, created with create_mask. Default
989 (no mask) is all channels.
[1855]990
[1819]991 unflag: if True, unflag the data
[1846]992
[1001]993 """
994 varlist = vars()
[1593]995 mask = mask or []
[1859]996 self._flag(mask, unflag)
[1001]997 self._add_history("flag", varlist)
998
[1862]999 @asaplog_post_dec
[1819]1000 def flag_row(self, rows=[], unflag=False):
[1846]1001 """\
[1819]1002 Flag the selected data in row-based manner.
[1846]1003
[1819]1004 Parameters:
[1846]1005
[1843]1006 rows: list of row numbers to be flagged. Default is no row
1007 (must be explicitly specified to execute row-based flagging).
[1855]1008
[1819]1009 unflag: if True, unflag the data.
[1846]1010
[1819]1011 """
1012 varlist = vars()
[1859]1013 self._flag_row(rows, unflag)
[1819]1014 self._add_history("flag_row", varlist)
1015
[1862]1016 @asaplog_post_dec
[1819]1017 def clip(self, uthres=None, dthres=None, clipoutside=True, unflag=False):
[1846]1018 """\
[1819]1019 Flag the selected data outside a specified range (in channel-base)
[1846]1020
[1819]1021 Parameters:
[1846]1022
[1819]1023 uthres: upper threshold.
[1855]1024
[1819]1025 dthres: lower threshold
[1846]1026
[1819]1027 clipoutside: True for flagging data outside the range [dthres:uthres].
1028 False for glagging data inside the range.
[1855]1029
[1846]1030 unflag: if True, unflag the data.
1031
[1819]1032 """
1033 varlist = vars()
[1859]1034 self._clip(uthres, dthres, clipoutside, unflag)
[1819]1035 self._add_history("clip", varlist)
1036
[1862]1037 @asaplog_post_dec
[1584]1038 def lag_flag(self, start, end, unit="MHz", insitu=None):
[1846]1039 """\
[1192]1040 Flag the data in 'lag' space by providing a frequency to remove.
[1584]1041 Flagged data in the scantable gets interpolated over the region.
[1192]1042 No taper is applied.
[1846]1043
[1192]1044 Parameters:
[1846]1045
[1579]1046 start: the start frequency (really a period within the
1047 bandwidth) or period to remove
[1855]1048
[1579]1049 end: the end frequency or period to remove
[1855]1050
[1584]1051 unit: the frequency unit (default "MHz") or "" for
[1579]1052 explicit lag channels
[1846]1053
1054 *Notes*:
1055
[1579]1056 It is recommended to flag edges of the band or strong
[1348]1057 signals beforehand.
[1846]1058
[1192]1059 """
1060 if insitu is None: insitu = rcParams['insitu']
1061 self._math._setinsitu(insitu)
1062 varlist = vars()
[1579]1063 base = { "GHz": 1000000000., "MHz": 1000000., "kHz": 1000., "Hz": 1.}
1064 if not (unit == "" or base.has_key(unit)):
[1192]1065 raise ValueError("%s is not a valid unit." % unit)
[1859]1066 if unit == "":
1067 s = scantable(self._math._lag_flag(self, start, end, "lags"))
1068 else:
1069 s = scantable(self._math._lag_flag(self, start*base[unit],
1070 end*base[unit], "frequency"))
[1192]1071 s._add_history("lag_flag", varlist)
1072 if insitu:
1073 self._assign(s)
1074 else:
1075 return s
[1001]1076
[1862]1077 @asaplog_post_dec
[113]1078 def create_mask(self, *args, **kwargs):
[1846]1079 """\
[1118]1080 Compute and return a mask based on [min, max] windows.
[189]1081 The specified windows are to be INCLUDED, when the mask is
[113]1082 applied.
[1846]1083
[102]1084 Parameters:
[1846]1085
[1118]1086 [min, max], [min2, max2], ...
[1024]1087 Pairs of start/end points (inclusive)specifying the regions
[102]1088 to be masked
[1855]1089
[189]1090 invert: optional argument. If specified as True,
1091 return an inverted mask, i.e. the regions
1092 specified are EXCLUDED
[1855]1093
[513]1094 row: create the mask using the specified row for
1095 unit conversions, default is row=0
1096 only necessary if frequency varies over rows.
[1846]1097
1098 Examples::
1099
[113]1100 scan.set_unit('channel')
[1846]1101 # a)
[1118]1102 msk = scan.create_mask([400, 500], [800, 900])
[189]1103 # masks everything outside 400 and 500
[113]1104 # and 800 and 900 in the unit 'channel'
1105
[1846]1106 # b)
[1118]1107 msk = scan.create_mask([400, 500], [800, 900], invert=True)
[189]1108 # masks the regions between 400 and 500
[113]1109 # and 800 and 900 in the unit 'channel'
[1846]1110
1111 # c)
1112 #mask only channel 400
[1554]1113 msk = scan.create_mask([400])
[1846]1114
[102]1115 """
[1554]1116 row = kwargs.get("row", 0)
[513]1117 data = self._getabcissa(row)
[113]1118 u = self._getcoordinfo()[0]
[1859]1119 if u == "":
1120 u = "channel"
1121 msg = "The current mask window unit is %s" % u
1122 i = self._check_ifs()
1123 if not i:
1124 msg += "\nThis mask is only valid for IF=%d" % (self.getif(i))
1125 asaplog.push(msg)
[102]1126 n = self.nchan()
[1295]1127 msk = _n_bools(n, False)
[710]1128 # test if args is a 'list' or a 'normal *args - UGLY!!!
1129
[1118]1130 ws = (isinstance(args[-1][-1], int) or isinstance(args[-1][-1], float)) \
1131 and args or args[0]
[710]1132 for window in ws:
[1554]1133 if len(window) == 1:
1134 window = [window[0], window[0]]
1135 if len(window) == 0 or len(window) > 2:
1136 raise ValueError("A window needs to be defined as [start(, end)]")
[1545]1137 if window[0] > window[1]:
1138 tmp = window[0]
1139 window[0] = window[1]
1140 window[1] = tmp
[102]1141 for i in range(n):
[1024]1142 if data[i] >= window[0] and data[i] <= window[1]:
[1295]1143 msk[i] = True
[113]1144 if kwargs.has_key('invert'):
1145 if kwargs.get('invert'):
[1295]1146 msk = mask_not(msk)
[102]1147 return msk
[710]1148
[1819]1149 def get_masklist(self, mask=None, row=0):
[1846]1150 """\
[1819]1151 Compute and return a list of mask windows, [min, max].
[1846]1152
[1819]1153 Parameters:
[1846]1154
[1819]1155 mask: channel mask, created with create_mask.
[1855]1156
[1819]1157 row: calcutate the masklist using the specified row
1158 for unit conversions, default is row=0
1159 only necessary if frequency varies over rows.
[1846]1160
[1819]1161 Returns:
[1846]1162
[1819]1163 [min, max], [min2, max2], ...
1164 Pairs of start/end points (inclusive)specifying
1165 the masked regions
[1846]1166
[1819]1167 """
1168 if not (isinstance(mask,list) or isinstance(mask, tuple)):
1169 raise TypeError("The mask should be list or tuple.")
1170 if len(mask) < 2:
1171 raise TypeError("The mask elements should be > 1")
1172 if self.nchan() != len(mask):
1173 msg = "Number of channels in scantable != number of mask elements"
1174 raise TypeError(msg)
1175 data = self._getabcissa(row)
1176 u = self._getcoordinfo()[0]
[1859]1177 if u == "":
1178 u = "channel"
1179 msg = "The current mask window unit is %s" % u
1180 i = self._check_ifs()
1181 if not i:
1182 msg += "\nThis mask is only valid for IF=%d" % (self.getif(i))
1183 asaplog.push(msg)
[1819]1184 masklist=[]
1185 ist, ien = None, None
1186 ist, ien=self.get_mask_indices(mask)
1187 if ist is not None and ien is not None:
1188 for i in xrange(len(ist)):
1189 range=[data[ist[i]],data[ien[i]]]
1190 range.sort()
1191 masklist.append([range[0],range[1]])
1192 return masklist
1193
1194 def get_mask_indices(self, mask=None):
[1846]1195 """\
[1819]1196 Compute and Return lists of mask start indices and mask end indices.
[1855]1197
1198 Parameters:
1199
[1819]1200 mask: channel mask, created with create_mask.
[1846]1201
[1819]1202 Returns:
[1846]1203
[1819]1204 List of mask start indices and that of mask end indices,
1205 i.e., [istart1,istart2,....], [iend1,iend2,....].
[1846]1206
[1819]1207 """
1208 if not (isinstance(mask,list) or isinstance(mask, tuple)):
1209 raise TypeError("The mask should be list or tuple.")
1210 if len(mask) < 2:
1211 raise TypeError("The mask elements should be > 1")
1212 istart=[]
1213 iend=[]
1214 if mask[0]: istart.append(0)
1215 for i in range(len(mask)-1):
1216 if not mask[i] and mask[i+1]:
1217 istart.append(i+1)
1218 elif mask[i] and not mask[i+1]:
1219 iend.append(i)
1220 if mask[len(mask)-1]: iend.append(len(mask)-1)
1221 if len(istart) != len(iend):
1222 raise RuntimeError("Numbers of mask start != mask end.")
1223 for i in range(len(istart)):
1224 if istart[i] > iend[i]:
1225 raise RuntimeError("Mask start index > mask end index")
1226 break
1227 return istart,iend
1228
1229# def get_restfreqs(self):
1230# """
1231# Get the restfrequency(s) stored in this scantable.
1232# The return value(s) are always of unit 'Hz'
1233# Parameters:
1234# none
1235# Returns:
1236# a list of doubles
1237# """
1238# return list(self._getrestfreqs())
1239
1240 def get_restfreqs(self, ids=None):
[1846]1241 """\
[256]1242 Get the restfrequency(s) stored in this scantable.
1243 The return value(s) are always of unit 'Hz'
[1846]1244
[256]1245 Parameters:
[1846]1246
[1819]1247 ids: (optional) a list of MOLECULE_ID for that restfrequency(s) to
1248 be retrieved
[1846]1249
[256]1250 Returns:
[1846]1251
[1819]1252 dictionary containing ids and a list of doubles for each id
[1846]1253
[256]1254 """
[1819]1255 if ids is None:
1256 rfreqs={}
1257 idlist = self.getmolnos()
1258 for i in idlist:
1259 rfreqs[i]=list(self._getrestfreqs(i))
1260 return rfreqs
1261 else:
1262 if type(ids)==list or type(ids)==tuple:
1263 rfreqs={}
1264 for i in ids:
1265 rfreqs[i]=list(self._getrestfreqs(i))
1266 return rfreqs
1267 else:
1268 return list(self._getrestfreqs(ids))
1269 #return list(self._getrestfreqs(ids))
[102]1270
[931]1271 def set_restfreqs(self, freqs=None, unit='Hz'):
[1846]1272 """\
[931]1273 Set or replace the restfrequency specified and
1274 If the 'freqs' argument holds a scalar,
1275 then that rest frequency will be applied to all the selected
1276 data. If the 'freqs' argument holds
1277 a vector, then it MUST be of equal or smaller length than
1278 the number of IFs (and the available restfrequencies will be
1279 replaced by this vector). In this case, *all* data have
1280 the restfrequency set per IF according
1281 to the corresponding value you give in the 'freqs' vector.
[1118]1282 E.g. 'freqs=[1e9, 2e9]' would mean IF 0 gets restfreq 1e9 and
[931]1283 IF 1 gets restfreq 2e9.
[1846]1284
[1395]1285 You can also specify the frequencies via a linecatalog.
[1153]1286
[931]1287 Parameters:
[1846]1288
[931]1289 freqs: list of rest frequency values or string idenitfiers
[1855]1290
[931]1291 unit: unit for rest frequency (default 'Hz')
[402]1292
[1846]1293
1294 Example::
1295
[1819]1296 # set the given restfrequency for the all currently selected IFs
[931]1297 scan.set_restfreqs(freqs=1.4e9)
[1845]1298 # set restfrequencies for the n IFs (n > 1) in the order of the
1299 # list, i.e
1300 # IF0 -> 1.4e9, IF1 -> 1.41e9, IF3 -> 1.42e9
1301 # len(list_of_restfreqs) == nIF
1302 # for nIF == 1 the following will set multiple restfrequency for
1303 # that IF
[1819]1304 scan.set_restfreqs(freqs=[1.4e9, 1.41e9, 1.42e9])
[1845]1305 # set multiple restfrequencies per IF. as a list of lists where
1306 # the outer list has nIF elements, the inner s arbitrary
1307 scan.set_restfreqs(freqs=[[1.4e9, 1.41e9], [1.67e9]])
[391]1308
[1846]1309 *Note*:
[1845]1310
[931]1311 To do more sophisticate Restfrequency setting, e.g. on a
1312 source and IF basis, use scantable.set_selection() before using
[1846]1313 this function::
[931]1314
[1846]1315 # provided your scantable is called scan
1316 selection = selector()
1317 selection.set_name("ORION*")
1318 selection.set_ifs([1])
1319 scan.set_selection(selection)
1320 scan.set_restfreqs(freqs=86.6e9)
1321
[931]1322 """
1323 varlist = vars()
[1157]1324 from asap import linecatalog
1325 # simple value
[1118]1326 if isinstance(freqs, int) or isinstance(freqs, float):
[1845]1327 self._setrestfreqs([freqs], [""], unit)
[1157]1328 # list of values
[1118]1329 elif isinstance(freqs, list) or isinstance(freqs, tuple):
[1157]1330 # list values are scalars
[1118]1331 if isinstance(freqs[-1], int) or isinstance(freqs[-1], float):
[1845]1332 if len(freqs) == 1:
1333 self._setrestfreqs(freqs, [""], unit)
1334 else:
1335 # allow the 'old' mode of setting mulitple IFs
1336 sel = selector()
1337 savesel = self._getselection()
1338 iflist = self.getifnos()
1339 if len(freqs)>len(iflist):
1340 raise ValueError("number of elements in list of list "
1341 "exeeds the current IF selections")
1342 iflist = self.getifnos()
1343 for i, fval in enumerate(freqs):
1344 sel.set_ifs(iflist[i])
1345 self._setselection(sel)
1346 self._setrestfreqs([fval], [""], unit)
1347 self._setselection(savesel)
1348
1349 # list values are dict, {'value'=, 'name'=)
[1157]1350 elif isinstance(freqs[-1], dict):
[1845]1351 values = []
1352 names = []
1353 for d in freqs:
1354 values.append(d["value"])
1355 names.append(d["name"])
1356 self._setrestfreqs(values, names, unit)
[1819]1357 elif isinstance(freqs[-1], list) or isinstance(freqs[-1], tuple):
[1157]1358 sel = selector()
1359 savesel = self._getselection()
[1322]1360 iflist = self.getifnos()
[1819]1361 if len(freqs)>len(iflist):
[1845]1362 raise ValueError("number of elements in list of list exeeds"
1363 " the current IF selections")
1364 for i, fval in enumerate(freqs):
[1322]1365 sel.set_ifs(iflist[i])
[1259]1366 self._setselection(sel)
[1845]1367 self._setrestfreqs(fval, [""], unit)
[1157]1368 self._setselection(savesel)
1369 # freqs are to be taken from a linecatalog
[1153]1370 elif isinstance(freqs, linecatalog):
1371 sel = selector()
1372 savesel = self._getselection()
1373 for i in xrange(freqs.nrow()):
[1322]1374 sel.set_ifs(iflist[i])
[1153]1375 self._setselection(sel)
[1845]1376 self._setrestfreqs([freqs.get_frequency(i)],
1377 [freqs.get_name(i)], "MHz")
[1153]1378 # ensure that we are not iterating past nIF
1379 if i == self.nif()-1: break
1380 self._setselection(savesel)
[931]1381 else:
1382 return
1383 self._add_history("set_restfreqs", varlist)
1384
[1360]1385 def shift_refpix(self, delta):
[1846]1386 """\
[1589]1387 Shift the reference pixel of the Spectra Coordinate by an
1388 integer amount.
[1846]1389
[1589]1390 Parameters:
[1846]1391
[1589]1392 delta: the amount to shift by
[1846]1393
1394 *Note*:
1395
[1589]1396 Be careful using this with broadband data.
[1846]1397
[1360]1398 """
[1731]1399 Scantable.shift_refpix(self, delta)
[931]1400
[1862]1401 @asaplog_post_dec
[1259]1402 def history(self, filename=None):
[1846]1403 """\
[1259]1404 Print the history. Optionally to a file.
[1846]1405
[1348]1406 Parameters:
[1846]1407
[1348]1408 filename: The name of the file to save the history to.
[1846]1409
[1259]1410 """
[484]1411 hist = list(self._gethistory())
[794]1412 out = "-"*80
[484]1413 for h in hist:
[489]1414 if h.startswith("---"):
[1857]1415 out = "\n".join([out, h])
[489]1416 else:
1417 items = h.split("##")
1418 date = items[0]
1419 func = items[1]
1420 items = items[2:]
[794]1421 out += "\n"+date+"\n"
1422 out += "Function: %s\n Parameters:" % (func)
[489]1423 for i in items:
1424 s = i.split("=")
[1118]1425 out += "\n %s = %s" % (s[0], s[1])
[1857]1426 out = "\n".join([out, "-"*80])
[1259]1427 if filename is not None:
1428 if filename is "":
1429 filename = 'scantable_history.txt'
1430 import os
1431 filename = os.path.expandvars(os.path.expanduser(filename))
1432 if not os.path.isdir(filename):
1433 data = open(filename, 'w')
1434 data.write(out)
1435 data.close()
1436 else:
1437 msg = "Illegal file name '%s'." % (filename)
[1859]1438 raise IOError(msg)
1439 return page(out)
[513]1440 #
1441 # Maths business
1442 #
[1862]1443 @asaplog_post_dec
[931]1444 def average_time(self, mask=None, scanav=False, weight='tint', align=False):
[1846]1445 """\
[1070]1446 Return the (time) weighted average of a scan.
[1846]1447
1448 *Note*:
1449
[1070]1450 in channels only - align if necessary
[1846]1451
[513]1452 Parameters:
[1846]1453
[513]1454 mask: an optional mask (only used for 'var' and 'tsys'
1455 weighting)
[1855]1456
[558]1457 scanav: True averages each scan separately
1458 False (default) averages all scans together,
[1855]1459
[1099]1460 weight: Weighting scheme.
1461 'none' (mean no weight)
1462 'var' (1/var(spec) weighted)
1463 'tsys' (1/Tsys**2 weighted)
1464 'tint' (integration time weighted)
1465 'tintsys' (Tint/Tsys**2)
1466 'median' ( median averaging)
[535]1467 The default is 'tint'
[1855]1468
[931]1469 align: align the spectra in velocity before averaging. It takes
1470 the time of the first spectrum as reference time.
[1846]1471
1472 Example::
1473
[513]1474 # time average the scantable without using a mask
[710]1475 newscan = scan.average_time()
[1846]1476
[513]1477 """
1478 varlist = vars()
[1593]1479 weight = weight or 'TINT'
1480 mask = mask or ()
1481 scanav = (scanav and 'SCAN') or 'NONE'
[1118]1482 scan = (self, )
[1859]1483
1484 if align:
1485 scan = (self.freq_align(insitu=False), )
1486 s = None
1487 if weight.upper() == 'MEDIAN':
1488 s = scantable(self._math._averagechannel(scan[0], 'MEDIAN',
1489 scanav))
1490 else:
1491 s = scantable(self._math._average(scan, mask, weight.upper(),
1492 scanav))
[1099]1493 s._add_history("average_time", varlist)
[513]1494 return s
[710]1495
[1862]1496 @asaplog_post_dec
[876]1497 def convert_flux(self, jyperk=None, eta=None, d=None, insitu=None):
[1846]1498 """\
[513]1499 Return a scan where all spectra are converted to either
1500 Jansky or Kelvin depending upon the flux units of the scan table.
1501 By default the function tries to look the values up internally.
1502 If it can't find them (or if you want to over-ride), you must
1503 specify EITHER jyperk OR eta (and D which it will try to look up
1504 also if you don't set it). jyperk takes precedence if you set both.
[1846]1505
[513]1506 Parameters:
[1846]1507
[513]1508 jyperk: the Jy / K conversion factor
[1855]1509
[513]1510 eta: the aperture efficiency
[1855]1511
[513]1512 d: the geomtric diameter (metres)
[1855]1513
[513]1514 insitu: if False a new scantable is returned.
1515 Otherwise, the scaling is done in-situ
1516 The default is taken from .asaprc (False)
[1846]1517
[513]1518 """
1519 if insitu is None: insitu = rcParams['insitu']
[876]1520 self._math._setinsitu(insitu)
[513]1521 varlist = vars()
[1593]1522 jyperk = jyperk or -1.0
1523 d = d or -1.0
1524 eta = eta or -1.0
[876]1525 s = scantable(self._math._convertflux(self, d, eta, jyperk))
1526 s._add_history("convert_flux", varlist)
1527 if insitu: self._assign(s)
1528 else: return s
[513]1529
[1862]1530 @asaplog_post_dec
[876]1531 def gain_el(self, poly=None, filename="", method="linear", insitu=None):
[1846]1532 """\
[513]1533 Return a scan after applying a gain-elevation correction.
1534 The correction can be made via either a polynomial or a
1535 table-based interpolation (and extrapolation if necessary).
1536 You specify polynomial coefficients, an ascii table or neither.
1537 If you specify neither, then a polynomial correction will be made
1538 with built in coefficients known for certain telescopes (an error
1539 will occur if the instrument is not known).
1540 The data and Tsys are *divided* by the scaling factors.
[1846]1541
[513]1542 Parameters:
[1846]1543
[513]1544 poly: Polynomial coefficients (default None) to compute a
1545 gain-elevation correction as a function of
1546 elevation (in degrees).
[1855]1547
[513]1548 filename: The name of an ascii file holding correction factors.
1549 The first row of the ascii file must give the column
1550 names and these MUST include columns
1551 "ELEVATION" (degrees) and "FACTOR" (multiply data
1552 by this) somewhere.
1553 The second row must give the data type of the
1554 column. Use 'R' for Real and 'I' for Integer.
1555 An example file would be
1556 (actual factors are arbitrary) :
1557
1558 TIME ELEVATION FACTOR
1559 R R R
1560 0.1 0 0.8
1561 0.2 20 0.85
1562 0.3 40 0.9
1563 0.4 60 0.85
1564 0.5 80 0.8
1565 0.6 90 0.75
[1855]1566
[513]1567 method: Interpolation method when correcting from a table.
1568 Values are "nearest", "linear" (default), "cubic"
1569 and "spline"
[1855]1570
[513]1571 insitu: if False a new scantable is returned.
1572 Otherwise, the scaling is done in-situ
1573 The default is taken from .asaprc (False)
[1846]1574
[513]1575 """
1576
1577 if insitu is None: insitu = rcParams['insitu']
[876]1578 self._math._setinsitu(insitu)
[513]1579 varlist = vars()
[1593]1580 poly = poly or ()
[513]1581 from os.path import expandvars
1582 filename = expandvars(filename)
[876]1583 s = scantable(self._math._gainel(self, poly, filename, method))
1584 s._add_history("gain_el", varlist)
[1593]1585 if insitu:
1586 self._assign(s)
1587 else:
1588 return s
[710]1589
[1862]1590 @asaplog_post_dec
[931]1591 def freq_align(self, reftime=None, method='cubic', insitu=None):
[1846]1592 """\
[513]1593 Return a scan where all rows have been aligned in frequency/velocity.
1594 The alignment frequency frame (e.g. LSRK) is that set by function
1595 set_freqframe.
[1846]1596
[513]1597 Parameters:
[1855]1598
[513]1599 reftime: reference time to align at. By default, the time of
1600 the first row of data is used.
[1855]1601
[513]1602 method: Interpolation method for regridding the spectra.
1603 Choose from "nearest", "linear", "cubic" (default)
1604 and "spline"
[1855]1605
[513]1606 insitu: if False a new scantable is returned.
1607 Otherwise, the scaling is done in-situ
1608 The default is taken from .asaprc (False)
[1846]1609
[513]1610 """
[931]1611 if insitu is None: insitu = rcParams["insitu"]
[876]1612 self._math._setinsitu(insitu)
[513]1613 varlist = vars()
[1593]1614 reftime = reftime or ""
[931]1615 s = scantable(self._math._freq_align(self, reftime, method))
[876]1616 s._add_history("freq_align", varlist)
1617 if insitu: self._assign(s)
1618 else: return s
[513]1619
[1862]1620 @asaplog_post_dec
[1725]1621 def opacity(self, tau=None, insitu=None):
[1846]1622 """\
[513]1623 Apply an opacity correction. The data
1624 and Tsys are multiplied by the correction factor.
[1846]1625
[513]1626 Parameters:
[1855]1627
[1689]1628 tau: (list of) opacity from which the correction factor is
[513]1629 exp(tau*ZD)
[1689]1630 where ZD is the zenith-distance.
1631 If a list is provided, it has to be of length nIF,
1632 nIF*nPol or 1 and in order of IF/POL, e.g.
1633 [opif0pol0, opif0pol1, opif1pol0 ...]
[1725]1634 if tau is `None` the opacities are determined from a
1635 model.
[1855]1636
[513]1637 insitu: if False a new scantable is returned.
1638 Otherwise, the scaling is done in-situ
1639 The default is taken from .asaprc (False)
[1846]1640
[513]1641 """
1642 if insitu is None: insitu = rcParams['insitu']
[876]1643 self._math._setinsitu(insitu)
[513]1644 varlist = vars()
[1689]1645 if not hasattr(tau, "__len__"):
1646 tau = [tau]
[876]1647 s = scantable(self._math._opacity(self, tau))
1648 s._add_history("opacity", varlist)
1649 if insitu: self._assign(s)
1650 else: return s
[513]1651
[1862]1652 @asaplog_post_dec
[513]1653 def bin(self, width=5, insitu=None):
[1846]1654 """\
[513]1655 Return a scan where all spectra have been binned up.
[1846]1656
[1348]1657 Parameters:
[1846]1658
[513]1659 width: The bin width (default=5) in pixels
[1855]1660
[513]1661 insitu: if False a new scantable is returned.
1662 Otherwise, the scaling is done in-situ
1663 The default is taken from .asaprc (False)
[1846]1664
[513]1665 """
1666 if insitu is None: insitu = rcParams['insitu']
[876]1667 self._math._setinsitu(insitu)
[513]1668 varlist = vars()
[876]1669 s = scantable(self._math._bin(self, width))
[1118]1670 s._add_history("bin", varlist)
[1589]1671 if insitu:
1672 self._assign(s)
1673 else:
1674 return s
[513]1675
[1862]1676 @asaplog_post_dec
[513]1677 def resample(self, width=5, method='cubic', insitu=None):
[1846]1678 """\
[1348]1679 Return a scan where all spectra have been binned up.
[1573]1680
[1348]1681 Parameters:
[1846]1682
[513]1683 width: The bin width (default=5) in pixels
[1855]1684
[513]1685 method: Interpolation method when correcting from a table.
1686 Values are "nearest", "linear", "cubic" (default)
1687 and "spline"
[1855]1688
[513]1689 insitu: if False a new scantable is returned.
1690 Otherwise, the scaling is done in-situ
1691 The default is taken from .asaprc (False)
[1846]1692
[513]1693 """
1694 if insitu is None: insitu = rcParams['insitu']
[876]1695 self._math._setinsitu(insitu)
[513]1696 varlist = vars()
[876]1697 s = scantable(self._math._resample(self, method, width))
[1118]1698 s._add_history("resample", varlist)
[876]1699 if insitu: self._assign(s)
1700 else: return s
[513]1701
[1862]1702 @asaplog_post_dec
[946]1703 def average_pol(self, mask=None, weight='none'):
[1846]1704 """\
[946]1705 Average the Polarisations together.
[1846]1706
[946]1707 Parameters:
[1846]1708
[946]1709 mask: An optional mask defining the region, where the
1710 averaging will be applied. The output will have all
1711 specified points masked.
[1855]1712
[946]1713 weight: Weighting scheme. 'none' (default), 'var' (1/var(spec)
1714 weighted), or 'tsys' (1/Tsys**2 weighted)
[1846]1715
[946]1716 """
1717 varlist = vars()
[1593]1718 mask = mask or ()
[1010]1719 s = scantable(self._math._averagepol(self, mask, weight.upper()))
[1118]1720 s._add_history("average_pol", varlist)
[992]1721 return s
[513]1722
[1862]1723 @asaplog_post_dec
[1145]1724 def average_beam(self, mask=None, weight='none'):
[1846]1725 """\
[1145]1726 Average the Beams together.
[1846]1727
[1145]1728 Parameters:
1729 mask: An optional mask defining the region, where the
1730 averaging will be applied. The output will have all
1731 specified points masked.
[1855]1732
[1145]1733 weight: Weighting scheme. 'none' (default), 'var' (1/var(spec)
1734 weighted), or 'tsys' (1/Tsys**2 weighted)
[1846]1735
[1145]1736 """
1737 varlist = vars()
[1593]1738 mask = mask or ()
[1145]1739 s = scantable(self._math._averagebeams(self, mask, weight.upper()))
1740 s._add_history("average_beam", varlist)
1741 return s
1742
[1586]1743 def parallactify(self, pflag):
[1846]1744 """\
[1843]1745 Set a flag to indicate whether this data should be treated as having
[1617]1746 been 'parallactified' (total phase == 0.0)
[1846]1747
[1617]1748 Parameters:
[1855]1749
[1843]1750 pflag: Bool indicating whether to turn this on (True) or
[1617]1751 off (False)
[1846]1752
[1617]1753 """
[1586]1754 varlist = vars()
1755 self._parallactify(pflag)
1756 self._add_history("parallactify", varlist)
1757
[1862]1758 @asaplog_post_dec
[992]1759 def convert_pol(self, poltype=None):
[1846]1760 """\
[992]1761 Convert the data to a different polarisation type.
[1565]1762 Note that you will need cross-polarisation terms for most conversions.
[1846]1763
[992]1764 Parameters:
[1855]1765
[992]1766 poltype: The new polarisation type. Valid types are:
[1565]1767 "linear", "circular", "stokes" and "linpol"
[1846]1768
[992]1769 """
1770 varlist = vars()
[1859]1771 s = scantable(self._math._convertpol(self, poltype))
[1118]1772 s._add_history("convert_pol", varlist)
[992]1773 return s
1774
[1862]1775 @asaplog_post_dec
[1819]1776 def smooth(self, kernel="hanning", width=5.0, order=2, plot=False, insitu=None):
[1846]1777 """\
[513]1778 Smooth the spectrum by the specified kernel (conserving flux).
[1846]1779
[513]1780 Parameters:
[1846]1781
[513]1782 kernel: The type of smoothing kernel. Select from
[1574]1783 'hanning' (default), 'gaussian', 'boxcar', 'rmedian'
1784 or 'poly'
[1855]1785
[513]1786 width: The width of the kernel in pixels. For hanning this is
1787 ignored otherwise it defauls to 5 pixels.
1788 For 'gaussian' it is the Full Width Half
1789 Maximum. For 'boxcar' it is the full width.
[1574]1790 For 'rmedian' and 'poly' it is the half width.
[1855]1791
[1574]1792 order: Optional parameter for 'poly' kernel (default is 2), to
1793 specify the order of the polnomial. Ignored by all other
1794 kernels.
[1855]1795
[1819]1796 plot: plot the original and the smoothed spectra.
1797 In this each indivual fit has to be approved, by
1798 typing 'y' or 'n'
[1855]1799
[513]1800 insitu: if False a new scantable is returned.
1801 Otherwise, the scaling is done in-situ
1802 The default is taken from .asaprc (False)
[1846]1803
[513]1804 """
1805 if insitu is None: insitu = rcParams['insitu']
[876]1806 self._math._setinsitu(insitu)
[513]1807 varlist = vars()
[1819]1808
1809 if plot: orgscan = self.copy()
1810
[1574]1811 s = scantable(self._math._smooth(self, kernel.lower(), width, order))
[876]1812 s._add_history("smooth", varlist)
[1819]1813
1814 if plot:
1815 if rcParams['plotter.gui']:
1816 from asap.asaplotgui import asaplotgui as asaplot
1817 else:
1818 from asap.asaplot import asaplot
1819 self._p=asaplot()
1820 self._p.set_panels()
1821 ylab=s._get_ordinate_label()
1822 #self._p.palette(0,["#777777","red"])
1823 for r in xrange(s.nrow()):
1824 xsm=s._getabcissa(r)
1825 ysm=s._getspectrum(r)
1826 xorg=orgscan._getabcissa(r)
1827 yorg=orgscan._getspectrum(r)
1828 self._p.clear()
1829 self._p.hold()
1830 self._p.set_axes('ylabel',ylab)
1831 self._p.set_axes('xlabel',s._getabcissalabel(r))
1832 self._p.set_axes('title',s._getsourcename(r))
1833 self._p.set_line(label='Original',color="#777777")
1834 self._p.plot(xorg,yorg)
1835 self._p.set_line(label='Smoothed',color="red")
1836 self._p.plot(xsm,ysm)
1837 ### Ugly part for legend
1838 for i in [0,1]:
1839 self._p.subplots[0]['lines'].append([self._p.subplots[0]['axes'].lines[i]])
1840 self._p.release()
1841 ### Ugly part for legend
1842 self._p.subplots[0]['lines']=[]
1843 res = raw_input("Accept smoothing ([y]/n): ")
1844 if res.upper() == 'N':
1845 s._setspectrum(yorg, r)
1846 self._p.unmap()
1847 self._p = None
1848 del orgscan
1849
[876]1850 if insitu: self._assign(s)
1851 else: return s
[513]1852
[1862]1853 @asaplog_post_dec
[1907]1854 def old_poly_baseline(self, mask=None, order=0, plot=False, uselin=False, insitu=None, rows=None):
[1846]1855 """\
[513]1856 Return a scan which has been baselined (all rows) by a polynomial.
[1907]1857
[513]1858 Parameters:
[1846]1859
[794]1860 mask: an optional mask
[1855]1861
[794]1862 order: the order of the polynomial (default is 0)
[1855]1863
[1061]1864 plot: plot the fit and the residual. In this each
1865 indivual fit has to be approved, by typing 'y'
1866 or 'n'
[1855]1867
[1391]1868 uselin: use linear polynomial fit
[1855]1869
[794]1870 insitu: if False a new scantable is returned.
1871 Otherwise, the scaling is done in-situ
1872 The default is taken from .asaprc (False)
[1846]1873
[1907]1874 rows: row numbers of spectra to be processed.
1875 (default is None: for all rows)
1876
1877 Example:
[513]1878 # return a scan baselined by a third order polynomial,
1879 # not using a mask
1880 bscan = scan.poly_baseline(order=3)
[1846]1881
[579]1882 """
[513]1883 if insitu is None: insitu = rcParams['insitu']
[1819]1884 if not insitu:
1885 workscan = self.copy()
1886 else:
1887 workscan = self
[513]1888 varlist = vars()
1889 if mask is None:
[1907]1890 mask = [True for i in xrange(self.nchan())]
[1819]1891
[1217]1892 try:
1893 f = fitter()
[1391]1894 if uselin:
1895 f.set_function(lpoly=order)
1896 else:
1897 f.set_function(poly=order)
[1819]1898
[1907]1899 if rows == None:
1900 rows = xrange(workscan.nrow())
1901 elif isinstance(rows, int):
1902 rows = [ rows ]
1903
[1819]1904 if len(rows) > 0:
1905 self.blpars = []
[1907]1906 self.masklists = []
1907 self.actualmask = []
1908
[1819]1909 for r in rows:
1910 f.x = workscan._getabcissa(r)
1911 f.y = workscan._getspectrum(r)
[1907]1912 f.mask = mask_and(mask, workscan._getmask(r)) # (CAS-1434)
[1819]1913 f.data = None
1914 f.fit()
1915 if plot:
1916 f.plot(residual=True)
1917 x = raw_input("Accept fit ( [y]/n ): ")
1918 if x.upper() == 'N':
1919 self.blpars.append(None)
[1907]1920 self.masklists.append(None)
1921 self.actualmask.append(None)
[1819]1922 continue
1923 workscan._setspectrum(f.fitter.getresidual(), r)
1924 self.blpars.append(f.get_parameters())
[1907]1925 self.masklists.append(workscan.get_masklist(f.mask, row=r))
1926 self.actualmask.append(f.mask)
[1819]1927
1928 if plot:
1929 f._p.unmap()
1930 f._p = None
1931 workscan._add_history("poly_baseline", varlist)
[1856]1932 if insitu:
1933 self._assign(workscan)
1934 else:
1935 return workscan
[1217]1936 except RuntimeError:
1937 msg = "The fit failed, possibly because it didn't converge."
[1859]1938 raise RuntimeError(msg)
[513]1939
[1819]1940
[1907]1941 def poly_baseline(self, mask=None, order=0, plot=False, batch=False, insitu=None, rows=None):
1942 """\
1943 Return a scan which has been baselined (all rows) by a polynomial.
1944 Parameters:
1945 mask: an optional mask
1946 order: the order of the polynomial (default is 0)
1947 plot: plot the fit and the residual. In this each
1948 indivual fit has to be approved, by typing 'y'
1949 or 'n'. Ignored if batch = True.
1950 batch: if True a faster algorithm is used and logs
1951 including the fit results are not output
1952 (default is False)
1953 insitu: if False a new scantable is returned.
1954 Otherwise, the scaling is done in-situ
1955 The default is taken from .asaprc (False)
1956 rows: row numbers of spectra to be processed.
1957 (default is None: for all rows)
1958 Example:
1959 # return a scan baselined by a third order polynomial,
1960 # not using a mask
1961 bscan = scan.poly_baseline(order=3)
1962 """
1963 if insitu is None: insitu = rcParams["insitu"]
1964 if insitu:
1965 workscan = self
1966 else:
1967 workscan = self.copy()
1968
1969 varlist = vars()
1970 nchan = workscan.nchan()
1971
1972 if mask is None:
1973 mask = [True for i in xrange(nchan)]
1974
1975 try:
1976 if rows == None:
1977 rows = xrange(workscan.nrow())
1978 elif isinstance(rows, int):
1979 rows = [ rows ]
1980
1981 if len(rows) > 0:
1982 self.blpars = []
1983 self.masklists = []
1984 self.actualmask = []
1985
1986 if batch:
1987 for r in rows:
[1908]1988 workscan._poly_baseline_batch(mask, order, r)
[1907]1989 elif plot:
1990 f = fitter()
1991 f.set_function(lpoly=order)
1992 for r in rows:
1993 f.x = workscan._getabcissa(r)
1994 f.y = workscan._getspectrum(r)
1995 f.mask = mask_and(mask, workscan._getmask(r)) # (CAS-1434)
1996 f.data = None
1997 f.fit()
1998
1999 f.plot(residual=True)
2000 accept_fit = raw_input("Accept fit ( [y]/n ): ")
2001 if accept_fit.upper() == "N":
2002 self.blpars.append(None)
2003 self.masklists.append(None)
2004 self.actualmask.append(None)
2005 continue
2006 workscan._setspectrum(f.fitter.getresidual(), r)
2007 self.blpars.append(f.get_parameters())
2008 self.masklists.append(workscan.get_masklist(f.mask, row=r))
2009 self.actualmask.append(f.mask)
2010
2011 f._p.unmap()
2012 f._p = None
2013 else:
2014 import array
2015 for r in rows:
2016 pars = array.array("f", [0.0 for i in range(order+1)])
2017 pars_adr = pars.buffer_info()[0]
2018 pars_len = pars.buffer_info()[1]
2019
2020 errs = array.array("f", [0.0 for i in range(order+1)])
2021 errs_adr = errs.buffer_info()[0]
2022 errs_len = errs.buffer_info()[1]
2023
2024 fmsk = array.array("i", [1 for i in range(nchan)])
2025 fmsk_adr = fmsk.buffer_info()[0]
2026 fmsk_len = fmsk.buffer_info()[1]
2027
2028 workscan._poly_baseline(mask, order, r, pars_adr, pars_len, errs_adr, errs_len, fmsk_adr, fmsk_len)
2029
2030 params = pars.tolist()
2031 fmtd = ""
2032 for i in xrange(len(params)): fmtd += " p%d= %3.6f," % (i, params[i])
2033 fmtd = fmtd[:-1] # remove trailing ","
2034 errors = errs.tolist()
2035 fmask = fmsk.tolist()
2036 for i in xrange(len(fmask)): fmask[i] = (fmask[i] > 0) # transform (1/0) -> (True/False)
2037
2038 self.blpars.append({"params":params, "fixed":[], "formatted":fmtd, "errors":errors})
2039 self.masklists.append(workscan.get_masklist(fmask, r))
2040 self.actualmask.append(fmask)
2041
2042 asaplog.push(str(fmtd))
2043
2044 workscan._add_history("poly_baseline", varlist)
2045
2046 if insitu:
2047 self._assign(workscan)
2048 else:
2049 return workscan
2050
2051 except RuntimeError:
2052 msg = "The fit failed, possibly because it didn't converge."
2053 if rcParams["verbose"]:
2054 asaplog.push(str(msg))
2055 return
2056 else:
2057 raise RuntimeError(msg)
2058
2059
2060 def auto_poly_baseline(self, mask=None, edge=(0, 0), order=0,
[1280]2061 threshold=3, chan_avg_limit=1, plot=False,
[1907]2062 insitu=None, rows=None):
[1846]2063 """\
[880]2064 Return a scan which has been baselined (all rows) by a polynomial.
2065 Spectral lines are detected first using linefinder and masked out
2066 to avoid them affecting the baseline solution.
2067
2068 Parameters:
[1846]2069
[880]2070 mask: an optional mask retreived from scantable
[1846]2071
2072 edge: an optional number of channel to drop at the edge of
2073 spectrum. If only one value is
[880]2074 specified, the same number will be dropped from
2075 both sides of the spectrum. Default is to keep
[907]2076 all channels. Nested tuples represent individual
[976]2077 edge selection for different IFs (a number of spectral
2078 channels can be different)
[1846]2079
[880]2080 order: the order of the polynomial (default is 0)
[1846]2081
[880]2082 threshold: the threshold used by line finder. It is better to
2083 keep it large as only strong lines affect the
2084 baseline solution.
[1846]2085
[1280]2086 chan_avg_limit:
2087 a maximum number of consequtive spectral channels to
2088 average during the search of weak and broad lines.
2089 The default is no averaging (and no search for weak
2090 lines). If such lines can affect the fitted baseline
2091 (e.g. a high order polynomial is fitted), increase this
2092 parameter (usually values up to 8 are reasonable). Most
2093 users of this method should find the default value
2094 sufficient.
[1846]2095
[1061]2096 plot: plot the fit and the residual. In this each
2097 indivual fit has to be approved, by typing 'y'
2098 or 'n'
[1846]2099
[880]2100 insitu: if False a new scantable is returned.
2101 Otherwise, the scaling is done in-situ
2102 The default is taken from .asaprc (False)
[1907]2103 rows: row numbers of spectra to be processed.
2104 (default is None: for all rows)
[880]2105
[1846]2106
2107 Example::
2108
2109 scan2 = scan.auto_poly_baseline(order=7, insitu=False)
2110
[880]2111 """
2112 if insitu is None: insitu = rcParams['insitu']
2113 varlist = vars()
2114 from asap.asaplinefind import linefinder
2115 from asap import _is_sequence_or_number as _is_valid
2116
[976]2117 # check whether edge is set up for each IF individually
[1118]2118 individualedge = False;
2119 if len(edge) > 1:
2120 if isinstance(edge[0], list) or isinstance(edge[0], tuple):
2121 individualedge = True;
[907]2122
[1118]2123 if not _is_valid(edge, int) and not individualedge:
[909]2124 raise ValueError, "Parameter 'edge' has to be an integer or a \
[907]2125 pair of integers specified as a tuple. Nested tuples are allowed \
2126 to make individual selection for different IFs."
[919]2127
[1118]2128 curedge = (0, 0)
2129 if individualedge:
2130 for edgepar in edge:
2131 if not _is_valid(edgepar, int):
2132 raise ValueError, "Each element of the 'edge' tuple has \
2133 to be a pair of integers or an integer."
[907]2134 else:
[1118]2135 curedge = edge;
[880]2136
[1907]2137 if not insitu:
2138 workscan = self.copy()
2139 else:
2140 workscan = self
2141
[880]2142 # setup fitter
2143 f = fitter()
[1907]2144 f.set_function(lpoly=order)
[880]2145
2146 # setup line finder
[1118]2147 fl = linefinder()
[1268]2148 fl.set_options(threshold=threshold,avg_limit=chan_avg_limit)
[880]2149
[907]2150 fl.set_scan(workscan)
2151
[1907]2152 if mask is None:
2153 mask = _n_bools(workscan.nchan(), True)
2154
2155 if rows is None:
2156 rows = xrange(workscan.nrow())
2157 elif isinstance(rows, int):
2158 rows = [ rows ]
2159
[1819]2160 # Save parameters of baseline fits & masklists as a class attribute.
2161 # NOTICE: It does not reflect changes in scantable!
2162 if len(rows) > 0:
2163 self.blpars=[]
2164 self.masklists=[]
[1907]2165 self.actualmask=[]
[880]2166 asaplog.push("Processing:")
2167 for r in rows:
[1118]2168 msg = " Scan[%d] Beam[%d] IF[%d] Pol[%d] Cycle[%d]" % \
2169 (workscan.getscan(r), workscan.getbeam(r), workscan.getif(r), \
2170 workscan.getpol(r), workscan.getcycle(r))
[880]2171 asaplog.push(msg, False)
[907]2172
[976]2173 # figure out edge parameter
[1118]2174 if individualedge:
2175 if len(edge) >= workscan.getif(r):
2176 raise RuntimeError, "Number of edge elements appear to " \
2177 "be less than the number of IFs"
2178 curedge = edge[workscan.getif(r)]
[919]2179
[1907]2180 actualmask = mask_and(mask, workscan._getmask(r)) # (CAS-1434)
[1819]2181
[976]2182 # setup line finder
[1819]2183 fl.find_lines(r, actualmask, curedge)
[1907]2184
[1819]2185 f.x = workscan._getabcissa(r)
2186 f.y = workscan._getspectrum(r)
[1907]2187 f.mask = fl.get_mask()
[1819]2188 f.data = None
[880]2189 f.fit()
[1819]2190
2191 # Show mask list
[1907]2192 masklist=workscan.get_masklist(f.mask, row=r)
[1819]2193 msg = "mask range: "+str(masklist)
2194 asaplog.push(msg, False)
2195
[1061]2196 if plot:
2197 f.plot(residual=True)
2198 x = raw_input("Accept fit ( [y]/n ): ")
2199 if x.upper() == 'N':
[1819]2200 self.blpars.append(None)
2201 self.masklists.append(None)
[1907]2202 self.actualmask.append(None)
[1061]2203 continue
[1819]2204
[880]2205 workscan._setspectrum(f.fitter.getresidual(), r)
[1819]2206 self.blpars.append(f.get_parameters())
2207 self.masklists.append(masklist)
[1907]2208 self.actualmask.append(f.mask)
[1061]2209 if plot:
2210 f._p.unmap()
2211 f._p = None
2212 workscan._add_history("auto_poly_baseline", varlist)
[880]2213 if insitu:
2214 self._assign(workscan)
2215 else:
2216 return workscan
2217
[1862]2218 @asaplog_post_dec
[914]2219 def rotate_linpolphase(self, angle):
[1846]2220 """\
[914]2221 Rotate the phase of the complex polarization O=Q+iU correlation.
2222 This is always done in situ in the raw data. So if you call this
2223 function more than once then each call rotates the phase further.
[1846]2224
[914]2225 Parameters:
[1846]2226
[914]2227 angle: The angle (degrees) to rotate (add) by.
[1846]2228
2229 Example::
2230
[914]2231 scan.rotate_linpolphase(2.3)
[1846]2232
[914]2233 """
2234 varlist = vars()
[936]2235 self._math._rotate_linpolphase(self, angle)
[914]2236 self._add_history("rotate_linpolphase", varlist)
2237 return
[710]2238
[1862]2239 @asaplog_post_dec
[914]2240 def rotate_xyphase(self, angle):
[1846]2241 """\
[914]2242 Rotate the phase of the XY correlation. This is always done in situ
2243 in the data. So if you call this function more than once
2244 then each call rotates the phase further.
[1846]2245
[914]2246 Parameters:
[1846]2247
[914]2248 angle: The angle (degrees) to rotate (add) by.
[1846]2249
2250 Example::
2251
[914]2252 scan.rotate_xyphase(2.3)
[1846]2253
[914]2254 """
2255 varlist = vars()
[936]2256 self._math._rotate_xyphase(self, angle)
[914]2257 self._add_history("rotate_xyphase", varlist)
2258 return
2259
[1862]2260 @asaplog_post_dec
[914]2261 def swap_linears(self):
[1846]2262 """\
[1573]2263 Swap the linear polarisations XX and YY, or better the first two
[1348]2264 polarisations as this also works for ciculars.
[914]2265 """
2266 varlist = vars()
[936]2267 self._math._swap_linears(self)
[914]2268 self._add_history("swap_linears", varlist)
2269 return
2270
[1862]2271 @asaplog_post_dec
[914]2272 def invert_phase(self):
[1846]2273 """\
[914]2274 Invert the phase of the complex polarisation
2275 """
2276 varlist = vars()
[936]2277 self._math._invert_phase(self)
[914]2278 self._add_history("invert_phase", varlist)
2279 return
2280
[1862]2281 @asaplog_post_dec
[876]2282 def add(self, offset, insitu=None):
[1846]2283 """\
[513]2284 Return a scan where all spectra have the offset added
[1846]2285
[513]2286 Parameters:
[1846]2287
[513]2288 offset: the offset
[1855]2289
[513]2290 insitu: if False a new scantable is returned.
2291 Otherwise, the scaling is done in-situ
2292 The default is taken from .asaprc (False)
[1846]2293
[513]2294 """
2295 if insitu is None: insitu = rcParams['insitu']
[876]2296 self._math._setinsitu(insitu)
[513]2297 varlist = vars()
[876]2298 s = scantable(self._math._unaryop(self, offset, "ADD", False))
[1118]2299 s._add_history("add", varlist)
[876]2300 if insitu:
2301 self._assign(s)
2302 else:
[513]2303 return s
2304
[1862]2305 @asaplog_post_dec
[1308]2306 def scale(self, factor, tsys=True, insitu=None):
[1846]2307 """\
2308
[513]2309 Return a scan where all spectra are scaled by the give 'factor'
[1846]2310
[513]2311 Parameters:
[1846]2312
[1819]2313 factor: the scaling factor (float or 1D float list)
[1855]2314
[513]2315 insitu: if False a new scantable is returned.
2316 Otherwise, the scaling is done in-situ
2317 The default is taken from .asaprc (False)
[1855]2318
[513]2319 tsys: if True (default) then apply the operation to Tsys
2320 as well as the data
[1846]2321
[513]2322 """
2323 if insitu is None: insitu = rcParams['insitu']
[876]2324 self._math._setinsitu(insitu)
[513]2325 varlist = vars()
[1819]2326 s = None
2327 import numpy
2328 if isinstance(factor, list) or isinstance(factor, numpy.ndarray):
2329 if isinstance(factor[0], list) or isinstance(factor[0], numpy.ndarray):
2330 from asapmath import _array2dOp
2331 s = _array2dOp( self.copy(), factor, "MUL", tsys )
2332 else:
2333 s = scantable( self._math._arrayop( self.copy(), factor, "MUL", tsys ) )
2334 else:
2335 s = scantable(self._math._unaryop(self.copy(), factor, "MUL", tsys))
[1118]2336 s._add_history("scale", varlist)
[876]2337 if insitu:
2338 self._assign(s)
2339 else:
[513]2340 return s
2341
[1504]2342 def set_sourcetype(self, match, matchtype="pattern",
2343 sourcetype="reference"):
[1846]2344 """\
[1502]2345 Set the type of the source to be an source or reference scan
[1846]2346 using the provided pattern.
2347
[1502]2348 Parameters:
[1846]2349
[1504]2350 match: a Unix style pattern, regular expression or selector
[1855]2351
[1504]2352 matchtype: 'pattern' (default) UNIX style pattern or
2353 'regex' regular expression
[1855]2354
[1502]2355 sourcetype: the type of the source to use (source/reference)
[1846]2356
[1502]2357 """
2358 varlist = vars()
2359 basesel = self.get_selection()
2360 stype = -1
2361 if sourcetype.lower().startswith("r"):
2362 stype = 1
2363 elif sourcetype.lower().startswith("s"):
2364 stype = 0
[1504]2365 else:
[1502]2366 raise ValueError("Illegal sourcetype use s(ource) or r(eference)")
[1504]2367 if matchtype.lower().startswith("p"):
2368 matchtype = "pattern"
2369 elif matchtype.lower().startswith("r"):
2370 matchtype = "regex"
2371 else:
2372 raise ValueError("Illegal matchtype, use p(attern) or r(egex)")
[1502]2373 sel = selector()
2374 if isinstance(match, selector):
2375 sel = match
2376 else:
[1504]2377 sel.set_query("SRCNAME == %s('%s')" % (matchtype, match))
[1502]2378 self.set_selection(basesel+sel)
2379 self._setsourcetype(stype)
2380 self.set_selection(basesel)
[1573]2381 self._add_history("set_sourcetype", varlist)
[1502]2382
[1862]2383 @asaplog_post_dec
[1857]2384 @preserve_selection
[1819]2385 def auto_quotient(self, preserve=True, mode='paired', verify=False):
[1846]2386 """\
[670]2387 This function allows to build quotients automatically.
[1819]2388 It assumes the observation to have the same number of
[670]2389 "ons" and "offs"
[1846]2390
[670]2391 Parameters:
[1846]2392
[710]2393 preserve: you can preserve (default) the continuum or
2394 remove it. The equations used are
[1857]2395
[670]2396 preserve: Output = Toff * (on/off) - Toff
[1857]2397
[1070]2398 remove: Output = Toff * (on/off) - Ton
[1855]2399
[1573]2400 mode: the on/off detection mode
[1348]2401 'paired' (default)
2402 identifies 'off' scans by the
2403 trailing '_R' (Mopra/Parkes) or
2404 '_e'/'_w' (Tid) and matches
2405 on/off pairs from the observing pattern
[1502]2406 'time'
2407 finds the closest off in time
[1348]2408
[1857]2409 .. todo:: verify argument is not implemented
2410
[670]2411 """
[1857]2412 varlist = vars()
[1348]2413 modes = ["time", "paired"]
[670]2414 if not mode in modes:
[876]2415 msg = "please provide valid mode. Valid modes are %s" % (modes)
2416 raise ValueError(msg)
[1348]2417 s = None
2418 if mode.lower() == "paired":
[1857]2419 sel = self.get_selection()
[1875]2420 sel.set_query("SRCTYPE==psoff")
[1356]2421 self.set_selection(sel)
[1348]2422 offs = self.copy()
[1875]2423 sel.set_query("SRCTYPE==pson")
[1356]2424 self.set_selection(sel)
[1348]2425 ons = self.copy()
2426 s = scantable(self._math._quotient(ons, offs, preserve))
2427 elif mode.lower() == "time":
2428 s = scantable(self._math._auto_quotient(self, mode, preserve))
[1118]2429 s._add_history("auto_quotient", varlist)
[876]2430 return s
[710]2431
[1862]2432 @asaplog_post_dec
[1145]2433 def mx_quotient(self, mask = None, weight='median', preserve=True):
[1846]2434 """\
[1143]2435 Form a quotient using "off" beams when observing in "MX" mode.
[1846]2436
[1143]2437 Parameters:
[1846]2438
[1145]2439 mask: an optional mask to be used when weight == 'stddev'
[1855]2440
[1143]2441 weight: How to average the off beams. Default is 'median'.
[1855]2442
[1145]2443 preserve: you can preserve (default) the continuum or
[1855]2444 remove it. The equations used are:
[1846]2445
[1855]2446 preserve: Output = Toff * (on/off) - Toff
2447
2448 remove: Output = Toff * (on/off) - Ton
2449
[1217]2450 """
[1593]2451 mask = mask or ()
[1141]2452 varlist = vars()
2453 on = scantable(self._math._mx_extract(self, 'on'))
[1143]2454 preoff = scantable(self._math._mx_extract(self, 'off'))
2455 off = preoff.average_time(mask=mask, weight=weight, scanav=False)
[1217]2456 from asapmath import quotient
[1145]2457 q = quotient(on, off, preserve)
[1143]2458 q._add_history("mx_quotient", varlist)
[1217]2459 return q
[513]2460
[1862]2461 @asaplog_post_dec
[718]2462 def freq_switch(self, insitu=None):
[1846]2463 """\
[718]2464 Apply frequency switching to the data.
[1846]2465
[718]2466 Parameters:
[1846]2467
[718]2468 insitu: if False a new scantable is returned.
2469 Otherwise, the swictching is done in-situ
2470 The default is taken from .asaprc (False)
[1846]2471
[718]2472 """
2473 if insitu is None: insitu = rcParams['insitu']
[876]2474 self._math._setinsitu(insitu)
[718]2475 varlist = vars()
[876]2476 s = scantable(self._math._freqswitch(self))
[1118]2477 s._add_history("freq_switch", varlist)
[1856]2478 if insitu:
2479 self._assign(s)
2480 else:
2481 return s
[718]2482
[1862]2483 @asaplog_post_dec
[780]2484 def recalc_azel(self):
[1846]2485 """Recalculate the azimuth and elevation for each position."""
[780]2486 varlist = vars()
[876]2487 self._recalcazel()
[780]2488 self._add_history("recalc_azel", varlist)
2489 return
2490
[1862]2491 @asaplog_post_dec
[513]2492 def __add__(self, other):
2493 varlist = vars()
2494 s = None
2495 if isinstance(other, scantable):
[1573]2496 s = scantable(self._math._binaryop(self, other, "ADD"))
[513]2497 elif isinstance(other, float):
[876]2498 s = scantable(self._math._unaryop(self, other, "ADD", False))
[513]2499 else:
[718]2500 raise TypeError("Other input is not a scantable or float value")
[513]2501 s._add_history("operator +", varlist)
2502 return s
2503
[1862]2504 @asaplog_post_dec
[513]2505 def __sub__(self, other):
2506 """
2507 implicit on all axes and on Tsys
2508 """
2509 varlist = vars()
2510 s = None
2511 if isinstance(other, scantable):
[1588]2512 s = scantable(self._math._binaryop(self, other, "SUB"))
[513]2513 elif isinstance(other, float):
[876]2514 s = scantable(self._math._unaryop(self, other, "SUB", False))
[513]2515 else:
[718]2516 raise TypeError("Other input is not a scantable or float value")
[513]2517 s._add_history("operator -", varlist)
2518 return s
[710]2519
[1862]2520 @asaplog_post_dec
[513]2521 def __mul__(self, other):
2522 """
2523 implicit on all axes and on Tsys
2524 """
2525 varlist = vars()
2526 s = None
2527 if isinstance(other, scantable):
[1588]2528 s = scantable(self._math._binaryop(self, other, "MUL"))
[513]2529 elif isinstance(other, float):
[876]2530 s = scantable(self._math._unaryop(self, other, "MUL", False))
[513]2531 else:
[718]2532 raise TypeError("Other input is not a scantable or float value")
[513]2533 s._add_history("operator *", varlist)
2534 return s
2535
[710]2536
[1862]2537 @asaplog_post_dec
[513]2538 def __div__(self, other):
2539 """
2540 implicit on all axes and on Tsys
2541 """
2542 varlist = vars()
2543 s = None
2544 if isinstance(other, scantable):
[1589]2545 s = scantable(self._math._binaryop(self, other, "DIV"))
[513]2546 elif isinstance(other, float):
2547 if other == 0.0:
[718]2548 raise ZeroDivisionError("Dividing by zero is not recommended")
[876]2549 s = scantable(self._math._unaryop(self, other, "DIV", False))
[513]2550 else:
[718]2551 raise TypeError("Other input is not a scantable or float value")
[513]2552 s._add_history("operator /", varlist)
2553 return s
2554
[1862]2555 @asaplog_post_dec
[530]2556 def get_fit(self, row=0):
[1846]2557 """\
[530]2558 Print or return the stored fits for a row in the scantable
[1846]2559
[530]2560 Parameters:
[1846]2561
[530]2562 row: the row which the fit has been applied to.
[1846]2563
[530]2564 """
2565 if row > self.nrow():
2566 return
[976]2567 from asap.asapfit import asapfit
[530]2568 fit = asapfit(self._getfit(row))
[1859]2569 asaplog.push( '%s' %(fit) )
2570 return fit.as_dict()
[530]2571
[1483]2572 def flag_nans(self):
[1846]2573 """\
[1483]2574 Utility function to flag NaN values in the scantable.
2575 """
2576 import numpy
2577 basesel = self.get_selection()
2578 for i in range(self.nrow()):
[1589]2579 sel = self.get_row_selector(i)
2580 self.set_selection(basesel+sel)
[1483]2581 nans = numpy.isnan(self._getspectrum(0))
2582 if numpy.any(nans):
2583 bnans = [ bool(v) for v in nans]
2584 self.flag(bnans)
2585 self.set_selection(basesel)
2586
[1588]2587 def get_row_selector(self, rowno):
2588 return selector(beams=self.getbeam(rowno),
2589 ifs=self.getif(rowno),
2590 pols=self.getpol(rowno),
2591 scans=self.getscan(rowno),
2592 cycles=self.getcycle(rowno))
[1573]2593
[484]2594 def _add_history(self, funcname, parameters):
[1435]2595 if not rcParams['scantable.history']:
2596 return
[484]2597 # create date
2598 sep = "##"
2599 from datetime import datetime
2600 dstr = datetime.now().strftime('%Y/%m/%d %H:%M:%S')
2601 hist = dstr+sep
2602 hist += funcname+sep#cdate+sep
2603 if parameters.has_key('self'): del parameters['self']
[1118]2604 for k, v in parameters.iteritems():
[484]2605 if type(v) is dict:
[1118]2606 for k2, v2 in v.iteritems():
[484]2607 hist += k2
2608 hist += "="
[1118]2609 if isinstance(v2, scantable):
[484]2610 hist += 'scantable'
2611 elif k2 == 'mask':
[1118]2612 if isinstance(v2, list) or isinstance(v2, tuple):
[513]2613 hist += str(self._zip_mask(v2))
2614 else:
2615 hist += str(v2)
[484]2616 else:
[513]2617 hist += str(v2)
[484]2618 else:
2619 hist += k
2620 hist += "="
[1118]2621 if isinstance(v, scantable):
[484]2622 hist += 'scantable'
2623 elif k == 'mask':
[1118]2624 if isinstance(v, list) or isinstance(v, tuple):
[513]2625 hist += str(self._zip_mask(v))
2626 else:
2627 hist += str(v)
[484]2628 else:
2629 hist += str(v)
2630 hist += sep
2631 hist = hist[:-2] # remove trailing '##'
2632 self._addhistory(hist)
2633
[710]2634
[484]2635 def _zip_mask(self, mask):
2636 mask = list(mask)
2637 i = 0
2638 segments = []
2639 while mask[i:].count(1):
2640 i += mask[i:].index(1)
2641 if mask[i:].count(0):
2642 j = i + mask[i:].index(0)
2643 else:
[710]2644 j = len(mask)
[1118]2645 segments.append([i, j])
[710]2646 i = j
[484]2647 return segments
[714]2648
[626]2649 def _get_ordinate_label(self):
2650 fu = "("+self.get_fluxunit()+")"
2651 import re
2652 lbl = "Intensity"
[1118]2653 if re.match(".K.", fu):
[626]2654 lbl = "Brightness Temperature "+ fu
[1118]2655 elif re.match(".Jy.", fu):
[626]2656 lbl = "Flux density "+ fu
2657 return lbl
[710]2658
[876]2659 def _check_ifs(self):
2660 nchans = [self.nchan(i) for i in range(self.nif(-1))]
[889]2661 nchans = filter(lambda t: t > 0, nchans)
[876]2662 return (sum(nchans)/len(nchans) == nchans[0])
[976]2663
[1862]2664 @asaplog_post_dec
[1819]2665 def _fill(self, names, unit, average, getpt, antenna):
[976]2666 first = True
2667 fullnames = []
2668 for name in names:
2669 name = os.path.expandvars(name)
2670 name = os.path.expanduser(name)
2671 if not os.path.exists(name):
2672 msg = "File '%s' does not exists" % (name)
2673 raise IOError(msg)
2674 fullnames.append(name)
2675 if average:
2676 asaplog.push('Auto averaging integrations')
[1079]2677 stype = int(rcParams['scantable.storage'].lower() == 'disk')
[976]2678 for name in fullnames:
[1073]2679 tbl = Scantable(stype)
[1843]2680 r = filler(tbl)
[1504]2681 rx = rcParams['scantable.reference']
[1843]2682 r.setreferenceexpr(rx)
[976]2683 msg = "Importing %s..." % (name)
[1118]2684 asaplog.push(msg, False)
[1904]2685 opts = {'ms': {'antenna' : antenna, 'getpt': getpt} }
2686 r.open(name, opts)# antenna, -1, -1, getpt)
[1843]2687 r.fill()
[976]2688 if average:
[1118]2689 tbl = self._math._average((tbl, ), (), 'NONE', 'SCAN')
[976]2690 if not first:
2691 tbl = self._math._merge([self, tbl])
2692 Scantable.__init__(self, tbl)
[1843]2693 r.close()
[1118]2694 del r, tbl
[976]2695 first = False
[1861]2696 #flush log
2697 asaplog.post()
[976]2698 if unit is not None:
2699 self.set_fluxunit(unit)
[1824]2700 if not is_casapy():
2701 self.set_freqframe(rcParams['scantable.freqframe'])
[976]2702
[1402]2703 def __getitem__(self, key):
2704 if key < 0:
2705 key += self.nrow()
2706 if key >= self.nrow():
2707 raise IndexError("Row index out of range.")
2708 return self._getspectrum(key)
2709
2710 def __setitem__(self, key, value):
2711 if key < 0:
2712 key += self.nrow()
2713 if key >= self.nrow():
2714 raise IndexError("Row index out of range.")
2715 if not hasattr(value, "__len__") or \
2716 len(value) > self.nchan(self.getif(key)):
2717 raise ValueError("Spectrum length doesn't match.")
2718 return self._setspectrum(value, key)
2719
2720 def __len__(self):
2721 return self.nrow()
2722
2723 def __iter__(self):
2724 for i in range(len(self)):
2725 yield self[i]
Note: See TracBrowser for help on using the repository browser.