source: trunk/python/scantable.py@ 1144

Last change on this file since 1144 was 1143, checked in by mar637, 18 years ago

Implemented Ticket #45 as scantable.mx_quotient.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 57.9 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 convert_pol(self, poltype=None):
1024 """
1025 Convert the data to a different polarisation type.
1026 Parameters:
1027 poltype: The new polarisation type. Valid types are:
1028 "linear", "stokes" and "circular"
1029 """
1030 varlist = vars()
1031 try:
1032 s = scantable(self._math._convertpol(self, poltype))
1033 except RuntimeError, msg:
1034 if rcParams['verbose']:
1035 print msg
1036 return
1037 else:
1038 raise
1039 s._add_history("convert_pol", varlist)
1040 print_log()
1041 return s
1042
1043 def smooth(self, kernel="hanning", width=5.0, insitu=None):
1044 """
1045 Smooth the spectrum by the specified kernel (conserving flux).
1046 Parameters:
1047 scan: The input scan
1048 kernel: The type of smoothing kernel. Select from
1049 'hanning' (default), 'gaussian' and 'boxcar'.
1050 The first three characters are sufficient.
1051 width: The width of the kernel in pixels. For hanning this is
1052 ignored otherwise it defauls to 5 pixels.
1053 For 'gaussian' it is the Full Width Half
1054 Maximum. For 'boxcar' it is the full width.
1055 insitu: if False a new scantable is returned.
1056 Otherwise, the scaling is done in-situ
1057 The default is taken from .asaprc (False)
1058 Example:
1059 none
1060 """
1061 if insitu is None: insitu = rcParams['insitu']
1062 self._math._setinsitu(insitu)
1063 varlist = vars()
1064 s = scantable(self._math._smooth(self, kernel.lower(), width))
1065 s._add_history("smooth", varlist)
1066 print_log()
1067 if insitu: self._assign(s)
1068 else: return s
1069
1070
1071 def poly_baseline(self, mask=None, order=0, plot=False, insitu=None):
1072 """
1073 Return a scan which has been baselined (all rows) by a polynomial.
1074 Parameters:
1075 scan: a scantable
1076 mask: an optional mask
1077 order: the order of the polynomial (default is 0)
1078 plot: plot the fit and the residual. In this each
1079 indivual fit has to be approved, by typing 'y'
1080 or 'n'
1081 insitu: if False a new scantable is returned.
1082 Otherwise, the scaling is done in-situ
1083 The default is taken from .asaprc (False)
1084 Example:
1085 # return a scan baselined by a third order polynomial,
1086 # not using a mask
1087 bscan = scan.poly_baseline(order=3)
1088 """
1089 if insitu is None: insitu = rcParams['insitu']
1090 varlist = vars()
1091 if mask is None:
1092 mask = list(NUM.ones(self.nchan(-1)))
1093 from asap.asapfitter import fitter
1094 f = fitter()
1095 f.set_scan(self, mask)
1096 f.set_function(poly=order)
1097 s = f.auto_fit(insitu, plot=plot)
1098 s._add_history("poly_baseline", varlist)
1099 print_log()
1100 if insitu: self._assign(s)
1101 else: return s
1102
1103 def auto_poly_baseline(self, mask=[], edge=(0, 0), order=0,
1104 threshold=3, plot=False, insitu=None):
1105 """
1106 Return a scan which has been baselined (all rows) by a polynomial.
1107 Spectral lines are detected first using linefinder and masked out
1108 to avoid them affecting the baseline solution.
1109
1110 Parameters:
1111 mask: an optional mask retreived from scantable
1112 edge: an optional number of channel to drop at
1113 the edge of spectrum. If only one value is
1114 specified, the same number will be dropped from
1115 both sides of the spectrum. Default is to keep
1116 all channels. Nested tuples represent individual
1117 edge selection for different IFs (a number of spectral
1118 channels can be different)
1119 order: the order of the polynomial (default is 0)
1120 threshold: the threshold used by line finder. It is better to
1121 keep it large as only strong lines affect the
1122 baseline solution.
1123 plot: plot the fit and the residual. In this each
1124 indivual fit has to be approved, by typing 'y'
1125 or 'n'
1126 insitu: if False a new scantable is returned.
1127 Otherwise, the scaling is done in-situ
1128 The default is taken from .asaprc (False)
1129
1130 Example:
1131 scan2=scan.auto_poly_baseline(order=7)
1132 """
1133 if insitu is None: insitu = rcParams['insitu']
1134 varlist = vars()
1135 from asap.asapfitter import fitter
1136 from asap.asaplinefind import linefinder
1137 from asap import _is_sequence_or_number as _is_valid
1138
1139 # check whether edge is set up for each IF individually
1140 individualedge = False;
1141 if len(edge) > 1:
1142 if isinstance(edge[0], list) or isinstance(edge[0], tuple):
1143 individualedge = True;
1144
1145 if not _is_valid(edge, int) and not individualedge:
1146 raise ValueError, "Parameter 'edge' has to be an integer or a \
1147 pair of integers specified as a tuple. Nested tuples are allowed \
1148 to make individual selection for different IFs."
1149
1150 curedge = (0, 0)
1151 if individualedge:
1152 for edgepar in edge:
1153 if not _is_valid(edgepar, int):
1154 raise ValueError, "Each element of the 'edge' tuple has \
1155 to be a pair of integers or an integer."
1156 else:
1157 curedge = edge;
1158
1159 # setup fitter
1160 f = fitter()
1161 f.set_function(poly=order)
1162
1163 # setup line finder
1164 fl = linefinder()
1165 fl.set_options(threshold=threshold)
1166
1167 if not insitu:
1168 workscan = self.copy()
1169 else:
1170 workscan = self
1171
1172 fl.set_scan(workscan)
1173
1174 rows = range(workscan.nrow())
1175 asaplog.push("Processing:")
1176 for r in rows:
1177 msg = " Scan[%d] Beam[%d] IF[%d] Pol[%d] Cycle[%d]" % \
1178 (workscan.getscan(r), workscan.getbeam(r), workscan.getif(r), \
1179 workscan.getpol(r), workscan.getcycle(r))
1180 asaplog.push(msg, False)
1181
1182 # figure out edge parameter
1183 if individualedge:
1184 if len(edge) >= workscan.getif(r):
1185 raise RuntimeError, "Number of edge elements appear to " \
1186 "be less than the number of IFs"
1187 curedge = edge[workscan.getif(r)]
1188
1189 # setup line finder
1190 fl.find_lines(r, mask, curedge)
1191 f.set_scan(workscan, fl.get_mask())
1192 f.x = workscan._getabcissa(r)
1193 f.y = workscan._getspectrum(r)
1194 f.data = None
1195 f.fit()
1196 x = f.get_parameters()
1197 if plot:
1198 f.plot(residual=True)
1199 x = raw_input("Accept fit ( [y]/n ): ")
1200 if x.upper() == 'N':
1201 continue
1202 workscan._setspectrum(f.fitter.getresidual(), r)
1203 if plot:
1204 f._p.unmap()
1205 f._p = None
1206 workscan._add_history("auto_poly_baseline", varlist)
1207 if insitu:
1208 self._assign(workscan)
1209 else:
1210 return workscan
1211
1212 def rotate_linpolphase(self, angle):
1213 """
1214 Rotate the phase of the complex polarization O=Q+iU correlation.
1215 This is always done in situ in the raw data. So if you call this
1216 function more than once then each call rotates the phase further.
1217 Parameters:
1218 angle: The angle (degrees) to rotate (add) by.
1219 Examples:
1220 scan.rotate_linpolphase(2.3)
1221 """
1222 varlist = vars()
1223 self._math._rotate_linpolphase(self, angle)
1224 self._add_history("rotate_linpolphase", varlist)
1225 print_log()
1226 return
1227
1228
1229 def rotate_xyphase(self, angle):
1230 """
1231 Rotate the phase of the XY correlation. This is always done in situ
1232 in the data. So if you call this function more than once
1233 then each call rotates the phase further.
1234 Parameters:
1235 angle: The angle (degrees) to rotate (add) by.
1236 Examples:
1237 scan.rotate_xyphase(2.3)
1238 """
1239 varlist = vars()
1240 self._math._rotate_xyphase(self, angle)
1241 self._add_history("rotate_xyphase", varlist)
1242 print_log()
1243 return
1244
1245 def swap_linears(self):
1246 """
1247 Swap the linear polarisations XX and YY
1248 """
1249 varlist = vars()
1250 self._math._swap_linears(self)
1251 self._add_history("swap_linears", varlist)
1252 print_log()
1253 return
1254
1255 def invert_phase(self):
1256 """
1257 Invert the phase of the complex polarisation
1258 """
1259 varlist = vars()
1260 self._math._invert_phase(self)
1261 self._add_history("invert_phase", varlist)
1262 print_log()
1263 return
1264
1265 def add(self, offset, insitu=None):
1266 """
1267 Return a scan where all spectra have the offset added
1268 Parameters:
1269 offset: the offset
1270 insitu: if False a new scantable is returned.
1271 Otherwise, the scaling is done in-situ
1272 The default is taken from .asaprc (False)
1273 """
1274 if insitu is None: insitu = rcParams['insitu']
1275 self._math._setinsitu(insitu)
1276 varlist = vars()
1277 s = scantable(self._math._unaryop(self, offset, "ADD", False))
1278 s._add_history("add", varlist)
1279 print_log()
1280 if insitu:
1281 self._assign(s)
1282 else:
1283 return s
1284
1285 def scale(self, factor, tsys=True, insitu=None, ):
1286 """
1287 Return a scan where all spectra are scaled by the give 'factor'
1288 Parameters:
1289 factor: the scaling factor
1290 insitu: if False a new scantable is returned.
1291 Otherwise, the scaling is done in-situ
1292 The default is taken from .asaprc (False)
1293 tsys: if True (default) then apply the operation to Tsys
1294 as well as the data
1295 """
1296 if insitu is None: insitu = rcParams['insitu']
1297 self._math._setinsitu(insitu)
1298 varlist = vars()
1299 s = scantable(self._math._unaryop(self, factor, "MUL", tsys))
1300 s._add_history("scale", varlist)
1301 print_log()
1302 if insitu:
1303 self._assign(s)
1304 else:
1305 return s
1306
1307 def auto_quotient(self, mode='time', preserve=True):
1308 """
1309 This function allows to build quotients automatically.
1310 It assumes the observation to have the same numer of
1311 "ons" and "offs"
1312 It will support "closest off in time" in the future
1313 Parameters:
1314 mode: the on/off detection mode; 'suffix' (default)
1315 'suffix' identifies 'off' scans by the
1316 trailing '_R' (Mopra/Parkes) or
1317 '_e'/'_w' (Tid)
1318 preserve: you can preserve (default) the continuum or
1319 remove it. The equations used are
1320 preserve: Output = Toff * (on/off) - Toff
1321 remove: Output = Toff * (on/off) - Ton
1322 """
1323 modes = ["time"]
1324 if not mode in modes:
1325 msg = "please provide valid mode. Valid modes are %s" % (modes)
1326 raise ValueError(msg)
1327 varlist = vars()
1328 s = scantable(self._math._auto_quotient(self, mode, preserve))
1329 s._add_history("auto_quotient", varlist)
1330 print_log()
1331 return s
1332
1333 def mx_quotient(self, mask = None, weight='median'):
1334 """
1335 Form a quotient using "off" beams when observing in "MX" mode.
1336 Parameters:
1337 weight: How to average the off beams. Default is 'median'.
1338 """
1339 if mask is None: mask = ()
1340 varlist = vars()
1341 on = scantable(self._math._mx_extract(self, 'on'))
1342 preoff = scantable(self._math._mx_extract(self, 'off'))
1343 off = preoff.average_time(mask=mask, weight=weight, scanav=False)
1344 print_log()
1345 from asapmath import quotient
1346 q = quotient(on, off)
1347 q._add_history("mx_quotient", varlist)
1348 return q
1349
1350 def freq_switch(self, insitu=None):
1351 """
1352 Apply frequency switching to the data.
1353 Parameters:
1354 insitu: if False a new scantable is returned.
1355 Otherwise, the swictching is done in-situ
1356 The default is taken from .asaprc (False)
1357 Example:
1358 none
1359 """
1360 if insitu is None: insitu = rcParams['insitu']
1361 self._math._setinsitu(insitu)
1362 varlist = vars()
1363 s = scantable(self._math._freqswitch(self))
1364 s._add_history("freq_switch", varlist)
1365 print_log()
1366 if insitu: self._assign(s)
1367 else: return s
1368
1369 def recalc_azel(self):
1370 """
1371 Recalculate the azimuth and elevation for each position.
1372 Parameters:
1373 none
1374 Example:
1375 """
1376 varlist = vars()
1377 self._recalcazel()
1378 self._add_history("recalc_azel", varlist)
1379 print_log()
1380 return
1381
1382 def __add__(self, other):
1383 varlist = vars()
1384 s = None
1385 if isinstance(other, scantable):
1386 print "scantable + scantable NYI"
1387 return
1388 elif isinstance(other, float):
1389 s = scantable(self._math._unaryop(self, other, "ADD", False))
1390 else:
1391 raise TypeError("Other input is not a scantable or float value")
1392 s._add_history("operator +", varlist)
1393 print_log()
1394 return s
1395
1396 def __sub__(self, other):
1397 """
1398 implicit on all axes and on Tsys
1399 """
1400 varlist = vars()
1401 s = None
1402 if isinstance(other, scantable):
1403 print "scantable - scantable NYI"
1404 return
1405 elif isinstance(other, float):
1406 s = scantable(self._math._unaryop(self, other, "SUB", False))
1407 else:
1408 raise TypeError("Other input is not a scantable or float value")
1409 s._add_history("operator -", varlist)
1410 print_log()
1411 return s
1412
1413 def __mul__(self, other):
1414 """
1415 implicit on all axes and on Tsys
1416 """
1417 varlist = vars()
1418 s = None
1419 if isinstance(other, scantable):
1420 print "scantable * scantable NYI"
1421 return
1422 elif isinstance(other, float):
1423 s = scantable(self._math._unaryop(self, other, "MUL", False))
1424 else:
1425 raise TypeError("Other input is not a scantable or float value")
1426 s._add_history("operator *", varlist)
1427 print_log()
1428 return s
1429
1430
1431 def __div__(self, other):
1432 """
1433 implicit on all axes and on Tsys
1434 """
1435 varlist = vars()
1436 s = None
1437 if isinstance(other, scantable):
1438 print "scantable / scantable NYI"
1439 return
1440 elif isinstance(other, float):
1441 if other == 0.0:
1442 raise ZeroDivisionError("Dividing by zero is not recommended")
1443 s = scantable(self._math._unaryop(self, other, "DIV", False))
1444 else:
1445 raise TypeError("Other input is not a scantable or float value")
1446 s._add_history("operator /", varlist)
1447 print_log()
1448 return s
1449
1450 def get_fit(self, row=0):
1451 """
1452 Print or return the stored fits for a row in the scantable
1453 Parameters:
1454 row: the row which the fit has been applied to.
1455 """
1456 if row > self.nrow():
1457 return
1458 from asap.asapfit import asapfit
1459 fit = asapfit(self._getfit(row))
1460 if rcParams['verbose']:
1461 print fit
1462 return
1463 else:
1464 return fit.as_dict()
1465
1466 def _add_history(self, funcname, parameters):
1467 # create date
1468 sep = "##"
1469 from datetime import datetime
1470 dstr = datetime.now().strftime('%Y/%m/%d %H:%M:%S')
1471 hist = dstr+sep
1472 hist += funcname+sep#cdate+sep
1473 if parameters.has_key('self'): del parameters['self']
1474 for k, v in parameters.iteritems():
1475 if type(v) is dict:
1476 for k2, v2 in v.iteritems():
1477 hist += k2
1478 hist += "="
1479 if isinstance(v2, scantable):
1480 hist += 'scantable'
1481 elif k2 == 'mask':
1482 if isinstance(v2, list) or isinstance(v2, tuple):
1483 hist += str(self._zip_mask(v2))
1484 else:
1485 hist += str(v2)
1486 else:
1487 hist += str(v2)
1488 else:
1489 hist += k
1490 hist += "="
1491 if isinstance(v, scantable):
1492 hist += 'scantable'
1493 elif k == 'mask':
1494 if isinstance(v, list) or isinstance(v, tuple):
1495 hist += str(self._zip_mask(v))
1496 else:
1497 hist += str(v)
1498 else:
1499 hist += str(v)
1500 hist += sep
1501 hist = hist[:-2] # remove trailing '##'
1502 self._addhistory(hist)
1503
1504
1505 def _zip_mask(self, mask):
1506 mask = list(mask)
1507 i = 0
1508 segments = []
1509 while mask[i:].count(1):
1510 i += mask[i:].index(1)
1511 if mask[i:].count(0):
1512 j = i + mask[i:].index(0)
1513 else:
1514 j = len(mask)
1515 segments.append([i, j])
1516 i = j
1517 return segments
1518
1519 def _get_ordinate_label(self):
1520 fu = "("+self.get_fluxunit()+")"
1521 import re
1522 lbl = "Intensity"
1523 if re.match(".K.", fu):
1524 lbl = "Brightness Temperature "+ fu
1525 elif re.match(".Jy.", fu):
1526 lbl = "Flux density "+ fu
1527 return lbl
1528
1529 def _check_ifs(self):
1530 nchans = [self.nchan(i) for i in range(self.nif(-1))]
1531 nchans = filter(lambda t: t > 0, nchans)
1532 return (sum(nchans)/len(nchans) == nchans[0])
1533
1534 def _fill(self, names, unit, average):
1535 import os
1536 from asap._asap import stfiller
1537 first = True
1538 fullnames = []
1539 for name in names:
1540 name = os.path.expandvars(name)
1541 name = os.path.expanduser(name)
1542 if not os.path.exists(name):
1543 msg = "File '%s' does not exists" % (name)
1544 if rcParams['verbose']:
1545 asaplog.push(msg)
1546 print asaplog.pop().strip()
1547 return
1548 raise IOError(msg)
1549 fullnames.append(name)
1550 if average:
1551 asaplog.push('Auto averaging integrations')
1552 stype = int(rcParams['scantable.storage'].lower() == 'disk')
1553 for name in fullnames:
1554 tbl = Scantable(stype)
1555 r = stfiller(tbl)
1556 msg = "Importing %s..." % (name)
1557 asaplog.push(msg, False)
1558 print_log()
1559 r._open(name, -1, -1)
1560 r._read()
1561 #tbl = r._getdata()
1562 if average:
1563 tbl = self._math._average((tbl, ), (), 'NONE', 'SCAN')
1564 #tbl = tbl2
1565 if not first:
1566 tbl = self._math._merge([self, tbl])
1567 #tbl = tbl2
1568 Scantable.__init__(self, tbl)
1569 r._close()
1570 del r, tbl
1571 first = False
1572 if unit is not None:
1573 self.set_fluxunit(unit)
1574 self.set_freqframe(rcParams['scantable.freqframe'])
1575 #self._add_history("scantable", varlist)
1576
Note: See TracBrowser for help on using the repository browser.