source: trunk/python/scantable.py@ 768

Last change on this file since 768 was 762, checked in by mar637, 19 years ago

merge from Release12 branch

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