source: trunk/python/scantable.py@ 1090

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

make storage rcparam casa-insensitive

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