source: trunk/python/scantable.py@ 1150

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

added average_beam which is part of Ticket #45

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