source: branches/Release12/python/scantable.py@ 799

Last change on this file since 799 was 798, checked in by phi196, 19 years ago

Added swap_pol & invert_phase

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