source: trunk/python/scantable.py@ 498

Last change on this file since 498 was 497, checked in by kil064, 20 years ago

document ascii output format better

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.5 KB
Line 
1from asap._asap import sdtable
2from asap import rcParams
3from numarray import ones,zeros
4import sys
5
6class scantable(sdtable):
7 """
8 The ASAP container for scans
9 """
10
11 def __init__(self, filename, average=None, unit=None):
12 """
13 Create a scantable from a saved one or make a reference
14 Parameters:
15 filename: the name of an asap table on disk
16 or
17 the name of a rpfits/sdfits/ms file
18 (integrations within scans are auto averaged
19 and the whole file is read)
20 or
21 [advanced] a reference to an existing
22 scantable
23 average: average all integrations withinb a scan on read.
24 The default (True) is taken from .asaprc.
25 unit: brightness unit; must be consistent with K or Jy.
26 Over-rides the default selected by the reader
27 (input rpfits/sdfits/ms) or replaces the value
28 in existing scantables
29 """
30 if average is None or type(average) is not bool:
31 average = rcParams['scantable.autoaverage']
32
33 varlist = vars()
34 self._vb = rcParams['verbose']
35 self._p = None
36
37 if isinstance(filename,sdtable):
38 sdtable.__init__(self, filename)
39 if unit is not None:
40 self.set_fluxunit(unit)
41 else:
42 import os.path
43 if not os.path.exists(filename):
44 print "File '%s' not found." % (filename)
45 return
46 filename = os.path.expandvars(filename)
47 if os.path.isdir(filename):
48 # crude check if asap table
49 if os.path.exists(filename+'/table.info'):
50 sdtable.__init__(self, filename)
51 if unit is not None:
52 self.set_fluxunit(unit)
53 else:
54 print "The given file '%s'is not a valid asap table." % (filename)
55 return
56 else:
57 from asap._asap import sdreader
58 ifSel = -1
59 beamSel = -1
60 r = sdreader(filename,ifSel,beamSel)
61 print 'Importing data...'
62 r._read([-1])
63 tbl = r._getdata()
64 if unit is not None:
65 tbl.set_fluxunit(unit)
66 if average:
67 from asap._asap import average as _av
68 tmp = tuple([tbl])
69 print 'Auto averaging integrations...'
70 tbl2 = _av(tmp,(),True,'none')
71 sdtable.__init__(self,tbl2)
72 del r,tbl
73 else:
74 sdtable.__init__(self,tbl)
75 self._add_history("scantable", varlist)
76
77 def save(self, name=None, format=None, stokes=False, overwrite=False):
78 """
79 Store the scantable on disk. This can be an asap (aips++) Table, SDFITS,
80 Image FITS or MS2 format.
81 Parameters:
82 name: the name of the outputfile. For format="FITS" this
83 is the directory file name into which all the files
84 will be written (default is 'asap_FITS'). For format
85 "ASCII" this is the root file name (data in 'name'.txt
86 and header in 'name'_header.txt)
87 format: an optional file format. Default is ASAP.
88 Allowed are - 'ASAP' (save as ASAP [aips++] Table),
89 'SDFITS' (save as SDFITS file)
90 'FITS' (saves each row as a FITS Image)
91 'ASCII' (saves as ascii text file)
92 'MS2' (saves as an aips++
93 MeasurementSet V2)
94 stokes: Convert to Stokes parameters (only available
95 currently with FITS and ASCII formats.
96 Default is False.
97 overwrite: If the file should be overwritten if it exists.
98 The default False is to return with warning
99 without writing the output. USE WITH CARE.
100 Example:
101 scan.save('myscan.asap')
102 scan.save('myscan.sdfits','SDFITS')
103 """
104 from os import path
105 if format is None: format = rcParams['scantable.save']
106 suffix = '.'+format.lower()
107 if name is None or name =="":
108 name = 'scantable'+suffix
109 print "No filename given. Using default name %s..." % name
110 name = path.expandvars(name)
111 if path.isfile(name) or path.isdir(name):
112 if not overwrite:
113 print "File %s already exists." % name
114 return
115 format2 = format.upper()
116 if format2 == 'ASAP':
117 self._save(name)
118 else:
119 from asap._asap import sdwriter as _sw
120 w = _sw(format2)
121 w.write(self, name, stokes)
122 return
123
124 def copy(self):
125 """
126 Return a copy of this scantable.
127 Parameters:
128 none
129 Example:
130 copiedscan = scan.copy()
131 """
132 sd = scantable(sdtable._copy(self))
133 return sd
134
135 def get_scan(self, scanid=None):
136 """
137 Return a specific scan (by scanno) or collection of scans (by
138 source name) in a new scantable.
139 Parameters:
140 scanid: a scanno or a source name
141 Example:
142 scan.get_scan('323p459')
143 # gets all scans containing the source '323p459'
144 """
145 if scanid is None:
146 print "Please specify a scan no or name to retrieve from the scantable"
147 try:
148 if type(scanid) is str:
149 s = sdtable._getsource(self,scanid)
150 return scantable(s)
151 elif type(scanid) is int:
152 s = sdtable._getscan(self,[scanid])
153 return scantable(s)
154 elif type(scanid) is list:
155 s = sdtable._getscan(self,scanid)
156 return scantable(s)
157 else:
158 print "Illegal scanid type, use 'int' or 'list' if ints."
159 except RuntimeError:
160 print "Couldn't find any match."
161
162 def __str__(self):
163 return sdtable._summary(self,True)
164
165 def summary(self,filename=None, verbose=None):
166 """
167 Print a summary of the contents of this scantable.
168 Parameters:
169 filename: the name of a file to write the putput to
170 Default - no file output
171 verbose: print extra info such as the frequency table
172 The default (False) is taken from .asaprc
173 """
174 info = sdtable._summary(self, verbose)
175 if verbose is None: verbose = rcParams['scantable.verbosesummary']
176 if filename is not None:
177 if filename is "":
178 filename = 'scantable_summary.txt'
179 from os.path import expandvars, isdir
180 filename = expandvars(filename)
181 if not isdir(filename):
182 data = open(filename, 'w')
183 data.write(info)
184 data.close()
185 else:
186 print "Illegal file name '%s'." % (filename)
187 print info
188
189 def set_cursor(self, thebeam=0,theif=0,thepol=0):
190 """
191 Set the spectrum for individual operations.
192 Parameters:
193 thebeam,theif,thepol: a number
194 Example:
195 scan.set_cursor(0,0,1)
196 pol1sig = scan.stats(all=False) # returns std dev for beam=0
197 # if=0, pol=1
198 """
199 varlist = vars()
200 self.setbeam(thebeam)
201 self.setpol(thepol)
202 self.setif(theif)
203 self._add_history("set_cursor",varlist)
204 return
205
206 def get_cursor(self):
207 """
208 Return/print a the current 'cursor' into the Beam/IF/Pol cube.
209 Parameters:
210 none
211 Returns:
212 a list of values (currentBeam,currentIF,currentPol)
213 Example:
214 none
215 """
216 i = self.getbeam()
217 j = self.getif()
218 k = self.getpol()
219 if self._vb:
220 print "--------------------------------------------------"
221 print " Cursor position"
222 print "--------------------------------------------------"
223 out = 'Beam=%d IF=%d Pol=%d ' % (i,j,k)
224 print out
225 return i,j,k
226
227 def stats(self, stat='stddev', mask=None, allaxes=None):
228 """
229 Determine the specified statistic of the current beam/if/pol
230 Takes a 'mask' as an optional parameter to specify which
231 channels should be excluded.
232 Parameters:
233 stat: 'min', 'max', 'sumsq', 'sum', 'mean'
234 'var', 'stddev', 'avdev', 'rms', 'median'
235 mask: an optional mask specifying where the statistic
236 should be determined.
237 allaxes: if True apply to all spectra. Otherwise
238 apply only to the selected (beam/pol/if)spectra only.
239 The default is taken from .asaprc (True if none)
240 Example:
241 scan.set_unit('channel')
242 msk = scan.create_mask([100,200],[500,600])
243 scan.stats(stat='mean', mask=m)
244 """
245 if allaxes is None: allaxes = rcParams['scantable.allaxes']
246 from asap._asap import stats as _stats
247 from numarray import array,zeros,Float
248 if mask == None:
249 mask = ones(self.nchan())
250 axes = ['Beam','IF','Pol','Time']
251
252 beamSel,IFSel,polSel = (self.getbeam(),self.getif(),self.getpol())
253 if allaxes:
254 n = self.nbeam()*self.nif()*self.npol()*self.nrow()
255 shp = [self.nbeam(),self.nif(),self.npol(),self.nrow()]
256 arr = array(zeros(n),shape=shp,type=Float)
257
258 for i in range(self.nbeam()):
259 self.setbeam(i)
260 for j in range(self.nif()):
261 self.setif(j)
262 for k in range(self.npol()):
263 self.setpol(k)
264 arr[i,j,k,:] = _stats(self,mask,stat,-1)
265 retval = {'axes': axes, 'data': arr, 'cursor':None}
266 tm = [self._gettime(val) for val in range(self.nrow())]
267 if self._vb:
268 self._print_values(retval,stat,tm)
269 self.setbeam(beamSel)
270 self.setif(IFSel)
271 self.setpol(polSel)
272 return retval
273
274 else:
275 statval = _stats(self,mask,stat,-1)
276 out = ''
277 for l in range(self.nrow()):
278 tm = self._gettime(l)
279 out += 'Time[%s]:\n' % (tm)
280 if self.nbeam() > 1: out += ' Beam[%d] ' % (beamSel)
281 if self.nif() > 1: out += ' IF[%d] ' % (IFSel)
282 if self.npol() > 1: out += ' Pol[%d] ' % (polSel)
283 out += '= %3.3f\n' % (statval[l])
284 out += "--------------------------------------------------\n"
285
286 if self._vb:
287 print "--------------------------------------------------"
288 print " ",stat
289 print "--------------------------------------------------"
290 print out
291 retval = {'axes': axes, 'data': array(statval), 'cursor':(i,j,k)}
292 return retval
293
294 def stddev(self,mask=None, allaxes=None):
295 """
296 Determine the standard deviation of the current beam/if/pol
297 Takes a 'mask' as an optional parameter to specify which
298 channels should be excluded.
299 Parameters:
300 mask: an optional mask specifying where the standard
301 deviation should be determined.
302 allaxes: optional flag to show all or a cursor selected
303 spectrum of Beam/IF/Pol. Default is all or taken
304 from .asaprc
305
306 Example:
307 scan.set_unit('channel')
308 msk = scan.create_mask([100,200],[500,600])
309 scan.stddev(mask=m)
310 """
311 if allaxes is None: allaxes = rcParams['scantable.allaxes']
312 return self.stats(stat='stddev',mask=mask, allaxes=allaxes);
313
314 def get_tsys(self, allaxes=None):
315 """
316 Return the System temperatures.
317 Parameters:
318 allaxes: if True apply to all spectra. Otherwise
319 apply only to the selected (beam/pol/if)spectra only.
320 The default is taken from .asaprc (True if none)
321 Returns:
322 a list of Tsys values.
323 """
324 if allaxes is None: allaxes = rcParams['scantable.allaxes']
325 from numarray import array,zeros,Float
326 axes = ['Beam','IF','Pol','Time']
327
328 if allaxes:
329 n = self.nbeam()*self.nif()*self.npol()*self.nrow()
330 shp = [self.nbeam(),self.nif(),self.npol(),self.nrow()]
331 arr = array(zeros(n),shape=shp,type=Float)
332
333 for i in range(self.nbeam()):
334 self.setbeam(i)
335 for j in range(self.nif()):
336 self.setif(j)
337 for k in range(self.npol()):
338 self.setpol(k)
339 arr[i,j,k,:] = self._gettsys()
340 retval = {'axes': axes, 'data': arr, 'cursor':None}
341 tm = [self._gettime(val) for val in range(self.nrow())]
342 if self._vb:
343 self._print_values(retval,'Tsys',tm)
344 return retval
345
346 else:
347 i,j,k = (self.getbeam(),self.getif(),self.getpol())
348 statval = self._gettsys()
349 out = ''
350 for l in range(self.nrow()):
351 tm = self._gettime(l)
352 out += 'Time[%s]:\n' % (tm)
353 if self.nbeam() > 1: out += ' Beam[%d] ' % (i)
354 if self.nif() > 1: out += ' IF[%d] ' % (j)
355 if self.npol() > 1: out += ' Pol[%d] ' % (k)
356 out += '= %3.3f\n' % (statval[l])
357 out += "--------------------------------------------------\n"
358
359 if self._vb:
360 print "--------------------------------------------------"
361 print " TSys"
362 print "--------------------------------------------------"
363 print out
364 retval = {'axes': axes, 'data': array(statval), 'cursor':(i,j,k)}
365 return retval
366
367 def get_time(self, row=-1):
368 """
369 Get a list of time stamps for the observations.
370 Return a string for each integration in the scantable.
371 Parameters:
372 row: row no of integration. Default -1 return all rows
373 Example:
374 none
375 """
376 out = []
377 if row == -1:
378 for i in range(self.nrow()):
379 out.append(self._gettime(i))
380 return out
381 else:
382 if row < self.nrow():
383 return self._gettime(row)
384
385 def set_unit(self, unit='channel'):
386 """
387 Set the unit for all following operations on this scantable
388 Parameters:
389 unit: optional unit, default is 'channel'
390 one of '*Hz','km/s','channel', ''
391 """
392 varlist = vars()
393 if unit in ['','pixel', 'channel']:
394 unit = ''
395 inf = list(self._getcoordinfo())
396 inf[0] = unit
397 self._setcoordinfo(inf)
398 if self._p: self.plot()
399 self._add_history("set_unit",varlist)
400
401 def set_instrument(self, instr):
402 """
403 Set the instrument for subsequent processing
404 Parameters:
405 instr: Select from 'ATPKSMB', 'ATPKSHOH', 'ATMOPRA',
406 'DSS-43' (Tid), 'CEDUNA', and 'HOBART'
407 """
408 self._setInstrument(instr)
409 self._add_history("set_instument",vars())
410
411 def set_doppler(self, doppler='RADIO'):
412 """
413 Set the doppler for all following operations on this scantable.
414 Parameters:
415 doppler: One of 'RADIO', 'OPTICAL', 'Z', 'BETA', 'GAMMA'
416 """
417 varlist = vars()
418 inf = list(self._getcoordinfo())
419 inf[2] = doppler
420 self._setcoordinfo(inf)
421 if self._p: self.plot()
422 self._add_history("set_doppler",vars())
423
424 def set_freqframe(self, frame=None):
425 """
426 Set the frame type of the Spectral Axis.
427 Parameters:
428 frame: an optional frame type, default 'LSRK'.
429 Examples:
430 scan.set_freqframe('BARY')
431 """
432 if frame is None: frame = rcParams['scantable.freqframe']
433 varlist = vars()
434 valid = ['REST','TOPO','LSRD','LSRK','BARY', \
435 'GEO','GALACTO','LGROUP','CMB']
436 if frame in valid:
437 inf = list(self._getcoordinfo())
438 inf[1] = frame
439 self._setcoordinfo(inf)
440 self._add_history("set_freqframe",varlist)
441 else:
442 print "Please specify a valid freq type. Valid types are:\n",valid
443
444 def get_unit(self):
445 """
446 Get the default unit set in this scantable
447 Parameters:
448 Returns:
449 A unit string
450 """
451 inf = self._getcoordinfo()
452 unit = inf[0]
453 if unit == '': unit = 'channel'
454 return unit
455
456 def get_abcissa(self, rowno=0):
457 """
458 Get the abcissa in the current coordinate setup for the currently
459 selected Beam/IF/Pol
460 Parameters:
461 rowno: an optional row number in the scantable. Default is the
462 first row, i.e. rowno=0
463 Returns:
464 The abcissa values and it's format string (as a dictionary)
465 """
466 abc = self._getabcissa(rowno)
467 lbl = self._getabcissalabel(rowno)
468 return abc, lbl
469 #return {'abcissa':abc,'label':lbl}
470
471 def create_mask(self, *args, **kwargs):
472 """
473 Compute and return a mask based on [min,max] windows.
474 The specified windows are to be INCLUDED, when the mask is
475 applied.
476 Parameters:
477 [min,max],[min2,max2],...
478 Pairs of start/end points specifying the regions
479 to be masked
480 invert: optional argument. If specified as True,
481 return an inverted mask, i.e. the regions
482 specified are EXCLUDED
483 Example:
484 scan.set_unit('channel')
485
486 a)
487 msk = scan.set_mask([400,500],[800,900])
488 # masks everything outside 400 and 500
489 # and 800 and 900 in the unit 'channel'
490
491 b)
492 msk = scan.set_mask([400,500],[800,900], invert=True)
493 # masks the regions between 400 and 500
494 # and 800 and 900 in the unit 'channel'
495
496 """
497 varlist = vars()
498 u = self._getcoordinfo()[0]
499 if self._vb:
500 if u == "": u = "channel"
501 print "The current mask window unit is", u
502 n = self.nchan()
503 data = self._getabcissa()
504 msk = zeros(n)
505 for window in args:
506 if (len(window) != 2 or window[0] > window[1] ):
507 print "A window needs to be defined as [min,max]"
508 return
509 for i in range(n):
510 if data[i] >= window[0] and data[i] < window[1]:
511 msk[i] = 1
512 if kwargs.has_key('invert'):
513 if kwargs.get('invert'):
514 from numarray import logical_not
515 msk = logical_not(msk)
516 self._add_history("create_mask", varlist)
517 return msk
518
519 def get_restfreqs(self):
520 """
521 Get the restfrequency(s) stored in this scantable.
522 The return value(s) are always of unit 'Hz'
523 Parameters:
524 none
525 Returns:
526 a list of doubles
527 """
528 return list(self._getrestfreqs())
529
530 def lines(self):
531 """
532 Print the list of known spectral lines
533 """
534 sdtable._lines(self)
535
536 def set_restfreqs(self, freqs=None, unit='Hz', lines=None, source=None,
537 theif=None):
538 """
539 Select the restfrequency for the specified source and IF OR
540 replace for all IFs. If the 'freqs' argument holds a scalar,
541 then that rest frequency will be applied to the selected
542 data (and added to the list of available rest frequencies).
543 In this way, you can set a rest frequency for each
544 source and IF combination. If the 'freqs' argument holds
545 a vector, then it MUST be of length the number of IFs
546 (and the available restfrequencies will be replaced by
547 this vector). In this case, *all* data ('source' and
548 'theif' are ignored) have the restfrequency set per IF according
549 to the corresponding value you give in the 'freqs' vector.
550 E.g. 'freqs=[1e9,2e9]' would mean IF 0 gets restfreq 1e9 and
551 IF 1 gets restfreq 2e9.
552
553 You can also specify the frequencies via known line names
554 in the argument 'lines'. Use 'freqs' or 'lines'. 'freqs'
555 takes precedence. See the list of known names via function
556 scantable.lines()
557 Parameters:
558 freqs: list of rest frequencies
559 unit: unit for rest frequency (default 'Hz')
560 lines: list of known spectral lines names (alternative to freqs).
561 See possible list via scantable.lines()
562 source: Source name (blank means all)
563 theif: IF (-1 means all)
564 Example:
565 scan.set_restfreqs(freqs=1.4e9, source='NGC253', theif=2)
566 scan.set_restfreqs(freqs=[1.4e9,1.67e9])
567 """
568 varlist = vars()
569 if source is None:
570 source = ""
571 if theif is None:
572 theif = -1
573 t = type(freqs)
574 if t is int or t is float:
575 freqs = [freqs]
576 if freqs is None:
577 freqs = []
578 t = type(lines)
579 if t is str:
580 lines = [lines]
581 if lines is None:
582 lines = []
583 sdtable._setrestfreqs(self, freqs, unit, lines, source, theif)
584 self._add_history("set_restfreqs", varlist)
585
586
587
588 def flag_spectrum(self, thebeam, theif, thepol):
589 """
590 This flags a selected spectrum in the scan 'for good'.
591 USE WITH CARE - not reversible.
592 Use masks for non-permanent exclusion of channels.
593 Parameters:
594 thebeam,theif,thepol: all have to be explicitly
595 specified
596 Example:
597 scan.flag_spectrum(0,0,1)
598 flags the spectrum for Beam=0, IF=0, Pol=1
599 """
600 if (thebeam < self.nbeam() and
601 theif < self.nif() and
602 thepol < self.npol()):
603 sdtable.setbeam(self, thebeam)
604 sdtable.setif(self, theif)
605 sdtable.setpol(self, thepol)
606 sdtable._flag(self)
607 self._add_history("flag_spectrum", vars())
608 else:
609 print "Please specify a valid (Beam/IF/Pol)"
610 return
611
612 def plot(self, what='spectrum',col='Pol', panel=None):
613 """
614 Plot the spectra contained in the scan. Alternatively you can also
615 Plot Tsys vs Time
616 Parameters:
617 what: a choice of 'spectrum' (default) or 'tsys'
618 col: which out of Beams/IFs/Pols should be colour stacked
619 panel: set up multiple panels, currently not working.
620 """
621 print "Warning! Not fully functional. Use plotter.plot() instead"
622
623 validcol = {'Beam':self.nbeam(),'IF':self.nif(),'Pol':self.npol()}
624
625 validyax = ['spectrum','tsys']
626 from asap.asaplot import ASAPlot
627 if not self._p:
628 self._p = ASAPlot()
629 #print "Plotting not enabled"
630 #return
631 if self._p.is_dead:
632 del self._p
633 self._p = ASAPlot()
634 npan = 1
635 x = None
636 if what == 'tsys':
637 n = self.nrow()
638 if n < 2:
639 print "Only one integration. Can't plot."
640 return
641 self._p.hold()
642 self._p.clear()
643 if panel == 'Time':
644 npan = self.nrow()
645 self._p.set_panels(rows=npan)
646 xlab,ylab,tlab = None,None,None
647 self._vb = False
648 sel = self.get_cursor()
649 for i in range(npan):
650 if npan > 1:
651 self._p.subplot(i)
652 for j in range(validcol[col]):
653 x = None
654 y = None
655 m = None
656 tlab = self._getsourcename(i)
657 import re
658 tlab = re.sub('_S','',tlab)
659 if col == 'Beam':
660 self.setbeam(j)
661 elif col == 'IF':
662 self.setif(j)
663 elif col == 'Pol':
664 self.setpol(j)
665 if what == 'tsys':
666 x = range(self.nrow())
667 xlab = 'Time [pixel]'
668 m = list(ones(len(x)))
669 y = []
670 ylab = r'$T_{sys}$'
671 for k in range(len(x)):
672 y.append(self._gettsys(k))
673 else:
674 x,xlab = self.get_abcissa(i)
675 y = self._getspectrum(i)
676 ylab = r'Flux'
677 m = self._getmask(i)
678 llab = col+' '+str(j)
679 self._p.set_line(label=llab)
680 self._p.plot(x,y,m)
681 self._p.set_axes('xlabel',xlab)
682 self._p.set_axes('ylabel',ylab)
683 self._p.set_axes('title',tlab)
684 self._p.release()
685 self.set_cursor(sel[0],sel[1],sel[2])
686 self._vb = rcParams['verbose']
687 return
688
689 print out
690
691 def _print_values(self, dat, label='', timestamps=[]):
692 d = dat['data']
693 a = dat['axes']
694 shp = d.getshape()
695 out = ''
696 for i in range(shp[3]):
697 out += '%s [%s]:\n' % (a[3],timestamps[i])
698 t = d[:,:,:,i]
699 for j in range(shp[0]):
700 if shp[0] > 1: out += ' %s[%d] ' % (a[0],j)
701 for k in range(shp[1]):
702 if shp[1] > 1: out += ' %s[%d] ' % (a[1],k)
703 for l in range(shp[2]):
704 if shp[2] > 1: out += ' %s[%d] ' % (a[2],l)
705 out += '= %3.3f\n' % (t[j,k,l])
706 out += "-"*80
707 out += "\n"
708 print "-"*80
709 print " ", label
710 print "-"*80
711 print out
712
713 def history(self):
714 hist = list(self._gethistory())
715 print "-"*80
716 for h in hist:
717 if h.startswith("---"):
718 print h
719 else:
720 items = h.split("##")
721 date = items[0]
722 func = items[1]
723 items = items[2:]
724 print date
725 print "Function: %s\n Parameters:" % (func)
726 for i in items:
727 s = i.split("=")
728 print " %s = %s" % (s[0],s[1])
729 print "-"*80
730 return
731
732 def _add_history(self, funcname, parameters):
733 # create date
734 sep = "##"
735 from datetime import datetime
736 dstr = datetime.now().strftime('%Y/%m/%d %H:%M:%S')
737 hist = dstr+sep
738 hist += funcname+sep#cdate+sep
739 if parameters.has_key('self'): del parameters['self']
740 for k,v in parameters.iteritems():
741 if type(v) is dict:
742 for k2,v2 in v.iteritems():
743 hist += k2
744 hist += "="
745 if isinstance(v2,scantable):
746 hist += 'scantable'
747 elif k2 == 'mask':
748 hist += str(self._zip_mask(v2))
749 else:
750 hist += str(v2)
751 else:
752 hist += k
753 hist += "="
754 if isinstance(v,scantable):
755 hist += 'scantable'
756 elif k == 'mask':
757 hist += str(self._zip_mask(v))
758 else:
759 hist += str(v)
760 hist += sep
761 hist = hist[:-2] # remove trailing '##'
762 self._addhistory(hist)
763
764
765 def _zip_mask(self, mask):
766 mask = list(mask)
767 i = 0
768 segments = []
769 while mask[i:].count(1):
770 i += mask[i:].index(1)
771 if mask[i:].count(0):
772 j = i + mask[i:].index(0)
773 else:
774 j = len(mask)
775 segments.append([i,j])
776 i = j
777 return segments
Note: See TracBrowser for help on using the repository browser.