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

Last change on this file since 1613 was 1613, checked in by Takeshi Nakazato, 15 years ago

New Development: No

JIRA Issue: No

Ready to Release: Yes

Interface Changes: No

What Interface Changed: Please list interface changes

Test Programs: List test programs

Put in Release Notes: Yes/No

Module(s): Module Names change impacts.

Description: Describe your changes here...

Temporary file name has been changed.


  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 80.0 KB
RevLine 
[876]1from asap._asap import Scantable
[226]2from asap import rcParams
[1118]3from asap import print_log
4from asap import asaplog
[946]5from asap import selector
[1153]6from asap import linecatalog
[1295]7from asap import _n_bools, mask_not, mask_and, mask_or
[1612]8from taskinit import *
[102]9
[876]10class scantable(Scantable):
[102]11 """
12 The ASAP container for scans
13 """
[710]14
[1496]15 def __init__(self, filename, average=None, unit=None, getpt=None):
[102]16 """
17 Create a scantable from a saved one or make a reference
18 Parameters:
[181]19 filename: the name of an asap table on disk
20 or
21 the name of a rpfits/sdfits/ms file
22 (integrations within scans are auto averaged
23 and the whole file is read)
24 or
25 [advanced] a reference to an existing
[102]26 scantable
[484]27 average: average all integrations withinb a scan on read.
28 The default (True) is taken from .asaprc.
29 unit: brightness unit; must be consistent with K or Jy.
[340]30 Over-rides the default selected by the reader
31 (input rpfits/sdfits/ms) or replaces the value
32 in existing scantables
[1522]33 getpt: for MeasurementSet input data only:
34 If True, all pointing data are filled.
35 The deafult is False, which makes time to load
36 the MS data faster in some cases.
[710]37 """
[976]38 if average is None:
[710]39 average = rcParams['scantable.autoaverage']
[1496]40 if getpt is None:
41 getpt = False
[1259]42 varlist = vars()
[876]43 from asap._asap import stmath
44 self._math = stmath()
45 if isinstance(filename, Scantable):
46 Scantable.__init__(self, filename)
[181]47 else:
[1603]48 if isinstance(filename, str):# or \
49# (isinstance(filename, list) or isinstance(filename, tuple)) \
50# and isinstance(filename[-1], str):
[976]51 import os.path
52 filename = os.path.expandvars(filename)
53 filename = os.path.expanduser(filename)
54 if not os.path.exists(filename):
55 s = "File '%s' not found." % (filename)
[718]56 if rcParams['verbose']:
[976]57 asaplog.push(s)
[1612]58 #print asaplog.pop().strip()
59 print_log()
[718]60 return
[976]61 raise IOError(s)
[1115]62 if os.path.isdir(filename) \
[1118]63 and not os.path.exists(filename+'/table.f1'):
[976]64 # crude check if asap table
65 if os.path.exists(filename+'/table.info'):
[1118]66 ondisk = rcParams['scantable.storage'] == 'disk'
67 Scantable.__init__(self, filename, ondisk)
[976]68 if unit is not None:
69 self.set_fluxunit(unit)
[1496]70 # do not reset to the default freqframe
71 #self.set_freqframe(rcParams['scantable.freqframe'])
[718]72 else:
[1118]73 msg = "The given file '%s'is not a valid " \
74 "asap table." % (filename)
[976]75 if rcParams['verbose']:
[1612]76 #print msg
77 casalog.post( msg, 'WARN' )
[976]78 return
79 else:
80 raise IOError(msg)
[226]81 else:
[1496]82 self._fill([filename], unit, average, getpt)
[1118]83 elif (isinstance(filename, list) or isinstance(filename, tuple)) \
[976]84 and isinstance(filename[-1], str):
[1496]85 self._fill(filename, unit, average, getpt)
[1259]86 self._add_history("scantable", varlist)
[714]87 print_log()
[102]88
[876]89 def save(self, name=None, format=None, overwrite=False):
[116]90 """
[1280]91 Store the scantable on disk. This can be an asap (aips++) Table,
92 SDFITS or MS2 format.
[116]93 Parameters:
[1093]94 name: the name of the outputfile. For format "ASCII"
95 this is the root file name (data in 'name'.txt
[497]96 and header in 'name'_header.txt)
[116]97 format: an optional file format. Default is ASAP.
[280]98 Allowed are - 'ASAP' (save as ASAP [aips++] Table),
[194]99 'SDFITS' (save as SDFITS file)
[200]100 'ASCII' (saves as ascii text file)
[226]101 'MS2' (saves as an aips++
102 MeasurementSet V2)
[1603]103 'FITS' (save as image FITS - not
104 readable by class)
105 'CLASS' (save as FITS readable by CLASS)
[411]106 overwrite: If the file should be overwritten if it exists.
[256]107 The default False is to return with warning
[411]108 without writing the output. USE WITH CARE.
[116]109 Example:
110 scan.save('myscan.asap')
[1118]111 scan.save('myscan.sdfits', 'SDFITS')
[116]112 """
[411]113 from os import path
[226]114 if format is None: format = rcParams['scantable.save']
[256]115 suffix = '.'+format.lower()
[1118]116 if name is None or name == "":
[256]117 name = 'scantable'+suffix
[718]118 msg = "No filename given. Using default name %s..." % name
119 asaplog.push(msg)
[411]120 name = path.expandvars(name)
[256]121 if path.isfile(name) or path.isdir(name):
122 if not overwrite:
[718]123 msg = "File %s exists." % name
124 if rcParams['verbose']:
[1612]125 #print msg
126 casalog.post( msg, 'WARN' )
[718]127 return
128 else:
129 raise IOError(msg)
[451]130 format2 = format.upper()
131 if format2 == 'ASAP':
[116]132 self._save(name)
133 else:
[989]134 from asap._asap import stwriter as stw
[1118]135 writer = stw(format2)
136 writer.write(self, name)
[718]137 print_log()
[116]138 return
139
[102]140 def copy(self):
141 """
142 Return a copy of this scantable.
[1348]143 Note:
144 This makes a full (deep) copy. scan2 = scan1 makes a reference.
[102]145 Parameters:
[113]146 none
[102]147 Example:
148 copiedscan = scan.copy()
149 """
[876]150 sd = scantable(Scantable._copy(self))
[113]151 return sd
152
[1093]153 def drop_scan(self, scanid=None):
154 """
155 Return a new scantable where the specified scan number(s) has(have)
156 been dropped.
157 Parameters:
158 scanid: a (list of) scan number(s)
159 """
160 from asap import _is_sequence_or_number as _is_valid
161 from asap import _to_list
162 from asap import unique
163 if not _is_valid(scanid):
164 if rcParams['verbose']:
[1612]165 #print "Please specify a scanno to drop from the scantable"
166 casalog.post( "Please specify a scanno to drop from the scantable", 'WARN' )
[1093]167 return
168 else:
169 raise RuntimeError("No scan given")
170 try:
171 scanid = _to_list(scanid)
172 allscans = unique([ self.getscan(i) for i in range(self.nrow())])
173 for sid in scanid: allscans.remove(sid)
[1118]174 if len(allscans) == 0:
175 raise ValueError("Can't remove all scans")
[1093]176 except ValueError:
177 if rcParams['verbose']:
[1612]178 #print "Couldn't find any match."
179 casalog.post( "Couldn't find any match.", 'WARN' )
[1093]180 return
181 else: raise
182 try:
183 bsel = self.get_selection()
184 sel = selector()
185 sel.set_scans(allscans)
186 self.set_selection(bsel+sel)
187 scopy = self._copy()
188 self.set_selection(bsel)
189 return scantable(scopy)
190 except RuntimeError:
[1118]191 if rcParams['verbose']:
[1612]192 #print "Couldn't find any match."
193 casalog.post( "Couldn't find any match.", 'WARN' )
[1118]194 else:
195 raise
[1093]196
197
[102]198 def get_scan(self, scanid=None):
199 """
200 Return a specific scan (by scanno) or collection of scans (by
201 source name) in a new scantable.
[1348]202 Note:
203 See scantable.drop_scan() for the inverse operation.
[102]204 Parameters:
[513]205 scanid: a (list of) scanno or a source name, unix-style
206 patterns are accepted for source name matching, e.g.
207 '*_R' gets all 'ref scans
[102]208 Example:
[513]209 # get all scans containing the source '323p459'
210 newscan = scan.get_scan('323p459')
211 # get all 'off' scans
212 refscans = scan.get_scan('*_R')
213 # get a susbset of scans by scanno (as listed in scan.summary())
[1118]214 newscan = scan.get_scan([0, 2, 7, 10])
[102]215 """
216 if scanid is None:
[718]217 if rcParams['verbose']:
[1612]218 #print "Please specify a scan no or name to " \
219 # "retrieve from the scantable"
220 casalog.post( "Please specify a scan no or name to retrieve from the scantable", 'WARN' )
[718]221 return
222 else:
223 raise RuntimeError("No scan given")
224
[102]225 try:
[946]226 bsel = self.get_selection()
227 sel = selector()
[102]228 if type(scanid) is str:
[946]229 sel.set_name(scanid)
230 self.set_selection(bsel+sel)
[876]231 scopy = self._copy()
[946]232 self.set_selection(bsel)
[876]233 return scantable(scopy)
[102]234 elif type(scanid) is int:
[946]235 sel.set_scans([scanid])
236 self.set_selection(bsel+sel)
[876]237 scopy = self._copy()
[946]238 self.set_selection(bsel)
[876]239 return scantable(scopy)
[381]240 elif type(scanid) is list:
[946]241 sel.set_scans(scanid)
242 self.set_selection(sel)
[876]243 scopy = self._copy()
[946]244 self.set_selection(bsel)
[876]245 return scantable(scopy)
[381]246 else:
[718]247 msg = "Illegal scanid type, use 'int' or 'list' if ints."
248 if rcParams['verbose']:
[1612]249 #print msg
250 casalog.post( msg, 'WARN' )
[718]251 else:
252 raise TypeError(msg)
[102]253 except RuntimeError:
[1612]254 if rcParams['verbose']:
255 #print "Couldn't find any match."
256 casalog.post( "Couldn't find any match.", 'WARN' )
[718]257 else: raise
[102]258
259 def __str__(self):
[1118]260 return Scantable._summary(self, True)
[102]261
[976]262 def summary(self, filename=None):
[102]263 """
264 Print a summary of the contents of this scantable.
265 Parameters:
266 filename: the name of a file to write the putput to
267 Default - no file output
[381]268 verbose: print extra info such as the frequency table
269 The default (False) is taken from .asaprc
[102]270 """
[976]271 info = Scantable._summary(self, True)
272 #if verbose is None: verbose = rcParams['scantable.verbosesummary']
[102]273 if filename is not None:
[256]274 if filename is "":
275 filename = 'scantable_summary.txt'
[415]276 from os.path import expandvars, isdir
[411]277 filename = expandvars(filename)
[415]278 if not isdir(filename):
[413]279 data = open(filename, 'w')
280 data.write(info)
281 data.close()
282 else:
[718]283 msg = "Illegal file name '%s'." % (filename)
284 if rcParams['verbose']:
[1612]285 #print msg
286 casalog.post( msg, 'WARN' )
[718]287 else:
288 raise IOError(msg)
289 if rcParams['verbose']:
[794]290 try:
291 from IPython.genutils import page as pager
292 except ImportError:
293 from pydoc import pager
294 pager(info)
[718]295 else:
296 return info
[710]297
[1603]298 def get_spectrum(self, rowno):
299 """Return the spectrum for the current row in the scantable as a list.
300 Parameters:
301 rowno: the row number to retrieve the spectrum from
302 """
303 return self._getspectrum(rowno)
[946]304
[1603]305 def get_mask(self, rowno):
306 """Return the mask for the current row in the scantable as a list.
307 Parameters:
308 rowno: the row number to retrieve the mask from
309 """
310 return self._getmask(rowno)
311
312 def set_spectrum(self, spec, rowno):
313 """Return the spectrum for the current row in the scantable as a list.
314 Parameters:
315 spec: the spectrum
316 rowno: the row number to set the spectrum for
317 """
318 assert(len(spec) == self.nchan())
319 return self._setspectrum(spec, rowno)
320
[946]321 def get_selection(self):
322 """
[1005]323 Get the selection object currently set on this scantable.
324 Parameters:
325 none
326 Example:
327 sel = scan.get_selection()
328 sel.set_ifs(0) # select IF 0
329 scan.set_selection(sel) # apply modified selection
[946]330 """
331 return selector(self._getselection())
332
[1005]333 def set_selection(self, selection=selector()):
[946]334 """
[1005]335 Select a subset of the data. All following operations on this scantable
336 are only applied to thi selection.
337 Parameters:
338 selection: a selector object (default unset the selection)
339 Examples:
340 sel = selector() # create a selection object
[1118]341 self.set_scans([0, 3]) # select SCANNO 0 and 3
[1005]342 scan.set_selection(sel) # set the selection
343 scan.summary() # will only print summary of scanno 0 an 3
344 scan.set_selection() # unset the selection
[946]345 """
346 self._setselection(selection)
347
[1446]348 def get_row(self, row=0, insitu=None):
349 """
350 Select a row in the scantable.
351 Return a scantable with single row.
352 Parameters:
353 row: row no of integration, default is 0.
354 insitu: if False a new scantable is returned.
355 Otherwise, the scaling is done in-situ
356 The default is taken from .asaprc (False)
357 """
358 if insitu is None: insitu = rcParams['insitu']
359 if not insitu:
360 workscan = self.copy()
361 else:
362 workscan = self
363 # Select a row
364 sel=selector()
365 sel.set_scans([workscan.getscan(row)])
366 sel.set_cycles([workscan.getcycle(row)])
367 sel.set_beams([workscan.getbeam(row)])
368 sel.set_ifs([workscan.getif(row)])
369 sel.set_polarisations([workscan.getpol(row)])
370 sel.set_name(workscan._getsourcename(row))
371 workscan.set_selection(sel)
372 if not workscan.nrow() == 1:
373 msg = "Cloud not identify single row. %d rows selected."%(workscan.nrow())
374 raise RuntimeError(msg)
375 del sel
376 if insitu:
377 self._assign(workscan)
378 else:
379 return workscan
380
[876]381 def stats(self, stat='stddev', mask=None):
[102]382 """
[135]383 Determine the specified statistic of the current beam/if/pol
[102]384 Takes a 'mask' as an optional parameter to specify which
385 channels should be excluded.
386 Parameters:
[1517]387 stat: 'min', 'max', 'min_abc', 'max_abc', 'sumsq', 'sum',
[1515]388 'mean', 'var', 'stddev', 'avdev', 'rms', 'median'
[135]389 mask: an optional mask specifying where the statistic
[102]390 should be determined.
391 Example:
[113]392 scan.set_unit('channel')
[1118]393 msk = scan.create_mask([100, 200], [500, 600])
[135]394 scan.stats(stat='mean', mask=m)
[102]395 """
396 if mask == None:
[876]397 mask = []
[1118]398 axes = ['Beam', 'IF', 'Pol', 'Time']
[876]399 if not self._check_ifs():
[1118]400 raise ValueError("Cannot apply mask as the IFs have different "
401 "number of channels. Please use setselection() "
402 "to select individual IFs")
[1530]403 rtnabc = False
404 if stat.lower().endswith('_abc'): rtnabc = True
405 getchan = False
406 if stat.lower().startswith('min') or stat.lower().startswith('max'):
[1517]407 chan = self._math._minmaxchan(self, mask, stat)
408 getchan = True
[1515]409 statvals = []
[1530]410 if not rtnabc: statvals = self._math._stats(self, mask, stat)
411
[876]412 out = ''
413 axes = []
414 for i in range(self.nrow()):
415 axis = []
416 axis.append(self.getscan(i))
417 axis.append(self.getbeam(i))
418 axis.append(self.getif(i))
419 axis.append(self.getpol(i))
420 axis.append(self.getcycle(i))
421 axes.append(axis)
422 tm = self._gettime(i)
423 src = self._getsourcename(i)
[1530]424 refstr = ''
425 statunit= ''
[1517]426 if getchan:
427 qx, qy = self.chan2data(rowno=i, chan=chan[i])
[1530]428 if rtnabc:
429 statvals.append(qx['value'])
430 refstr = '(value: %3.3f' % (qy['value'])+' ['+qy['unit']+'])'
431 statunit= '['+qx['unit']+']'
432 else:
433 refstr = '(@ %3.3f' % (qx['value'])+' ['+qx['unit']+'])'
434 #statunit= ' ['+qy['unit']+']'
[876]435 out += 'Scan[%d] (%s) ' % (axis[0], src)
436 out += 'Time[%s]:\n' % (tm)
437 if self.nbeam(-1) > 1: out += ' Beam[%d] ' % (axis[1])
438 if self.nif(-1) > 1: out += ' IF[%d] ' % (axis[2])
439 if self.npol(-1) > 1: out += ' Pol[%d] ' % (axis[3])
[1530]440 out += '= %3.3f ' % (statvals[i]) +refstr+'\n'
[876]441 out += "--------------------------------------------------\n"
[256]442
[876]443 if rcParams['verbose']:
[1613]444 usr=os.environ['USER']
445 tmpfile='/tmp/tmp_'+usr+'_casapy_asap_scantable_stats'
[1612]446 f=open(tmpfile,'w')
447 print >> f, "--------------------------------------------------"
448 print >> f, " ", stat, statunit
449 print >> f, "--------------------------------------------------"
450 print >> f, out
451 f.close()
452 f=open(tmpfile,'r')
453 x=f.readlines()
454 f.close()
455 for xx in x:
456 casalog.post( xx )
[1295]457 #else:
458 #retval = { 'axesnames': ['scanno', 'beamno', 'ifno', 'polno', 'cycleno'],
459 # 'axes' : axes,
460 # 'data': statvals}
461 return statvals
[102]462
[1517]463 def chan2data(self, rowno=0, chan=0):
[1515]464 """
[1517]465 Returns channel/frequency/velocity and spectral value
[1515]466 at an arbitrary row and channel in the scantable.
467 Parameters:
468 rowno: a row number in the scantable. Default is the
469 first row, i.e. rowno=0
[1517]470 chan: a channel in the scantable. Default is the first
[1515]471 channel, i.e. pos=0
472 """
[1517]473 if isinstance(rowno, int) and isinstance(chan, int):
[1530]474 qx = {'unit': self.get_unit(),
475 'value': self._getabcissa(rowno)[chan]}
[1517]476 qy = {'unit': self.get_fluxunit(),
477 'value': self._getspectrum(rowno)[chan]}
478 return qx, qy
[1515]479
[1118]480 def stddev(self, mask=None):
[135]481 """
482 Determine the standard deviation of the current beam/if/pol
483 Takes a 'mask' as an optional parameter to specify which
484 channels should be excluded.
485 Parameters:
486 mask: an optional mask specifying where the standard
487 deviation should be determined.
488
489 Example:
490 scan.set_unit('channel')
[1118]491 msk = scan.create_mask([100, 200], [500, 600])
[135]492 scan.stddev(mask=m)
493 """
[1118]494 return self.stats(stat='stddev', mask=mask);
[135]495
[1003]496
[1259]497 def get_column_names(self):
[1003]498 """
499 Return a list of column names, which can be used for selection.
500 """
[1259]501 return list(Scantable.get_column_names(self))
[1003]502
[876]503 def get_tsys(self):
[113]504 """
505 Return the System temperatures.
506 Returns:
[876]507 a list of Tsys values for the current selection
[113]508 """
[256]509
[876]510 return self._row_callback(self._gettsys, "Tsys")
[256]511
[876]512 def _row_callback(self, callback, label):
513 axes = []
[1118]514 axesnames = ['scanno', 'beamno', 'ifno', 'polno', 'cycleno']
[876]515 out = ""
[1118]516 outvec = []
[876]517 for i in range(self.nrow()):
518 axis = []
519 axis.append(self.getscan(i))
520 axis.append(self.getbeam(i))
521 axis.append(self.getif(i))
522 axis.append(self.getpol(i))
523 axis.append(self.getcycle(i))
524 axes.append(axis)
525 tm = self._gettime(i)
526 src = self._getsourcename(i)
527 out += 'Scan[%d] (%s) ' % (axis[0], src)
528 out += 'Time[%s]:\n' % (tm)
529 if self.nbeam(-1) > 1: out += ' Beam[%d] ' % (axis[1])
530 if self.nif(-1) > 1: out += ' IF[%d] ' % (axis[2])
531 if self.npol(-1) > 1: out += ' Pol[%d] ' % (axis[3])
532 outvec.append(callback(i))
533 out += '= %3.3f\n' % (outvec[i])
534 out += "--------------------------------------------------\n"
535 if rcParams['verbose']:
[1612]536 #print "--------------------------------------------------"
537 #print " %s" % (label)
538 #print "--------------------------------------------------"
539 #print out
540 casalog.post( "--------------------------------------------------" )
541 casalog.post( " %s" % (label) )
542 casalog.post( "--------------------------------------------------" )
543 casalog.post( out )
[1175]544 # disabled because the vector seems more useful
545 #retval = {'axesnames': axesnames, 'axes': axes, 'data': outvec}
546 return outvec
[256]547
[1070]548 def _get_column(self, callback, row=-1):
549 """
550 """
551 if row == -1:
552 return [callback(i) for i in range(self.nrow())]
553 else:
554 if 0 <= row < self.nrow():
555 return callback(row)
[256]556
[1070]557
[1348]558 def get_time(self, row=-1, asdatetime=False):
[113]559 """
560 Get a list of time stamps for the observations.
[1348]561 Return a datetime object for each integration time stamp in the scantable.
[113]562 Parameters:
[1348]563 row: row no of integration. Default -1 return all rows
564 asdatetime: return values as datetime objects rather than strings
[113]565 Example:
566 none
567 """
[1175]568 from time import strptime
569 from datetime import datetime
[1457]570 times = self._get_column(self._gettime, row)
[1348]571 if not asdatetime:
[1603]572 return times
[1175]573 format = "%Y/%m/%d/%H:%M:%S"
574 if isinstance(times, list):
575 return [datetime(*strptime(i, format)[:6]) for i in times]
576 else:
577 return datetime(*strptime(times, format)[:6])
[102]578
[1348]579
580 def get_inttime(self, row=-1):
581 """
582 Get a list of integration times for the observations.
583 Return a time in seconds for each integration in the scantable.
584 Parameters:
585 row: row no of integration. Default -1 return all rows.
586 Example:
587 none
588 """
589 return self._get_column(self._getinttime, row)
590
591
[714]592 def get_sourcename(self, row=-1):
593 """
[794]594 Get a list source names for the observations.
[714]595 Return a string for each integration in the scantable.
596 Parameters:
[1348]597 row: row no of integration. Default -1 return all rows.
[714]598 Example:
599 none
600 """
[1070]601 return self._get_column(self._getsourcename, row)
[714]602
[794]603 def get_elevation(self, row=-1):
604 """
605 Get a list of elevations for the observations.
606 Return a float for each integration in the scantable.
607 Parameters:
[1348]608 row: row no of integration. Default -1 return all rows.
[794]609 Example:
610 none
611 """
[1070]612 return self._get_column(self._getelevation, row)
[794]613
614 def get_azimuth(self, row=-1):
615 """
616 Get a list of azimuths for the observations.
617 Return a float for each integration in the scantable.
618 Parameters:
[1348]619 row: row no of integration. Default -1 return all rows.
[794]620 Example:
621 none
622 """
[1070]623 return self._get_column(self._getazimuth, row)
[794]624
625 def get_parangle(self, row=-1):
626 """
627 Get a list of parallactic angles for the observations.
628 Return a float for each integration in the scantable.
629 Parameters:
[1348]630 row: row no of integration. Default -1 return all rows.
[794]631 Example:
632 none
633 """
[1070]634 return self._get_column(self._getparangle, row)
[794]635
[1070]636 def get_direction(self, row=-1):
637 """
638 Get a list of Positions on the sky (direction) for the observations.
639 Return a float for each integration in the scantable.
640 Parameters:
641 row: row no of integration. Default -1 return all rows
642 Example:
643 none
644 """
645 return self._get_column(self._getdirection, row)
646
[1389]647 def get_directionval(self, row=-1):
648 """
649 Get a list of Positions on the sky (direction) for the observations.
650 Return a float for each integration in the scantable.
651 Parameters:
652 row: row no of integration. Default -1 return all rows
653 Example:
654 none
655 """
656 return self._get_column(self._getdirectionvec, row)
657
[102]658 def set_unit(self, unit='channel'):
659 """
660 Set the unit for all following operations on this scantable
661 Parameters:
662 unit: optional unit, default is 'channel'
[1118]663 one of '*Hz', 'km/s', 'channel', ''
[102]664 """
[484]665 varlist = vars()
[1118]666 if unit in ['', 'pixel', 'channel']:
[113]667 unit = ''
668 inf = list(self._getcoordinfo())
669 inf[0] = unit
670 self._setcoordinfo(inf)
[1118]671 self._add_history("set_unit", varlist)
[113]672
[484]673 def set_instrument(self, instr):
[358]674 """
[1348]675 Set the instrument for subsequent processing.
[358]676 Parameters:
[710]677 instr: Select from 'ATPKSMB', 'ATPKSHOH', 'ATMOPRA',
[407]678 'DSS-43' (Tid), 'CEDUNA', and 'HOBART'
[358]679 """
680 self._setInstrument(instr)
[1118]681 self._add_history("set_instument", vars())
[718]682 print_log()
[358]683
[1190]684 def set_feedtype(self, feedtype):
685 """
686 Overwrite the feed type, which might not be set correctly.
687 Parameters:
688 feedtype: 'linear' or 'circular'
689 """
690 self._setfeedtype(feedtype)
691 self._add_history("set_feedtype", vars())
692 print_log()
693
[276]694 def set_doppler(self, doppler='RADIO'):
695 """
696 Set the doppler for all following operations on this scantable.
697 Parameters:
698 doppler: One of 'RADIO', 'OPTICAL', 'Z', 'BETA', 'GAMMA'
699 """
[484]700 varlist = vars()
[276]701 inf = list(self._getcoordinfo())
702 inf[2] = doppler
703 self._setcoordinfo(inf)
[1118]704 self._add_history("set_doppler", vars())
[718]705 print_log()
[710]706
[226]707 def set_freqframe(self, frame=None):
[113]708 """
709 Set the frame type of the Spectral Axis.
710 Parameters:
[591]711 frame: an optional frame type, default 'LSRK'. Valid frames are:
[1118]712 'REST', 'TOPO', 'LSRD', 'LSRK', 'BARY',
713 'GEO', 'GALACTO', 'LGROUP', 'CMB'
[113]714 Examples:
715 scan.set_freqframe('BARY')
716 """
[484]717 if frame is None: frame = rcParams['scantable.freqframe']
718 varlist = vars()
[1118]719 valid = ['REST', 'TOPO', 'LSRD', 'LSRK', 'BARY', \
720 'GEO', 'GALACTO', 'LGROUP', 'CMB']
[591]721
[989]722 if frame in valid:
[113]723 inf = list(self._getcoordinfo())
724 inf[1] = frame
725 self._setcoordinfo(inf)
[1118]726 self._add_history("set_freqframe", varlist)
[102]727 else:
[1118]728 msg = "Please specify a valid freq type. Valid types are:\n", valid
[718]729 if rcParams['verbose']:
[1612]730 #print msg
731 casalog.post( msg, 'WARN' )
[718]732 else:
733 raise TypeError(msg)
734 print_log()
[710]735
[989]736 def set_dirframe(self, frame=""):
737 """
738 Set the frame type of the Direction on the sky.
739 Parameters:
740 frame: an optional frame type, default ''. Valid frames are:
741 'J2000', 'B1950', 'GALACTIC'
742 Examples:
743 scan.set_dirframe('GALACTIC')
744 """
745 varlist = vars()
746 try:
747 Scantable.set_dirframe(self, frame)
[1118]748 except RuntimeError, msg:
[989]749 if rcParams['verbose']:
[1612]750 #print msg
751 casalog.post( msg, 'WARN' )
[989]752 else:
753 raise
[1118]754 self._add_history("set_dirframe", varlist)
[989]755
[113]756 def get_unit(self):
757 """
758 Get the default unit set in this scantable
759 Returns:
760 A unit string
761 """
762 inf = self._getcoordinfo()
763 unit = inf[0]
764 if unit == '': unit = 'channel'
765 return unit
[102]766
[158]767 def get_abcissa(self, rowno=0):
[102]768 """
[158]769 Get the abcissa in the current coordinate setup for the currently
[113]770 selected Beam/IF/Pol
771 Parameters:
[226]772 rowno: an optional row number in the scantable. Default is the
773 first row, i.e. rowno=0
[113]774 Returns:
[1348]775 The abcissa values and the format string (as a dictionary)
[113]776 """
[256]777 abc = self._getabcissa(rowno)
[710]778 lbl = self._getabcissalabel(rowno)
[718]779 print_log()
[158]780 return abc, lbl
[113]781
[1401]782 def flag(self, mask=None, unflag=False):
[1001]783 """
784 Flag the selected data using an optional channel mask.
785 Parameters:
786 mask: an optional channel mask, created with create_mask. Default
787 (no mask) is all channels.
[1401]788 unflag: if True, unflag the data
[1001]789 """
790 varlist = vars()
[1118]791 if mask is None:
792 mask = []
[1001]793 try:
[1401]794 self._flag(mask, unflag)
[1118]795 except RuntimeError, msg:
[1001]796 if rcParams['verbose']:
[1612]797 #print msg
798 casalog.post( msg, 'WARN' )
[1001]799 return
800 else: raise
801 self._add_history("flag", varlist)
802
[1203]803 def lag_flag(self, frequency, width=0.0, unit="GHz", insitu=None):
[1192]804 """
805 Flag the data in 'lag' space by providing a frequency to remove.
806 Flagged data in the scantable gets set to 0.0 before the fft.
807 No taper is applied.
808 Parameters:
[1348]809 frequency: the frequency (really a period within the bandwidth)
810 to remove
811 width: the width of the frequency to remove, to remove a
[1603]812 range of frequencies around the centre.
[1203]813 unit: the frequency unit (default "GHz")
814 Notes:
[1348]815 It is recommended to flag edges of the band or strong
816 signals beforehand.
[1192]817 """
818 if insitu is None: insitu = rcParams['insitu']
819 self._math._setinsitu(insitu)
820 varlist = vars()
[1370]821 base = { "GHz": 1000000000., "MHz": 1000000., "kHz": 1000., "Hz": 1. }
[1192]822 if not base.has_key(unit):
823 raise ValueError("%s is not a valid unit." % unit)
824 try:
[1200]825 s = scantable(self._math._lag_flag(self, frequency*base[unit],
826 width*base[unit]))
[1192]827 except RuntimeError, msg:
828 if rcParams['verbose']:
[1612]829 #print msg
830 casalog.post( msg, 'WARN' )
[1192]831 return
832 else: raise
833 s._add_history("lag_flag", varlist)
834 print_log()
835 if insitu:
836 self._assign(s)
837 else:
838 return s
[1001]839
[1192]840
[113]841 def create_mask(self, *args, **kwargs):
842 """
[1118]843 Compute and return a mask based on [min, max] windows.
[189]844 The specified windows are to be INCLUDED, when the mask is
[113]845 applied.
[102]846 Parameters:
[1118]847 [min, max], [min2, max2], ...
[1024]848 Pairs of start/end points (inclusive)specifying the regions
[102]849 to be masked
[189]850 invert: optional argument. If specified as True,
851 return an inverted mask, i.e. the regions
852 specified are EXCLUDED
[513]853 row: create the mask using the specified row for
854 unit conversions, default is row=0
855 only necessary if frequency varies over rows.
[102]856 Example:
[113]857 scan.set_unit('channel')
858 a)
[1118]859 msk = scan.create_mask([400, 500], [800, 900])
[189]860 # masks everything outside 400 and 500
[113]861 # and 800 and 900 in the unit 'channel'
862
863 b)
[1118]864 msk = scan.create_mask([400, 500], [800, 900], invert=True)
[189]865 # masks the regions between 400 and 500
[113]866 # and 800 and 900 in the unit 'channel'
[1024]867 c)
868 mask only channel 400
[1118]869 msk = scan.create_mask([400, 400])
[102]870 """
[513]871 row = 0
872 if kwargs.has_key("row"):
873 row = kwargs.get("row")
874 data = self._getabcissa(row)
[113]875 u = self._getcoordinfo()[0]
[718]876 if rcParams['verbose']:
[113]877 if u == "": u = "channel"
[718]878 msg = "The current mask window unit is %s" % u
[1118]879 i = self._check_ifs()
880 if not i:
[876]881 msg += "\nThis mask is only valid for IF=%d" % (self.getif(i))
[718]882 asaplog.push(msg)
[102]883 n = self.nchan()
[1295]884 msk = _n_bools(n, False)
[710]885 # test if args is a 'list' or a 'normal *args - UGLY!!!
886
[1118]887 ws = (isinstance(args[-1][-1], int) or isinstance(args[-1][-1], float)) \
888 and args or args[0]
[710]889 for window in ws:
[102]890 if (len(window) != 2 or window[0] > window[1] ):
[1118]891 raise TypeError("A window needs to be defined as [min, max]")
[102]892 for i in range(n):
[1024]893 if data[i] >= window[0] and data[i] <= window[1]:
[1295]894 msk[i] = True
[113]895 if kwargs.has_key('invert'):
896 if kwargs.get('invert'):
[1295]897 msk = mask_not(msk)
[718]898 print_log()
[102]899 return msk
[710]900
[1446]901 def get_masklist(self, mask=None, row=0):
[256]902 """
[1446]903 Compute and return a list of mask windows, [min, max].
904 Parameters:
905 mask: channel mask, created with create_mask.
906 row: calcutate the masklist using the specified row
907 for unit conversions, default is row=0
908 only necessary if frequency varies over rows.
909 Returns:
910 [min, max], [min2, max2], ...
911 Pairs of start/end points (inclusive)specifying
912 the masked regions
913 """
914 if not (isinstance(mask,list) or isinstance(mask, tuple)):
915 raise TypeError("The mask should be list or tuple.")
916 if len(mask) < 2:
917 raise TypeError("The mask elements should be > 1")
918 if self.nchan() != len(mask):
919 msg = "Number of channels in scantable != number of mask elements"
920 raise TypeError(msg)
921 data = self._getabcissa(row)
922 u = self._getcoordinfo()[0]
923 if rcParams['verbose']:
924 if u == "": u = "channel"
925 msg = "The current mask window unit is %s" % u
926 i = self._check_ifs()
927 if not i:
928 msg += "\nThis mask is only valid for IF=%d" % (self.getif(i))
929 asaplog.push(msg)
930 masklist=[]
931 ist, ien = None, None
932 ist, ien=self.get_mask_indices(mask)
933 if ist is not None and ien is not None:
934 for i in xrange(len(ist)):
935 range=[data[ist[i]],data[ien[i]]]
936 range.sort()
937 masklist.append([range[0],range[1]])
938 return masklist
939
940 def get_mask_indices(self, mask=None):
941 """
942 Compute and Return lists of mask start indices and mask end indices.
943 Parameters:
944 mask: channel mask, created with create_mask.
945 Returns:
946 List of mask start indices and that of mask end indices,
947 i.e., [istart1,istart2,....], [iend1,iend2,....].
948 """
949 if not (isinstance(mask,list) or isinstance(mask, tuple)):
950 raise TypeError("The mask should be list or tuple.")
951 if len(mask) < 2:
952 raise TypeError("The mask elements should be > 1")
953 istart=[]
954 iend=[]
955 if mask[0]: istart.append(0)
956 for i in range(len(mask)-1):
957 if not mask[i] and mask[i+1]:
958 istart.append(i+1)
959 elif mask[i] and not mask[i+1]:
960 iend.append(i)
961 if mask[len(mask)-1]: iend.append(len(mask)-1)
962 if len(istart) != len(iend):
963 raise RuntimeError("Numbers of mask start != mask end.")
964 for i in range(len(istart)):
965 if istart[i] > iend[i]:
966 raise RuntimeError("Mask start index > mask end index")
967 break
968 return istart,iend
969
970# def get_restfreqs(self):
971# """
972# Get the restfrequency(s) stored in this scantable.
973# The return value(s) are always of unit 'Hz'
974# Parameters:
975# none
976# Returns:
977# a list of doubles
978# """
979# return list(self._getrestfreqs())
980
981 def get_restfreqs(self, ids=None):
982 """
[256]983 Get the restfrequency(s) stored in this scantable.
984 The return value(s) are always of unit 'Hz'
985 Parameters:
[1446]986 ids: (optional) a list of MOLECULE_ID for that restfrequency(s) to
987 be retrieved
[256]988 Returns:
[1446]989 dictionary containing ids and a list of doubles for each id
[256]990 """
[1446]991 if ids is None:
992 rfreqs={}
993 idlist = self.getmolnos()
994 for i in idlist:
995 rfreqs[i]=list(self._getrestfreqs(i))
996 return rfreqs
997 else:
998 if type(ids)==list or type(ids)==tuple:
999 rfreqs={}
1000 for i in ids:
1001 rfreqs[i]=list(self._getrestfreqs(i))
1002 return rfreqs
1003 else:
1004 return list(self._getrestfreqs(ids))
1005 #return list(self._getrestfreqs(ids))
[102]1006
[931]1007 def set_restfreqs(self, freqs=None, unit='Hz'):
1008 """
[1446]1009 ********NEED TO BE UPDATED begin************
[931]1010 Set or replace the restfrequency specified and
1011 If the 'freqs' argument holds a scalar,
1012 then that rest frequency will be applied to all the selected
1013 data. If the 'freqs' argument holds
1014 a vector, then it MUST be of equal or smaller length than
1015 the number of IFs (and the available restfrequencies will be
1016 replaced by this vector). In this case, *all* data have
1017 the restfrequency set per IF according
1018 to the corresponding value you give in the 'freqs' vector.
[1118]1019 E.g. 'freqs=[1e9, 2e9]' would mean IF 0 gets restfreq 1e9 and
[931]1020 IF 1 gets restfreq 2e9.
[1446]1021 ********NEED TO BE UPDATED end************
[1603]1022 You can also specify the frequencies via a linecatalog.
[1153]1023
[931]1024 Parameters:
1025 freqs: list of rest frequency values or string idenitfiers
1026 unit: unit for rest frequency (default 'Hz')
[402]1027
[931]1028 Example:
[1446]1029 # set the given restfrequency for the all currently selected IFs
[931]1030 scan.set_restfreqs(freqs=1.4e9)
[1446]1031 # set multiple restfrequencies to all the selected data
1032 scan.set_restfreqs(freqs=[1.4e9, 1.41e9, 1.42e9])
1033 # If the number of IFs in the data is >= 2 the IF0 gets the first
1034 # value IF1 the second... NOTE that freqs needs to be
1035 # specified in list of list (e.g. [[],[],...] ).
1036 scan.set_restfreqs(freqs=[[1.4e9],[1.67e9]])
[931]1037 #set the given restfrequency for the whole table (by name)
1038 scan.set_restfreqs(freqs="OH1667")
[391]1039
[931]1040 Note:
1041 To do more sophisticate Restfrequency setting, e.g. on a
1042 source and IF basis, use scantable.set_selection() before using
1043 this function.
1044 # provide your scantable is call scan
1045 selection = selector()
1046 selection.set_name("ORION*")
1047 selection.set_ifs([1])
1048 scan.set_selection(selection)
1049 scan.set_restfreqs(freqs=86.6e9)
1050
1051 """
1052 varlist = vars()
[1157]1053 from asap import linecatalog
1054 # simple value
[1118]1055 if isinstance(freqs, int) or isinstance(freqs, float):
[1446]1056 # TT mod
1057 #self._setrestfreqs(freqs, "",unit)
1058 self._setrestfreqs([freqs], [""],unit)
[1157]1059 # list of values
[1118]1060 elif isinstance(freqs, list) or isinstance(freqs, tuple):
[1157]1061 # list values are scalars
[1118]1062 if isinstance(freqs[-1], int) or isinstance(freqs[-1], float):
[1446]1063 self._setrestfreqs(freqs, [""],unit)
[1157]1064 # list values are tuples, (value, name)
1065 elif isinstance(freqs[-1], dict):
[1446]1066 #sel = selector()
1067 #savesel = self._getselection()
1068 #iflist = self.getifnos()
1069 #for i in xrange(len(freqs)):
1070 # sel.set_ifs(iflist[i])
1071 # self._setselection(sel)
1072 # self._setrestfreqs(freqs[i], "",unit)
1073 #self._setselection(savesel)
1074 self._setrestfreqs(freqs["value"],
1075 freqs["name"], "MHz")
1076 elif isinstance(freqs[-1], list) or isinstance(freqs[-1], tuple):
[1157]1077 sel = selector()
1078 savesel = self._getselection()
[1322]1079 iflist = self.getifnos()
[1446]1080 if len(freqs)>len(iflist):
1081 raise ValueError("number of elements in list of list exeeds the current IF selections")
[1157]1082 for i in xrange(len(freqs)):
[1322]1083 sel.set_ifs(iflist[i])
[1259]1084 self._setselection(sel)
[1157]1085 self._setrestfreqs(freqs[i]["value"],
1086 freqs[i]["name"], "MHz")
1087 self._setselection(savesel)
1088 # freqs are to be taken from a linecatalog
[1153]1089 elif isinstance(freqs, linecatalog):
1090 sel = selector()
1091 savesel = self._getselection()
1092 for i in xrange(freqs.nrow()):
[1322]1093 sel.set_ifs(iflist[i])
[1153]1094 self._setselection(sel)
1095 self._setrestfreqs(freqs.get_frequency(i),
1096 freqs.get_name(i), "MHz")
1097 # ensure that we are not iterating past nIF
1098 if i == self.nif()-1: break
1099 self._setselection(savesel)
[931]1100 else:
1101 return
1102 self._add_history("set_restfreqs", varlist)
1103
[1360]1104 def shift_refpix(self, delta):
1105 """
1106 Shift the reference pixel of the Spectra Coordinate by an
1107 integer amount.
1108 Parameters:
1109 delta: the amount to shift by
1110 Note:
1111 Be careful using this with broadband data.
1112 """
1113 Scantable.shift(self, delta)
[931]1114
[1259]1115 def history(self, filename=None):
1116 """
1117 Print the history. Optionally to a file.
[1348]1118 Parameters:
1119 filename: The name of the file to save the history to.
[1259]1120 """
[484]1121 hist = list(self._gethistory())
[794]1122 out = "-"*80
[484]1123 for h in hist:
[489]1124 if h.startswith("---"):
[794]1125 out += "\n"+h
[489]1126 else:
1127 items = h.split("##")
1128 date = items[0]
1129 func = items[1]
1130 items = items[2:]
[794]1131 out += "\n"+date+"\n"
1132 out += "Function: %s\n Parameters:" % (func)
[489]1133 for i in items:
1134 s = i.split("=")
[1118]1135 out += "\n %s = %s" % (s[0], s[1])
[794]1136 out += "\n"+"-"*80
[1259]1137 if filename is not None:
1138 if filename is "":
1139 filename = 'scantable_history.txt'
1140 import os
1141 filename = os.path.expandvars(os.path.expanduser(filename))
1142 if not os.path.isdir(filename):
1143 data = open(filename, 'w')
1144 data.write(out)
1145 data.close()
1146 else:
1147 msg = "Illegal file name '%s'." % (filename)
1148 if rcParams['verbose']:
[1612]1149 #print msg
1150 casalog.post( msg, 'WARN' )
[1259]1151 else:
1152 raise IOError(msg)
1153 if rcParams['verbose']:
1154 try:
1155 from IPython.genutils import page as pager
1156 except ImportError:
1157 from pydoc import pager
1158 pager(out)
1159 else:
1160 return out
[484]1161 return
[513]1162 #
1163 # Maths business
1164 #
1165
[931]1166 def average_time(self, mask=None, scanav=False, weight='tint', align=False):
[513]1167 """
[1070]1168 Return the (time) weighted average of a scan.
[513]1169 Note:
[1070]1170 in channels only - align if necessary
[513]1171 Parameters:
1172 mask: an optional mask (only used for 'var' and 'tsys'
1173 weighting)
[558]1174 scanav: True averages each scan separately
1175 False (default) averages all scans together,
[1099]1176 weight: Weighting scheme.
1177 'none' (mean no weight)
1178 'var' (1/var(spec) weighted)
1179 'tsys' (1/Tsys**2 weighted)
1180 'tint' (integration time weighted)
1181 'tintsys' (Tint/Tsys**2)
1182 'median' ( median averaging)
[535]1183 The default is 'tint'
[931]1184 align: align the spectra in velocity before averaging. It takes
1185 the time of the first spectrum as reference time.
[513]1186 Example:
1187 # time average the scantable without using a mask
[710]1188 newscan = scan.average_time()
[513]1189 """
1190 varlist = vars()
[976]1191 if weight is None: weight = 'TINT'
[513]1192 if mask is None: mask = ()
[1099]1193 if scanav: scanav = "SCAN"
1194 else: scanav = "NONE"
[1118]1195 scan = (self, )
[989]1196 try:
[1118]1197 if align:
1198 scan = (self.freq_align(insitu=False), )
1199 s = None
1200 if weight.upper() == 'MEDIAN':
1201 s = scantable(self._math._averagechannel(scan[0], 'MEDIAN',
1202 scanav))
1203 else:
1204 s = scantable(self._math._average(scan, mask, weight.upper(),
1205 scanav))
1206 except RuntimeError, msg:
[989]1207 if rcParams['verbose']:
[1612]1208 #print msg
1209 casalog.post( msg, 'WARN' )
[989]1210 return
1211 else: raise
[1099]1212 s._add_history("average_time", varlist)
[718]1213 print_log()
[513]1214 return s
[710]1215
[876]1216 def convert_flux(self, jyperk=None, eta=None, d=None, insitu=None):
[513]1217 """
1218 Return a scan where all spectra are converted to either
1219 Jansky or Kelvin depending upon the flux units of the scan table.
1220 By default the function tries to look the values up internally.
1221 If it can't find them (or if you want to over-ride), you must
1222 specify EITHER jyperk OR eta (and D which it will try to look up
1223 also if you don't set it). jyperk takes precedence if you set both.
1224 Parameters:
1225 jyperk: the Jy / K conversion factor
1226 eta: the aperture efficiency
1227 d: the geomtric diameter (metres)
1228 insitu: if False a new scantable is returned.
1229 Otherwise, the scaling is done in-situ
1230 The default is taken from .asaprc (False)
1231 """
1232 if insitu is None: insitu = rcParams['insitu']
[876]1233 self._math._setinsitu(insitu)
[513]1234 varlist = vars()
1235 if jyperk is None: jyperk = -1.0
1236 if d is None: d = -1.0
1237 if eta is None: eta = -1.0
[876]1238 s = scantable(self._math._convertflux(self, d, eta, jyperk))
1239 s._add_history("convert_flux", varlist)
1240 print_log()
1241 if insitu: self._assign(s)
1242 else: return s
[513]1243
[876]1244 def gain_el(self, poly=None, filename="", method="linear", insitu=None):
[513]1245 """
1246 Return a scan after applying a gain-elevation correction.
1247 The correction can be made via either a polynomial or a
1248 table-based interpolation (and extrapolation if necessary).
1249 You specify polynomial coefficients, an ascii table or neither.
1250 If you specify neither, then a polynomial correction will be made
1251 with built in coefficients known for certain telescopes (an error
1252 will occur if the instrument is not known).
1253 The data and Tsys are *divided* by the scaling factors.
1254 Parameters:
1255 poly: Polynomial coefficients (default None) to compute a
1256 gain-elevation correction as a function of
1257 elevation (in degrees).
1258 filename: The name of an ascii file holding correction factors.
1259 The first row of the ascii file must give the column
1260 names and these MUST include columns
1261 "ELEVATION" (degrees) and "FACTOR" (multiply data
1262 by this) somewhere.
1263 The second row must give the data type of the
1264 column. Use 'R' for Real and 'I' for Integer.
1265 An example file would be
1266 (actual factors are arbitrary) :
1267
1268 TIME ELEVATION FACTOR
1269 R R R
1270 0.1 0 0.8
1271 0.2 20 0.85
1272 0.3 40 0.9
1273 0.4 60 0.85
1274 0.5 80 0.8
1275 0.6 90 0.75
1276 method: Interpolation method when correcting from a table.
1277 Values are "nearest", "linear" (default), "cubic"
1278 and "spline"
1279 insitu: if False a new scantable is returned.
1280 Otherwise, the scaling is done in-situ
1281 The default is taken from .asaprc (False)
1282 """
1283
1284 if insitu is None: insitu = rcParams['insitu']
[876]1285 self._math._setinsitu(insitu)
[513]1286 varlist = vars()
1287 if poly is None:
[1118]1288 poly = ()
[513]1289 from os.path import expandvars
1290 filename = expandvars(filename)
[876]1291 s = scantable(self._math._gainel(self, poly, filename, method))
1292 s._add_history("gain_el", varlist)
1293 print_log()
1294 if insitu: self._assign(s)
1295 else: return s
[710]1296
[931]1297 def freq_align(self, reftime=None, method='cubic', insitu=None):
[513]1298 """
1299 Return a scan where all rows have been aligned in frequency/velocity.
1300 The alignment frequency frame (e.g. LSRK) is that set by function
1301 set_freqframe.
1302 Parameters:
1303 reftime: reference time to align at. By default, the time of
1304 the first row of data is used.
1305 method: Interpolation method for regridding the spectra.
1306 Choose from "nearest", "linear", "cubic" (default)
1307 and "spline"
1308 insitu: if False a new scantable is returned.
1309 Otherwise, the scaling is done in-situ
1310 The default is taken from .asaprc (False)
1311 """
[931]1312 if insitu is None: insitu = rcParams["insitu"]
[876]1313 self._math._setinsitu(insitu)
[513]1314 varlist = vars()
[931]1315 if reftime is None: reftime = ""
1316 s = scantable(self._math._freq_align(self, reftime, method))
[876]1317 s._add_history("freq_align", varlist)
1318 print_log()
1319 if insitu: self._assign(s)
1320 else: return s
[513]1321
[876]1322 def opacity(self, tau, insitu=None):
[513]1323 """
1324 Apply an opacity correction. The data
1325 and Tsys are multiplied by the correction factor.
1326 Parameters:
1327 tau: Opacity from which the correction factor is
1328 exp(tau*ZD)
1329 where ZD is the zenith-distance
1330 insitu: if False a new scantable is returned.
1331 Otherwise, the scaling is done in-situ
1332 The default is taken from .asaprc (False)
1333 """
1334 if insitu is None: insitu = rcParams['insitu']
[876]1335 self._math._setinsitu(insitu)
[513]1336 varlist = vars()
[876]1337 s = scantable(self._math._opacity(self, tau))
1338 s._add_history("opacity", varlist)
1339 print_log()
1340 if insitu: self._assign(s)
1341 else: return s
[513]1342
1343 def bin(self, width=5, insitu=None):
1344 """
1345 Return a scan where all spectra have been binned up.
[1348]1346 Parameters:
[513]1347 width: The bin width (default=5) in pixels
1348 insitu: if False a new scantable is returned.
1349 Otherwise, the scaling is done in-situ
1350 The default is taken from .asaprc (False)
1351 """
1352 if insitu is None: insitu = rcParams['insitu']
[876]1353 self._math._setinsitu(insitu)
[513]1354 varlist = vars()
[876]1355 s = scantable(self._math._bin(self, width))
[1118]1356 s._add_history("bin", varlist)
[876]1357 print_log()
1358 if insitu: self._assign(s)
1359 else: return s
[513]1360
[710]1361
[513]1362 def resample(self, width=5, method='cubic', insitu=None):
1363 """
[1348]1364 Return a scan where all spectra have been binned up.
1365
1366 Parameters:
[513]1367 width: The bin width (default=5) in pixels
1368 method: Interpolation method when correcting from a table.
1369 Values are "nearest", "linear", "cubic" (default)
1370 and "spline"
1371 insitu: if False a new scantable is returned.
1372 Otherwise, the scaling is done in-situ
1373 The default is taken from .asaprc (False)
1374 """
1375 if insitu is None: insitu = rcParams['insitu']
[876]1376 self._math._setinsitu(insitu)
[513]1377 varlist = vars()
[876]1378 s = scantable(self._math._resample(self, method, width))
[1118]1379 s._add_history("resample", varlist)
[876]1380 print_log()
1381 if insitu: self._assign(s)
1382 else: return s
[513]1383
1384
[946]1385 def average_pol(self, mask=None, weight='none'):
1386 """
1387 Average the Polarisations together.
1388 Parameters:
1389 mask: An optional mask defining the region, where the
1390 averaging will be applied. The output will have all
1391 specified points masked.
1392 weight: Weighting scheme. 'none' (default), 'var' (1/var(spec)
1393 weighted), or 'tsys' (1/Tsys**2 weighted)
1394 """
1395 varlist = vars()
1396 if mask is None:
1397 mask = ()
[1010]1398 s = scantable(self._math._averagepol(self, mask, weight.upper()))
[1118]1399 s._add_history("average_pol", varlist)
[946]1400 print_log()
[992]1401 return s
[513]1402
[1145]1403 def average_beam(self, mask=None, weight='none'):
1404 """
1405 Average the Beams together.
1406 Parameters:
1407 mask: An optional mask defining the region, where the
1408 averaging will be applied. The output will have all
1409 specified points masked.
1410 weight: Weighting scheme. 'none' (default), 'var' (1/var(spec)
1411 weighted), or 'tsys' (1/Tsys**2 weighted)
1412 """
1413 varlist = vars()
1414 if mask is None:
1415 mask = ()
1416 s = scantable(self._math._averagebeams(self, mask, weight.upper()))
1417 s._add_history("average_beam", varlist)
1418 print_log()
1419 return s
1420
[992]1421 def convert_pol(self, poltype=None):
1422 """
1423 Convert the data to a different polarisation type.
1424 Parameters:
1425 poltype: The new polarisation type. Valid types are:
1426 "linear", "stokes" and "circular"
1427 """
1428 varlist = vars()
1429 try:
1430 s = scantable(self._math._convertpol(self, poltype))
[1118]1431 except RuntimeError, msg:
[992]1432 if rcParams['verbose']:
[1612]1433 #print msg
1434 casalog.post( msg, 'WARN' )
[1118]1435 return
[992]1436 else:
1437 raise
[1118]1438 s._add_history("convert_pol", varlist)
[992]1439 print_log()
1440 return s
1441
[876]1442 def smooth(self, kernel="hanning", width=5.0, insitu=None):
[513]1443 """
1444 Smooth the spectrum by the specified kernel (conserving flux).
1445 Parameters:
1446 kernel: The type of smoothing kernel. Select from
[1373]1447 'hanning' (default), 'gaussian', 'boxcar' and
1448 'rmedian'
[513]1449 width: The width of the kernel in pixels. For hanning this is
1450 ignored otherwise it defauls to 5 pixels.
1451 For 'gaussian' it is the Full Width Half
1452 Maximum. For 'boxcar' it is the full width.
[1373]1453 For 'rmedian' it is the half width.
[513]1454 insitu: if False a new scantable is returned.
1455 Otherwise, the scaling is done in-situ
1456 The default is taken from .asaprc (False)
1457 Example:
1458 none
1459 """
1460 if insitu is None: insitu = rcParams['insitu']
[876]1461 self._math._setinsitu(insitu)
[513]1462 varlist = vars()
[1118]1463 s = scantable(self._math._smooth(self, kernel.lower(), width))
[876]1464 s._add_history("smooth", varlist)
1465 print_log()
1466 if insitu: self._assign(s)
1467 else: return s
[513]1468
[876]1469
[1389]1470 def poly_baseline(self, mask=None, order=0, plot=False, uselin=False, insitu=None):
[513]1471 """
1472 Return a scan which has been baselined (all rows) by a polynomial.
1473 Parameters:
[794]1474 mask: an optional mask
1475 order: the order of the polynomial (default is 0)
[1061]1476 plot: plot the fit and the residual. In this each
1477 indivual fit has to be approved, by typing 'y'
1478 or 'n'
[1389]1479 uselin: use linear polynomial fit
[794]1480 insitu: if False a new scantable is returned.
1481 Otherwise, the scaling is done in-situ
1482 The default is taken from .asaprc (False)
[513]1483 Example:
1484 # return a scan baselined by a third order polynomial,
1485 # not using a mask
1486 bscan = scan.poly_baseline(order=3)
[579]1487 """
[513]1488 if insitu is None: insitu = rcParams['insitu']
1489 varlist = vars()
1490 if mask is None:
[1295]1491 mask = [True for i in xrange(self.nchan(-1))]
[513]1492 from asap.asapfitter import fitter
[1217]1493 try:
1494 f = fitter()
1495 f.set_scan(self, mask)
[1389]1496 if uselin:
1497 f.set_function(lpoly=order)
1498 else:
1499 f.set_function(poly=order)
[1217]1500 s = f.auto_fit(insitu, plot=plot)
[1446]1501 # Save parameters of baseline fits as a class attribute.
1502 # NOTICE: It does not reflect changes in scantable!
1503 self.blpars = f.blpars
[1217]1504 s._add_history("poly_baseline", varlist)
1505 print_log()
1506 if insitu: self._assign(s)
1507 else: return s
1508 except RuntimeError:
1509 msg = "The fit failed, possibly because it didn't converge."
1510 if rcParams['verbose']:
[1612]1511 #print msg
1512 casalog.post( msg, 'WARN' )
[1217]1513 return
1514 else:
1515 raise RuntimeError(msg)
[513]1516
[1217]1517
[1118]1518 def auto_poly_baseline(self, mask=[], edge=(0, 0), order=0,
[1280]1519 threshold=3, chan_avg_limit=1, plot=False,
1520 insitu=None):
[880]1521 """
1522 Return a scan which has been baselined (all rows) by a polynomial.
1523 Spectral lines are detected first using linefinder and masked out
1524 to avoid them affecting the baseline solution.
1525
1526 Parameters:
1527 mask: an optional mask retreived from scantable
1528 edge: an optional number of channel to drop at
1529 the edge of spectrum. If only one value is
1530 specified, the same number will be dropped from
1531 both sides of the spectrum. Default is to keep
[907]1532 all channels. Nested tuples represent individual
[976]1533 edge selection for different IFs (a number of spectral
1534 channels can be different)
[880]1535 order: the order of the polynomial (default is 0)
1536 threshold: the threshold used by line finder. It is better to
1537 keep it large as only strong lines affect the
1538 baseline solution.
[1280]1539 chan_avg_limit:
1540 a maximum number of consequtive spectral channels to
1541 average during the search of weak and broad lines.
1542 The default is no averaging (and no search for weak
1543 lines). If such lines can affect the fitted baseline
1544 (e.g. a high order polynomial is fitted), increase this
1545 parameter (usually values up to 8 are reasonable). Most
1546 users of this method should find the default value
1547 sufficient.
[1061]1548 plot: plot the fit and the residual. In this each
1549 indivual fit has to be approved, by typing 'y'
1550 or 'n'
[880]1551 insitu: if False a new scantable is returned.
1552 Otherwise, the scaling is done in-situ
1553 The default is taken from .asaprc (False)
1554
1555 Example:
1556 scan2=scan.auto_poly_baseline(order=7)
1557 """
1558 if insitu is None: insitu = rcParams['insitu']
1559 varlist = vars()
1560 from asap.asapfitter import fitter
1561 from asap.asaplinefind import linefinder
1562 from asap import _is_sequence_or_number as _is_valid
1563
[976]1564 # check whether edge is set up for each IF individually
[1118]1565 individualedge = False;
1566 if len(edge) > 1:
1567 if isinstance(edge[0], list) or isinstance(edge[0], tuple):
1568 individualedge = True;
[907]1569
[1118]1570 if not _is_valid(edge, int) and not individualedge:
[909]1571 raise ValueError, "Parameter 'edge' has to be an integer or a \
[907]1572 pair of integers specified as a tuple. Nested tuples are allowed \
1573 to make individual selection for different IFs."
[919]1574
[1118]1575 curedge = (0, 0)
1576 if individualedge:
1577 for edgepar in edge:
1578 if not _is_valid(edgepar, int):
1579 raise ValueError, "Each element of the 'edge' tuple has \
1580 to be a pair of integers or an integer."
[907]1581 else:
[1118]1582 curedge = edge;
[880]1583
1584 # setup fitter
1585 f = fitter()
1586 f.set_function(poly=order)
1587
1588 # setup line finder
[1118]1589 fl = linefinder()
[1268]1590 fl.set_options(threshold=threshold,avg_limit=chan_avg_limit)
[880]1591
1592 if not insitu:
[1118]1593 workscan = self.copy()
[880]1594 else:
[1118]1595 workscan = self
[880]1596
[907]1597 fl.set_scan(workscan)
1598
[1118]1599 rows = range(workscan.nrow())
[1446]1600 # Save parameters of baseline fits & masklists as a class attribute.
1601 # NOTICE: It does not reflect changes in scantable!
1602 if len(rows) > 0:
1603 self.blpars=[]
1604 self.masklists=[]
[880]1605 asaplog.push("Processing:")
1606 for r in rows:
[1118]1607 msg = " Scan[%d] Beam[%d] IF[%d] Pol[%d] Cycle[%d]" % \
1608 (workscan.getscan(r), workscan.getbeam(r), workscan.getif(r), \
1609 workscan.getpol(r), workscan.getcycle(r))
[880]1610 asaplog.push(msg, False)
[907]1611
[976]1612 # figure out edge parameter
[1118]1613 if individualedge:
1614 if len(edge) >= workscan.getif(r):
1615 raise RuntimeError, "Number of edge elements appear to " \
1616 "be less than the number of IFs"
1617 curedge = edge[workscan.getif(r)]
[919]1618
[976]1619 # setup line finder
[1118]1620 fl.find_lines(r, mask, curedge)
[1446]1621 outmask=fl.get_mask()
[880]1622 f.set_scan(workscan, fl.get_mask())
1623 f.x = workscan._getabcissa(r)
1624 f.y = workscan._getspectrum(r)
1625 f.data = None
1626 f.fit()
[1446]1627
1628 # Show mask list
1629 masklist=workscan.get_masklist(fl.get_mask(),row=r)
1630 msg = "mask range: "+str(masklist)
1631 asaplog.push(msg, False)
1632
1633 fpar = f.get_parameters()
[1061]1634 if plot:
1635 f.plot(residual=True)
1636 x = raw_input("Accept fit ( [y]/n ): ")
1637 if x.upper() == 'N':
[1446]1638 self.blpars.append(None)
1639 self.masklists.append(None)
[1061]1640 continue
[880]1641 workscan._setspectrum(f.fitter.getresidual(), r)
[1446]1642 self.blpars.append(fpar)
1643 self.masklists.append(masklist)
[1061]1644 if plot:
1645 f._p.unmap()
1646 f._p = None
1647 workscan._add_history("auto_poly_baseline", varlist)
[880]1648 if insitu:
1649 self._assign(workscan)
1650 else:
1651 return workscan
1652
[914]1653 def rotate_linpolphase(self, angle):
1654 """
1655 Rotate the phase of the complex polarization O=Q+iU correlation.
1656 This is always done in situ in the raw data. So if you call this
1657 function more than once then each call rotates the phase further.
1658 Parameters:
1659 angle: The angle (degrees) to rotate (add) by.
1660 Examples:
1661 scan.rotate_linpolphase(2.3)
1662 """
1663 varlist = vars()
[936]1664 self._math._rotate_linpolphase(self, angle)
[914]1665 self._add_history("rotate_linpolphase", varlist)
1666 print_log()
1667 return
[710]1668
[513]1669
[914]1670 def rotate_xyphase(self, angle):
1671 """
1672 Rotate the phase of the XY correlation. This is always done in situ
1673 in the data. So if you call this function more than once
1674 then each call rotates the phase further.
1675 Parameters:
1676 angle: The angle (degrees) to rotate (add) by.
1677 Examples:
1678 scan.rotate_xyphase(2.3)
1679 """
1680 varlist = vars()
[936]1681 self._math._rotate_xyphase(self, angle)
[914]1682 self._add_history("rotate_xyphase", varlist)
1683 print_log()
1684 return
1685
1686 def swap_linears(self):
1687 """
[1348]1688 Swap the linear polarisations XX and YY, or better the first two
1689 polarisations as this also works for ciculars.
[914]1690 """
1691 varlist = vars()
[936]1692 self._math._swap_linears(self)
[914]1693 self._add_history("swap_linears", varlist)
1694 print_log()
1695 return
1696
1697 def invert_phase(self):
1698 """
1699 Invert the phase of the complex polarisation
1700 """
1701 varlist = vars()
[936]1702 self._math._invert_phase(self)
[914]1703 self._add_history("invert_phase", varlist)
1704 print_log()
1705 return
1706
[876]1707 def add(self, offset, insitu=None):
[513]1708 """
1709 Return a scan where all spectra have the offset added
1710 Parameters:
1711 offset: the offset
1712 insitu: if False a new scantable is returned.
1713 Otherwise, the scaling is done in-situ
1714 The default is taken from .asaprc (False)
1715 """
1716 if insitu is None: insitu = rcParams['insitu']
[876]1717 self._math._setinsitu(insitu)
[513]1718 varlist = vars()
[876]1719 s = scantable(self._math._unaryop(self, offset, "ADD", False))
[1118]1720 s._add_history("add", varlist)
[876]1721 print_log()
1722 if insitu:
1723 self._assign(s)
1724 else:
[513]1725 return s
1726
[1308]1727 def scale(self, factor, tsys=True, insitu=None):
[513]1728 """
1729 Return a scan where all spectra are scaled by the give 'factor'
1730 Parameters:
1731 factor: the scaling factor
1732 insitu: if False a new scantable is returned.
1733 Otherwise, the scaling is done in-situ
1734 The default is taken from .asaprc (False)
1735 tsys: if True (default) then apply the operation to Tsys
1736 as well as the data
1737 """
1738 if insitu is None: insitu = rcParams['insitu']
[876]1739 self._math._setinsitu(insitu)
[513]1740 varlist = vars()
[876]1741 s = scantable(self._math._unaryop(self, factor, "MUL", tsys))
[1118]1742 s._add_history("scale", varlist)
[876]1743 print_log()
1744 if insitu:
1745 self._assign(s)
1746 else:
[513]1747 return s
1748
[1603]1749 def set_sourcetype(self, match, matchtype="pattern",
1750 sourcetype="reference"):
1751 """
1752 Set the type of the source to be an source or reference scan
1753 using the provided pattern:
1754 Parameters:
1755 match: a Unix style pattern, regular expression or selector
1756 matchtype: 'pattern' (default) UNIX style pattern or
1757 'regex' regular expression
1758 sourcetype: the type of the source to use (source/reference)
1759 """
1760 varlist = vars()
1761 basesel = self.get_selection()
1762 stype = -1
1763 if sourcetype.lower().startswith("r"):
1764 stype = 1
1765 elif sourcetype.lower().startswith("s"):
1766 stype = 0
1767 else:
1768 raise ValueError("Illegal sourcetype use s(ource) or r(eference)")
1769 if matchtype.lower().startswith("p"):
1770 matchtype = "pattern"
1771 elif matchtype.lower().startswith("r"):
1772 matchtype = "regex"
1773 else:
1774 raise ValueError("Illegal matchtype, use p(attern) or r(egex)")
1775 sel = selector()
1776 if isinstance(match, selector):
1777 sel = match
1778 else:
1779 sel.set_query("SRCNAME == %s('%s')" % (matchtype, match))
1780 self.set_selection(basesel+sel)
1781 self._setsourcetype(stype)
1782 self.set_selection(basesel)
1783 s._add_history("set_sourcetype", varlist)
1784
[1348]1785 def auto_quotient(self, preserve=True, mode='paired'):
[670]1786 """
1787 This function allows to build quotients automatically.
1788 It assumes the observation to have the same numer of
1789 "ons" and "offs"
1790 Parameters:
[710]1791 preserve: you can preserve (default) the continuum or
1792 remove it. The equations used are
[670]1793 preserve: Output = Toff * (on/off) - Toff
[1070]1794 remove: Output = Toff * (on/off) - Ton
[1348]1795 mode: the on/off detection mode
1796 'paired' (default)
1797 identifies 'off' scans by the
1798 trailing '_R' (Mopra/Parkes) or
1799 '_e'/'_w' (Tid) and matches
1800 on/off pairs from the observing pattern
[1603]1801 'time'
1802 finds the closest off in time
[1348]1803
[670]1804 """
[1348]1805 modes = ["time", "paired"]
[670]1806 if not mode in modes:
[876]1807 msg = "please provide valid mode. Valid modes are %s" % (modes)
1808 raise ValueError(msg)
1809 varlist = vars()
[1348]1810 s = None
1811 if mode.lower() == "paired":
1812 basesel = self.get_selection()
[1356]1813 sel = selector()+basesel
1814 sel.set_query("SRCTYPE==1")
1815 self.set_selection(sel)
[1348]1816 offs = self.copy()
1817 sel.set_query("SRCTYPE==0")
[1356]1818 self.set_selection(sel)
[1348]1819 ons = self.copy()
1820 s = scantable(self._math._quotient(ons, offs, preserve))
1821 self.set_selection(basesel)
1822 elif mode.lower() == "time":
1823 s = scantable(self._math._auto_quotient(self, mode, preserve))
[1118]1824 s._add_history("auto_quotient", varlist)
[876]1825 print_log()
1826 return s
[710]1827
[1145]1828 def mx_quotient(self, mask = None, weight='median', preserve=True):
[1141]1829 """
[1143]1830 Form a quotient using "off" beams when observing in "MX" mode.
1831 Parameters:
[1145]1832 mask: an optional mask to be used when weight == 'stddev'
[1143]1833 weight: How to average the off beams. Default is 'median'.
[1145]1834 preserve: you can preserve (default) the continuum or
1835 remove it. The equations used are
1836 preserve: Output = Toff * (on/off) - Toff
1837 remove: Output = Toff * (on/off) - Ton
[1217]1838 """
[1143]1839 if mask is None: mask = ()
[1141]1840 varlist = vars()
1841 on = scantable(self._math._mx_extract(self, 'on'))
[1143]1842 preoff = scantable(self._math._mx_extract(self, 'off'))
1843 off = preoff.average_time(mask=mask, weight=weight, scanav=False)
[1217]1844 from asapmath import quotient
[1145]1845 q = quotient(on, off, preserve)
[1143]1846 q._add_history("mx_quotient", varlist)
[1145]1847 print_log()
[1217]1848 return q
[513]1849
[718]1850 def freq_switch(self, insitu=None):
1851 """
1852 Apply frequency switching to the data.
1853 Parameters:
1854 insitu: if False a new scantable is returned.
1855 Otherwise, the swictching is done in-situ
1856 The default is taken from .asaprc (False)
1857 Example:
1858 none
1859 """
1860 if insitu is None: insitu = rcParams['insitu']
[876]1861 self._math._setinsitu(insitu)
[718]1862 varlist = vars()
[876]1863 s = scantable(self._math._freqswitch(self))
[1118]1864 s._add_history("freq_switch", varlist)
[876]1865 print_log()
1866 if insitu: self._assign(s)
1867 else: return s
[718]1868
[780]1869 def recalc_azel(self):
1870 """
1871 Recalculate the azimuth and elevation for each position.
1872 Parameters:
1873 none
1874 Example:
1875 """
1876 varlist = vars()
[876]1877 self._recalcazel()
[780]1878 self._add_history("recalc_azel", varlist)
1879 print_log()
1880 return
1881
[513]1882 def __add__(self, other):
1883 varlist = vars()
1884 s = None
1885 if isinstance(other, scantable):
[1308]1886 s = scantable(self._math._binaryop(self, other, "ADD"))
[513]1887 elif isinstance(other, float):
[876]1888 s = scantable(self._math._unaryop(self, other, "ADD", False))
[513]1889 else:
[718]1890 raise TypeError("Other input is not a scantable or float value")
[513]1891 s._add_history("operator +", varlist)
[718]1892 print_log()
[513]1893 return s
1894
1895 def __sub__(self, other):
1896 """
1897 implicit on all axes and on Tsys
1898 """
1899 varlist = vars()
1900 s = None
1901 if isinstance(other, scantable):
[1308]1902 s = scantable(self._math._binaryop(self, other, "SUB"))
[513]1903 elif isinstance(other, float):
[876]1904 s = scantable(self._math._unaryop(self, other, "SUB", False))
[513]1905 else:
[718]1906 raise TypeError("Other input is not a scantable or float value")
[513]1907 s._add_history("operator -", varlist)
[718]1908 print_log()
[513]1909 return s
[710]1910
[513]1911 def __mul__(self, other):
1912 """
1913 implicit on all axes and on Tsys
1914 """
1915 varlist = vars()
1916 s = None
1917 if isinstance(other, scantable):
[1308]1918 s = scantable(self._math._binaryop(self, other, "MUL"))
[513]1919 elif isinstance(other, float):
[876]1920 s = scantable(self._math._unaryop(self, other, "MUL", False))
[513]1921 else:
[718]1922 raise TypeError("Other input is not a scantable or float value")
[513]1923 s._add_history("operator *", varlist)
[718]1924 print_log()
[513]1925 return s
1926
[710]1927
[513]1928 def __div__(self, other):
1929 """
1930 implicit on all axes and on Tsys
1931 """
1932 varlist = vars()
1933 s = None
1934 if isinstance(other, scantable):
[1308]1935 s = scantable(self._math._binaryop(self, other, "DIV"))
[513]1936 elif isinstance(other, float):
1937 if other == 0.0:
[718]1938 raise ZeroDivisionError("Dividing by zero is not recommended")
[876]1939 s = scantable(self._math._unaryop(self, other, "DIV", False))
[513]1940 else:
[718]1941 raise TypeError("Other input is not a scantable or float value")
[513]1942 s._add_history("operator /", varlist)
[718]1943 print_log()
[513]1944 return s
1945
[530]1946 def get_fit(self, row=0):
1947 """
1948 Print or return the stored fits for a row in the scantable
1949 Parameters:
1950 row: the row which the fit has been applied to.
1951 """
1952 if row > self.nrow():
1953 return
[976]1954 from asap.asapfit import asapfit
[530]1955 fit = asapfit(self._getfit(row))
[718]1956 if rcParams['verbose']:
[1612]1957 #print fit
1958 casalog.post( '%s' %(fit) )
[530]1959 return
1960 else:
1961 return fit.as_dict()
1962
[1603]1963 def flag_nans(self):
1964 """
1965 Utility function to flag NaN values in the scantable.
1966 """
1967 import numpy
1968 basesel = self.get_selection()
1969 for i in range(self.nrow()):
1970 sel = selector()+basesel
1971 sel.set_scans(self.getscan(i))
1972 sel.set_beams(self.getbeam(i))
1973 sel.set_ifs(self.getif(i))
1974 sel.set_polarisations(self.getpol(i))
1975 self.set_selection(sel)
1976 nans = numpy.isnan(self._getspectrum(0))
1977 if numpy.any(nans):
1978 bnans = [ bool(v) for v in nans]
1979 self.flag(bnans)
1980 self.set_selection(basesel)
1981
1982
[484]1983 def _add_history(self, funcname, parameters):
[1603]1984 if not rcParams['scantable.history']:
1985 return
[484]1986 # create date
1987 sep = "##"
1988 from datetime import datetime
1989 dstr = datetime.now().strftime('%Y/%m/%d %H:%M:%S')
1990 hist = dstr+sep
1991 hist += funcname+sep#cdate+sep
1992 if parameters.has_key('self'): del parameters['self']
[1118]1993 for k, v in parameters.iteritems():
[484]1994 if type(v) is dict:
[1118]1995 for k2, v2 in v.iteritems():
[484]1996 hist += k2
1997 hist += "="
[1118]1998 if isinstance(v2, scantable):
[484]1999 hist += 'scantable'
2000 elif k2 == 'mask':
[1118]2001 if isinstance(v2, list) or isinstance(v2, tuple):
[513]2002 hist += str(self._zip_mask(v2))
2003 else:
2004 hist += str(v2)
[484]2005 else:
[513]2006 hist += str(v2)
[484]2007 else:
2008 hist += k
2009 hist += "="
[1118]2010 if isinstance(v, scantable):
[484]2011 hist += 'scantable'
2012 elif k == 'mask':
[1118]2013 if isinstance(v, list) or isinstance(v, tuple):
[513]2014 hist += str(self._zip_mask(v))
2015 else:
2016 hist += str(v)
[484]2017 else:
2018 hist += str(v)
2019 hist += sep
2020 hist = hist[:-2] # remove trailing '##'
2021 self._addhistory(hist)
2022
[710]2023
[484]2024 def _zip_mask(self, mask):
2025 mask = list(mask)
2026 i = 0
2027 segments = []
2028 while mask[i:].count(1):
2029 i += mask[i:].index(1)
2030 if mask[i:].count(0):
2031 j = i + mask[i:].index(0)
2032 else:
[710]2033 j = len(mask)
[1118]2034 segments.append([i, j])
[710]2035 i = j
[484]2036 return segments
[714]2037
[626]2038 def _get_ordinate_label(self):
2039 fu = "("+self.get_fluxunit()+")"
2040 import re
2041 lbl = "Intensity"
[1118]2042 if re.match(".K.", fu):
[626]2043 lbl = "Brightness Temperature "+ fu
[1118]2044 elif re.match(".Jy.", fu):
[626]2045 lbl = "Flux density "+ fu
2046 return lbl
[710]2047
[876]2048 def _check_ifs(self):
2049 nchans = [self.nchan(i) for i in range(self.nif(-1))]
[889]2050 nchans = filter(lambda t: t > 0, nchans)
[876]2051 return (sum(nchans)/len(nchans) == nchans[0])
[976]2052
[1496]2053 def _fill(self, names, unit, average, getpt):
[976]2054 import os
2055 from asap._asap import stfiller
2056 first = True
2057 fullnames = []
2058 for name in names:
2059 name = os.path.expandvars(name)
2060 name = os.path.expanduser(name)
2061 if not os.path.exists(name):
2062 msg = "File '%s' does not exists" % (name)
2063 if rcParams['verbose']:
2064 asaplog.push(msg)
[1612]2065 #print asaplog.pop().strip()
2066 casalog.post( asaplog.pop().strip(), 'WARN' )
[976]2067 return
2068 raise IOError(msg)
2069 fullnames.append(name)
2070 if average:
2071 asaplog.push('Auto averaging integrations')
[1079]2072 stype = int(rcParams['scantable.storage'].lower() == 'disk')
[976]2073 for name in fullnames:
[1073]2074 tbl = Scantable(stype)
2075 r = stfiller(tbl)
[1603]2076 rx = rcParams['scantable.reference']
2077 r._setreferenceexpr(rx)
[976]2078 msg = "Importing %s..." % (name)
[1118]2079 asaplog.push(msg, False)
[976]2080 print_log()
[1496]2081 r._open(name, -1, -1, getpt)
[976]2082 r._read()
2083 if average:
[1118]2084 tbl = self._math._average((tbl, ), (), 'NONE', 'SCAN')
[976]2085 if not first:
2086 tbl = self._math._merge([self, tbl])
2087 Scantable.__init__(self, tbl)
2088 r._close()
[1118]2089 del r, tbl
[976]2090 first = False
2091 if unit is not None:
2092 self.set_fluxunit(unit)
[1446]2093 #self.set_freqframe(rcParams['scantable.freqframe'])
[976]2094
[1603]2095 def __getitem__(self, key):
2096 if key < 0:
2097 key += self.nrow()
2098 if key >= self.nrow():
2099 raise IndexError("Row index out of range.")
2100 return self._getspectrum(key)
2101
2102 def __setitem__(self, key, value):
2103 if key < 0:
2104 key += self.nrow()
2105 if key >= self.nrow():
2106 raise IndexError("Row index out of range.")
2107 if not hasattr(value, "__len__") or \
2108 len(value) > self.nchan(self.getif(key)):
2109 raise ValueError("Spectrum length doesn't match.")
2110 return self._setspectrum(value, key)
2111
2112 def __len__(self):
2113 return self.nrow()
2114
2115 def __iter__(self):
2116 for i in range(len(self)):
2117 yield self[i]
Note: See TracBrowser for help on using the repository browser.