source: trunk/python/scantable.py@ 2811

Last change on this file since 2811 was 2810, checked in by WataruKawasaki, 12 years ago

New Development: No

JIRA Issue: No

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs:

Put in Release Notes: No

Module(s): sd.scantable

Description: a bug fix in sd.scantable.pack_blinfo().


  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 181.5 KB
Line 
1"""This module defines the scantable class."""
2
3import os
4import re
5import tempfile
6import numpy
7try:
8 from functools import wraps as wraps_dec
9except ImportError:
10 from asap.compatibility import wraps as wraps_dec
11
12from asap.env import is_casapy
13from asap._asap import Scantable
14from asap._asap import filler, msfiller
15from asap.parameters import rcParams
16from asap.logging import asaplog, asaplog_post_dec
17from asap.selector import selector
18from asap.linecatalog import linecatalog
19from asap.coordinate import coordinate
20from asap.utils import _n_bools, mask_not, mask_and, mask_or, page
21from asap.asapfitter import fitter
22
23def preserve_selection(func):
24 @wraps_dec(func)
25 def wrap(obj, *args, **kw):
26 basesel = obj.get_selection()
27 try:
28 val = func(obj, *args, **kw)
29 finally:
30 obj.set_selection(basesel)
31 return val
32 return wrap
33
34def is_scantable(filename):
35 """Is the given file a scantable?
36
37 Parameters:
38
39 filename: the name of the file/directory to test
40
41 """
42 if ( os.path.isdir(filename)
43 and os.path.exists(filename+'/table.info')
44 and os.path.exists(filename+'/table.dat') ):
45 f=open(filename+'/table.info')
46 l=f.readline()
47 f.close()
48 match_pattern = '^Type = (Scantable)? *$'
49 if re.match(match_pattern,l):
50 return True
51 else:
52 return False
53 else:
54 return False
55## return (os.path.isdir(filename)
56## and not os.path.exists(filename+'/table.f1')
57## and os.path.exists(filename+'/table.info'))
58
59def is_ms(filename):
60 """Is the given file a MeasurementSet?
61
62 Parameters:
63
64 filename: the name of the file/directory to test
65
66 """
67 if ( os.path.isdir(filename)
68 and os.path.exists(filename+'/table.info')
69 and os.path.exists(filename+'/table.dat') ):
70 f=open(filename+'/table.info')
71 l=f.readline()
72 f.close()
73 if ( l.find('Measurement Set') != -1 ):
74 return True
75 else:
76 return False
77 else:
78 return False
79
80def normalise_edge_param(edge):
81 """\
82 Convert a given edge value to a one-dimensional array that can be
83 given to baseline-fitting/subtraction functions.
84 The length of the output value will be an even because values for
85 the both sides of spectra are to be contained for each IF. When
86 the length is 2, the values will be applied to all IFs. If the length
87 is larger than 2, it will be 2*ifnos().
88 Accepted format of edge include:
89 * an integer - will be used for both sides of spectra of all IFs.
90 e.g. 10 is converted to [10,10]
91 * an empty list/tuple [] - converted to [0, 0] and used for all IFs.
92 * a list/tuple containing an integer - same as the above case.
93 e.g. [10] is converted to [10,10]
94 * a list/tuple containing two integers - will be used for all IFs.
95 e.g. [5,10] is output as it is. no need to convert.
96 * a list/tuple of lists/tuples containing TWO integers -
97 each element of edge will be used for each IF.
98 e.g. [[5,10],[15,20]] - [5,10] for IF[0] and [15,20] for IF[1].
99
100 If an element contains the same integer values, the input 'edge'
101 parameter can be given in a simpler shape in the following cases:
102 ** when len(edge)!=2
103 any elements containing the same values can be replaced
104 to single integers.
105 e.g. [[15,15]] can be simplified to [15] (or [15,15] or 15 also).
106 e.g. [[1,1],[2,2],[3,3]] can be simplified to [1,2,3].
107 ** when len(edge)=2
108 care is needed for this case: ONLY ONE of the
109 elements can be a single integer,
110 e.g. [[5,5],[10,10]] can be simplified to [5,[10,10]]
111 or [[5,5],10], but can NOT be simplified to [5,10].
112 when [5,10] given, it is interpreted as
113 [[5,10],[5,10],[5,10],...] instead, as shown before.
114 """
115 from asap import _is_sequence_or_number as _is_valid
116 if isinstance(edge, list) or isinstance(edge, tuple):
117 for edgepar in edge:
118 if not _is_valid(edgepar, int):
119 raise ValueError, "Each element of the 'edge' tuple has \
120 to be a pair of integers or an integer."
121 if isinstance(edgepar, list) or isinstance(edgepar, tuple):
122 if len(edgepar) != 2:
123 raise ValueError, "Each element of the 'edge' tuple has \
124 to be a pair of integers or an integer."
125 else:
126 if not _is_valid(edge, int):
127 raise ValueError, "Parameter 'edge' has to be an integer or a \
128 pair of integers specified as a tuple. \
129 Nested tuples are allowed \
130 to make individual selection for different IFs."
131
132
133 if isinstance(edge, int):
134 edge = [ edge, edge ] # e.g. 3 => [3,3]
135 elif isinstance(edge, list) or isinstance(edge, tuple):
136 if len(edge) == 0:
137 edge = [0, 0] # e.g. [] => [0,0]
138 elif len(edge) == 1:
139 if isinstance(edge[0], int):
140 edge = [ edge[0], edge[0] ] # e.g. [1] => [1,1]
141
142 commonedge = True
143 if len(edge) > 2: commonedge = False
144 else:
145 for edgepar in edge:
146 if isinstance(edgepar, list) or isinstance(edgepar, tuple):
147 commonedge = False
148 break
149
150 if commonedge:
151 if len(edge) > 1:
152 norm_edge = edge
153 else:
154 norm_edge = edge + edge
155 else:
156 norm_edge = []
157 for edgepar in edge:
158 if isinstance(edgepar, int):
159 norm_edge += [edgepar, edgepar]
160 else:
161 norm_edge += edgepar
162
163 return norm_edge
164
165def raise_fitting_failure_exception(e):
166 msg = "The fit failed, possibly because it didn't converge."
167 if rcParams["verbose"]:
168 asaplog.push(str(e))
169 asaplog.push(str(msg))
170 else:
171 raise RuntimeError(str(e)+'\n'+msg)
172
173def pack_progress_params(showprogress, minnrow):
174 return str(showprogress).lower() + ',' + str(minnrow)
175
176def pack_blinfo(blinfo, maxirow):
177 """\
178 convert a dictionary or a list of dictionaries of baseline info
179 into a list of comma-separated strings.
180 """
181 if isinstance(blinfo, dict):
182 res = do_pack_blinfo(blinfo, maxirow)
183 return [res] if res != '' else []
184 elif isinstance(blinfo, list) or isinstance(blinfo, tuple):
185 res = []
186 for i in xrange(len(blinfo)):
187 resi = do_pack_blinfo(blinfo[i], maxirow)
188 if resi != '':
189 res.append(resi)
190 return res
191
192def do_pack_blinfo(blinfo, maxirow):
193 """\
194 convert a dictionary of baseline info for a spectrum into
195 a comma-separated string.
196 """
197 dinfo = {}
198 for key in ['row', 'blfunc', 'masklist']:
199 if blinfo.has_key(key):
200 val = blinfo[key]
201 if key == 'row':
202 irow = val
203 if isinstance(val, list) or isinstance(val, tuple):
204 slval = []
205 for i in xrange(len(val)):
206 if isinstance(val[i], list) or isinstance(val[i], tuple):
207 for j in xrange(len(val[i])):
208 slval.append(str(val[i][j]))
209 else:
210 slval.append(str(val[i]))
211 sval = ",".join(slval)
212 else:
213 sval = str(val)
214
215 dinfo[key] = sval
216 else:
217 raise ValueError("'"+key+"' is missing in blinfo.")
218
219 if irow >= maxirow: return ''
220
221 for key in ['order', 'npiece', 'nwave']:
222 if blinfo.has_key(key):
223 val = blinfo[key]
224 if isinstance(val, list) or isinstance(val, tuple):
225 slval = []
226 for i in xrange(len(val)):
227 slval.append(str(val[i]))
228 sval = ",".join(slval)
229 else:
230 sval = str(val)
231 dinfo[key] = sval
232
233 blfunc = dinfo['blfunc']
234 fspec_keys = {'poly': 'order', 'chebyshev': 'order', 'cspline': 'npiece', 'sinusoid': 'nwave'}
235
236 fspec_key = fspec_keys[blfunc]
237 if not blinfo.has_key(fspec_key):
238 raise ValueError("'"+fspec_key+"' is missing in blinfo.")
239
240 clip_params_n = 0
241 for key in ['clipthresh', 'clipniter']:
242 if blinfo.has_key(key):
243 clip_params_n += 1
244 dinfo[key] = str(blinfo[key])
245
246 if clip_params_n == 0:
247 dinfo['clipthresh'] = '0.0'
248 dinfo['clipniter'] = '0'
249 elif clip_params_n != 2:
250 raise ValueError("both 'clipthresh' and 'clipniter' must be given for n-sigma clipping.")
251
252 lf_params_n = 0
253 for key in ['thresh', 'edge', 'chan_avg_limit']:
254 if blinfo.has_key(key):
255 lf_params_n += 1
256 val = blinfo[key]
257 if isinstance(val, list) or isinstance(val, tuple):
258 slval = []
259 for i in xrange(len(val)):
260 slval.append(str(val[i]))
261 sval = ",".join(slval)
262 else:
263 sval = str(val)
264 dinfo[key] = sval
265
266 if lf_params_n == 3:
267 dinfo['use_linefinder'] = 'true'
268 elif lf_params_n == 0:
269 dinfo['use_linefinder'] = 'false'
270 dinfo['thresh'] = ''
271 dinfo['edge'] = ''
272 dinfo['chan_avg_limit'] = ''
273 else:
274 raise ValueError("all of 'thresh', 'edge' and 'chan_avg_limit' must be given to use linefinder.")
275
276 slblinfo = [dinfo['row'], blfunc, dinfo[fspec_key], dinfo['masklist'], \
277 dinfo['clipthresh'], dinfo['clipniter'], \
278 dinfo['use_linefinder'], dinfo['thresh'], dinfo['edge'], dinfo['chan_avg_limit']]
279
280 return ":".join(slblinfo)
281
282def parse_fitresult(sres):
283 """\
284 Parse the returned value of apply_bltable() or sub_baseline() and
285 extract row number, the best-fit coefficients and rms, then pack
286 them into a dictionary.
287 The input value is generated by Scantable::packFittingResults() and
288 formatted as 'row:coeff[0],coeff[1],..,coeff[n-1]:rms'.
289 """
290 res = []
291 for i in xrange(len(sres)):
292 (srow, scoeff, srms) = sres[i].split(":")
293 row = int(srow)
294 rms = float(srms)
295 lscoeff = scoeff.split(",")
296 coeff = []
297 for j in xrange(len(lscoeff)):
298 coeff.append(float(lscoeff[j]))
299 res.append({'row': row, 'coeff': coeff, 'rms': rms})
300
301 return res
302
303class scantable(Scantable):
304 """\
305 The ASAP container for scans (single-dish data).
306 """
307
308 @asaplog_post_dec
309 def __init__(self, filename, average=None, unit=None, parallactify=None,
310 **args):
311 """\
312 Create a scantable from a saved one or make a reference
313
314 Parameters:
315
316 filename: the name of an asap table on disk
317 or
318 the name of a rpfits/sdfits/ms file
319 (integrations within scans are auto averaged
320 and the whole file is read) or
321 [advanced] a reference to an existing scantable
322
323 average: average all integrations withinb a scan on read.
324 The default (True) is taken from .asaprc.
325
326 unit: brightness unit; must be consistent with K or Jy.
327 Over-rides the default selected by the filler
328 (input rpfits/sdfits/ms) or replaces the value
329 in existing scantables
330
331 antenna: for MeasurementSet input data only:
332 Antenna selection. integer (id) or string
333 (name or id).
334
335 parallactify: Indicate that the data had been parallactified.
336 Default (false) is taken from rc file.
337
338 getpt: Whether to import direction from MS/POINTING
339 table properly or not.
340 This is effective only when filename is MS.
341 The default (True) is to import direction
342 from MS/POINTING.
343
344 freq_tolsr: Whether to convert frequency frame information
345 to LSRK or not.
346 This is effective only when filename is MS.
347 The default (False) is to import frequency
348 as is.
349
350 """
351 if average is None:
352 average = rcParams['scantable.autoaverage']
353 parallactify = parallactify or rcParams['scantable.parallactify']
354 varlist = vars()
355 from asap._asap import stmath
356 self._math = stmath( rcParams['insitu'] )
357 if isinstance(filename, Scantable):
358 Scantable.__init__(self, filename)
359 else:
360 if isinstance(filename, str):
361 filename = os.path.expandvars(filename)
362 filename = os.path.expanduser(filename)
363 if not os.path.exists(filename):
364 s = "File '%s' not found." % (filename)
365 raise IOError(s)
366 if is_scantable(filename):
367 ondisk = rcParams['scantable.storage'] == 'disk'
368 Scantable.__init__(self, filename, ondisk)
369 if unit is not None:
370 self.set_fluxunit(unit)
371 if average:
372 self._assign( self.average_time( scanav=True ) )
373 # do not reset to the default freqframe
374 #self.set_freqframe(rcParams['scantable.freqframe'])
375 elif is_ms(filename):
376 # Measurement Set
377 opts={'ms': {}}
378 mskeys=['getpt','antenna','freq_tolsr']
379 for key in mskeys:
380 if key in args.keys():
381 opts['ms'][key] = args[key]
382 self._fill([filename], unit, average, opts)
383 elif os.path.isfile(filename):
384 opts={'nro': {}}
385 nrokeys=['freqref']
386 for key in nrokeys:
387 if key in args.keys():
388 opts['nro'][key] = args[key]
389 self._fill([filename], unit, average, opts)
390 # only apply to new data not "copy constructor"
391 self.parallactify(parallactify)
392 else:
393 msg = "The given file '%s'is not a valid " \
394 "asap table." % (filename)
395 raise IOError(msg)
396 elif (isinstance(filename, list) or isinstance(filename, tuple)) \
397 and isinstance(filename[-1], str):
398 self._fill(filename, unit, average)
399 self.parallactify(parallactify)
400 self._add_history("scantable", varlist)
401
402 @asaplog_post_dec
403 def save(self, name=None, format=None, overwrite=False):
404 """\
405 Store the scantable on disk. This can be an asap (aips++) Table,
406 SDFITS or MS2 format.
407
408 Parameters:
409
410 name: the name of the outputfile. For format 'ASCII'
411 this is the root file name (data in 'name'.txt
412 and header in 'name'_header.txt)
413
414 format: an optional file format. Default is ASAP.
415 Allowed are:
416
417 * 'ASAP' (save as ASAP [aips++] Table),
418 * 'SDFITS' (save as SDFITS file)
419 * 'ASCII' (saves as ascii text file)
420 * 'MS2' (saves as an casacore MeasurementSet V2)
421 * 'FITS' (save as image FITS - not readable by
422 class)
423 * 'CLASS' (save as FITS readable by CLASS)
424
425 overwrite: If the file should be overwritten if it exists.
426 The default False is to return with warning
427 without writing the output. USE WITH CARE.
428
429 Example::
430
431 scan.save('myscan.asap')
432 scan.save('myscan.sdfits', 'SDFITS')
433
434 """
435 from os import path
436 format = format or rcParams['scantable.save']
437 suffix = '.'+format.lower()
438 if name is None or name == "":
439 name = 'scantable'+suffix
440 msg = "No filename given. Using default name %s..." % name
441 asaplog.push(msg)
442 name = path.expandvars(name)
443 if path.isfile(name) or path.isdir(name):
444 if not overwrite:
445 msg = "File %s exists." % name
446 raise IOError(msg)
447 format2 = format.upper()
448 if format2 == 'ASAP':
449 self._save(name)
450 elif format2 == 'MS2':
451 msopt = {'ms': {'overwrite': overwrite } }
452 from asap._asap import mswriter
453 writer = mswriter( self )
454 writer.write( name, msopt )
455 else:
456 from asap._asap import stwriter as stw
457 writer = stw(format2)
458 writer.write(self, name)
459 return
460
461 def copy(self):
462 """Return a copy of this scantable.
463
464 *Note*:
465
466 This makes a full (deep) copy. scan2 = scan1 makes a reference.
467
468 Example::
469
470 copiedscan = scan.copy()
471
472 """
473 sd = scantable(Scantable._copy(self))
474 return sd
475
476 def drop_scan(self, scanid=None):
477 """\
478 Return a new scantable where the specified scan number(s) has(have)
479 been dropped.
480
481 Parameters:
482
483 scanid: a (list of) scan number(s)
484
485 """
486 from asap import _is_sequence_or_number as _is_valid
487 from asap import _to_list
488 from asap import unique
489 if not _is_valid(scanid):
490 raise RuntimeError( 'Please specify a scanno to drop from the'
491 ' scantable' )
492 scanid = _to_list(scanid)
493 allscans = unique([ self.getscan(i) for i in range(self.nrow())])
494 for sid in scanid: allscans.remove(sid)
495 if len(allscans) == 0:
496 raise ValueError("Can't remove all scans")
497 sel = selector(scans=allscans)
498 return self._select_copy(sel)
499
500 def _select_copy(self, selection):
501 orig = self.get_selection()
502 self.set_selection(orig+selection)
503 cp = self.copy()
504 self.set_selection(orig)
505 return cp
506
507 def get_scan(self, scanid=None):
508 """\
509 Return a specific scan (by scanno) or collection of scans (by
510 source name) in a new scantable.
511
512 *Note*:
513
514 See scantable.drop_scan() for the inverse operation.
515
516 Parameters:
517
518 scanid: a (list of) scanno or a source name, unix-style
519 patterns are accepted for source name matching, e.g.
520 '*_R' gets all 'ref scans
521
522 Example::
523
524 # get all scans containing the source '323p459'
525 newscan = scan.get_scan('323p459')
526 # get all 'off' scans
527 refscans = scan.get_scan('*_R')
528 # get a susbset of scans by scanno (as listed in scan.summary())
529 newscan = scan.get_scan([0, 2, 7, 10])
530
531 """
532 if scanid is None:
533 raise RuntimeError( 'Please specify a scan no or name to '
534 'retrieve from the scantable' )
535 try:
536 bsel = self.get_selection()
537 sel = selector()
538 if type(scanid) is str:
539 sel.set_name(scanid)
540 return self._select_copy(sel)
541 elif type(scanid) is int:
542 sel.set_scans([scanid])
543 return self._select_copy(sel)
544 elif type(scanid) is list:
545 sel.set_scans(scanid)
546 return self._select_copy(sel)
547 else:
548 msg = "Illegal scanid type, use 'int' or 'list' if ints."
549 raise TypeError(msg)
550 except RuntimeError:
551 raise
552
553 def __str__(self):
554 tempFile = tempfile.NamedTemporaryFile()
555 Scantable._summary(self, tempFile.name)
556 tempFile.seek(0)
557 asaplog.clear()
558 return tempFile.file.read()
559
560 @asaplog_post_dec
561 def summary(self, filename=None):
562 """\
563 Print a summary of the contents of this scantable.
564
565 Parameters:
566
567 filename: the name of a file to write the putput to
568 Default - no file output
569
570 """
571 if filename is not None:
572 if filename is "":
573 filename = 'scantable_summary.txt'
574 from os.path import expandvars, isdir
575 filename = expandvars(filename)
576 if isdir(filename):
577 msg = "Illegal file name '%s'." % (filename)
578 raise IOError(msg)
579 else:
580 filename = ""
581 Scantable._summary(self, filename)
582
583 def get_spectrum(self, rowno):
584 """Return the spectrum for the current row in the scantable as a list.
585
586 Parameters:
587
588 rowno: the row number to retrieve the spectrum from
589
590 """
591 return self._getspectrum(rowno)
592
593 def get_mask(self, rowno):
594 """Return the mask for the current row in the scantable as a list.
595
596 Parameters:
597
598 rowno: the row number to retrieve the mask from
599
600 """
601 return self._getmask(rowno)
602
603 def set_spectrum(self, spec, rowno):
604 """Set the spectrum for the current row in the scantable.
605
606 Parameters:
607
608 spec: the new spectrum
609
610 rowno: the row number to set the spectrum for
611
612 """
613 assert(len(spec) == self.nchan(self.getif(rowno)))
614 return self._setspectrum(spec, rowno)
615
616 def get_coordinate(self, rowno):
617 """Return the (spectral) coordinate for a a given 'rowno'.
618
619 *Note*:
620
621 * This coordinate is only valid until a scantable method modifies
622 the frequency axis.
623 * This coordinate does contain the original frequency set-up
624 NOT the new frame. The conversions however are done using the user
625 specified frame (e.g. LSRK/TOPO). To get the 'real' coordinate,
626 use scantable.freq_align first. Without it there is no closure,
627 i.e.::
628
629 c = myscan.get_coordinate(0)
630 c.to_frequency(c.get_reference_pixel()) != c.get_reference_value()
631
632 Parameters:
633
634 rowno: the row number for the spectral coordinate
635
636 """
637 return coordinate(Scantable.get_coordinate(self, rowno))
638
639 def get_selection(self):
640 """\
641 Get the selection object currently set on this scantable.
642
643 Example::
644
645 sel = scan.get_selection()
646 sel.set_ifs(0) # select IF 0
647 scan.set_selection(sel) # apply modified selection
648
649 """
650 return selector(self._getselection())
651
652 def set_selection(self, selection=None, **kw):
653 """\
654 Select a subset of the data. All following operations on this scantable
655 are only applied to thi selection.
656
657 Parameters:
658
659 selection: a selector object (default unset the selection), or
660 any combination of 'pols', 'ifs', 'beams', 'scans',
661 'cycles', 'name', 'query'
662
663 Examples::
664
665 sel = selector() # create a selection object
666 self.set_scans([0, 3]) # select SCANNO 0 and 3
667 scan.set_selection(sel) # set the selection
668 scan.summary() # will only print summary of scanno 0 an 3
669 scan.set_selection() # unset the selection
670 # or the equivalent
671 scan.set_selection(scans=[0,3])
672 scan.summary() # will only print summary of scanno 0 an 3
673 scan.set_selection() # unset the selection
674
675 """
676 if selection is None:
677 # reset
678 if len(kw) == 0:
679 selection = selector()
680 else:
681 # try keywords
682 for k in kw:
683 if k not in selector.fields:
684 raise KeyError("Invalid selection key '%s', "
685 "valid keys are %s" % (k,
686 selector.fields))
687 selection = selector(**kw)
688 self._setselection(selection)
689
690 def get_row(self, row=0, insitu=None):
691 """\
692 Select a row in the scantable.
693 Return a scantable with single row.
694
695 Parameters:
696
697 row: row no of integration, default is 0.
698 insitu: if False a new scantable is returned. Otherwise, the
699 scaling is done in-situ. The default is taken from .asaprc
700 (False)
701
702 """
703 if insitu is None:
704 insitu = rcParams['insitu']
705 if not insitu:
706 workscan = self.copy()
707 else:
708 workscan = self
709 # Select a row
710 sel = selector()
711 sel.set_rows([row])
712 workscan.set_selection(sel)
713 if not workscan.nrow() == 1:
714 msg = "Could not identify single row. %d rows selected." \
715 % (workscan.nrow())
716 raise RuntimeError(msg)
717 if insitu:
718 self._assign(workscan)
719 else:
720 return workscan
721
722 @asaplog_post_dec
723 def stats(self, stat='stddev', mask=None, form='3.3f', row=None):
724 """\
725 Determine the specified statistic of the current beam/if/pol
726 Takes a 'mask' as an optional parameter to specify which
727 channels should be excluded.
728
729 Parameters:
730
731 stat: 'min', 'max', 'min_abc', 'max_abc', 'sumsq', 'sum',
732 'mean', 'var', 'stddev', 'avdev', 'rms', 'median'
733
734 mask: an optional mask specifying where the statistic
735 should be determined.
736
737 form: format string to print statistic values
738
739 row: row number of spectrum to process.
740 (default is None: for all rows)
741
742 Example:
743 scan.set_unit('channel')
744 msk = scan.create_mask([100, 200], [500, 600])
745 scan.stats(stat='mean', mask=m)
746
747 """
748 mask = mask or []
749 if not self._check_ifs():
750 raise ValueError("Cannot apply mask as the IFs have different "
751 "number of channels. Please use setselection() "
752 "to select individual IFs")
753 rtnabc = False
754 if stat.lower().endswith('_abc'): rtnabc = True
755 getchan = False
756 if stat.lower().startswith('min') or stat.lower().startswith('max'):
757 chan = self._math._minmaxchan(self, mask, stat)
758 getchan = True
759 statvals = []
760 if not rtnabc:
761 if row == None:
762 statvals = self._math._stats(self, mask, stat)
763 else:
764 statvals = self._math._statsrow(self, mask, stat, int(row))
765
766 #def cb(i):
767 # return statvals[i]
768
769 #return self._row_callback(cb, stat)
770
771 label=stat
772 #callback=cb
773 out = ""
774 #outvec = []
775 sep = '-'*50
776
777 if row == None:
778 rows = xrange(self.nrow())
779 elif isinstance(row, int):
780 rows = [ row ]
781
782 for i in rows:
783 refstr = ''
784 statunit= ''
785 if getchan:
786 qx, qy = self.chan2data(rowno=i, chan=chan[i])
787 if rtnabc:
788 statvals.append(qx['value'])
789 refstr = ('(value: %'+form) % (qy['value'])+' ['+qy['unit']+'])'
790 statunit= '['+qx['unit']+']'
791 else:
792 refstr = ('(@ %'+form) % (qx['value'])+' ['+qx['unit']+'])'
793
794 tm = self._gettime(i)
795 src = self._getsourcename(i)
796 out += 'Scan[%d] (%s) ' % (self.getscan(i), src)
797 out += 'Time[%s]:\n' % (tm)
798 if self.nbeam(-1) > 1: out += ' Beam[%d] ' % (self.getbeam(i))
799 if self.nif(-1) > 1: out += ' IF[%d] ' % (self.getif(i))
800 if self.npol(-1) > 1: out += ' Pol[%d] ' % (self.getpol(i))
801 #outvec.append(callback(i))
802 if len(rows) > 1:
803 # out += ('= %'+form) % (outvec[i]) +' '+refstr+'\n'
804 out += ('= %'+form) % (statvals[i]) +' '+refstr+'\n'
805 else:
806 # out += ('= %'+form) % (outvec[0]) +' '+refstr+'\n'
807 out += ('= %'+form) % (statvals[0]) +' '+refstr+'\n'
808 out += sep+"\n"
809
810 import os
811 if os.environ.has_key( 'USER' ):
812 usr = os.environ['USER']
813 else:
814 import commands
815 usr = commands.getoutput( 'whoami' )
816 tmpfile = '/tmp/tmp_'+usr+'_casapy_asap_scantable_stats'
817 f = open(tmpfile,'w')
818 print >> f, sep
819 print >> f, ' %s %s' % (label, statunit)
820 print >> f, sep
821 print >> f, out
822 f.close()
823 f = open(tmpfile,'r')
824 x = f.readlines()
825 f.close()
826 asaplog.push(''.join(x), False)
827
828 return statvals
829
830 def chan2data(self, rowno=0, chan=0):
831 """\
832 Returns channel/frequency/velocity and spectral value
833 at an arbitrary row and channel in the scantable.
834
835 Parameters:
836
837 rowno: a row number in the scantable. Default is the
838 first row, i.e. rowno=0
839
840 chan: a channel in the scantable. Default is the first
841 channel, i.e. pos=0
842
843 """
844 if isinstance(rowno, int) and isinstance(chan, int):
845 qx = {'unit': self.get_unit(),
846 'value': self._getabcissa(rowno)[chan]}
847 qy = {'unit': self.get_fluxunit(),
848 'value': self._getspectrum(rowno)[chan]}
849 return qx, qy
850
851 def stddev(self, mask=None):
852 """\
853 Determine the standard deviation of the current beam/if/pol
854 Takes a 'mask' as an optional parameter to specify which
855 channels should be excluded.
856
857 Parameters:
858
859 mask: an optional mask specifying where the standard
860 deviation should be determined.
861
862 Example::
863
864 scan.set_unit('channel')
865 msk = scan.create_mask([100, 200], [500, 600])
866 scan.stddev(mask=m)
867
868 """
869 return self.stats(stat='stddev', mask=mask);
870
871
872 def get_column_names(self):
873 """\
874 Return a list of column names, which can be used for selection.
875 """
876 return list(Scantable.get_column_names(self))
877
878 def get_tsys(self, row=-1):
879 """\
880 Return the System temperatures.
881
882 Parameters:
883
884 row: the rowno to get the information for. (default all rows)
885
886 Returns:
887
888 a list of Tsys values for the current selection
889
890 """
891 if row > -1:
892 return self._get_column(self._gettsys, row)
893 return self._row_callback(self._gettsys, "Tsys")
894
895 def get_tsysspectrum(self, row=-1):
896 """\
897 Return the channel dependent system temperatures.
898
899 Parameters:
900
901 row: the rowno to get the information for. (default all rows)
902
903 Returns:
904
905 a list of Tsys values for the current selection
906
907 """
908 return self._get_column( self._gettsysspectrum, row )
909
910 def set_tsys(self, values, row=-1):
911 """\
912 Set the Tsys value(s) of the given 'row' or the whole scantable
913 (selection).
914
915 Parameters:
916
917 values: a scalar or list (if Tsys is a vector) of Tsys value(s)
918 row: the row number to apply Tsys values to.
919 (default all rows)
920
921 """
922
923 if not hasattr(values, "__len__"):
924 values = [values]
925 self._settsys(values, row)
926
927 def get_weather(self, row=-1):
928 """\
929 Return the weather informations.
930
931 Parameters:
932
933 row: the rowno to get the information for. (default all rows)
934
935 Returns:
936
937 a dict or list of of dicts of values for the current selection
938
939 """
940
941 values = self._get_column(self._get_weather, row)
942 if row > -1:
943 return {'temperature': values[0],
944 'pressure': values[1], 'humidity' : values[2],
945 'windspeed' : values[3], 'windaz' : values[4]
946 }
947 else:
948 out = []
949 for r in values:
950
951 out.append({'temperature': r[0],
952 'pressure': r[1], 'humidity' : r[2],
953 'windspeed' : r[3], 'windaz' : r[4]
954 })
955 return out
956
957 def _row_callback(self, callback, label):
958 out = ""
959 outvec = []
960 sep = '-'*50
961 for i in range(self.nrow()):
962 tm = self._gettime(i)
963 src = self._getsourcename(i)
964 out += 'Scan[%d] (%s) ' % (self.getscan(i), src)
965 out += 'Time[%s]:\n' % (tm)
966 if self.nbeam(-1) > 1:
967 out += ' Beam[%d] ' % (self.getbeam(i))
968 if self.nif(-1) > 1: out += ' IF[%d] ' % (self.getif(i))
969 if self.npol(-1) > 1: out += ' Pol[%d] ' % (self.getpol(i))
970 outvec.append(callback(i))
971 out += '= %3.3f\n' % (outvec[i])
972 out += sep+'\n'
973
974 asaplog.push(sep)
975 asaplog.push(" %s" % (label))
976 asaplog.push(sep)
977 asaplog.push(out)
978 asaplog.post()
979 return outvec
980
981 def _get_column(self, callback, row=-1, *args):
982 """
983 """
984 if row == -1:
985 return [callback(i, *args) for i in range(self.nrow())]
986 else:
987 if 0 <= row < self.nrow():
988 return callback(row, *args)
989
990
991 def get_time(self, row=-1, asdatetime=False, prec=-1):
992 """\
993 Get a list of time stamps for the observations.
994 Return a datetime object or a string (default) for each
995 integration time stamp in the scantable.
996
997 Parameters:
998
999 row: row no of integration. Default -1 return all rows
1000
1001 asdatetime: return values as datetime objects rather than strings
1002
1003 prec: number of digits shown. Default -1 to automatic
1004 calculation.
1005 Note this number is equals to the digits of MVTime,
1006 i.e., 0<prec<3: dates with hh:: only,
1007 <5: with hh:mm:, <7 or 0: with hh:mm:ss,
1008 and 6> : with hh:mm:ss.tt... (prec-6 t's added)
1009
1010 """
1011 from datetime import datetime
1012 if prec < 0:
1013 # automagically set necessary precision +1
1014 prec = 7 - \
1015 numpy.floor(numpy.log10(numpy.min(self.get_inttime(row))))
1016 prec = max(6, int(prec))
1017 else:
1018 prec = max(0, prec)
1019 if asdatetime:
1020 #precision can be 1 millisecond at max
1021 prec = min(12, prec)
1022
1023 times = self._get_column(self._gettime, row, prec)
1024 if not asdatetime:
1025 return times
1026 format = "%Y/%m/%d/%H:%M:%S.%f"
1027 if prec < 7:
1028 nsub = 1 + (((6-prec)/2) % 3)
1029 substr = [".%f","%S","%M"]
1030 for i in range(nsub):
1031 format = format.replace(substr[i],"")
1032 if isinstance(times, list):
1033 return [datetime.strptime(i, format) for i in times]
1034 else:
1035 return datetime.strptime(times, format)
1036
1037
1038 def get_inttime(self, row=-1):
1039 """\
1040 Get a list of integration times for the observations.
1041 Return a time in seconds for each integration in the scantable.
1042
1043 Parameters:
1044
1045 row: row no of integration. Default -1 return all rows.
1046
1047 """
1048 return self._get_column(self._getinttime, row)
1049
1050
1051 def get_sourcename(self, row=-1):
1052 """\
1053 Get a list source names for the observations.
1054 Return a string for each integration in the scantable.
1055 Parameters:
1056
1057 row: row no of integration. Default -1 return all rows.
1058
1059 """
1060 return self._get_column(self._getsourcename, row)
1061
1062 def get_elevation(self, row=-1):
1063 """\
1064 Get a list of elevations for the observations.
1065 Return a float for each integration in the scantable.
1066
1067 Parameters:
1068
1069 row: row no of integration. Default -1 return all rows.
1070
1071 """
1072 return self._get_column(self._getelevation, row)
1073
1074 def get_azimuth(self, row=-1):
1075 """\
1076 Get a list of azimuths for the observations.
1077 Return a float for each integration in the scantable.
1078
1079 Parameters:
1080 row: row no of integration. Default -1 return all rows.
1081
1082 """
1083 return self._get_column(self._getazimuth, row)
1084
1085 def get_parangle(self, row=-1):
1086 """\
1087 Get a list of parallactic angles for the observations.
1088 Return a float for each integration in the scantable.
1089
1090 Parameters:
1091
1092 row: row no of integration. Default -1 return all rows.
1093
1094 """
1095 return self._get_column(self._getparangle, row)
1096
1097 def get_direction(self, row=-1):
1098 """
1099 Get a list of Positions on the sky (direction) for the observations.
1100 Return a string for each integration in the scantable.
1101
1102 Parameters:
1103
1104 row: row no of integration. Default -1 return all rows
1105
1106 """
1107 return self._get_column(self._getdirection, row)
1108
1109 def get_directionval(self, row=-1):
1110 """\
1111 Get a list of Positions on the sky (direction) for the observations.
1112 Return a float for each integration in the scantable.
1113
1114 Parameters:
1115
1116 row: row no of integration. Default -1 return all rows
1117
1118 """
1119 return self._get_column(self._getdirectionvec, row)
1120
1121 @asaplog_post_dec
1122 def set_unit(self, unit='channel'):
1123 """\
1124 Set the unit for all following operations on this scantable
1125
1126 Parameters:
1127
1128 unit: optional unit, default is 'channel'. Use one of '*Hz',
1129 'km/s', 'channel' or equivalent ''
1130
1131 """
1132 varlist = vars()
1133 if unit in ['', 'pixel', 'channel']:
1134 unit = ''
1135 inf = list(self._getcoordinfo())
1136 inf[0] = unit
1137 self._setcoordinfo(inf)
1138 self._add_history("set_unit", varlist)
1139
1140 @asaplog_post_dec
1141 def set_instrument(self, instr):
1142 """\
1143 Set the instrument for subsequent processing.
1144
1145 Parameters:
1146
1147 instr: Select from 'ATPKSMB', 'ATPKSHOH', 'ATMOPRA',
1148 'DSS-43' (Tid), 'CEDUNA', and 'HOBART'
1149
1150 """
1151 self._setInstrument(instr)
1152 self._add_history("set_instument", vars())
1153
1154 @asaplog_post_dec
1155 def set_feedtype(self, feedtype):
1156 """\
1157 Overwrite the feed type, which might not be set correctly.
1158
1159 Parameters:
1160
1161 feedtype: 'linear' or 'circular'
1162
1163 """
1164 self._setfeedtype(feedtype)
1165 self._add_history("set_feedtype", vars())
1166
1167 @asaplog_post_dec
1168 def set_doppler(self, doppler='RADIO'):
1169 """\
1170 Set the doppler for all following operations on this scantable.
1171
1172 Parameters:
1173
1174 doppler: One of 'RADIO', 'OPTICAL', 'Z', 'BETA', 'GAMMA'
1175
1176 """
1177 varlist = vars()
1178 inf = list(self._getcoordinfo())
1179 inf[2] = doppler
1180 self._setcoordinfo(inf)
1181 self._add_history("set_doppler", vars())
1182
1183 @asaplog_post_dec
1184 def set_freqframe(self, frame=None):
1185 """\
1186 Set the frame type of the Spectral Axis.
1187
1188 Parameters:
1189
1190 frame: an optional frame type, default 'LSRK'. Valid frames are:
1191 'TOPO', 'LSRD', 'LSRK', 'BARY',
1192 'GEO', 'GALACTO', 'LGROUP', 'CMB'
1193
1194 Example::
1195
1196 scan.set_freqframe('BARY')
1197
1198 """
1199 frame = frame or rcParams['scantable.freqframe']
1200 varlist = vars()
1201 # "REST" is not implemented in casacore
1202 #valid = ['REST', 'TOPO', 'LSRD', 'LSRK', 'BARY', \
1203 # 'GEO', 'GALACTO', 'LGROUP', 'CMB']
1204 valid = ['TOPO', 'LSRD', 'LSRK', 'BARY', \
1205 'GEO', 'GALACTO', 'LGROUP', 'CMB']
1206
1207 if frame in valid:
1208 inf = list(self._getcoordinfo())
1209 inf[1] = frame
1210 self._setcoordinfo(inf)
1211 self._add_history("set_freqframe", varlist)
1212 else:
1213 msg = "Please specify a valid freq type. Valid types are:\n", valid
1214 raise TypeError(msg)
1215
1216 @asaplog_post_dec
1217 def set_dirframe(self, frame=""):
1218 """\
1219 Set the frame type of the Direction on the sky.
1220
1221 Parameters:
1222
1223 frame: an optional frame type, default ''. Valid frames are:
1224 'J2000', 'B1950', 'GALACTIC'
1225
1226 Example:
1227
1228 scan.set_dirframe('GALACTIC')
1229
1230 """
1231 varlist = vars()
1232 Scantable.set_dirframe(self, frame)
1233 self._add_history("set_dirframe", varlist)
1234
1235 def get_unit(self):
1236 """\
1237 Get the default unit set in this scantable
1238
1239 Returns:
1240
1241 A unit string
1242
1243 """
1244 inf = self._getcoordinfo()
1245 unit = inf[0]
1246 if unit == '': unit = 'channel'
1247 return unit
1248
1249 @asaplog_post_dec
1250 def get_abcissa(self, rowno=0):
1251 """\
1252 Get the abcissa in the current coordinate setup for the currently
1253 selected Beam/IF/Pol
1254
1255 Parameters:
1256
1257 rowno: an optional row number in the scantable. Default is the
1258 first row, i.e. rowno=0
1259
1260 Returns:
1261
1262 The abcissa values and the format string (as a dictionary)
1263
1264 """
1265 abc = self._getabcissa(rowno)
1266 lbl = self._getabcissalabel(rowno)
1267 return abc, lbl
1268
1269 @asaplog_post_dec
1270 def flag(self, mask=None, unflag=False, row=-1):
1271 """\
1272 Flag the selected data using an optional channel mask.
1273
1274 Parameters:
1275
1276 mask: an optional channel mask, created with create_mask. Default
1277 (no mask) is all channels.
1278
1279 unflag: if True, unflag the data
1280
1281 row: an optional row number in the scantable.
1282 Default -1 flags all rows
1283
1284 """
1285 varlist = vars()
1286 mask = mask or []
1287 self._flag(row, mask, unflag)
1288 self._add_history("flag", varlist)
1289
1290 @asaplog_post_dec
1291 def flag_row(self, rows=None, unflag=False):
1292 """\
1293 Flag the selected data in row-based manner.
1294
1295 Parameters:
1296
1297 rows: list of row numbers to be flagged. Default is no row
1298 (must be explicitly specified to execute row-based
1299 flagging).
1300
1301 unflag: if True, unflag the data.
1302
1303 """
1304 varlist = vars()
1305 if rows is None:
1306 rows = []
1307 self._flag_row(rows, unflag)
1308 self._add_history("flag_row", varlist)
1309
1310 @asaplog_post_dec
1311 def clip(self, uthres=None, dthres=None, clipoutside=True, unflag=False):
1312 """\
1313 Flag the selected data outside a specified range (in channel-base)
1314
1315 Parameters:
1316
1317 uthres: upper threshold.
1318
1319 dthres: lower threshold
1320
1321 clipoutside: True for flagging data outside the range
1322 [dthres:uthres].
1323 False for flagging data inside the range.
1324
1325 unflag: if True, unflag the data.
1326
1327 """
1328 varlist = vars()
1329 self._clip(uthres, dthres, clipoutside, unflag)
1330 self._add_history("clip", varlist)
1331
1332 @asaplog_post_dec
1333 def lag_flag(self, start, end, unit="MHz", insitu=None):
1334 """\
1335 Flag the data in 'lag' space by providing a frequency to remove.
1336 Flagged data in the scantable get interpolated over the region.
1337 No taper is applied.
1338
1339 Parameters:
1340
1341 start: the start frequency (really a period within the
1342 bandwidth) or period to remove
1343
1344 end: the end frequency or period to remove
1345
1346 unit: the frequency unit (default 'MHz') or '' for
1347 explicit lag channels
1348
1349 *Notes*:
1350
1351 It is recommended to flag edges of the band or strong
1352 signals beforehand.
1353
1354 """
1355 if insitu is None: insitu = rcParams['insitu']
1356 self._math._setinsitu(insitu)
1357 varlist = vars()
1358 base = { "GHz": 1000000000., "MHz": 1000000., "kHz": 1000., "Hz": 1.}
1359 if not (unit == "" or base.has_key(unit)):
1360 raise ValueError("%s is not a valid unit." % unit)
1361 if unit == "":
1362 s = scantable(self._math._lag_flag(self, start, end, "lags"))
1363 else:
1364 s = scantable(self._math._lag_flag(self, start*base[unit],
1365 end*base[unit], "frequency"))
1366 s._add_history("lag_flag", varlist)
1367 if insitu:
1368 self._assign(s)
1369 else:
1370 return s
1371
1372 @asaplog_post_dec
1373 def fft(self, rowno=None, mask=None, getrealimag=False):
1374 """\
1375 Apply FFT to the spectra.
1376 Flagged data in the scantable get interpolated over the region.
1377
1378 Parameters:
1379
1380 rowno: The row number(s) to be processed. int, list
1381 and tuple are accepted. By default (None), FFT
1382 is applied to the whole data.
1383
1384 mask: Auxiliary channel mask(s). Given as a boolean
1385 list, it is applied to all specified rows.
1386 A list of boolean lists can also be used to
1387 apply different masks. In the latter case, the
1388 length of 'mask' must be the same as that of
1389 'rowno'. The default is None.
1390
1391 getrealimag: If True, returns the real and imaginary part
1392 values of the complex results.
1393 If False (the default), returns the amplitude
1394 (absolute value) normalised with Ndata/2 and
1395 phase (argument, in unit of radian).
1396
1397 Returns:
1398
1399 A list of dictionaries containing the results for each spectrum.
1400 Each dictionary contains two values, the real and the imaginary
1401 parts when getrealimag = True, or the amplitude(absolute value)
1402 and the phase(argument) when getrealimag = False. The key for
1403 these values are 'real' and 'imag', or 'ampl' and 'phase',
1404 respectively.
1405 """
1406 if rowno is None:
1407 rowno = []
1408 if isinstance(rowno, int):
1409 rowno = [rowno]
1410 elif not (isinstance(rowno, list) or isinstance(rowno, tuple)):
1411 raise TypeError("The row number(s) must be int, list or tuple.")
1412 if len(rowno) == 0: rowno = [i for i in xrange(self.nrow())]
1413
1414 usecommonmask = True
1415
1416 if mask is None:
1417 mask = []
1418 if isinstance(mask, list) or isinstance(mask, tuple):
1419 if len(mask) == 0:
1420 mask = [[]]
1421 else:
1422 if isinstance(mask[0], bool):
1423 if len(mask) != self.nchan(self.getif(rowno[0])):
1424 raise ValueError("The spectra and the mask have "
1425 "different length.")
1426 mask = [mask]
1427 elif isinstance(mask[0], list) or isinstance(mask[0], tuple):
1428 usecommonmask = False
1429 if len(mask) != len(rowno):
1430 raise ValueError("When specifying masks for each "
1431 "spectrum, the numbers of them "
1432 "must be identical.")
1433 for i in xrange(mask):
1434 if len(mask[i]) != self.nchan(self.getif(rowno[i])):
1435 raise ValueError("The spectra and the mask have "
1436 "different length.")
1437 else:
1438 raise TypeError("The mask must be a boolean list or "
1439 "a list of boolean list.")
1440 else:
1441 raise TypeError("The mask must be a boolean list or a list of "
1442 "boolean list.")
1443
1444 res = []
1445
1446 imask = 0
1447 for whichrow in rowno:
1448 fspec = self._fft(whichrow, mask[imask], getrealimag)
1449 nspec = len(fspec)
1450
1451 i = 0
1452 v1 = []
1453 v2 = []
1454 reselem = {"real":[],"imag":[]} if getrealimag \
1455 else {"ampl":[],"phase":[]}
1456
1457 while (i < nspec):
1458 v1.append(fspec[i])
1459 v2.append(fspec[i+1])
1460 i += 2
1461
1462 if getrealimag:
1463 reselem["real"] += v1
1464 reselem["imag"] += v2
1465 else:
1466 reselem["ampl"] += v1
1467 reselem["phase"] += v2
1468
1469 res.append(reselem)
1470
1471 if not usecommonmask:
1472 imask += 1
1473
1474 return res
1475
1476 @asaplog_post_dec
1477 def create_mask(self, *args, **kwargs):
1478 """\
1479 Compute and return a mask based on [min, max] windows.
1480 The specified windows are to be INCLUDED, when the mask is
1481 applied.
1482
1483 Parameters:
1484
1485 [min, max], [min2, max2], ...
1486 Pairs of start/end points (inclusive)specifying the regions
1487 to be masked
1488
1489 invert: optional argument. If specified as True,
1490 return an inverted mask, i.e. the regions
1491 specified are EXCLUDED
1492
1493 row: create the mask using the specified row for
1494 unit conversions, default is row=0
1495 only necessary if frequency varies over rows.
1496
1497 Examples::
1498
1499 scan.set_unit('channel')
1500 # a)
1501 msk = scan.create_mask([400, 500], [800, 900])
1502 # masks everything outside 400 and 500
1503 # and 800 and 900 in the unit 'channel'
1504
1505 # b)
1506 msk = scan.create_mask([400, 500], [800, 900], invert=True)
1507 # masks the regions between 400 and 500
1508 # and 800 and 900 in the unit 'channel'
1509
1510 # c)
1511 #mask only channel 400
1512 msk = scan.create_mask([400])
1513
1514 """
1515 row = kwargs.get("row", 0)
1516 data = self._getabcissa(row)
1517 u = self._getcoordinfo()[0]
1518 if u == "":
1519 u = "channel"
1520 msg = "The current mask window unit is %s" % u
1521 i = self._check_ifs()
1522 if not i:
1523 msg += "\nThis mask is only valid for IF=%d" % (self.getif(i))
1524 asaplog.push(msg)
1525 n = len(data)
1526 msk = _n_bools(n, False)
1527 # test if args is a 'list' or a 'normal *args - UGLY!!!
1528
1529 ws = (isinstance(args[-1][-1], int)
1530 or isinstance(args[-1][-1], float)) and args or args[0]
1531 for window in ws:
1532 if len(window) == 1:
1533 window = [window[0], window[0]]
1534 if len(window) == 0 or len(window) > 2:
1535 raise ValueError("A window needs to be defined as "
1536 "[start(, end)]")
1537 if window[0] > window[1]:
1538 tmp = window[0]
1539 window[0] = window[1]
1540 window[1] = tmp
1541 for i in range(n):
1542 if data[i] >= window[0] and data[i] <= window[1]:
1543 msk[i] = True
1544 if kwargs.has_key('invert'):
1545 if kwargs.get('invert'):
1546 msk = mask_not(msk)
1547 return msk
1548
1549 def get_masklist(self, mask=None, row=0, silent=False):
1550 """\
1551 Compute and return a list of mask windows, [min, max].
1552
1553 Parameters:
1554
1555 mask: channel mask, created with create_mask.
1556
1557 row: calcutate the masklist using the specified row
1558 for unit conversions, default is row=0
1559 only necessary if frequency varies over rows.
1560
1561 Returns:
1562
1563 [min, max], [min2, max2], ...
1564 Pairs of start/end points (inclusive)specifying
1565 the masked regions
1566
1567 """
1568 if not (isinstance(mask,list) or isinstance(mask, tuple)):
1569 raise TypeError("The mask should be list or tuple.")
1570 if len(mask) <= 0:
1571 raise TypeError("The mask elements should be > 0")
1572 data = self._getabcissa(row)
1573 if len(data) != len(mask):
1574 msg = "Number of channels in scantable != number of mask elements"
1575 raise TypeError(msg)
1576 u = self._getcoordinfo()[0]
1577 if u == "":
1578 u = "channel"
1579 msg = "The current mask window unit is %s" % u
1580 i = self._check_ifs()
1581 if not i:
1582 msg += "\nThis mask is only valid for IF=%d" % (self.getif(i))
1583 if not silent:
1584 asaplog.push(msg)
1585 masklist = []
1586 ist, ien = None, None
1587 ist, ien=self.get_mask_indices(mask)
1588 if ist is not None and ien is not None:
1589 for i in xrange(len(ist)):
1590 range=[data[ist[i]],data[ien[i]]]
1591 range.sort()
1592 masklist.append([range[0],range[1]])
1593 return masklist
1594
1595 def get_mask_indices(self, mask=None):
1596 """\
1597 Compute and Return lists of mask start indices and mask end indices.
1598
1599 Parameters:
1600
1601 mask: channel mask, created with create_mask.
1602
1603 Returns:
1604
1605 List of mask start indices and that of mask end indices,
1606 i.e., [istart1,istart2,....], [iend1,iend2,....].
1607
1608 """
1609 if not (isinstance(mask,list) or isinstance(mask, tuple)):
1610 raise TypeError("The mask should be list or tuple.")
1611 if len(mask) <= 0:
1612 raise TypeError("The mask elements should be > 0")
1613 istart = []
1614 iend = []
1615 if mask[0]:
1616 istart.append(0)
1617 for i in range(len(mask)-1):
1618 if not mask[i] and mask[i+1]:
1619 istart.append(i+1)
1620 elif mask[i] and not mask[i+1]:
1621 iend.append(i)
1622 if mask[len(mask)-1]:
1623 iend.append(len(mask)-1)
1624 if len(istart) != len(iend):
1625 raise RuntimeError("Numbers of mask start != mask end.")
1626 for i in range(len(istart)):
1627 if istart[i] > iend[i]:
1628 raise RuntimeError("Mask start index > mask end index")
1629 break
1630 return istart,iend
1631
1632 @asaplog_post_dec
1633 def parse_maskexpr(self, maskstring):
1634 """
1635 Parse CASA type mask selection syntax (IF dependent).
1636
1637 Parameters:
1638 maskstring : A string mask selection expression.
1639 A comma separated selections mean different IF -
1640 channel combinations. IFs and channel selections
1641 are partitioned by a colon, ':'.
1642 examples:
1643 '' = all IFs (all channels)
1644 '<2,4~6,9' = IFs 0,1,4,5,6,9 (all channels)
1645 '3:3~45;60' = channels 3 to 45 and 60 in IF 3
1646 '0~1:2~6,8' = channels 2 to 6 in IFs 0,1, and
1647 all channels in IF8
1648 Returns:
1649 A dictionary of selected (valid) IF and masklist pairs,
1650 e.g. {'0': [[50,250],[350,462]], '2': [[100,400],[550,974]]}
1651 """
1652 if not isinstance(maskstring,str):
1653 asaplog.post()
1654 asaplog.push("Mask expression should be a string.")
1655 asaplog.post("ERROR")
1656
1657 valid_ifs = self.getifnos()
1658 frequnit = self.get_unit()
1659 seldict = {}
1660 if maskstring == "":
1661 maskstring = str(valid_ifs)[1:-1]
1662 ## split each selection "IF range[:CHAN range]"
1663 sellist = maskstring.split(',')
1664 for currselstr in sellist:
1665 selset = currselstr.split(':')
1666 # spw and mask string (may include ~, < or >)
1667 spwmasklist = self._parse_selection(selset[0], typestr='integer',
1668 minval=min(valid_ifs),
1669 maxval=max(valid_ifs))
1670 for spwlist in spwmasklist:
1671 selspws = []
1672 for ispw in range(spwlist[0],spwlist[1]+1):
1673 # Put into the list only if ispw exists
1674 if valid_ifs.count(ispw):
1675 selspws.append(ispw)
1676 del spwmasklist, spwlist
1677
1678 # parse frequency mask list
1679 if len(selset) > 1:
1680 freqmasklist = self._parse_selection(selset[1], typestr='float',
1681 offset=0.)
1682 else:
1683 # want to select the whole spectrum
1684 freqmasklist = [None]
1685
1686 ## define a dictionary of spw - masklist combination
1687 for ispw in selspws:
1688 #print "working on", ispw
1689 spwstr = str(ispw)
1690 if len(selspws) == 0:
1691 # empty spw
1692 continue
1693 else:
1694 ## want to get min and max of the spw and
1695 ## offset to set for '<' and '>'
1696 if frequnit == 'channel':
1697 minfreq = 0
1698 maxfreq = self.nchan(ifno=ispw)
1699 offset = 0.5
1700 else:
1701 ## This is ugly part. need improvement
1702 for ifrow in xrange(self.nrow()):
1703 if self.getif(ifrow) == ispw:
1704 #print "IF",ispw,"found in row =",ifrow
1705 break
1706 freqcoord = self.get_coordinate(ifrow)
1707 freqs = self._getabcissa(ifrow)
1708 minfreq = min(freqs)
1709 maxfreq = max(freqs)
1710 if len(freqs) == 1:
1711 offset = 0.5
1712 elif frequnit.find('Hz') > 0:
1713 offset = abs(freqcoord.to_frequency(1,
1714 unit=frequnit)
1715 -freqcoord.to_frequency(0,
1716 unit=frequnit)
1717 )*0.5
1718 elif frequnit.find('m/s') > 0:
1719 offset = abs(freqcoord.to_velocity(1,
1720 unit=frequnit)
1721 -freqcoord.to_velocity(0,
1722 unit=frequnit)
1723 )*0.5
1724 else:
1725 asaplog.post()
1726 asaplog.push("Invalid frequency unit")
1727 asaplog.post("ERROR")
1728 del freqs, freqcoord, ifrow
1729 for freq in freqmasklist:
1730 selmask = freq or [minfreq, maxfreq]
1731 if selmask[0] == None:
1732 ## selection was "<freq[1]".
1733 if selmask[1] < minfreq:
1734 ## avoid adding region selection
1735 selmask = None
1736 else:
1737 selmask = [minfreq,selmask[1]-offset]
1738 elif selmask[1] == None:
1739 ## selection was ">freq[0]"
1740 if selmask[0] > maxfreq:
1741 ## avoid adding region selection
1742 selmask = None
1743 else:
1744 selmask = [selmask[0]+offset,maxfreq]
1745 if selmask:
1746 if not seldict.has_key(spwstr):
1747 # new spw selection
1748 seldict[spwstr] = []
1749 seldict[spwstr] += [selmask]
1750 del minfreq,maxfreq,offset,freq,selmask
1751 del spwstr
1752 del freqmasklist
1753 del valid_ifs
1754 if len(seldict) == 0:
1755 asaplog.post()
1756 asaplog.push("No valid selection in the mask expression: "
1757 +maskstring)
1758 asaplog.post("WARN")
1759 return None
1760 msg = "Selected masklist:\n"
1761 for sif, lmask in seldict.iteritems():
1762 msg += " IF"+sif+" - "+str(lmask)+"\n"
1763 asaplog.push(msg)
1764 return seldict
1765
1766 @asaplog_post_dec
1767 def parse_idx_selection(self, mode, selexpr):
1768 """
1769 Parse CASA type mask selection syntax of SCANNO, IFNO, POLNO,
1770 BEAMNO, and row number
1771
1772 Parameters:
1773 mode : which column to select.
1774 ['scan',|'if'|'pol'|'beam'|'row']
1775 selexpr : A comma separated selection expression.
1776 examples:
1777 '' = all (returns [])
1778 '<2,4~6,9' = indices less than 2, 4 to 6 and 9
1779 (returns [0,1,4,5,6,9])
1780 Returns:
1781 A List of selected indices
1782 """
1783 if selexpr == "":
1784 return []
1785 valid_modes = {'s': 'scan', 'i': 'if', 'p': 'pol',
1786 'b': 'beam', 'r': 'row'}
1787 smode = mode.lower()[0]
1788 if not (smode in valid_modes.keys()):
1789 msg = "Invalid mode '%s'. Valid modes are %s" %\
1790 (mode, str(valid_modes.values()))
1791 asaplog.post()
1792 asaplog.push(msg)
1793 asaplog.post("ERROR")
1794 mode = valid_modes[smode]
1795 minidx = None
1796 maxidx = None
1797 if smode == 'r':
1798 minidx = 0
1799 maxidx = self.nrow()
1800 else:
1801 idx = getattr(self,"get"+mode+"nos")()
1802 minidx = min(idx)
1803 maxidx = max(idx)
1804 del idx
1805 sellist = selexpr.split(',')
1806 idxlist = []
1807 for currselstr in sellist:
1808 # single range (may include ~, < or >)
1809 currlist = self._parse_selection(currselstr, typestr='integer',
1810 minval=minidx,maxval=maxidx)
1811 for thelist in currlist:
1812 idxlist += range(thelist[0],thelist[1]+1)
1813 msg = "Selected %s: %s" % (mode.upper()+"NO", str(idxlist))
1814 asaplog.push(msg)
1815 return idxlist
1816
1817 def _parse_selection(self, selstr, typestr='float', offset=0.,
1818 minval=None, maxval=None):
1819 """
1820 Parameters:
1821 selstr : The Selection string, e.g., '<3;5~7;100~103;9'
1822 typestr : The type of the values in returned list
1823 ('integer' or 'float')
1824 offset : The offset value to subtract from or add to
1825 the boundary value if the selection string
1826 includes '<' or '>' [Valid only for typestr='float']
1827 minval, maxval : The minimum/maximum values to set if the
1828 selection string includes '<' or '>'.
1829 The list element is filled with None by default.
1830 Returns:
1831 A list of min/max pair of selections.
1832 Example:
1833 _parse_selection('<3;5~7;9',typestr='int',minval=0)
1834 --> returns [[0,2],[5,7],[9,9]]
1835 _parse_selection('<3;5~7;9',typestr='float',offset=0.5,minval=0)
1836 --> returns [[0.,2.5],[5.0,7.0],[9.,9.]]
1837 """
1838 selgroups = selstr.split(';')
1839 sellists = []
1840 if typestr.lower().startswith('int'):
1841 formatfunc = int
1842 offset = 1
1843 else:
1844 formatfunc = float
1845
1846 for currsel in selgroups:
1847 if currsel.find('~') > 0:
1848 # val0 <= x <= val1
1849 minsel = formatfunc(currsel.split('~')[0].strip())
1850 maxsel = formatfunc(currsel.split('~')[1].strip())
1851 elif currsel.strip().find('<=') > -1:
1852 bound = currsel.split('<=')
1853 try: # try "x <= val"
1854 minsel = minval
1855 maxsel = formatfunc(bound[1].strip())
1856 except ValueError: # now "val <= x"
1857 minsel = formatfunc(bound[0].strip())
1858 maxsel = maxval
1859 elif currsel.strip().find('>=') > -1:
1860 bound = currsel.split('>=')
1861 try: # try "x >= val"
1862 minsel = formatfunc(bound[1].strip())
1863 maxsel = maxval
1864 except ValueError: # now "val >= x"
1865 minsel = minval
1866 maxsel = formatfunc(bound[0].strip())
1867 elif currsel.strip().find('<') > -1:
1868 bound = currsel.split('<')
1869 try: # try "x < val"
1870 minsel = minval
1871 maxsel = formatfunc(bound[1].strip()) \
1872 - formatfunc(offset)
1873 except ValueError: # now "val < x"
1874 minsel = formatfunc(bound[0].strip()) \
1875 + formatfunc(offset)
1876 maxsel = maxval
1877 elif currsel.strip().find('>') > -1:
1878 bound = currsel.split('>')
1879 try: # try "x > val"
1880 minsel = formatfunc(bound[1].strip()) \
1881 + formatfunc(offset)
1882 maxsel = maxval
1883 except ValueError: # now "val > x"
1884 minsel = minval
1885 maxsel = formatfunc(bound[0].strip()) \
1886 - formatfunc(offset)
1887 else:
1888 minsel = formatfunc(currsel)
1889 maxsel = formatfunc(currsel)
1890 sellists.append([minsel,maxsel])
1891 return sellists
1892
1893# def get_restfreqs(self):
1894# """
1895# Get the restfrequency(s) stored in this scantable.
1896# The return value(s) are always of unit 'Hz'
1897# Parameters:
1898# none
1899# Returns:
1900# a list of doubles
1901# """
1902# return list(self._getrestfreqs())
1903
1904 def get_restfreqs(self, ids=None):
1905 """\
1906 Get the restfrequency(s) stored in this scantable.
1907 The return value(s) are always of unit 'Hz'
1908
1909 Parameters:
1910
1911 ids: (optional) a list of MOLECULE_ID for that restfrequency(s) to
1912 be retrieved
1913
1914 Returns:
1915
1916 dictionary containing ids and a list of doubles for each id
1917
1918 """
1919 if ids is None:
1920 rfreqs = {}
1921 idlist = self.getmolnos()
1922 for i in idlist:
1923 rfreqs[i] = list(self._getrestfreqs(i))
1924 return rfreqs
1925 else:
1926 if type(ids) == list or type(ids) == tuple:
1927 rfreqs = {}
1928 for i in ids:
1929 rfreqs[i] = list(self._getrestfreqs(i))
1930 return rfreqs
1931 else:
1932 return list(self._getrestfreqs(ids))
1933
1934 @asaplog_post_dec
1935 def set_restfreqs(self, freqs=None, unit='Hz'):
1936 """\
1937 Set or replace the restfrequency specified and
1938 if the 'freqs' argument holds a scalar,
1939 then that rest frequency will be applied to all the selected
1940 data. If the 'freqs' argument holds
1941 a vector, then it MUST be of equal or smaller length than
1942 the number of IFs (and the available restfrequencies will be
1943 replaced by this vector). In this case, *all* data have
1944 the restfrequency set per IF according
1945 to the corresponding value you give in the 'freqs' vector.
1946 E.g. 'freqs=[1e9, 2e9]' would mean IF 0 gets restfreq 1e9 and
1947 IF 1 gets restfreq 2e9.
1948
1949 You can also specify the frequencies via a linecatalog.
1950
1951 Parameters:
1952
1953 freqs: list of rest frequency values or string idenitfiers
1954
1955 unit: unit for rest frequency (default 'Hz')
1956
1957
1958 Example::
1959
1960 # set the given restfrequency for the all currently selected IFs
1961 scan.set_restfreqs(freqs=1.4e9)
1962 # set restfrequencies for the n IFs (n > 1) in the order of the
1963 # list, i.e
1964 # IF0 -> 1.4e9, IF1 -> 1.41e9, IF3 -> 1.42e9
1965 # len(list_of_restfreqs) == nIF
1966 # for nIF == 1 the following will set multiple restfrequency for
1967 # that IF
1968 scan.set_restfreqs(freqs=[1.4e9, 1.41e9, 1.42e9])
1969 # set multiple restfrequencies per IF. as a list of lists where
1970 # the outer list has nIF elements, the inner s arbitrary
1971 scan.set_restfreqs(freqs=[[1.4e9, 1.41e9], [1.67e9]])
1972
1973 *Note*:
1974
1975 To do more sophisticate Restfrequency setting, e.g. on a
1976 source and IF basis, use scantable.set_selection() before using
1977 this function::
1978
1979 # provided your scantable is called scan
1980 selection = selector()
1981 selection.set_name('ORION*')
1982 selection.set_ifs([1])
1983 scan.set_selection(selection)
1984 scan.set_restfreqs(freqs=86.6e9)
1985
1986 """
1987 varlist = vars()
1988 from asap import linecatalog
1989 # simple value
1990 if isinstance(freqs, int) or isinstance(freqs, float):
1991 self._setrestfreqs([freqs], [""], unit)
1992 # list of values
1993 elif isinstance(freqs, list) or isinstance(freqs, tuple):
1994 # list values are scalars
1995 if isinstance(freqs[-1], int) or isinstance(freqs[-1], float):
1996 if len(freqs) == 1:
1997 self._setrestfreqs(freqs, [""], unit)
1998 else:
1999 # allow the 'old' mode of setting mulitple IFs
2000 savesel = self._getselection()
2001 sel = self.get_selection()
2002 iflist = self.getifnos()
2003 if len(freqs)>len(iflist):
2004 raise ValueError("number of elements in list of list "
2005 "exeeds the current IF selections")
2006 iflist = self.getifnos()
2007 for i, fval in enumerate(freqs):
2008 sel.set_ifs(iflist[i])
2009 self._setselection(sel)
2010 self._setrestfreqs([fval], [""], unit)
2011 self._setselection(savesel)
2012
2013 # list values are dict, {'value'=, 'name'=)
2014 elif isinstance(freqs[-1], dict):
2015 values = []
2016 names = []
2017 for d in freqs:
2018 values.append(d["value"])
2019 names.append(d["name"])
2020 self._setrestfreqs(values, names, unit)
2021 elif isinstance(freqs[-1], list) or isinstance(freqs[-1], tuple):
2022 savesel = self._getselection()
2023 sel = self.get_selection()
2024 iflist = self.getifnos()
2025 if len(freqs)>len(iflist):
2026 raise ValueError("number of elements in list of list exeeds"
2027 " the current IF selections")
2028 for i, fval in enumerate(freqs):
2029 sel.set_ifs(iflist[i])
2030 self._setselection(sel)
2031 self._setrestfreqs(fval, [""], unit)
2032 self._setselection(savesel)
2033 # freqs are to be taken from a linecatalog
2034 elif isinstance(freqs, linecatalog):
2035 savesel = self._getselection()
2036 sel = self.get_selection()
2037 for i in xrange(freqs.nrow()):
2038 sel.set_ifs(iflist[i])
2039 self._setselection(sel)
2040 self._setrestfreqs([freqs.get_frequency(i)],
2041 [freqs.get_name(i)], "MHz")
2042 # ensure that we are not iterating past nIF
2043 if i == self.nif()-1: break
2044 self._setselection(savesel)
2045 else:
2046 return
2047 self._add_history("set_restfreqs", varlist)
2048
2049 @asaplog_post_dec
2050 def shift_refpix(self, delta):
2051 """\
2052 Shift the reference pixel of the Spectra Coordinate by an
2053 integer amount.
2054
2055 Parameters:
2056
2057 delta: the amount to shift by
2058
2059 *Note*:
2060
2061 Be careful using this with broadband data.
2062
2063 """
2064 varlist = vars()
2065 Scantable.shift_refpix(self, delta)
2066 s._add_history("shift_refpix", varlist)
2067
2068 @asaplog_post_dec
2069 def history(self, filename=None):
2070 """\
2071 Print the history. Optionally to a file.
2072
2073 Parameters:
2074
2075 filename: The name of the file to save the history to.
2076
2077 """
2078 hist = list(self._gethistory())
2079 out = "-"*80
2080 for h in hist:
2081 if h.startswith("---"):
2082 out = "\n".join([out, h])
2083 else:
2084 items = h.split("##")
2085 date = items[0]
2086 func = items[1]
2087 items = items[2:]
2088 out += "\n"+date+"\n"
2089 out += "Function: %s\n Parameters:" % (func)
2090 for i in items:
2091 if i == '':
2092 continue
2093 s = i.split("=")
2094 out += "\n %s = %s" % (s[0], s[1])
2095 out = "\n".join([out, "-"*80])
2096 if filename is not None:
2097 if filename is "":
2098 filename = 'scantable_history.txt'
2099 import os
2100 filename = os.path.expandvars(os.path.expanduser(filename))
2101 if not os.path.isdir(filename):
2102 data = open(filename, 'w')
2103 data.write(out)
2104 data.close()
2105 else:
2106 msg = "Illegal file name '%s'." % (filename)
2107 raise IOError(msg)
2108 return page(out)
2109
2110 #
2111 # Maths business
2112 #
2113 @asaplog_post_dec
2114 def average_time(self, mask=None, scanav=False, weight='tint', align=False):
2115 """\
2116 Return the (time) weighted average of a scan. Scans will be averaged
2117 only if the source direction (RA/DEC) is within 1' otherwise
2118
2119 *Note*:
2120
2121 in channels only - align if necessary
2122
2123 Parameters:
2124
2125 mask: an optional mask (only used for 'var' and 'tsys'
2126 weighting)
2127
2128 scanav: True averages each scan separately
2129 False (default) averages all scans together,
2130
2131 weight: Weighting scheme.
2132 'none' (mean no weight)
2133 'var' (1/var(spec) weighted)
2134 'tsys' (1/Tsys**2 weighted)
2135 'tint' (integration time weighted)
2136 'tintsys' (Tint/Tsys**2)
2137 'median' ( median averaging)
2138 The default is 'tint'
2139
2140 align: align the spectra in velocity before averaging. It takes
2141 the time of the first spectrum as reference time.
2142
2143 Example::
2144
2145 # time average the scantable without using a mask
2146 newscan = scan.average_time()
2147
2148 """
2149 varlist = vars()
2150 weight = weight or 'TINT'
2151 mask = mask or ()
2152 scanav = (scanav and 'SCAN') or 'NONE'
2153 scan = (self, )
2154
2155 if align:
2156 scan = (self.freq_align(insitu=False), )
2157 s = None
2158 if weight.upper() == 'MEDIAN':
2159 s = scantable(self._math._averagechannel(scan[0], 'MEDIAN',
2160 scanav))
2161 else:
2162 s = scantable(self._math._average(scan, mask, weight.upper(),
2163 scanav))
2164 s._add_history("average_time", varlist)
2165 return s
2166
2167 @asaplog_post_dec
2168 def convert_flux(self, jyperk=None, eta=None, d=None, insitu=None):
2169 """\
2170 Return a scan where all spectra are converted to either
2171 Jansky or Kelvin depending upon the flux units of the scan table.
2172 By default the function tries to look the values up internally.
2173 If it can't find them (or if you want to over-ride), you must
2174 specify EITHER jyperk OR eta (and D which it will try to look up
2175 also if you don't set it). jyperk takes precedence if you set both.
2176
2177 Parameters:
2178
2179 jyperk: the Jy / K conversion factor
2180
2181 eta: the aperture efficiency
2182
2183 d: the geometric diameter (metres)
2184
2185 insitu: if False a new scantable is returned.
2186 Otherwise, the scaling is done in-situ
2187 The default is taken from .asaprc (False)
2188
2189 """
2190 if insitu is None: insitu = rcParams['insitu']
2191 self._math._setinsitu(insitu)
2192 varlist = vars()
2193 jyperk = jyperk or -1.0
2194 d = d or -1.0
2195 eta = eta or -1.0
2196 s = scantable(self._math._convertflux(self, d, eta, jyperk))
2197 s._add_history("convert_flux", varlist)
2198 if insitu: self._assign(s)
2199 else: return s
2200
2201 @asaplog_post_dec
2202 def gain_el(self, poly=None, filename="", method="linear", insitu=None):
2203 """\
2204 Return a scan after applying a gain-elevation correction.
2205 The correction can be made via either a polynomial or a
2206 table-based interpolation (and extrapolation if necessary).
2207 You specify polynomial coefficients, an ascii table or neither.
2208 If you specify neither, then a polynomial correction will be made
2209 with built in coefficients known for certain telescopes (an error
2210 will occur if the instrument is not known).
2211 The data and Tsys are *divided* by the scaling factors.
2212
2213 Parameters:
2214
2215 poly: Polynomial coefficients (default None) to compute a
2216 gain-elevation correction as a function of
2217 elevation (in degrees).
2218
2219 filename: The name of an ascii file holding correction factors.
2220 The first row of the ascii file must give the column
2221 names and these MUST include columns
2222 'ELEVATION' (degrees) and 'FACTOR' (multiply data
2223 by this) somewhere.
2224 The second row must give the data type of the
2225 column. Use 'R' for Real and 'I' for Integer.
2226 An example file would be
2227 (actual factors are arbitrary) :
2228
2229 TIME ELEVATION FACTOR
2230 R R R
2231 0.1 0 0.8
2232 0.2 20 0.85
2233 0.3 40 0.9
2234 0.4 60 0.85
2235 0.5 80 0.8
2236 0.6 90 0.75
2237
2238 method: Interpolation method when correcting from a table.
2239 Values are 'nearest', 'linear' (default), 'cubic'
2240 and 'spline'
2241
2242 insitu: if False a new scantable is returned.
2243 Otherwise, the scaling is done in-situ
2244 The default is taken from .asaprc (False)
2245
2246 """
2247
2248 if insitu is None: insitu = rcParams['insitu']
2249 self._math._setinsitu(insitu)
2250 varlist = vars()
2251 poly = poly or ()
2252 from os.path import expandvars
2253 filename = expandvars(filename)
2254 s = scantable(self._math._gainel(self, poly, filename, method))
2255 s._add_history("gain_el", varlist)
2256 if insitu:
2257 self._assign(s)
2258 else:
2259 return s
2260
2261 @asaplog_post_dec
2262 def freq_align(self, reftime=None, method='cubic', insitu=None):
2263 """\
2264 Return a scan where all rows have been aligned in frequency/velocity.
2265 The alignment frequency frame (e.g. LSRK) is that set by function
2266 set_freqframe.
2267
2268 Parameters:
2269
2270 reftime: reference time to align at. By default, the time of
2271 the first row of data is used.
2272
2273 method: Interpolation method for regridding the spectra.
2274 Choose from 'nearest', 'linear', 'cubic' (default)
2275 and 'spline'
2276
2277 insitu: if False a new scantable is returned.
2278 Otherwise, the scaling is done in-situ
2279 The default is taken from .asaprc (False)
2280
2281 """
2282 if insitu is None: insitu = rcParams["insitu"]
2283 oldInsitu = self._math._insitu()
2284 self._math._setinsitu(insitu)
2285 varlist = vars()
2286 reftime = reftime or ""
2287 s = scantable(self._math._freq_align(self, reftime, method))
2288 s._add_history("freq_align", varlist)
2289 self._math._setinsitu(oldInsitu)
2290 if insitu:
2291 self._assign(s)
2292 else:
2293 return s
2294
2295 @asaplog_post_dec
2296 def opacity(self, tau=None, insitu=None):
2297 """\
2298 Apply an opacity correction. The data
2299 and Tsys are multiplied by the correction factor.
2300
2301 Parameters:
2302
2303 tau: (list of) opacity from which the correction factor is
2304 exp(tau*ZD)
2305 where ZD is the zenith-distance.
2306 If a list is provided, it has to be of length nIF,
2307 nIF*nPol or 1 and in order of IF/POL, e.g.
2308 [opif0pol0, opif0pol1, opif1pol0 ...]
2309 if tau is `None` the opacities are determined from a
2310 model.
2311
2312 insitu: if False a new scantable is returned.
2313 Otherwise, the scaling is done in-situ
2314 The default is taken from .asaprc (False)
2315
2316 """
2317 if insitu is None:
2318 insitu = rcParams['insitu']
2319 self._math._setinsitu(insitu)
2320 varlist = vars()
2321 if not hasattr(tau, "__len__"):
2322 tau = [tau]
2323 s = scantable(self._math._opacity(self, tau))
2324 s._add_history("opacity", varlist)
2325 if insitu:
2326 self._assign(s)
2327 else:
2328 return s
2329
2330 @asaplog_post_dec
2331 def bin(self, width=5, insitu=None):
2332 """\
2333 Return a scan where all spectra have been binned up.
2334
2335 Parameters:
2336
2337 width: The bin width (default=5) in pixels
2338
2339 insitu: if False a new scantable is returned.
2340 Otherwise, the scaling is done in-situ
2341 The default is taken from .asaprc (False)
2342
2343 """
2344 if insitu is None:
2345 insitu = rcParams['insitu']
2346 self._math._setinsitu(insitu)
2347 varlist = vars()
2348 s = scantable(self._math._bin(self, width))
2349 s._add_history("bin", varlist)
2350 if insitu:
2351 self._assign(s)
2352 else:
2353 return s
2354
2355 @asaplog_post_dec
2356 def reshape(self, first, last, insitu=None):
2357 """Resize the band by providing first and last channel.
2358 This will cut off all channels outside [first, last].
2359 """
2360 if insitu is None:
2361 insitu = rcParams['insitu']
2362 varlist = vars()
2363 if last < 0:
2364 last = self.nchan()-1 + last
2365 s = None
2366 if insitu:
2367 s = self
2368 else:
2369 s = self.copy()
2370 s._reshape(first,last)
2371 s._add_history("reshape", varlist)
2372 if not insitu:
2373 return s
2374
2375 @asaplog_post_dec
2376 def resample(self, width=5, method='cubic', insitu=None):
2377 """\
2378 Return a scan where all spectra have been binned up.
2379
2380 Parameters:
2381
2382 width: The bin width (default=5) in pixels
2383
2384 method: Interpolation method when correcting from a table.
2385 Values are 'nearest', 'linear', 'cubic' (default)
2386 and 'spline'
2387
2388 insitu: if False a new scantable is returned.
2389 Otherwise, the scaling is done in-situ
2390 The default is taken from .asaprc (False)
2391
2392 """
2393 if insitu is None:
2394 insitu = rcParams['insitu']
2395 self._math._setinsitu(insitu)
2396 varlist = vars()
2397 s = scantable(self._math._resample(self, method, width))
2398 s._add_history("resample", varlist)
2399 if insitu:
2400 self._assign(s)
2401 else:
2402 return s
2403
2404 @asaplog_post_dec
2405 def average_pol(self, mask=None, weight='none'):
2406 """\
2407 Average the Polarisations together.
2408
2409 Parameters:
2410
2411 mask: An optional mask defining the region, where the
2412 averaging will be applied. The output will have all
2413 specified points masked.
2414
2415 weight: Weighting scheme. 'none' (default), 'var' (1/var(spec)
2416 weighted), or 'tsys' (1/Tsys**2 weighted)
2417
2418 """
2419 varlist = vars()
2420 mask = mask or ()
2421 s = scantable(self._math._averagepol(self, mask, weight.upper()))
2422 s._add_history("average_pol", varlist)
2423 return s
2424
2425 @asaplog_post_dec
2426 def average_beam(self, mask=None, weight='none'):
2427 """\
2428 Average the Beams together.
2429
2430 Parameters:
2431 mask: An optional mask defining the region, where the
2432 averaging will be applied. The output will have all
2433 specified points masked.
2434
2435 weight: Weighting scheme. 'none' (default), 'var' (1/var(spec)
2436 weighted), or 'tsys' (1/Tsys**2 weighted)
2437
2438 """
2439 varlist = vars()
2440 mask = mask or ()
2441 s = scantable(self._math._averagebeams(self, mask, weight.upper()))
2442 s._add_history("average_beam", varlist)
2443 return s
2444
2445 def parallactify(self, pflag):
2446 """\
2447 Set a flag to indicate whether this data should be treated as having
2448 been 'parallactified' (total phase == 0.0)
2449
2450 Parameters:
2451
2452 pflag: Bool indicating whether to turn this on (True) or
2453 off (False)
2454
2455 """
2456 varlist = vars()
2457 self._parallactify(pflag)
2458 self._add_history("parallactify", varlist)
2459
2460 @asaplog_post_dec
2461 def convert_pol(self, poltype=None):
2462 """\
2463 Convert the data to a different polarisation type.
2464 Note that you will need cross-polarisation terms for most conversions.
2465
2466 Parameters:
2467
2468 poltype: The new polarisation type. Valid types are:
2469 'linear', 'circular', 'stokes' and 'linpol'
2470
2471 """
2472 varlist = vars()
2473 s = scantable(self._math._convertpol(self, poltype))
2474 s._add_history("convert_pol", varlist)
2475 return s
2476
2477 @asaplog_post_dec
2478 def smooth(self, kernel="hanning", width=5.0, order=2, plot=False,
2479 insitu=None):
2480 """\
2481 Smooth the spectrum by the specified kernel (conserving flux).
2482
2483 Parameters:
2484
2485 kernel: The type of smoothing kernel. Select from
2486 'hanning' (default), 'gaussian', 'boxcar', 'rmedian'
2487 or 'poly'
2488
2489 width: The width of the kernel in pixels. For hanning this is
2490 ignored otherwise it defauls to 5 pixels.
2491 For 'gaussian' it is the Full Width Half
2492 Maximum. For 'boxcar' it is the full width.
2493 For 'rmedian' and 'poly' it is the half width.
2494
2495 order: Optional parameter for 'poly' kernel (default is 2), to
2496 specify the order of the polnomial. Ignored by all other
2497 kernels.
2498
2499 plot: plot the original and the smoothed spectra.
2500 In this each indivual fit has to be approved, by
2501 typing 'y' or 'n'
2502
2503 insitu: if False a new scantable is returned.
2504 Otherwise, the scaling is done in-situ
2505 The default is taken from .asaprc (False)
2506
2507 """
2508 if insitu is None: insitu = rcParams['insitu']
2509 self._math._setinsitu(insitu)
2510 varlist = vars()
2511
2512 if plot: orgscan = self.copy()
2513
2514 s = scantable(self._math._smooth(self, kernel.lower(), width, order))
2515 s._add_history("smooth", varlist)
2516
2517 action = 'H'
2518 if plot:
2519 from asap.asapplotter import new_asaplot
2520 theplot = new_asaplot(rcParams['plotter.gui'])
2521 from matplotlib import rc as rcp
2522 rcp('lines', linewidth=1)
2523 theplot.set_panels()
2524 ylab=s._get_ordinate_label()
2525 #theplot.palette(0,["#777777","red"])
2526 for r in xrange(s.nrow()):
2527 xsm=s._getabcissa(r)
2528 ysm=s._getspectrum(r)
2529 xorg=orgscan._getabcissa(r)
2530 yorg=orgscan._getspectrum(r)
2531 if action != "N": #skip plotting if rejecting all
2532 theplot.clear()
2533 theplot.hold()
2534 theplot.set_axes('ylabel',ylab)
2535 theplot.set_axes('xlabel',s._getabcissalabel(r))
2536 theplot.set_axes('title',s._getsourcename(r))
2537 theplot.set_line(label='Original',color="#777777")
2538 theplot.plot(xorg,yorg)
2539 theplot.set_line(label='Smoothed',color="red")
2540 theplot.plot(xsm,ysm)
2541 ### Ugly part for legend
2542 for i in [0,1]:
2543 theplot.subplots[0]['lines'].append(
2544 [theplot.subplots[0]['axes'].lines[i]]
2545 )
2546 theplot.release()
2547 ### Ugly part for legend
2548 theplot.subplots[0]['lines']=[]
2549 res = self._get_verify_action("Accept smoothing?",action)
2550 #print "IF%d, POL%d: got result = %s" %(s.getif(r),s.getpol(r),res)
2551 if r == 0: action = None
2552 #res = raw_input("Accept smoothing ([y]/n): ")
2553 if res.upper() == 'N':
2554 # reject for the current rows
2555 s._setspectrum(yorg, r)
2556 elif res.upper() == 'R':
2557 # reject all the following rows
2558 action = "N"
2559 s._setspectrum(yorg, r)
2560 elif res.upper() == 'A':
2561 # accept all the following rows
2562 break
2563 theplot.quit()
2564 del theplot
2565 del orgscan
2566
2567 if insitu: self._assign(s)
2568 else: return s
2569
2570 @asaplog_post_dec
2571 def regrid_channel(self, width=5, plot=False, insitu=None):
2572 """\
2573 Regrid the spectra by the specified channel width
2574
2575 Parameters:
2576
2577 width: The channel width (float) of regridded spectra
2578 in the current spectral unit.
2579
2580 plot: [NOT IMPLEMENTED YET]
2581 plot the original and the regridded spectra.
2582 In this each indivual fit has to be approved, by
2583 typing 'y' or 'n'
2584
2585 insitu: if False a new scantable is returned.
2586 Otherwise, the scaling is done in-situ
2587 The default is taken from .asaprc (False)
2588
2589 """
2590 if insitu is None: insitu = rcParams['insitu']
2591 varlist = vars()
2592
2593 if plot:
2594 asaplog.post()
2595 asaplog.push("Verification plot is not implemtnetd yet.")
2596 asaplog.post("WARN")
2597
2598 s = self.copy()
2599 s._regrid_specchan(width)
2600
2601 s._add_history("regrid_channel", varlist)
2602
2603# if plot:
2604# from asap.asapplotter import new_asaplot
2605# theplot = new_asaplot(rcParams['plotter.gui'])
2606# from matplotlib import rc as rcp
2607# rcp('lines', linewidth=1)
2608# theplot.set_panels()
2609# ylab=s._get_ordinate_label()
2610# #theplot.palette(0,["#777777","red"])
2611# for r in xrange(s.nrow()):
2612# xsm=s._getabcissa(r)
2613# ysm=s._getspectrum(r)
2614# xorg=orgscan._getabcissa(r)
2615# yorg=orgscan._getspectrum(r)
2616# theplot.clear()
2617# theplot.hold()
2618# theplot.set_axes('ylabel',ylab)
2619# theplot.set_axes('xlabel',s._getabcissalabel(r))
2620# theplot.set_axes('title',s._getsourcename(r))
2621# theplot.set_line(label='Original',color="#777777")
2622# theplot.plot(xorg,yorg)
2623# theplot.set_line(label='Smoothed',color="red")
2624# theplot.plot(xsm,ysm)
2625# ### Ugly part for legend
2626# for i in [0,1]:
2627# theplot.subplots[0]['lines'].append(
2628# [theplot.subplots[0]['axes'].lines[i]]
2629# )
2630# theplot.release()
2631# ### Ugly part for legend
2632# theplot.subplots[0]['lines']=[]
2633# res = raw_input("Accept smoothing ([y]/n): ")
2634# if res.upper() == 'N':
2635# s._setspectrum(yorg, r)
2636# theplot.quit()
2637# del theplot
2638# del orgscan
2639
2640 if insitu: self._assign(s)
2641 else: return s
2642
2643 @asaplog_post_dec
2644 def _parse_wn(self, wn):
2645 if isinstance(wn, list) or isinstance(wn, tuple):
2646 return wn
2647 elif isinstance(wn, int):
2648 return [ wn ]
2649 elif isinstance(wn, str):
2650 if '-' in wn: # case 'a-b' : return [a,a+1,...,b-1,b]
2651 val = wn.split('-')
2652 val = [int(val[0]), int(val[1])]
2653 val.sort()
2654 res = [i for i in xrange(val[0], val[1]+1)]
2655 elif wn[:2] == '<=' or wn[:2] == '=<': # cases '<=a','=<a' : return [0,1,...,a-1,a]
2656 val = int(wn[2:])+1
2657 res = [i for i in xrange(val)]
2658 elif wn[-2:] == '>=' or wn[-2:] == '=>': # cases 'a>=','a=>' : return [0,1,...,a-1,a]
2659 val = int(wn[:-2])+1
2660 res = [i for i in xrange(val)]
2661 elif wn[0] == '<': # case '<a' : return [0,1,...,a-2,a-1]
2662 val = int(wn[1:])
2663 res = [i for i in xrange(val)]
2664 elif wn[-1] == '>': # case 'a>' : return [0,1,...,a-2,a-1]
2665 val = int(wn[:-1])
2666 res = [i for i in xrange(val)]
2667 elif wn[:2] == '>=' or wn[:2] == '=>': # cases '>=a','=>a' : return [a,-999], which is
2668 # then interpreted in C++
2669 # side as [a,a+1,...,a_nyq]
2670 # (CAS-3759)
2671 val = int(wn[2:])
2672 res = [val, -999]
2673 #res = [i for i in xrange(val, self.nchan()/2+1)]
2674 elif wn[-2:] == '<=' or wn[-2:] == '=<': # cases 'a<=','a=<' : return [a,-999], which is
2675 # then interpreted in C++
2676 # side as [a,a+1,...,a_nyq]
2677 # (CAS-3759)
2678 val = int(wn[:-2])
2679 res = [val, -999]
2680 #res = [i for i in xrange(val, self.nchan()/2+1)]
2681 elif wn[0] == '>': # case '>a' : return [a+1,-999], which is
2682 # then interpreted in C++
2683 # side as [a+1,a+2,...,a_nyq]
2684 # (CAS-3759)
2685 val = int(wn[1:])+1
2686 res = [val, -999]
2687 #res = [i for i in xrange(val, self.nchan()/2+1)]
2688 elif wn[-1] == '<': # case 'a<' : return [a+1,-999], which is
2689 # then interpreted in C++
2690 # side as [a+1,a+2,...,a_nyq]
2691 # (CAS-3759)
2692 val = int(wn[:-1])+1
2693 res = [val, -999]
2694 #res = [i for i in xrange(val, self.nchan()/2+1)]
2695
2696 return res
2697 else:
2698 msg = 'wrong value given for addwn/rejwn'
2699 raise RuntimeError(msg)
2700
2701 @asaplog_post_dec
2702 def apply_bltable(self, insitu=None, retfitres=None, inbltable=None, outbltable=None, overwrite=None):
2703 """\
2704 Subtract baseline based on parameters written in Baseline Table.
2705
2706 Parameters:
2707 insitu: if True, baseline fitting/subtraction is done
2708 in-situ. If False, a new scantable with
2709 baseline subtracted is returned. Actually,
2710 format of the returned value depends on both
2711 insitu and retfitres (see below).
2712 The default is taken from .asaprc (False)
2713 retfitres: if True, the results of baseline fitting (i.e.,
2714 coefficients and rms) are returned.
2715 default is False.
2716 The format of the returned value of this
2717 function varies as follows:
2718 (1) in case insitu=True and retfitres=True:
2719 fitting result.
2720 (2) in case insitu=True and retfitres=False:
2721 None.
2722 (3) in case insitu=False and retfitres=True:
2723 a dictionary containing a new scantable
2724 (with baseline subtracted) and the fitting
2725 results.
2726 (4) in case insitu=False and retfitres=False:
2727 a new scantable (with baseline subtracted).
2728 inbltable: name of input baseline table. The row number of
2729 scantable and that of inbltable must be
2730 identical.
2731 outbltable: name of output baseline table where baseline
2732 parameters and fitting results recorded.
2733 default is ''(no output).
2734 overwrite: if True when an existing baseline table is
2735 specified for outbltable, overwrites it.
2736 Otherwise there is no harm.
2737 default is False.
2738 """
2739
2740 try:
2741 varlist = vars()
2742 if retfitres is None: retfitres = False
2743 if inbltable is None: raise ValueError("bltable missing.")
2744 if outbltable is None: outbltable = ''
2745 if overwrite is None: overwrite = False
2746
2747 if insitu is None: insitu = rcParams['insitu']
2748 if insitu:
2749 workscan = self
2750 else:
2751 workscan = self.copy()
2752
2753 sres = workscan._apply_bltable(inbltable,
2754 retfitres,
2755 outbltable,
2756 os.path.exists(outbltable),
2757 overwrite)
2758 if retfitres: res = parse_fitresult(sres)
2759
2760 workscan._add_history('apply_bltable', varlist)
2761
2762 if insitu:
2763 self._assign(workscan)
2764 if retfitres:
2765 return res
2766 else:
2767 return None
2768 else:
2769 if retfitres:
2770 return {'scantable': workscan, 'fitresults': res}
2771 else:
2772 return workscan
2773
2774 except RuntimeError, e:
2775 raise_fitting_failure_exception(e)
2776
2777 @asaplog_post_dec
2778 def sub_baseline(self, insitu=None, retfitres=None, blinfo=None, bltable=None, overwrite=None):
2779 """\
2780 Subtract baseline based on parameters written in the input list.
2781
2782 Parameters:
2783 insitu: if True, baseline fitting/subtraction is done
2784 in-situ. If False, a new scantable with
2785 baseline subtracted is returned. Actually,
2786 format of the returned value depends on both
2787 insitu and retfitres (see below).
2788 The default is taken from .asaprc (False)
2789 retfitres: if True, the results of baseline fitting (i.e.,
2790 coefficients and rms) are returned.
2791 default is False.
2792 The format of the returned value of this
2793 function varies as follows:
2794 (1) in case insitu=True and retfitres=True:
2795 fitting result.
2796 (2) in case insitu=True and retfitres=False:
2797 None.
2798 (3) in case insitu=False and retfitres=True:
2799 a dictionary containing a new scantable
2800 (with baseline subtracted) and the fitting
2801 results.
2802 (4) in case insitu=False and retfitres=False:
2803 a new scantable (with baseline subtracted).
2804 blinfo: baseline parameter set stored in a dictionary
2805 or a list of dictionary. Each dictionary
2806 corresponds to each spectrum and must contain
2807 the following keys and values:
2808 'row': row number,
2809 'blfunc': function name. available ones include
2810 'poly', 'chebyshev', 'cspline' and
2811 'sinusoid',
2812 'order': maximum order of polynomial. needed
2813 if blfunc='poly' or 'chebyshev',
2814 'npiece': number or piecewise polynomial.
2815 needed if blfunc='cspline',
2816 'nwave': a list of sinusoidal wave numbers.
2817 needed if blfunc='sinusoid', and
2818 'masklist': min-max windows for channel mask.
2819 the specified ranges will be used
2820 for fitting.
2821 bltable: name of output baseline table where baseline
2822 parameters and fitting results recorded.
2823 default is ''(no output).
2824 overwrite: if True when an existing baseline table is
2825 specified for bltable, overwrites it.
2826 Otherwise there is no harm.
2827 default is False.
2828
2829 Example:
2830 sub_baseline(blinfo=[{'row':0, 'blfunc':'poly', 'order':5,
2831 'masklist':[[10,350],[352,510]]},
2832 {'row':1, 'blfunc':'cspline', 'npiece':3,
2833 'masklist':[[3,16],[19,404],[407,511]]}
2834 ])
2835
2836 the first spectrum (row=0) will be fitted with polynomial
2837 of order=5 and the next one (row=1) will be fitted with cubic
2838 spline consisting of 3 pieces.
2839 """
2840
2841 try:
2842 varlist = vars()
2843 if retfitres is None: retfitres = False
2844 if blinfo is None: blinfo = []
2845 if bltable is None: bltable = ''
2846 if overwrite is None: overwrite = False
2847
2848 if insitu is None: insitu = rcParams['insitu']
2849 if insitu:
2850 workscan = self
2851 else:
2852 workscan = self.copy()
2853
2854 nrow = workscan.nrow()
2855
2856 in_blinfo = pack_blinfo(blinfo=blinfo, maxirow=nrow)
2857
2858 print "in_blinfo=< "+ str(in_blinfo)+" >"
2859
2860 sres = workscan._sub_baseline(in_blinfo,
2861 retfitres,
2862 bltable,
2863 os.path.exists(bltable),
2864 overwrite)
2865 if retfitres: res = parse_fitresult(sres)
2866
2867 workscan._add_history('sub_baseline', varlist)
2868
2869 if insitu:
2870 self._assign(workscan)
2871 if retfitres:
2872 return res
2873 else:
2874 return None
2875 else:
2876 if retfitres:
2877 return {'scantable': workscan, 'fitresults': res}
2878 else:
2879 return workscan
2880
2881 except RuntimeError, e:
2882 raise_fitting_failure_exception(e)
2883
2884 @asaplog_post_dec
2885 def calc_aic(self, value=None, blfunc=None, order=None, mask=None,
2886 whichrow=None, uselinefinder=None, edge=None,
2887 threshold=None, chan_avg_limit=None):
2888 """\
2889 Calculates and returns model selection criteria for a specified
2890 baseline model and a given spectrum data.
2891 Available values include Akaike Information Criterion (AIC), the
2892 corrected Akaike Information Criterion (AICc) by Sugiura(1978),
2893 Bayesian Information Criterion (BIC) and the Generalised Cross
2894 Validation (GCV).
2895
2896 Parameters:
2897 value: name of model selection criteria to calculate.
2898 available ones include 'aic', 'aicc', 'bic' and
2899 'gcv'. default is 'aicc'.
2900 blfunc: baseline function name. available ones include
2901 'chebyshev', 'cspline' and 'sinusoid'.
2902 default is 'chebyshev'.
2903 order: parameter for basline function. actually stands for
2904 order of polynomial (order) for 'chebyshev',
2905 number of spline pieces (npiece) for 'cspline' and
2906 maximum wave number for 'sinusoid', respectively.
2907 default is 5 (which is also the default order value
2908 for [auto_]chebyshev_baseline()).
2909 mask: an optional mask. default is [].
2910 whichrow: row number. default is 0 (the first row)
2911 uselinefinder: use sd.linefinder() to flag out line regions
2912 default is True.
2913 edge: an optional number of channel to drop at
2914 the edge of spectrum. If only one value is
2915 specified, the same number will be dropped
2916 from both sides of the spectrum. Default
2917 is to keep all channels. Nested tuples
2918 represent individual edge selection for
2919 different IFs (a number of spectral channels
2920 can be different)
2921 default is (0, 0).
2922 threshold: the threshold used by line finder. It is
2923 better to keep it large as only strong lines
2924 affect the baseline solution.
2925 default is 3.
2926 chan_avg_limit: a maximum number of consequtive spectral
2927 channels to average during the search of
2928 weak and broad lines. The default is no
2929 averaging (and no search for weak lines).
2930 If such lines can affect the fitted baseline
2931 (e.g. a high order polynomial is fitted),
2932 increase this parameter (usually values up
2933 to 8 are reasonable). Most users of this
2934 method should find the default value sufficient.
2935 default is 1.
2936
2937 Example:
2938 aic = scan.calc_aic(blfunc='chebyshev', order=5, whichrow=0)
2939 """
2940
2941 try:
2942 varlist = vars()
2943
2944 if value is None: value = 'aicc'
2945 if blfunc is None: blfunc = 'chebyshev'
2946 if order is None: order = 5
2947 if mask is None: mask = []
2948 if whichrow is None: whichrow = 0
2949 if uselinefinder is None: uselinefinder = True
2950 if edge is None: edge = (0, 0)
2951 if threshold is None: threshold = 3
2952 if chan_avg_limit is None: chan_avg_limit = 1
2953
2954 return self._calc_aic(value, blfunc, order, mask,
2955 whichrow, uselinefinder, edge,
2956 threshold, chan_avg_limit)
2957
2958 except RuntimeError, e:
2959 raise_fitting_failure_exception(e)
2960
2961 @asaplog_post_dec
2962 def sinusoid_baseline(self, mask=None, applyfft=None,
2963 fftmethod=None, fftthresh=None,
2964 addwn=None, rejwn=None,
2965 insitu=None,
2966 clipthresh=None, clipniter=None,
2967 plot=None,
2968 getresidual=None,
2969 showprogress=None, minnrow=None,
2970 outlog=None,
2971 blfile=None, csvformat=None,
2972 bltable=None):
2973 """\
2974 Return a scan which has been baselined (all rows) with sinusoidal
2975 functions.
2976
2977 Parameters:
2978 mask: an optional mask
2979 applyfft: if True use some method, such as FFT, to find
2980 strongest sinusoidal components in the wavenumber
2981 domain to be used for baseline fitting.
2982 default is True.
2983 fftmethod: method to find the strong sinusoidal components.
2984 now only 'fft' is available and it is the default.
2985 fftthresh: the threshold to select wave numbers to be used for
2986 fitting from the distribution of amplitudes in the
2987 wavenumber domain.
2988 both float and string values accepted.
2989 given a float value, the unit is set to sigma.
2990 for string values, allowed formats include:
2991 'xsigma' or 'x' (= x-sigma level. e.g.,
2992 '3sigma'), or
2993 'topx' (= the x strongest ones, e.g. 'top5').
2994 default is 3.0 (unit: sigma).
2995 addwn: the additional wave numbers to be used for fitting.
2996 list or integer value is accepted to specify every
2997 wave numbers. also string value can be used in case
2998 you need to specify wave numbers in a certain range,
2999 e.g., 'a-b' (= a, a+1, a+2, ..., b-1, b),
3000 '<a' (= 0,1,...,a-2,a-1),
3001 '>=a' (= a, a+1, ... up to the maximum wave
3002 number corresponding to the Nyquist
3003 frequency for the case of FFT).
3004 default is [0].
3005 rejwn: the wave numbers NOT to be used for fitting.
3006 can be set just as addwn but has higher priority:
3007 wave numbers which are specified both in addwn
3008 and rejwn will NOT be used. default is [].
3009 insitu: if False a new scantable is returned.
3010 Otherwise, the scaling is done in-situ
3011 The default is taken from .asaprc (False)
3012 clipthresh: Clipping threshold. (default is 3.0, unit: sigma)
3013 clipniter: maximum number of iteration of 'clipthresh'-sigma
3014 clipping (default is 0)
3015 plot: *** CURRENTLY UNAVAILABLE, ALWAYS FALSE ***
3016 plot the fit and the residual. In this each
3017 indivual fit has to be approved, by typing 'y'
3018 or 'n'
3019 getresidual: if False, returns best-fit values instead of
3020 residual. (default is True)
3021 showprogress: show progress status for large data.
3022 default is True.
3023 minnrow: minimum number of input spectra to show.
3024 default is 1000.
3025 outlog: Output the coefficients of the best-fit
3026 function to logger (default is False)
3027 blfile: Name of a text file in which the best-fit
3028 parameter values to be written
3029 (default is '': no file/logger output)
3030 csvformat: if True blfile is csv-formatted, default is False.
3031 bltable: name of a baseline table where fitting results
3032 (coefficients, rms, etc.) are to be written.
3033 if given, fitting results will NOT be output to
3034 scantable (insitu=True) or None will be
3035 returned (insitu=False).
3036 (default is "": no table output)
3037
3038 Example:
3039 # return a scan baselined by a combination of sinusoidal curves
3040 # having wave numbers in spectral window up to 10,
3041 # also with 3-sigma clipping, iteration up to 4 times
3042 bscan = scan.sinusoid_baseline(addwn='<=10',clipthresh=3.0,clipniter=4)
3043
3044 Note:
3045 The best-fit parameter values output in logger and/or blfile are now
3046 based on specunit of 'channel'.
3047 """
3048
3049 try:
3050 varlist = vars()
3051
3052 if insitu is None: insitu = rcParams['insitu']
3053 if insitu:
3054 workscan = self
3055 else:
3056 workscan = self.copy()
3057
3058 if mask is None: mask = []
3059 if applyfft is None: applyfft = True
3060 if fftmethod is None: fftmethod = 'fft'
3061 if fftthresh is None: fftthresh = 3.0
3062 if addwn is None: addwn = [0]
3063 if rejwn is None: rejwn = []
3064 if clipthresh is None: clipthresh = 3.0
3065 if clipniter is None: clipniter = 0
3066 if plot is None: plot = False
3067 if getresidual is None: getresidual = True
3068 if showprogress is None: showprogress = True
3069 if minnrow is None: minnrow = 1000
3070 if outlog is None: outlog = False
3071 if blfile is None: blfile = ''
3072 if csvformat is None: csvformat = False
3073 if bltable is None: bltable = ''
3074
3075 sapplyfft = 'true' if applyfft else 'false'
3076 fftinfo = ','.join([sapplyfft, fftmethod.lower(), str(fftthresh).lower()])
3077
3078 scsvformat = 'T' if csvformat else 'F'
3079
3080 #CURRENTLY, PLOT=true is UNAVAILABLE UNTIL sinusoidal fitting is implemented as a fitter method.
3081 workscan._sinusoid_baseline(mask,
3082 fftinfo,
3083 #applyfft, fftmethod.lower(),
3084 #str(fftthresh).lower(),
3085 workscan._parse_wn(addwn),
3086 workscan._parse_wn(rejwn),
3087 clipthresh, clipniter,
3088 getresidual,
3089 pack_progress_params(showprogress,
3090 minnrow),
3091 outlog, scsvformat+blfile,
3092 bltable)
3093 workscan._add_history('sinusoid_baseline', varlist)
3094
3095 if bltable == '':
3096 if insitu:
3097 self._assign(workscan)
3098 else:
3099 return workscan
3100 else:
3101 if not insitu:
3102 return None
3103
3104 except RuntimeError, e:
3105 raise_fitting_failure_exception(e)
3106
3107
3108 @asaplog_post_dec
3109 def auto_sinusoid_baseline(self, mask=None, applyfft=None,
3110 fftmethod=None, fftthresh=None,
3111 addwn=None, rejwn=None,
3112 insitu=None,
3113 clipthresh=None, clipniter=None,
3114 edge=None, threshold=None, chan_avg_limit=None,
3115 plot=None,
3116 getresidual=None,
3117 showprogress=None, minnrow=None,
3118 outlog=None,
3119 blfile=None, csvformat=None,
3120 bltable=None):
3121 """\
3122 Return a scan which has been baselined (all rows) with sinusoidal
3123 functions.
3124 Spectral lines are detected first using linefinder and masked out
3125 to avoid them affecting the baseline solution.
3126
3127 Parameters:
3128 mask: an optional mask retreived from scantable
3129 applyfft: if True use some method, such as FFT, to find
3130 strongest sinusoidal components in the wavenumber
3131 domain to be used for baseline fitting.
3132 default is True.
3133 fftmethod: method to find the strong sinusoidal components.
3134 now only 'fft' is available and it is the default.
3135 fftthresh: the threshold to select wave numbers to be used for
3136 fitting from the distribution of amplitudes in the
3137 wavenumber domain.
3138 both float and string values accepted.
3139 given a float value, the unit is set to sigma.
3140 for string values, allowed formats include:
3141 'xsigma' or 'x' (= x-sigma level. e.g.,
3142 '3sigma'), or
3143 'topx' (= the x strongest ones, e.g. 'top5').
3144 default is 3.0 (unit: sigma).
3145 addwn: the additional wave numbers to be used for fitting.
3146 list or integer value is accepted to specify every
3147 wave numbers. also string value can be used in case
3148 you need to specify wave numbers in a certain range,
3149 e.g., 'a-b' (= a, a+1, a+2, ..., b-1, b),
3150 '<a' (= 0,1,...,a-2,a-1),
3151 '>=a' (= a, a+1, ... up to the maximum wave
3152 number corresponding to the Nyquist
3153 frequency for the case of FFT).
3154 default is [0].
3155 rejwn: the wave numbers NOT to be used for fitting.
3156 can be set just as addwn but has higher priority:
3157 wave numbers which are specified both in addwn
3158 and rejwn will NOT be used. default is [].
3159 insitu: if False a new scantable is returned.
3160 Otherwise, the scaling is done in-situ
3161 The default is taken from .asaprc (False)
3162 clipthresh: Clipping threshold. (default is 3.0, unit: sigma)
3163 clipniter: maximum number of iteration of 'clipthresh'-sigma
3164 clipping (default is 0)
3165 edge: an optional number of channel to drop at
3166 the edge of spectrum. If only one value is
3167 specified, the same number will be dropped
3168 from both sides of the spectrum. Default
3169 is to keep all channels. Nested tuples
3170 represent individual edge selection for
3171 different IFs (a number of spectral channels
3172 can be different)
3173 threshold: the threshold used by line finder. It is
3174 better to keep it large as only strong lines
3175 affect the baseline solution.
3176 chan_avg_limit: a maximum number of consequtive spectral
3177 channels to average during the search of
3178 weak and broad lines. The default is no
3179 averaging (and no search for weak lines).
3180 If such lines can affect the fitted baseline
3181 (e.g. a high order polynomial is fitted),
3182 increase this parameter (usually values up
3183 to 8 are reasonable). Most users of this
3184 method should find the default value sufficient.
3185 plot: *** CURRENTLY UNAVAILABLE, ALWAYS FALSE ***
3186 plot the fit and the residual. In this each
3187 indivual fit has to be approved, by typing 'y'
3188 or 'n'
3189 getresidual: if False, returns best-fit values instead of
3190 residual. (default is True)
3191 showprogress: show progress status for large data.
3192 default is True.
3193 minnrow: minimum number of input spectra to show.
3194 default is 1000.
3195 outlog: Output the coefficients of the best-fit
3196 function to logger (default is False)
3197 blfile: Name of a text file in which the best-fit
3198 parameter values to be written
3199 (default is "": no file/logger output)
3200 csvformat: if True blfile is csv-formatted, default is False.
3201 bltable: name of a baseline table where fitting results
3202 (coefficients, rms, etc.) are to be written.
3203 if given, fitting results will NOT be output to
3204 scantable (insitu=True) or None will be
3205 returned (insitu=False).
3206 (default is "": no table output)
3207
3208 Example:
3209 bscan = scan.auto_sinusoid_baseline(addwn='<=10', insitu=False)
3210
3211 Note:
3212 The best-fit parameter values output in logger and/or blfile are now
3213 based on specunit of 'channel'.
3214 """
3215
3216 try:
3217 varlist = vars()
3218
3219 if insitu is None: insitu = rcParams['insitu']
3220 if insitu:
3221 workscan = self
3222 else:
3223 workscan = self.copy()
3224
3225 if mask is None: mask = []
3226 if applyfft is None: applyfft = True
3227 if fftmethod is None: fftmethod = 'fft'
3228 if fftthresh is None: fftthresh = 3.0
3229 if addwn is None: addwn = [0]
3230 if rejwn is None: rejwn = []
3231 if clipthresh is None: clipthresh = 3.0
3232 if clipniter is None: clipniter = 0
3233 if edge is None: edge = (0,0)
3234 if threshold is None: threshold = 3
3235 if chan_avg_limit is None: chan_avg_limit = 1
3236 if plot is None: plot = False
3237 if getresidual is None: getresidual = True
3238 if showprogress is None: showprogress = True
3239 if minnrow is None: minnrow = 1000
3240 if outlog is None: outlog = False
3241 if blfile is None: blfile = ''
3242 if csvformat is None: csvformat = False
3243 if bltable is None: bltable = ''
3244
3245 sapplyfft = 'true' if applyfft else 'false'
3246 fftinfo = ','.join([sapplyfft, fftmethod.lower(), str(fftthresh).lower()])
3247
3248 scsvformat = 'T' if csvformat else 'F'
3249
3250 #CURRENTLY, PLOT=true is UNAVAILABLE UNTIL sinusoidal fitting is implemented as a fitter method.
3251 workscan._auto_sinusoid_baseline(mask,
3252 fftinfo,
3253 workscan._parse_wn(addwn),
3254 workscan._parse_wn(rejwn),
3255 clipthresh, clipniter,
3256 normalise_edge_param(edge),
3257 threshold, chan_avg_limit,
3258 getresidual,
3259 pack_progress_params(showprogress,
3260 minnrow),
3261 outlog, scsvformat+blfile, bltable)
3262 workscan._add_history("auto_sinusoid_baseline", varlist)
3263
3264 if bltable == '':
3265 if insitu:
3266 self._assign(workscan)
3267 else:
3268 return workscan
3269 else:
3270 if not insitu:
3271 return None
3272
3273 except RuntimeError, e:
3274 raise_fitting_failure_exception(e)
3275
3276 @asaplog_post_dec
3277 def cspline_baseline(self, mask=None, npiece=None, insitu=None,
3278 clipthresh=None, clipniter=None, plot=None,
3279 getresidual=None, showprogress=None, minnrow=None,
3280 outlog=None, blfile=None, csvformat=None,
3281 bltable=None):
3282 """\
3283 Return a scan which has been baselined (all rows) by cubic spline
3284 function (piecewise cubic polynomial).
3285
3286 Parameters:
3287 mask: An optional mask
3288 npiece: Number of pieces. (default is 2)
3289 insitu: If False a new scantable is returned.
3290 Otherwise, the scaling is done in-situ
3291 The default is taken from .asaprc (False)
3292 clipthresh: Clipping threshold. (default is 3.0, unit: sigma)
3293 clipniter: maximum number of iteration of 'clipthresh'-sigma
3294 clipping (default is 0)
3295 plot: *** CURRENTLY UNAVAILABLE, ALWAYS FALSE ***
3296 plot the fit and the residual. In this each
3297 indivual fit has to be approved, by typing 'y'
3298 or 'n'
3299 getresidual: if False, returns best-fit values instead of
3300 residual. (default is True)
3301 showprogress: show progress status for large data.
3302 default is True.
3303 minnrow: minimum number of input spectra to show.
3304 default is 1000.
3305 outlog: Output the coefficients of the best-fit
3306 function to logger (default is False)
3307 blfile: Name of a text file in which the best-fit
3308 parameter values to be written
3309 (default is "": no file/logger output)
3310 csvformat: if True blfile is csv-formatted, default is False.
3311 bltable: name of a baseline table where fitting results
3312 (coefficients, rms, etc.) are to be written.
3313 if given, fitting results will NOT be output to
3314 scantable (insitu=True) or None will be
3315 returned (insitu=False).
3316 (default is "": no table output)
3317
3318 Example:
3319 # return a scan baselined by a cubic spline consisting of 2 pieces
3320 # (i.e., 1 internal knot),
3321 # also with 3-sigma clipping, iteration up to 4 times
3322 bscan = scan.cspline_baseline(npiece=2,clipthresh=3.0,clipniter=4)
3323
3324 Note:
3325 The best-fit parameter values output in logger and/or blfile are now
3326 based on specunit of 'channel'.
3327 """
3328
3329 try:
3330 varlist = vars()
3331
3332 if insitu is None: insitu = rcParams['insitu']
3333 if insitu:
3334 workscan = self
3335 else:
3336 workscan = self.copy()
3337
3338 if mask is None: mask = []
3339 if npiece is None: npiece = 2
3340 if clipthresh is None: clipthresh = 3.0
3341 if clipniter is None: clipniter = 0
3342 if plot is None: plot = False
3343 if getresidual is None: getresidual = True
3344 if showprogress is None: showprogress = True
3345 if minnrow is None: minnrow = 1000
3346 if outlog is None: outlog = False
3347 if blfile is None: blfile = ''
3348 if csvformat is None: csvformat = False
3349 if bltable is None: bltable = ''
3350
3351 scsvformat = 'T' if csvformat else 'F'
3352
3353 #CURRENTLY, PLOT=true UNAVAILABLE UNTIL cubic spline fitting is implemented as a fitter method.
3354 workscan._cspline_baseline(mask, npiece,
3355 clipthresh, clipniter,
3356 getresidual,
3357 pack_progress_params(showprogress,
3358 minnrow),
3359 outlog, scsvformat+blfile,
3360 bltable)
3361 workscan._add_history("cspline_baseline", varlist)
3362
3363 if bltable == '':
3364 if insitu:
3365 self._assign(workscan)
3366 else:
3367 return workscan
3368 else:
3369 if not insitu:
3370 return None
3371
3372 except RuntimeError, e:
3373 raise_fitting_failure_exception(e)
3374
3375 @asaplog_post_dec
3376 def auto_cspline_baseline(self, mask=None, npiece=None, insitu=None,
3377 clipthresh=None, clipniter=None,
3378 edge=None, threshold=None, chan_avg_limit=None,
3379 getresidual=None, plot=None,
3380 showprogress=None, minnrow=None, outlog=None,
3381 blfile=None, csvformat=None, bltable=None):
3382 """\
3383 Return a scan which has been baselined (all rows) by cubic spline
3384 function (piecewise cubic polynomial).
3385 Spectral lines are detected first using linefinder and masked out
3386 to avoid them affecting the baseline solution.
3387
3388 Parameters:
3389 mask: an optional mask retreived from scantable
3390 npiece: Number of pieces. (default is 2)
3391 insitu: if False a new scantable is returned.
3392 Otherwise, the scaling is done in-situ
3393 The default is taken from .asaprc (False)
3394 clipthresh: Clipping threshold. (default is 3.0, unit: sigma)
3395 clipniter: maximum number of iteration of 'clipthresh'-sigma
3396 clipping (default is 0)
3397 edge: an optional number of channel to drop at
3398 the edge of spectrum. If only one value is
3399 specified, the same number will be dropped
3400 from both sides of the spectrum. Default
3401 is to keep all channels. Nested tuples
3402 represent individual edge selection for
3403 different IFs (a number of spectral channels
3404 can be different)
3405 threshold: the threshold used by line finder. It is
3406 better to keep it large as only strong lines
3407 affect the baseline solution.
3408 chan_avg_limit: a maximum number of consequtive spectral
3409 channels to average during the search of
3410 weak and broad lines. The default is no
3411 averaging (and no search for weak lines).
3412 If such lines can affect the fitted baseline
3413 (e.g. a high order polynomial is fitted),
3414 increase this parameter (usually values up
3415 to 8 are reasonable). Most users of this
3416 method should find the default value sufficient.
3417 plot: *** CURRENTLY UNAVAILABLE, ALWAYS FALSE ***
3418 plot the fit and the residual. In this each
3419 indivual fit has to be approved, by typing 'y'
3420 or 'n'
3421 getresidual: if False, returns best-fit values instead of
3422 residual. (default is True)
3423 showprogress: show progress status for large data.
3424 default is True.
3425 minnrow: minimum number of input spectra to show.
3426 default is 1000.
3427 outlog: Output the coefficients of the best-fit
3428 function to logger (default is False)
3429 blfile: Name of a text file in which the best-fit
3430 parameter values to be written
3431 (default is "": no file/logger output)
3432 csvformat: if True blfile is csv-formatted, default is False.
3433 bltable: name of a baseline table where fitting results
3434 (coefficients, rms, etc.) are to be written.
3435 if given, fitting results will NOT be output to
3436 scantable (insitu=True) or None will be
3437 returned (insitu=False).
3438 (default is "": no table output)
3439
3440 Example:
3441 bscan = scan.auto_cspline_baseline(npiece=3, insitu=False)
3442
3443 Note:
3444 The best-fit parameter values output in logger and/or blfile are now
3445 based on specunit of 'channel'.
3446 """
3447
3448 try:
3449 varlist = vars()
3450
3451 if insitu is None: insitu = rcParams['insitu']
3452 if insitu:
3453 workscan = self
3454 else:
3455 workscan = self.copy()
3456
3457 #if mask is None: mask = [True for i in xrange(workscan.nchan())]
3458 if mask is None: mask = []
3459 if npiece is None: npiece = 2
3460 if clipthresh is None: clipthresh = 3.0
3461 if clipniter is None: clipniter = 0
3462 if edge is None: edge = (0, 0)
3463 if threshold is None: threshold = 3
3464 if chan_avg_limit is None: chan_avg_limit = 1
3465 if plot is None: plot = False
3466 if getresidual is None: getresidual = True
3467 if showprogress is None: showprogress = True
3468 if minnrow is None: minnrow = 1000
3469 if outlog is None: outlog = False
3470 if blfile is None: blfile = ''
3471 if csvformat is None: csvformat = False
3472 if bltable is None: bltable = ''
3473
3474 scsvformat = 'T' if csvformat else 'F'
3475
3476 #CURRENTLY, PLOT=true UNAVAILABLE UNTIL cubic spline fitting is implemented as a fitter method.
3477 workscan._auto_cspline_baseline(mask, npiece,
3478 clipthresh, clipniter,
3479 normalise_edge_param(edge),
3480 threshold,
3481 chan_avg_limit, getresidual,
3482 pack_progress_params(showprogress,
3483 minnrow),
3484 outlog,
3485 scsvformat+blfile,
3486 bltable)
3487 workscan._add_history("auto_cspline_baseline", varlist)
3488
3489 if bltable == '':
3490 if insitu:
3491 self._assign(workscan)
3492 else:
3493 return workscan
3494 else:
3495 if not insitu:
3496 return None
3497
3498 except RuntimeError, e:
3499 raise_fitting_failure_exception(e)
3500
3501 @asaplog_post_dec
3502 def chebyshev_baseline(self, mask=None, order=None, insitu=None,
3503 clipthresh=None, clipniter=None, plot=None,
3504 getresidual=None, showprogress=None, minnrow=None,
3505 outlog=None, blfile=None, csvformat=None,
3506 bltable=None):
3507 """\
3508 Return a scan which has been baselined (all rows) by Chebyshev polynomials.
3509
3510 Parameters:
3511 mask: An optional mask
3512 order: the maximum order of Chebyshev polynomial (default is 5)
3513 insitu: If False a new scantable is returned.
3514 Otherwise, the scaling is done in-situ
3515 The default is taken from .asaprc (False)
3516 clipthresh: Clipping threshold. (default is 3.0, unit: sigma)
3517 clipniter: maximum number of iteration of 'clipthresh'-sigma
3518 clipping (default is 0)
3519 plot: *** CURRENTLY UNAVAILABLE, ALWAYS FALSE ***
3520 plot the fit and the residual. In this each
3521 indivual fit has to be approved, by typing 'y'
3522 or 'n'
3523 getresidual: if False, returns best-fit values instead of
3524 residual. (default is True)
3525 showprogress: show progress status for large data.
3526 default is True.
3527 minnrow: minimum number of input spectra to show.
3528 default is 1000.
3529 outlog: Output the coefficients of the best-fit
3530 function to logger (default is False)
3531 blfile: Name of a text file in which the best-fit
3532 parameter values to be written
3533 (default is "": no file/logger output)
3534 csvformat: if True blfile is csv-formatted, default is False.
3535 bltable: name of a baseline table where fitting results
3536 (coefficients, rms, etc.) are to be written.
3537 if given, fitting results will NOT be output to
3538 scantable (insitu=True) or None will be
3539 returned (insitu=False).
3540 (default is "": no table output)
3541
3542 Example:
3543 # return a scan baselined by a cubic spline consisting of 2 pieces
3544 # (i.e., 1 internal knot),
3545 # also with 3-sigma clipping, iteration up to 4 times
3546 bscan = scan.cspline_baseline(npiece=2,clipthresh=3.0,clipniter=4)
3547
3548 Note:
3549 The best-fit parameter values output in logger and/or blfile are now
3550 based on specunit of 'channel'.
3551 """
3552
3553 try:
3554 varlist = vars()
3555
3556 if insitu is None: insitu = rcParams['insitu']
3557 if insitu:
3558 workscan = self
3559 else:
3560 workscan = self.copy()
3561
3562 if mask is None: mask = []
3563 if order is None: order = 5
3564 if clipthresh is None: clipthresh = 3.0
3565 if clipniter is None: clipniter = 0
3566 if plot is None: plot = False
3567 if getresidual is None: getresidual = True
3568 if showprogress is None: showprogress = True
3569 if minnrow is None: minnrow = 1000
3570 if outlog is None: outlog = False
3571 if blfile is None: blfile = ''
3572 if csvformat is None: csvformat = False
3573 if bltable is None: bltable = ''
3574
3575 scsvformat = 'T' if csvformat else 'F'
3576
3577 #CURRENTLY, PLOT=true UNAVAILABLE UNTIL cubic spline fitting is implemented as a fitter method.
3578 workscan._chebyshev_baseline(mask, order,
3579 clipthresh, clipniter,
3580 getresidual,
3581 pack_progress_params(showprogress,
3582 minnrow),
3583 outlog, scsvformat+blfile,
3584 bltable)
3585 workscan._add_history("chebyshev_baseline", varlist)
3586
3587 if bltable == '':
3588 if insitu:
3589 self._assign(workscan)
3590 else:
3591 return workscan
3592 else:
3593 if not insitu:
3594 return None
3595
3596 except RuntimeError, e:
3597 raise_fitting_failure_exception(e)
3598
3599 @asaplog_post_dec
3600 def auto_chebyshev_baseline(self, mask=None, order=None, insitu=None,
3601 clipthresh=None, clipniter=None,
3602 edge=None, threshold=None, chan_avg_limit=None,
3603 getresidual=None, plot=None,
3604 showprogress=None, minnrow=None, outlog=None,
3605 blfile=None, csvformat=None, bltable=None):
3606 """\
3607 Return a scan which has been baselined (all rows) by Chebyshev polynomials.
3608 Spectral lines are detected first using linefinder and masked out
3609 to avoid them affecting the baseline solution.
3610
3611 Parameters:
3612 mask: an optional mask retreived from scantable
3613 order: the maximum order of Chebyshev polynomial (default is 5)
3614 insitu: if False a new scantable is returned.
3615 Otherwise, the scaling is done in-situ
3616 The default is taken from .asaprc (False)
3617 clipthresh: Clipping threshold. (default is 3.0, unit: sigma)
3618 clipniter: maximum number of iteration of 'clipthresh'-sigma
3619 clipping (default is 0)
3620 edge: an optional number of channel to drop at
3621 the edge of spectrum. If only one value is
3622 specified, the same number will be dropped
3623 from both sides of the spectrum. Default
3624 is to keep all channels. Nested tuples
3625 represent individual edge selection for
3626 different IFs (a number of spectral channels
3627 can be different)
3628 threshold: the threshold used by line finder. It is
3629 better to keep it large as only strong lines
3630 affect the baseline solution.
3631 chan_avg_limit: a maximum number of consequtive spectral
3632 channels to average during the search of
3633 weak and broad lines. The default is no
3634 averaging (and no search for weak lines).
3635 If such lines can affect the fitted baseline
3636 (e.g. a high order polynomial is fitted),
3637 increase this parameter (usually values up
3638 to 8 are reasonable). Most users of this
3639 method should find the default value sufficient.
3640 plot: *** CURRENTLY UNAVAILABLE, ALWAYS FALSE ***
3641 plot the fit and the residual. In this each
3642 indivual fit has to be approved, by typing 'y'
3643 or 'n'
3644 getresidual: if False, returns best-fit values instead of
3645 residual. (default is True)
3646 showprogress: show progress status for large data.
3647 default is True.
3648 minnrow: minimum number of input spectra to show.
3649 default is 1000.
3650 outlog: Output the coefficients of the best-fit
3651 function to logger (default is False)
3652 blfile: Name of a text file in which the best-fit
3653 parameter values to be written
3654 (default is "": no file/logger output)
3655 csvformat: if True blfile is csv-formatted, default is False.
3656 bltable: name of a baseline table where fitting results
3657 (coefficients, rms, etc.) are to be written.
3658 if given, fitting results will NOT be output to
3659 scantable (insitu=True) or None will be
3660 returned (insitu=False).
3661 (default is "": no table output)
3662
3663 Example:
3664 bscan = scan.auto_cspline_baseline(npiece=3, insitu=False)
3665
3666 Note:
3667 The best-fit parameter values output in logger and/or blfile are now
3668 based on specunit of 'channel'.
3669 """
3670
3671 try:
3672 varlist = vars()
3673
3674 if insitu is None: insitu = rcParams['insitu']
3675 if insitu:
3676 workscan = self
3677 else:
3678 workscan = self.copy()
3679
3680 if mask is None: mask = []
3681 if order is None: order = 5
3682 if clipthresh is None: clipthresh = 3.0
3683 if clipniter is None: clipniter = 0
3684 if edge is None: edge = (0, 0)
3685 if threshold is None: threshold = 3
3686 if chan_avg_limit is None: chan_avg_limit = 1
3687 if plot is None: plot = False
3688 if getresidual is None: getresidual = True
3689 if showprogress is None: showprogress = True
3690 if minnrow is None: minnrow = 1000
3691 if outlog is None: outlog = False
3692 if blfile is None: blfile = ''
3693 if csvformat is None: csvformat = False
3694 if bltable is None: bltable = ''
3695
3696 scsvformat = 'T' if csvformat else 'F'
3697
3698 #CURRENTLY, PLOT=true UNAVAILABLE UNTIL cubic spline fitting is implemented as a fitter method.
3699 workscan._auto_chebyshev_baseline(mask, order,
3700 clipthresh, clipniter,
3701 normalise_edge_param(edge),
3702 threshold,
3703 chan_avg_limit, getresidual,
3704 pack_progress_params(showprogress,
3705 minnrow),
3706 outlog, scsvformat+blfile,
3707 bltable)
3708 workscan._add_history("auto_chebyshev_baseline", varlist)
3709
3710 if bltable == '':
3711 if insitu:
3712 self._assign(workscan)
3713 else:
3714 return workscan
3715 else:
3716 if not insitu:
3717 return None
3718
3719 except RuntimeError, e:
3720 raise_fitting_failure_exception(e)
3721
3722 @asaplog_post_dec
3723 def poly_baseline(self, mask=None, order=None, insitu=None,
3724 clipthresh=None, clipniter=None, plot=None,
3725 getresidual=None, showprogress=None, minnrow=None,
3726 outlog=None, blfile=None, csvformat=None,
3727 bltable=None):
3728 """\
3729 Return a scan which has been baselined (all rows) by a polynomial.
3730 Parameters:
3731 mask: an optional mask
3732 order: the order of the polynomial (default is 0)
3733 insitu: if False a new scantable is returned.
3734 Otherwise, the scaling is done in-situ
3735 The default is taken from .asaprc (False)
3736 clipthresh: Clipping threshold. (default is 3.0, unit: sigma)
3737 clipniter: maximum number of iteration of 'clipthresh'-sigma
3738 clipping (default is 0)
3739 plot: plot the fit and the residual. In this each
3740 indivual fit has to be approved, by typing 'y'
3741 or 'n'
3742 getresidual: if False, returns best-fit values instead of
3743 residual. (default is True)
3744 showprogress: show progress status for large data.
3745 default is True.
3746 minnrow: minimum number of input spectra to show.
3747 default is 1000.
3748 outlog: Output the coefficients of the best-fit
3749 function to logger (default is False)
3750 blfile: Name of a text file in which the best-fit
3751 parameter values to be written
3752 (default is "": no file/logger output)
3753 csvformat: if True blfile is csv-formatted, default is False.
3754 bltable: name of a baseline table where fitting results
3755 (coefficients, rms, etc.) are to be written.
3756 if given, fitting results will NOT be output to
3757 scantable (insitu=True) or None will be
3758 returned (insitu=False).
3759 (default is "": no table output)
3760
3761 Example:
3762 # return a scan baselined by a third order polynomial,
3763 # not using a mask
3764 bscan = scan.poly_baseline(order=3)
3765 """
3766
3767 try:
3768 varlist = vars()
3769
3770 if insitu is None:
3771 insitu = rcParams["insitu"]
3772 if insitu:
3773 workscan = self
3774 else:
3775 workscan = self.copy()
3776
3777 if mask is None: mask = []
3778 if order is None: order = 0
3779 if clipthresh is None: clipthresh = 3.0
3780 if clipniter is None: clipniter = 0
3781 if plot is None: plot = False
3782 if getresidual is None: getresidual = True
3783 if showprogress is None: showprogress = True
3784 if minnrow is None: minnrow = 1000
3785 if outlog is None: outlog = False
3786 if blfile is None: blfile = ''
3787 if csvformat is None: csvformat = False
3788 if bltable is None: bltable = ''
3789
3790 scsvformat = 'T' if csvformat else 'F'
3791
3792 if plot:
3793 outblfile = (blfile != "") and \
3794 os.path.exists(os.path.expanduser(
3795 os.path.expandvars(blfile))
3796 )
3797 if outblfile:
3798 blf = open(blfile, "a")
3799
3800 f = fitter()
3801 f.set_function(lpoly=order)
3802
3803 rows = xrange(workscan.nrow())
3804 #if len(rows) > 0: workscan._init_blinfo()
3805
3806 action = "H"
3807 for r in rows:
3808 f.x = workscan._getabcissa(r)
3809 f.y = workscan._getspectrum(r)
3810 if mask:
3811 f.mask = mask_and(mask, workscan._getmask(r)) # (CAS-1434)
3812 else: # mask=None
3813 f.mask = workscan._getmask(r)
3814
3815 f.data = None
3816 f.fit()
3817
3818 if action != "Y": # skip plotting when accepting all
3819 f.plot(residual=True)
3820 #accept_fit = raw_input("Accept fit ( [y]/n ): ")
3821 #if accept_fit.upper() == "N":
3822 # #workscan._append_blinfo(None, None, None)
3823 # continue
3824 accept_fit = self._get_verify_action("Accept fit?",action)
3825 if r == 0: action = None
3826 if accept_fit.upper() == "N":
3827 continue
3828 elif accept_fit.upper() == "R":
3829 break
3830 elif accept_fit.upper() == "A":
3831 action = "Y"
3832
3833 blpars = f.get_parameters()
3834 masklist = workscan.get_masklist(f.mask, row=r, silent=True)
3835 #workscan._append_blinfo(blpars, masklist, f.mask)
3836 workscan._setspectrum((f.fitter.getresidual()
3837 if getresidual else f.fitter.getfit()), r)
3838
3839 if outblfile:
3840 rms = workscan.get_rms(f.mask, r)
3841 dataout = \
3842 workscan.format_blparams_row(blpars["params"],
3843 blpars["fixed"],
3844 rms, str(masklist),
3845 r, True, csvformat)
3846 blf.write(dataout)
3847
3848 f._p.unmap()
3849 f._p = None
3850
3851 if outblfile:
3852 blf.close()
3853 else:
3854 workscan._poly_baseline(mask, order,
3855 clipthresh, clipniter, #
3856 getresidual,
3857 pack_progress_params(showprogress,
3858 minnrow),
3859 outlog, scsvformat+blfile,
3860 bltable) #
3861
3862 workscan._add_history("poly_baseline", varlist)
3863
3864 if insitu:
3865 self._assign(workscan)
3866 else:
3867 return workscan
3868
3869 except RuntimeError, e:
3870 raise_fitting_failure_exception(e)
3871
3872 @asaplog_post_dec
3873 def auto_poly_baseline(self, mask=None, order=None, insitu=None,
3874 clipthresh=None, clipniter=None,
3875 edge=None, threshold=None, chan_avg_limit=None,
3876 getresidual=None, plot=None,
3877 showprogress=None, minnrow=None, outlog=None,
3878 blfile=None, csvformat=None, bltable=None):
3879 """\
3880 Return a scan which has been baselined (all rows) by a polynomial.
3881 Spectral lines are detected first using linefinder and masked out
3882 to avoid them affecting the baseline solution.
3883
3884 Parameters:
3885 mask: an optional mask retreived from scantable
3886 order: the order of the polynomial (default is 0)
3887 insitu: if False a new scantable is returned.
3888 Otherwise, the scaling is done in-situ
3889 The default is taken from .asaprc (False)
3890 clipthresh: Clipping threshold. (default is 3.0, unit: sigma)
3891 clipniter: maximum number of iteration of 'clipthresh'-sigma
3892 clipping (default is 0)
3893 edge: an optional number of channel to drop at
3894 the edge of spectrum. If only one value is
3895 specified, the same number will be dropped
3896 from both sides of the spectrum. Default
3897 is to keep all channels. Nested tuples
3898 represent individual edge selection for
3899 different IFs (a number of spectral channels
3900 can be different)
3901 threshold: the threshold used by line finder. It is
3902 better to keep it large as only strong lines
3903 affect the baseline solution.
3904 chan_avg_limit: a maximum number of consequtive spectral
3905 channels to average during the search of
3906 weak and broad lines. The default is no
3907 averaging (and no search for weak lines).
3908 If such lines can affect the fitted baseline
3909 (e.g. a high order polynomial is fitted),
3910 increase this parameter (usually values up
3911 to 8 are reasonable). Most users of this
3912 method should find the default value sufficient.
3913 plot: plot the fit and the residual. In this each
3914 indivual fit has to be approved, by typing 'y'
3915 or 'n'
3916 getresidual: if False, returns best-fit values instead of
3917 residual. (default is True)
3918 showprogress: show progress status for large data.
3919 default is True.
3920 minnrow: minimum number of input spectra to show.
3921 default is 1000.
3922 outlog: Output the coefficients of the best-fit
3923 function to logger (default is False)
3924 blfile: Name of a text file in which the best-fit
3925 parameter values to be written
3926 (default is "": no file/logger output)
3927 csvformat: if True blfile is csv-formatted, default is False.
3928 bltable: name of a baseline table where fitting results
3929 (coefficients, rms, etc.) are to be written.
3930 if given, fitting results will NOT be output to
3931 scantable (insitu=True) or None will be
3932 returned (insitu=False).
3933 (default is "": no table output)
3934
3935 Example:
3936 bscan = scan.auto_poly_baseline(order=7, insitu=False)
3937 """
3938
3939 try:
3940 varlist = vars()
3941
3942 if insitu is None:
3943 insitu = rcParams['insitu']
3944 if insitu:
3945 workscan = self
3946 else:
3947 workscan = self.copy()
3948
3949 if mask is None: mask = []
3950 if order is None: order = 0
3951 if clipthresh is None: clipthresh = 3.0
3952 if clipniter is None: clipniter = 0
3953 if edge is None: edge = (0, 0)
3954 if threshold is None: threshold = 3
3955 if chan_avg_limit is None: chan_avg_limit = 1
3956 if plot is None: plot = False
3957 if getresidual is None: getresidual = True
3958 if showprogress is None: showprogress = True
3959 if minnrow is None: minnrow = 1000
3960 if outlog is None: outlog = False
3961 if blfile is None: blfile = ''
3962 if csvformat is None: csvformat = False
3963 if bltable is None: bltable = ''
3964
3965 scsvformat = 'T' if csvformat else 'F'
3966
3967 edge = normalise_edge_param(edge)
3968
3969 if plot:
3970 outblfile = (blfile != "") and \
3971 os.path.exists(os.path.expanduser(os.path.expandvars(blfile)))
3972 if outblfile: blf = open(blfile, "a")
3973
3974 from asap.asaplinefind import linefinder
3975 fl = linefinder()
3976 fl.set_options(threshold=threshold, avg_limit=chan_avg_limit)
3977 fl.set_scan(workscan)
3978
3979 f = fitter()
3980 f.set_function(lpoly=order)
3981
3982 rows = xrange(workscan.nrow())
3983 #if len(rows) > 0: workscan._init_blinfo()
3984
3985 action = "H"
3986 for r in rows:
3987 idx = 2*workscan.getif(r)
3988 if mask:
3989 msk = mask_and(mask, workscan._getmask(r)) # (CAS-1434)
3990 else: # mask=None
3991 msk = workscan._getmask(r)
3992 fl.find_lines(r, msk, edge[idx:idx+2])
3993
3994 f.x = workscan._getabcissa(r)
3995 f.y = workscan._getspectrum(r)
3996 f.mask = fl.get_mask()
3997 f.data = None
3998 f.fit()
3999
4000 if action != "Y": # skip plotting when accepting all
4001 f.plot(residual=True)
4002 #accept_fit = raw_input("Accept fit ( [y]/n ): ")
4003 accept_fit = self._get_verify_action("Accept fit?",action)
4004 if r == 0: action = None
4005 if accept_fit.upper() == "N":
4006 #workscan._append_blinfo(None, None, None)
4007 continue
4008 elif accept_fit.upper() == "R":
4009 break
4010 elif accept_fit.upper() == "A":
4011 action = "Y"
4012
4013 blpars = f.get_parameters()
4014 masklist = workscan.get_masklist(f.mask, row=r, silent=True)
4015 #workscan._append_blinfo(blpars, masklist, f.mask)
4016 workscan._setspectrum(
4017 (f.fitter.getresidual() if getresidual
4018 else f.fitter.getfit()), r
4019 )
4020
4021 if outblfile:
4022 rms = workscan.get_rms(f.mask, r)
4023 dataout = \
4024 workscan.format_blparams_row(blpars["params"],
4025 blpars["fixed"],
4026 rms, str(masklist),
4027 r, True, csvformat)
4028 blf.write(dataout)
4029
4030 f._p.unmap()
4031 f._p = None
4032
4033 if outblfile: blf.close()
4034 else:
4035 workscan._auto_poly_baseline(mask, order,
4036 clipthresh, clipniter,
4037 edge, threshold,
4038 chan_avg_limit, getresidual,
4039 pack_progress_params(showprogress,
4040 minnrow),
4041 outlog, scsvformat+blfile,
4042 bltable)
4043 workscan._add_history("auto_poly_baseline", varlist)
4044
4045 if bltable == '':
4046 if insitu:
4047 self._assign(workscan)
4048 else:
4049 return workscan
4050 else:
4051 if not insitu:
4052 return None
4053
4054 except RuntimeError, e:
4055 raise_fitting_failure_exception(e)
4056
4057 def _init_blinfo(self):
4058 """\
4059 Initialise the following three auxiliary members:
4060 blpars : parameters of the best-fit baseline,
4061 masklists : mask data (edge positions of masked channels) and
4062 actualmask : mask data (in boolean list),
4063 to keep for use later (including output to logger/text files).
4064 Used by poly_baseline() and auto_poly_baseline() in case of
4065 'plot=True'.
4066 """
4067 self.blpars = []
4068 self.masklists = []
4069 self.actualmask = []
4070 return
4071
4072 def _append_blinfo(self, data_blpars, data_masklists, data_actualmask):
4073 """\
4074 Append baseline-fitting related info to blpars, masklist and
4075 actualmask.
4076 """
4077 self.blpars.append(data_blpars)
4078 self.masklists.append(data_masklists)
4079 self.actualmask.append(data_actualmask)
4080 return
4081
4082 @asaplog_post_dec
4083 def rotate_linpolphase(self, angle):
4084 """\
4085 Rotate the phase of the complex polarization O=Q+iU correlation.
4086 This is always done in situ in the raw data. So if you call this
4087 function more than once then each call rotates the phase further.
4088
4089 Parameters:
4090
4091 angle: The angle (degrees) to rotate (add) by.
4092
4093 Example::
4094
4095 scan.rotate_linpolphase(2.3)
4096
4097 """
4098 varlist = vars()
4099 self._math._rotate_linpolphase(self, angle)
4100 self._add_history("rotate_linpolphase", varlist)
4101 return
4102
4103 @asaplog_post_dec
4104 def rotate_xyphase(self, angle):
4105 """\
4106 Rotate the phase of the XY correlation. This is always done in situ
4107 in the data. So if you call this function more than once
4108 then each call rotates the phase further.
4109
4110 Parameters:
4111
4112 angle: The angle (degrees) to rotate (add) by.
4113
4114 Example::
4115
4116 scan.rotate_xyphase(2.3)
4117
4118 """
4119 varlist = vars()
4120 self._math._rotate_xyphase(self, angle)
4121 self._add_history("rotate_xyphase", varlist)
4122 return
4123
4124 @asaplog_post_dec
4125 def swap_linears(self):
4126 """\
4127 Swap the linear polarisations XX and YY, or better the first two
4128 polarisations as this also works for ciculars.
4129 """
4130 varlist = vars()
4131 self._math._swap_linears(self)
4132 self._add_history("swap_linears", varlist)
4133 return
4134
4135 @asaplog_post_dec
4136 def invert_phase(self):
4137 """\
4138 Invert the phase of the complex polarisation
4139 """
4140 varlist = vars()
4141 self._math._invert_phase(self)
4142 self._add_history("invert_phase", varlist)
4143 return
4144
4145 @asaplog_post_dec
4146 def add(self, offset, insitu=None):
4147 """\
4148 Return a scan where all spectra have the offset added
4149
4150 Parameters:
4151
4152 offset: the offset
4153
4154 insitu: if False a new scantable is returned.
4155 Otherwise, the scaling is done in-situ
4156 The default is taken from .asaprc (False)
4157
4158 """
4159 if insitu is None: insitu = rcParams['insitu']
4160 self._math._setinsitu(insitu)
4161 varlist = vars()
4162 s = scantable(self._math._unaryop(self, offset, "ADD", False))
4163 s._add_history("add", varlist)
4164 if insitu:
4165 self._assign(s)
4166 else:
4167 return s
4168
4169 @asaplog_post_dec
4170 def scale(self, factor, tsys=True, insitu=None):
4171 """\
4172
4173 Return a scan where all spectra are scaled by the given 'factor'
4174
4175 Parameters:
4176
4177 factor: the scaling factor (float or 1D float list)
4178
4179 insitu: if False a new scantable is returned.
4180 Otherwise, the scaling is done in-situ
4181 The default is taken from .asaprc (False)
4182
4183 tsys: if True (default) then apply the operation to Tsys
4184 as well as the data
4185
4186 """
4187 if insitu is None: insitu = rcParams['insitu']
4188 self._math._setinsitu(insitu)
4189 varlist = vars()
4190 s = None
4191 import numpy
4192 if isinstance(factor, list) or isinstance(factor, numpy.ndarray):
4193 if isinstance(factor[0], list) or isinstance(factor[0],
4194 numpy.ndarray):
4195 from asapmath import _array2dOp
4196 s = _array2dOp( self, factor, "MUL", tsys, insitu )
4197 else:
4198 s = scantable( self._math._arrayop( self, factor,
4199 "MUL", tsys ) )
4200 else:
4201 s = scantable(self._math._unaryop(self, factor, "MUL", tsys))
4202 s._add_history("scale", varlist)
4203 if insitu:
4204 self._assign(s)
4205 else:
4206 return s
4207
4208 @preserve_selection
4209 def set_sourcetype(self, match, matchtype="pattern",
4210 sourcetype="reference"):
4211 """\
4212 Set the type of the source to be an source or reference scan
4213 using the provided pattern.
4214
4215 Parameters:
4216
4217 match: a Unix style pattern, regular expression or selector
4218
4219 matchtype: 'pattern' (default) UNIX style pattern or
4220 'regex' regular expression
4221
4222 sourcetype: the type of the source to use (source/reference)
4223
4224 """
4225 varlist = vars()
4226 stype = -1
4227 if sourcetype.lower().startswith("r") or sourcetype.lower() == "off":
4228 stype = 1
4229 elif sourcetype.lower().startswith("s") or sourcetype.lower() == "on":
4230 stype = 0
4231 else:
4232 raise ValueError("Illegal sourcetype use s(ource)/on or r(eference)/off")
4233 if matchtype.lower().startswith("p"):
4234 matchtype = "pattern"
4235 elif matchtype.lower().startswith("r"):
4236 matchtype = "regex"
4237 else:
4238 raise ValueError("Illegal matchtype, use p(attern) or r(egex)")
4239 sel = selector()
4240 if isinstance(match, selector):
4241 sel = match
4242 else:
4243 sel.set_query("SRCNAME=%s('%s')" % (matchtype, match))
4244 self.set_selection(sel)
4245 self._setsourcetype(stype)
4246 self._add_history("set_sourcetype", varlist)
4247
4248 @asaplog_post_dec
4249 @preserve_selection
4250 def auto_quotient(self, preserve=True, mode='paired', verify=False):
4251 """\
4252 This function allows to build quotients automatically.
4253 It assumes the observation to have the same number of
4254 "ons" and "offs"
4255
4256 Parameters:
4257
4258 preserve: you can preserve (default) the continuum or
4259 remove it. The equations used are
4260
4261 preserve: Output = Toff * (on/off) - Toff
4262
4263 remove: Output = Toff * (on/off) - Ton
4264
4265 mode: the on/off detection mode
4266 'paired' (default)
4267 identifies 'off' scans by the
4268 trailing '_R' (Mopra/Parkes) or
4269 '_e'/'_w' (Tid) and matches
4270 on/off pairs from the observing pattern
4271 'time'
4272 finds the closest off in time
4273
4274 .. todo:: verify argument is not implemented
4275
4276 """
4277 varlist = vars()
4278 modes = ["time", "paired"]
4279 if not mode in modes:
4280 msg = "please provide valid mode. Valid modes are %s" % (modes)
4281 raise ValueError(msg)
4282 s = None
4283 if mode.lower() == "paired":
4284 sel = self.get_selection()
4285 sel.set_query("SRCTYPE==psoff")
4286 self.set_selection(sel)
4287 offs = self.copy()
4288 sel.set_query("SRCTYPE==pson")
4289 self.set_selection(sel)
4290 ons = self.copy()
4291 s = scantable(self._math._quotient(ons, offs, preserve))
4292 elif mode.lower() == "time":
4293 s = scantable(self._math._auto_quotient(self, mode, preserve))
4294 s._add_history("auto_quotient", varlist)
4295 return s
4296
4297 @asaplog_post_dec
4298 def mx_quotient(self, mask = None, weight='median', preserve=True):
4299 """\
4300 Form a quotient using "off" beams when observing in "MX" mode.
4301
4302 Parameters:
4303
4304 mask: an optional mask to be used when weight == 'stddev'
4305
4306 weight: How to average the off beams. Default is 'median'.
4307
4308 preserve: you can preserve (default) the continuum or
4309 remove it. The equations used are:
4310
4311 preserve: Output = Toff * (on/off) - Toff
4312
4313 remove: Output = Toff * (on/off) - Ton
4314
4315 """
4316 mask = mask or ()
4317 varlist = vars()
4318 on = scantable(self._math._mx_extract(self, 'on'))
4319 preoff = scantable(self._math._mx_extract(self, 'off'))
4320 off = preoff.average_time(mask=mask, weight=weight, scanav=False)
4321 from asapmath import quotient
4322 q = quotient(on, off, preserve)
4323 q._add_history("mx_quotient", varlist)
4324 return q
4325
4326 @asaplog_post_dec
4327 def freq_switch(self, insitu=None):
4328 """\
4329 Apply frequency switching to the data.
4330
4331 Parameters:
4332
4333 insitu: if False a new scantable is returned.
4334 Otherwise, the swictching is done in-situ
4335 The default is taken from .asaprc (False)
4336
4337 """
4338 if insitu is None: insitu = rcParams['insitu']
4339 self._math._setinsitu(insitu)
4340 varlist = vars()
4341 s = scantable(self._math._freqswitch(self))
4342 s._add_history("freq_switch", varlist)
4343 if insitu:
4344 self._assign(s)
4345 else:
4346 return s
4347
4348 @asaplog_post_dec
4349 def recalc_azel(self):
4350 """Recalculate the azimuth and elevation for each position."""
4351 varlist = vars()
4352 self._recalcazel()
4353 self._add_history("recalc_azel", varlist)
4354 return
4355
4356 @asaplog_post_dec
4357 def __add__(self, other):
4358 """
4359 implicit on all axes and on Tsys
4360 """
4361 varlist = vars()
4362 s = self.__op( other, "ADD" )
4363 s._add_history("operator +", varlist)
4364 return s
4365
4366 @asaplog_post_dec
4367 def __sub__(self, other):
4368 """
4369 implicit on all axes and on Tsys
4370 """
4371 varlist = vars()
4372 s = self.__op( other, "SUB" )
4373 s._add_history("operator -", varlist)
4374 return s
4375
4376 @asaplog_post_dec
4377 def __mul__(self, other):
4378 """
4379 implicit on all axes and on Tsys
4380 """
4381 varlist = vars()
4382 s = self.__op( other, "MUL" ) ;
4383 s._add_history("operator *", varlist)
4384 return s
4385
4386
4387 @asaplog_post_dec
4388 def __div__(self, other):
4389 """
4390 implicit on all axes and on Tsys
4391 """
4392 varlist = vars()
4393 s = self.__op( other, "DIV" )
4394 s._add_history("operator /", varlist)
4395 return s
4396
4397 @asaplog_post_dec
4398 def __op( self, other, mode ):
4399 s = None
4400 if isinstance(other, scantable):
4401 s = scantable(self._math._binaryop(self, other, mode))
4402 elif isinstance(other, float):
4403 if other == 0.0:
4404 raise ZeroDivisionError("Dividing by zero is not recommended")
4405 s = scantable(self._math._unaryop(self, other, mode, False))
4406 elif isinstance(other, list) or isinstance(other, numpy.ndarray):
4407 if isinstance(other[0], list) \
4408 or isinstance(other[0], numpy.ndarray):
4409 from asapmath import _array2dOp
4410 s = _array2dOp( self, other, mode, False )
4411 else:
4412 s = scantable( self._math._arrayop( self, other,
4413 mode, False ) )
4414 else:
4415 raise TypeError("Other input is not a scantable or float value")
4416 return s
4417
4418 @asaplog_post_dec
4419 def get_fit(self, row=0):
4420 """\
4421 Print or return the stored fits for a row in the scantable
4422
4423 Parameters:
4424
4425 row: the row which the fit has been applied to.
4426
4427 """
4428 if row > self.nrow():
4429 return
4430 from asap.asapfit import asapfit
4431 fit = asapfit(self._getfit(row))
4432 asaplog.push( '%s' %(fit) )
4433 return fit.as_dict()
4434
4435 @preserve_selection
4436 def flag_nans(self):
4437 """\
4438 Utility function to flag NaN values in the scantable.
4439 """
4440 import numpy
4441 basesel = self.get_selection()
4442 for i in range(self.nrow()):
4443 sel = self.get_row_selector(i)
4444 self.set_selection(basesel+sel)
4445 nans = numpy.isnan(self._getspectrum(0))
4446 if numpy.any(nans):
4447 bnans = [ bool(v) for v in nans]
4448 self.flag(bnans)
4449
4450 def get_row_selector(self, rowno):
4451 return selector(rows=[rowno])
4452
4453 def _add_history(self, funcname, parameters):
4454 if not rcParams['scantable.history']:
4455 return
4456 # create date
4457 sep = "##"
4458 from datetime import datetime
4459 dstr = datetime.now().strftime('%Y/%m/%d %H:%M:%S')
4460 hist = dstr+sep
4461 hist += funcname+sep#cdate+sep
4462 if parameters.has_key('self'):
4463 del parameters['self']
4464 for k, v in parameters.iteritems():
4465 if type(v) is dict:
4466 for k2, v2 in v.iteritems():
4467 hist += k2
4468 hist += "="
4469 if isinstance(v2, scantable):
4470 hist += 'scantable'
4471 elif k2 == 'mask':
4472 if isinstance(v2, list) or isinstance(v2, tuple):
4473 hist += str(self._zip_mask(v2))
4474 else:
4475 hist += str(v2)
4476 else:
4477 hist += str(v2)
4478 else:
4479 hist += k
4480 hist += "="
4481 if isinstance(v, scantable):
4482 hist += 'scantable'
4483 elif k == 'mask':
4484 if isinstance(v, list) or isinstance(v, tuple):
4485 hist += str(self._zip_mask(v))
4486 else:
4487 hist += str(v)
4488 else:
4489 hist += str(v)
4490 hist += sep
4491 hist = hist[:-2] # remove trailing '##'
4492 self._addhistory(hist)
4493
4494
4495 def _zip_mask(self, mask):
4496 mask = list(mask)
4497 i = 0
4498 segments = []
4499 while mask[i:].count(1):
4500 i += mask[i:].index(1)
4501 if mask[i:].count(0):
4502 j = i + mask[i:].index(0)
4503 else:
4504 j = len(mask)
4505 segments.append([i, j])
4506 i = j
4507 return segments
4508
4509 def _get_ordinate_label(self):
4510 fu = "("+self.get_fluxunit()+")"
4511 import re
4512 lbl = "Intensity"
4513 if re.match(".K.", fu):
4514 lbl = "Brightness Temperature "+ fu
4515 elif re.match(".Jy.", fu):
4516 lbl = "Flux density "+ fu
4517 return lbl
4518
4519 def _check_ifs(self):
4520# return len(set([self.nchan(i) for i in self.getifnos()])) == 1
4521 nchans = [self.nchan(i) for i in self.getifnos()]
4522 nchans = filter(lambda t: t > 0, nchans)
4523 return (sum(nchans)/len(nchans) == nchans[0])
4524
4525 @asaplog_post_dec
4526 def _fill(self, names, unit, average, opts={}):
4527 first = True
4528 fullnames = []
4529 for name in names:
4530 name = os.path.expandvars(name)
4531 name = os.path.expanduser(name)
4532 if not os.path.exists(name):
4533 msg = "File '%s' does not exists" % (name)
4534 raise IOError(msg)
4535 fullnames.append(name)
4536 if average:
4537 asaplog.push('Auto averaging integrations')
4538 stype = int(rcParams['scantable.storage'].lower() == 'disk')
4539 for name in fullnames:
4540 tbl = Scantable(stype)
4541 if is_ms( name ):
4542 r = msfiller( tbl )
4543 else:
4544 r = filler( tbl )
4545 msg = "Importing %s..." % (name)
4546 asaplog.push(msg, False)
4547 r.open(name, opts)
4548 rx = rcParams['scantable.reference']
4549 r.setreferenceexpr(rx)
4550 r.fill()
4551 if average:
4552 tbl = self._math._average((tbl, ), (), 'NONE', 'SCAN')
4553 if not first:
4554 tbl = self._math._merge([self, tbl])
4555 Scantable.__init__(self, tbl)
4556 r.close()
4557 del r, tbl
4558 first = False
4559 #flush log
4560 asaplog.post()
4561 if unit is not None:
4562 self.set_fluxunit(unit)
4563 if not is_casapy():
4564 self.set_freqframe(rcParams['scantable.freqframe'])
4565
4566 def _get_verify_action( self, msg, action=None ):
4567 valid_act = ['Y', 'N', 'A', 'R']
4568 if not action or not isinstance(action, str):
4569 action = raw_input("%s [Y/n/a/r] (h for help): " % msg)
4570 if action == '':
4571 return "Y"
4572 elif (action.upper()[0] in valid_act):
4573 return action.upper()[0]
4574 elif (action.upper()[0] in ['H','?']):
4575 print "Available actions of verification [Y|n|a|r]"
4576 print " Y : Yes for current data (default)"
4577 print " N : No for current data"
4578 print " A : Accept all in the following and exit from verification"
4579 print " R : Reject all in the following and exit from verification"
4580 print " H or ?: help (show this message)"
4581 return self._get_verify_action(msg)
4582 else:
4583 return 'Y'
4584
4585 def __getitem__(self, key):
4586 if key < 0:
4587 key += self.nrow()
4588 if key >= self.nrow():
4589 raise IndexError("Row index out of range.")
4590 return self._getspectrum(key)
4591
4592 def __setitem__(self, key, value):
4593 if key < 0:
4594 key += self.nrow()
4595 if key >= self.nrow():
4596 raise IndexError("Row index out of range.")
4597 if not hasattr(value, "__len__") or \
4598 len(value) > self.nchan(self.getif(key)):
4599 raise ValueError("Spectrum length doesn't match.")
4600 return self._setspectrum(value, key)
4601
4602 def __len__(self):
4603 return self.nrow()
4604
4605 def __iter__(self):
4606 for i in range(len(self)):
4607 yield self[i]
Note: See TracBrowser for help on using the repository browser.