source: trunk/python/scantable.py@ 2769

Last change on this file since 2769 was 2767, checked in by WataruKawasaki, 12 years ago

New Development: Yes

JIRA Issue: Yes CAS-4794

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs:

Put in Release Notes: No

Module(s): sd

Description: functions to apply/write STBaselineTable in which baseline parameters stored.


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