source: trunk/python/scantable.py@ 1140

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

added numpy/numarray detection

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