Changeset 513 for trunk


Ignore:
Timestamp:
02/28/05 15:28:33 (20 years ago)
Author:
mar637
Message:

*Moved most asapmath functions to scantable member functions. Only ones taking more than one scantable as input remain.

  • added asap._is_sequence_or_number to check input args
Location:
trunk/python
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/python/__init__.py

    r510 r513  
    55import os,sys
    66
    7 def validate_bool(b):
     7def _validate_bool(b):
    88    'Convert b to a boolean or raise'
    99    bl = b.lower()
     
    1313        raise ValueError('Could not convert "%s" to boolean' % b)
    1414
    15 def validate_int(s):
     15def _validate_int(s):
    1616    'convert s to int or raise'
    1717    try: return int(s)
     
    1919        raise ValueError('Could not convert "%s" to int' % s)
    2020
    21 def asap_fname():
     21def _asap_fname():
    2222    """
    2323    Return the path to the rc file
     
    5151defaultParams = {
    5252    # general
    53     'verbose'             : [True, validate_bool],
    54     'useplotter'          : [True, validate_bool],
    55     'insitu'              : [False, validate_bool],
     53    'verbose'             : [True, _validate_bool],
     54    'useplotter'          : [True, _validate_bool],
     55    'insitu'              : [False, _validate_bool],
    5656   
    5757    # plotting
     
    6161    # scantable
    6262    'scantable.save'      : ['ASAP', str],
    63     'scantable.autoaverage'      : [True, validate_bool],
     63    'scantable.autoaverage'      : [True, _validate_bool],
    6464    'scantable.freqframe' : ['LSRK', str],  #default frequency frame
    65     'scantable.allaxes'   : [True, validate_bool],  # apply action to all axes
    66     'scantable.plotter'   : [True, validate_bool], # use internal plotter
    67     'scantable.verbosesummary'   : [False, validate_bool]
     65    'scantable.allaxes'   : [True, _validate_bool],  # apply action to all axes
     66    'scantable.plotter'   : [True, _validate_bool], # use internal plotter
     67    'scantable.verbosesummary'   : [False, _validate_bool]
    6868
    6969    # fitter
     
    115115    'Return the default params updated from the values in the rc file'
    116116   
    117     fname = asap_fname()
     117    fname = _asap_fname()
    118118   
    119119    if fname is None or not os.path.exists(fname):
     
    199199    rcParams.update(rcParamsDefault)
    200200
     201
     202def _is_sequence_or_number(param, ptype=int):
     203    if isinstance(param,tuple) or isinstance(param,list):
     204        out = True
     205        for p in param:
     206            out &= isinstance(p,ptype)
     207        return out
     208    elif isinstance(param, ptype):
     209        return True
     210    return False
     211
    201212from asapfitter import *
    202213from asapreader import reader
     
    221232
    222233__date__ = '$Date$'
    223 __version__  = '0.2'
     234__version__  = '0.9'
    224235
    225236def list_scans(t = scantable):
     
    253264            get_time        - get the timestamps of the integrations
    254265            get_unit        - get the currnt unit
    255             set_unit        - set the abcissa unit to be used from this point on
     266            set_unit        - set the abcissa unit to be used from this
     267                              point on
    256268            get_abcissa     - get the abcissa values and name for a given
    257269                              row (time)
     
    273285            nbeam,nif,nchan,npol - the number of beams/IFs/Pols/Chans
    274286            history         - print the history of the scantable
    275     [Math]
    276         average_time       - return the (weighted) time average of a scan
    277                              or a list of scans
    278         average_pol         - average the polarisations together.
     287
     288            average_time    - return the (weighted) time average of a scan
     289                              or a list of scans
     290            average_pol     - average the polarisations together.
    279291                              The dimension won't be reduced and
    280292                              all polarisations will contain the
    281293                              averaged spectrum.
    282         quotient            - return the on/off quotient
    283         simple_math         - simple mathematical operations on two scantables,
     294            quotient        - return the on/off quotient
     295            scale           - return a scan scaled by a given factor
     296            add             - return a scan with given value added
     297            bin             - return a scan with binned channels
     298            resample        - return a scan with resampled channels
     299            smooth          - return the spectrally smoothed scan
     300            poly_baseline   - fit a polynomial baseline to all Beams/IFs/Pols
     301            gain_el         - apply gain-elevation correction
     302            opacity         - apply opacity correction
     303            convert_flux    - convert to and from Jy and Kelvin brightness
     304                              units
     305            freq_align      - align spectra in frequency frame
     306            rotate_xyphase  - rotate XY phase of cross correlation
     307            rotate_linpolphase - rotate the phase of the complex
     308                                 polarization O=Q+iU correlation
     309     [Math] Mainly functions which operate on more than one scantable
     310
     311            average_time    - return the (weighted) time average
     312                              of a list of scans
     313            quotient        - return the on/off quotient
     314            simple_math     - simple mathematical operations on two scantables,
    284315                              'add', 'sub', 'mul', 'div'
    285         scale               - return a scan scaled by a given factor
    286         add                 - return a scan with given value added
    287         bin                 - return a scan with binned channels
    288         resample            - return a scan with resampled channels
    289         smooth              - return the spectrally smoothed scan
    290         poly_baseline       - fit a polynomial baseline to all Beams/IFs/Pols
    291         auto_poly_baseline  - automatically fit a polynomial baseline
    292         gain_el             - apply gain-elevation correction
    293         opacity             - apply opacity correction
    294         convert_flux        - convert to and from Jy and Kelvin brightness
    295                               units
    296         freq_align          - align spectra in frequency frame
    297         rotate_xyphase      - rotate XY phase of cross correlation
    298 
     316     [Fitting]
    299317        fitter
    300318            auto_fit        - return a scan where the function is
     
    308326            set_parameters  - set the parameters for the function(s), and
    309327                              set if they should be held fixed during fitting
     328            set_gauss_parameters - same as above but specialised for individual
     329                                   gaussian components
    310330            get_parameters  - get the fitted parameters
     331            plot            - plot the resulting fit and/or components and
     332                              residual
    311333    [Plotter]
    312334        asapplotter         - a plotter for asap, default plotter is
  • trunk/python/asapmath.py

    r509 r513  
    6060                          remove   - Output = Tref * (sig/ref) - Tsig
    6161    """
     62    varlist = vars()
    6263    from asap._asap import quotient as _quot
    63     return scantable(_quot(source, reference, preserve))
     64    s = scantable(_quot(source, reference, preserve))
     65    s._add_history("quotient",varlist)
     66    return s
    6467
    6568def simple_math(left, right, op='add', tsys=True):
     
    8487    s._add_history("simple_math", varlist)
    8588    return s
    86 
    87 def scale(scan, factor, insitu=None, allaxes=None, tsys=True):
    88     """
    89     Return a scan where all spectra are scaled by the give 'factor'
    90     Parameters:
    91         scan:        a scantable
    92         factor:      the scaling factor
    93         insitu:      if False a new scantable is returned.
    94                      Otherwise, the scaling is done in-situ
    95                      The default is taken from .asaprc (False)
    96         allaxes:     if True apply to all spectra. Otherwise
    97                      apply only to the selected (beam/pol/if)spectra only.
    98                      The default is taken from .asaprc (True if none)
    99         tsys:        if True (default) then apply the operation to Tsys
    100                      as well as the data
    101     """
    102     if allaxes is None: allaxes = rcParams['scantable.allaxes']
    103     if insitu is None: insitu = rcParams['insitu']
    104     varlist = vars()
    105     if not insitu:
    106         from asap._asap import scale as _scale
    107         s = scantable(_scale(scan, factor, allaxes, tsys))
    108         s._add_history("scale",varlist)
    109         return s
    110     else:
    111         from asap._asap import scale_insitu as _scale
    112         _scale(scan, factor, allaxes, tsys)
    113         scan._add_history("scale",varlist)
    114         return
    115        
    116 def add(scan, offset, insitu=None, allaxes=None):
    117     """
    118     Return a scan where all spectra have the offset added
    119     Parameters:
    120         scan:        a scantable
    121         offset:      the offset
    122         insitu:      if False a new scantable is returned.
    123                      Otherwise, the scaling is done in-situ
    124                      The default is taken from .asaprc (False)
    125         allaxes:     if True apply to all spectra. Otherwise
    126                      apply only to the selected (beam/pol/if)spectra only
    127                      The default is taken from .asaprc (True if none)
    128     """
    129     if allaxes is None: allaxes = rcParams['scantable.allaxes']
    130     if insitu is None: insitu = rcParams['insitu']
    131     if not insitu:
    132         from asap._asap import add as _add
    133         return scantable(_add(scan, offset, allaxes))
    134     else:
    135         from asap._asap import add_insitu as _add
    136         _add(scan, offset, allaxes)
    137         return
    138        
    139 def convert_flux(scan, jyperk=None, eta=None, d=None, insitu=None,
    140                  allaxes=None):
    141     """
    142     Return a scan where all spectra are converted to either Jansky or Kelvin
    143         depending upon the flux units of the scan table.  By default the
    144         function tries to look the values up internally. If it can't find
    145         them (or if you want to over-ride), you must specify EITHER jyperk
    146         OR eta (and D which it will try to look up also if you don't
    147         set it).  jyperk takes precedence if you set both.
    148     Parameters:
    149         scan:        a scantable
    150         jyperk:      the Jy / K conversion factor
    151         eta:         the aperture efficiency 
    152         d:           the geomtric diameter (metres)
    153         insitu:      if False a new scantable is returned.
    154                      Otherwise, the scaling is done in-situ
    155                      The default is taken from .asaprc (False)
    156         allaxes:         if True apply to all spectra. Otherwise
    157                      apply only to the selected (beam/pol/if)spectra only
    158                      The default is taken from .asaprc (True if none)
    159     """
    160     if allaxes is None: allaxes = rcParams['scantable.allaxes']
    161     if insitu is None: insitu = rcParams['insitu']
    162     varlist = vars()
    163     if jyperk is None: jyperk = -1.0
    164     if d is None: d = -1.0
    165     if eta is None: eta = -1.0
    166     if not insitu:
    167         from asap._asap import convertflux as _convert
    168         s = scantable(_convert(scan, d, eta, jyperk, allaxes))
    169         s._add_history("convert_flux", varlist)
    170         return s
    171     else:
    172         from asap._asap import convertflux_insitu as _convert
    173         _convert(scan, d, eta, jyperk, allaxes)
    174         scan._add_history("convert_flux", varlist)
    175         return
    176 
    177 def gain_el(scan, poly=None, filename="", method="linear",
    178             insitu=None, allaxes=None):
    179     """
    180     Return a scan after applying a gain-elevation correction. The correction
    181     can be made via either a polynomial or a table-based interpolation
    182     (and extrapolation if necessary).
    183     You specify polynomial coefficients, an ascii table or neither.
    184     If you specify neither, then a polynomial correction will be made
    185     with built in coefficients known for certain telescopes (an error will
    186     occur if the instrument is not known).   The data and Tsys are *divided*
    187     by the scaling factors.
    188     Parameters:
    189         scan:        a scantable
    190         poly:        Polynomial coefficients (default None) to compute a
    191                      gain-elevation correction as a function of
    192                      elevation (in degrees).
    193         filename:    The name of an ascii file holding correction factors.
    194                      The first row of the ascii file must give the column
    195                      names and these MUST include columns
    196                      "ELEVATION" (degrees) and "FACTOR" (multiply data by this)
    197                      somewhere.
    198                      The second row must give the data type of the column. Use
    199                      'R' for Real and 'I' for Integer.  An example file
    200                      would be (actual factors are arbitrary) :
    201 
    202                      TIME ELEVATION FACTOR
    203                      R R R
    204                      0.1 0 0.8
    205                      0.2 20 0.85
    206                      0.3 40 0.9
    207                      0.4 60 0.85
    208                      0.5 80 0.8
    209                      0.6 90 0.75
    210         method:      Interpolation method when correcting from a table. Values
    211                      are  "nearest", "linear" (default), "cubic" and "spline"
    212         insitu:      if False a new scantable is returned.
    213                      Otherwise, the scaling is done in-situ
    214                      The default is taken from .asaprc (False)
    215         allaxes:         if True apply to all spectra. Otherwise
    216                      apply only to the selected (beam/pol/if) spectra only
    217                      The default is taken from .asaprc (True if none)
    218     """
    219     if allaxes is None: allaxes = rcParams['scantable.allaxes']
    220     if insitu is None: insitu = rcParams['insitu']
    221     varlist = vars()
    222     if poly is None:
    223        poly = ()
    224     from os.path import expandvars
    225     filename = expandvars(filename)
    226     if not insitu:
    227         from asap._asap import gainel as _gainEl
    228         s = scantable(_gainEl(scan, poly, filename, method, allaxes))
    229         s._add_history("gain_el", varlist)
    230         return s
    231     else:
    232         from asap._asap import gainel_insitu as _gainEl
    233         _gainEl(scan, poly, filename, method, allaxes)
    234         scan._add_history("gain_el", varlist)
    235         return
    236        
    237 def freq_align(scan, reftime=None, method='cubic', perif=False, insitu=None):
    238     """
    239         Return a scan where all rows have been aligned in frequency/velocity.
    240         The alignment frequency frame (e.g. LSRK) is that set by function
    241         set_freqframe. 
    242         scan:        a scantable
    243         reftime:     reference time to align at. By default, the time of
    244                      the first row of data is used. 
    245         method:      Interpolation method for regridding the spectra. Choose
    246                      from "nearest", "linear", "cubic" (default) and "spline"
    247         perif:       Generate aligners per freqID (no doppler tracking) or
    248                      per IF (scan-based doppler tracking)
    249         insitu:      if False a new scantable is returned.
    250                      Otherwise, the scaling is done in-situ
    251                      The default is taken from .asaprc (False)
    252     """
    253     if insitu is None: insitu = rcParams['insitu']
    254     varlist = vars()
    255     if reftime is None: reftime = ''
    256     perfreqid = not perif
    257     if not insitu:
    258         from asap._asap import freq_align as _align
    259         s = scantable(_align(scan, reftime, method, perfreqid))
    260         s._add_history("freq_align", varlist)
    261         return s
    262     else:
    263         from asap._asap import freq_align_insitu as _align
    264         _align(scan, reftime, method, perfreqid)
    265         scan._add_history("freq_align", varlist)
    266         return
    267        
    268 def opacity(scan, tau, insitu=None, allaxes=None):
    269     """
    270     Return a scan after applying an opacity correction. The data
    271     and Tsys are multiplied by the correction factor.
    272     Parameters:
    273         scan:        a scantable
    274         tau:         Opacity from which the correction factor is exp(tau*ZD)
    275                      where ZD is the zenith-distance
    276         insitu:      if False a new scantable is returned.
    277                      Otherwise, the scaling is done in-situ
    278                      The default is taken from .asaprc (False)
    279         allaxes:     if True apply to all spectra. Otherwise
    280                      apply only to the selected (beam/pol/if)spectra only
    281                      The default is taken from .asaprc (True if none)
    282     """
    283     if allaxes is None: allaxes = rcParams['scantable.allaxes']
    284     if insitu is None: insitu = rcParams['insitu']
    285     varlist = vars()
    286     if not insitu:
    287         from asap._asap import opacity as _opacity
    288         s = scantable(_opacity(scan, tau, allaxes))
    289         s._add_history("opacity", varlist)
    290         return s
    291     else:
    292         from asap._asap import opacity_insitu as _opacity
    293         _opacity(scan, tau, allaxes)
    294         scan._add_history("opacity", varlist)
    295         return
    296        
    297 def bin(scan, width=5, insitu=None):
    298     """
    299     Return a scan where all spectra have been binned up
    300         width:       The bin width (default=5) in pixels
    301         insitu:      if False a new scantable is returned.
    302                      Otherwise, the scaling is done in-situ
    303                      The default is taken from .asaprc (False)
    304     """
    305     if insitu is None: insitu = rcParams['insitu']
    306     varlist = vars()
    307     if not insitu:
    308         from asap._asap import bin as _bin
    309         s = scantable(_bin(scan, width))
    310         s._add_history("bin",varlist)
    311         return s
    312     else:
    313         from asap._asap import bin_insitu as _bin
    314         _bin(scan, width)
    315         scan._add_history("bin",varlist)
    316         return
    317 
    318 def resample(scan, width=5, method='cubic', insitu=None):
    319     """
    320     Return a scan where all spectra have been binned up
    321         width:       The bin width (default=5) in pixels
    322         method:      Interpolation method when correcting from a table. Values
    323                      are  "nearest", "linear", "cubic" (default) and "spline"
    324         insitu:      if False a new scantable is returned.
    325                      Otherwise, the scaling is done in-situ
    326                      The default is taken from .asaprc (False)
    327     """
    328     if insitu is None: insitu = rcParams['insitu']
    329     varlist = vars()
    330     if not insitu:
    331         from asap._asap import resample as _resample
    332         s = scantable(_resample(scan, method, width))
    333         s._add_history("resample",varlist)
    334         return s
    335     else:
    336         from asap._asap import resample_insitu as _resample
    337         _resample(scan, method, width)
    338         scan._add_history("resample",varlist)
    339         return
    340 
    341 def average_pol(scan, mask=None, weight='none', insitu=None):
    342     """
    343     Average the Polarisations together.
    344     The polarisation cursor of the output scan is set to 0
    345     Parameters:
    346         scan:        The scantable
    347         mask:        An optional mask defining the region, where the
    348                      averaging will be applied. The output will have all
    349                      specified points masked.
    350         weight:      Weighting scheme. 'none' (default), or 'var' (variance
    351                      weighted)
    352         insitu:      if False a new scantable is returned.
    353                      Otherwise, the scaling is done in-situ
    354                      The default is taken from .asaprc (False)
    355     Example:
    356         polav = average_pols(myscan)
    357     """
    358     if insitu is None: insitu = rcParams['insitu']
    359     varlist = vars()
    360 
    361     if mask is None:
    362         mask = ()
    363     if not insitu:
    364         from asap._asap import averagepol as _avpol
    365         s = scantable(_avpol(scan, mask, weight))
    366         s._add_history("average_pol",varlist)
    367         return s
    368     else:
    369         from asap._asap import averagepol_insitu as _avpol
    370         _avpol(scan, mask, weight)
    371         scan._add_history("average_pol",varlist)
    372         return
    373    
    374 def smooth(scan, kernel="hanning", width=5.0, insitu=None, allaxes=None):
    375     """
    376     Smooth the spectrum by the specified kernel (conserving flux).
    377     Parameters:
    378         scan:       The input scan
    379         kernel:     The type of smoothing kernel. Select from
    380                     'hanning' (default), 'gaussian' and 'boxcar'.
    381                     The first three characters are sufficient.
    382         width:      The width of the kernel in pixels. For hanning this is
    383                     ignored otherwise it defauls to 5 pixels.
    384                     For 'gaussian' it is the Full Width Half
    385                     Maximum. For 'boxcar' it is the full width.
    386         insitu:     if False a new scantable is returned.
    387                     Otherwise, the scaling is done in-situ
    388                     The default is taken from .asaprc (False)
    389         allaxes:    If True (default) apply to all spectra. Otherwise
    390                     apply only to the selected (beam/pol/if)spectra only
    391                     The default is taken from .asaprc (True if none)
    392     Example:
    393          none
    394     """
    395     if allaxes is None: allaxes = rcParams['scantable.allaxes']
    396     if insitu is None: insitu = rcParams['insitu']
    397     varlist = vars()
    398     if not insitu:
    399         from asap._asap import smooth as _smooth
    400         s = scantable(_smooth(scan,kernel,width,allaxes))
    401         s._add_history("smooth", varlist)
    402         return s
    403     else:
    404         from asap._asap import smooth_insitu as _smooth
    405         _smooth(scan,kernel,width,allaxes)
    406         scan._add_history("smooth", varlist)
    407         return
    408    
    409 def poly_baseline(scan, mask=None, order=0, insitu=None):
    410     """
    411     Return a scan which has been baselined (all rows) by a polynomial.
    412     Parameters:
    413         scan:    a scantable
    414         mask:    an optional mask
    415         order:   the order of the polynomial (default is 0)
    416         insitu:      if False a new scantable is returned.
    417                      Otherwise, the scaling is done in-situ
    418                      The default is taken from .asaprc (False)
    419     Example:
    420         # return a scan baselined by a third order polynomial,
    421         # not using a mask
    422         bscan = poly_baseline(scan, order=3)
    423     """
    424     if insitu is None: insitu = rcParams['insitu']
    425     varlist = vars()
    426     from asap.asapfitter import fitter
    427     if mask is None:
    428         from numarray import ones
    429         mask = tuple(ones(scan.nchan()))
    430     f = fitter()
    431     f._verbose(True)
    432     f.set_scan(scan, mask)
    433     f.set_function(poly=order)   
    434     sf = f.auto_fit(insitu)
    435     sf._add_history("poly_baseline", varlist)
    436     return sf
    437 
    438 def rotate_xyphase(scan, angle, allaxes=None):
    439     """
    440     Rotate the phase of the XY correlation.  This is always done in situ
    441     in the data.  So if you call this function more than once
    442     then each call rotates the phase further.
    443     Parameters:
    444         angle:   The angle (degrees) to rotate (add) by.
    445         allaxes: If True apply to all spectra. Otherwise
    446                  apply only to the selected (beam/pol/if)spectra only.
    447                  The default is taken from .asaprc (True if none)
    448     Examples:
    449         rotate_xyphase(scan, 2.3)
    450     """
    451     if allaxes is None: allaxes = rcParams['scantable.allaxes']
    452     varlist = vars()
    453     from asap._asap import _rotate_xyphase as _rotate
    454     _rotate(scan, angle, allaxes)
    455     scan._add_history("rotate_xyphase", varlist)
    456     return
    457 
    458 def rotate_linpolphase(scan, angle, allaxes=None):
    459     """
    460     Rotate the phase of the complex polarization O=Q+iU correlation. 
    461     This is always done in situ in the raw data.  So if you call this
    462     function more than once then each call rotates the phase further.
    463     Parameters:
    464         angle:   The angle (degrees) to rotate (add) by.
    465         allaxes: If True apply to all spectra. Otherwise
    466                  apply only to the selected (beam/pol/if)spectra only.
    467                  The default is taken from .asaprc (True if none)
    468     Examples:
    469         rotate_linpolphase(scan, 2.3)
    470     """
    471     if allaxes is None: allaxes = rcParams['scantable.allaxes']
    472     varlist = vars()
    473     from asap._asap import _rotate_linpolphase as _rotate
    474     _rotate(scan, angle, allaxes)
    475     scan._add_history("rotate_linpolphase", varlist)
    476     return
    477 
  • trunk/python/scantable.py

    r497 r513  
    6666                if average:
    6767                    from asap._asap import average as _av
    68                     tmp = tuple([tbl])
    6968                    print 'Auto averaging integrations...'
    70                     tbl2 = _av(tmp,(),True,'none')
     69                    tbl2 = _av((tbl,),(),True,'none')
    7170                    sdtable.__init__(self,tbl2)
    72                     del r,tbl
     71                    del tbl2
    7372                else:
    7473                    sdtable.__init__(self,tbl)
     74                del r,tbl
    7575                self._add_history("scantable", varlist)
    7676
     
    138138        source name) in a new scantable.
    139139        Parameters:
    140             scanid:    a scanno or a source name
    141         Example:
    142             scan.get_scan('323p459')
    143             # gets all scans containing the source '323p459'
     140            scanid:    a (list of) scanno or a source name, unix-style
     141                       patterns are accepted for source name matching, e.g.
     142                       '*_R' gets all 'ref scans
     143        Example:
     144            # get all scans containing the source '323p459'
     145            newscan = scan.get_scan('323p459')
     146            # get all 'off' scans
     147            refscans = scan.get_scan('*_R')
     148            # get a susbset of scans by scanno (as listed in scan.summary())
     149            newscan = scan.get_scan([0,2,7,10])
    144150        """
    145151        if scanid is None:
     
    481487                        return an inverted mask, i.e. the regions
    482488                        specified are EXCLUDED
     489            row:        create the mask using the specified row for
     490                        unit conversions, default is row=0
     491                        only necessary if frequency varies over rows.
    483492        Example:
    484493            scan.set_unit('channel')
     
    495504           
    496505        """
    497         varlist = vars()
     506        row = 0
     507        if kwargs.has_key("row"):
     508            row = kwargs.get("row")
     509        data = self._getabcissa(row)
    498510        u = self._getcoordinfo()[0]
    499511        if self._vb:
     
    501513            print "The current mask window unit is", u
    502514        n = self.nchan()
    503         data = self._getabcissa()
    504515        msk = zeros(n)
    505516        for window in args:
     
    513524            if kwargs.get('invert'):
    514525                from numarray import logical_not
    515                 msk = logical_not(msk)
    516         self._add_history("create_mask", varlist)
     526                msk = logical_not(msk)           
    517527        return msk
    518528   
     
    730740        return
    731741
     742    #
     743    # Maths business
     744    #
     745
     746    def average_time(self, mask=None, scanav=True, weight=None):
     747        """
     748        Return the (time) average of a scan, or apply it 'insitu'.
     749        Note:
     750            in channels only
     751            The cursor of the output scan is set to 0.
     752        Parameters:
     753            one scan or comma separated  scans
     754            mask:     an optional mask (only used for 'var' and 'tsys'
     755                      weighting)
     756            scanav:   True (default) averages each scan separately
     757                      False averages all scans together,
     758            weight:   Weighting scheme. 'none' (default), 'var' (variance
     759                      weighted), 'tsys'
     760
     761        Example:
     762            # time average the scantable without using a mask
     763            newscan = scan.average_time()           
     764        """
     765        varlist = vars()
     766        if weight is None: weight = 'none'
     767        if mask is None: mask = ()
     768        from asap._asap import average as _av       
     769        s = scantable(_av((self,), mask, scanav, weight))
     770        s._add_history("average_time",varlist)
     771        return s
     772       
     773    def convert_flux(self, jyperk=None, eta=None, d=None, insitu=None,
     774                     allaxes=None):
     775        """
     776        Return a scan where all spectra are converted to either
     777        Jansky or Kelvin depending upon the flux units of the scan table.
     778        By default the function tries to look the values up internally.
     779        If it can't find them (or if you want to over-ride), you must
     780        specify EITHER jyperk OR eta (and D which it will try to look up
     781        also if you don't set it). jyperk takes precedence if you set both.
     782        Parameters:
     783            jyperk:      the Jy / K conversion factor
     784            eta:         the aperture efficiency
     785            d:           the geomtric diameter (metres)
     786            insitu:      if False a new scantable is returned.
     787                         Otherwise, the scaling is done in-situ
     788                         The default is taken from .asaprc (False)
     789            allaxes:         if True apply to all spectra. Otherwise
     790                         apply only to the selected (beam/pol/if)spectra only
     791                         The default is taken from .asaprc (True if none)
     792        """
     793        if allaxes is None: allaxes = rcParams['scantable.allaxes']
     794        if insitu is None: insitu = rcParams['insitu']
     795        varlist = vars()
     796        if jyperk is None: jyperk = -1.0
     797        if d is None: d = -1.0
     798        if eta is None: eta = -1.0
     799        if not insitu:
     800            from asap._asap import convertflux as _convert
     801            s = scantable(_convert(self, d, eta, jyperk, allaxes))
     802            s._add_history("convert_flux", varlist)
     803            return s
     804        else:
     805            from asap._asap import convertflux_insitu as _convert
     806            _convert(self, d, eta, jyperk, allaxes)
     807            self._add_history("convert_flux", varlist)
     808            return
     809
     810    def gain_el(self, poly=None, filename="", method="linear",
     811                insitu=None, allaxes=None):
     812        """
     813        Return a scan after applying a gain-elevation correction.
     814        The correction can be made via either a polynomial or a
     815        table-based interpolation (and extrapolation if necessary).
     816        You specify polynomial coefficients, an ascii table or neither.
     817        If you specify neither, then a polynomial correction will be made
     818        with built in coefficients known for certain telescopes (an error
     819        will occur if the instrument is not known).
     820        The data and Tsys are *divided* by the scaling factors.
     821        Parameters:
     822            poly:        Polynomial coefficients (default None) to compute a
     823                         gain-elevation correction as a function of
     824                         elevation (in degrees).
     825            filename:    The name of an ascii file holding correction factors.
     826                         The first row of the ascii file must give the column
     827                         names and these MUST include columns
     828                         "ELEVATION" (degrees) and "FACTOR" (multiply data
     829                         by this) somewhere.
     830                         The second row must give the data type of the
     831                         column. Use 'R' for Real and 'I' for Integer.
     832                         An example file would be
     833                         (actual factors are arbitrary) :
     834
     835                         TIME ELEVATION FACTOR
     836                         R R R
     837                         0.1 0 0.8
     838                         0.2 20 0.85
     839                         0.3 40 0.9
     840                         0.4 60 0.85
     841                         0.5 80 0.8
     842                         0.6 90 0.75
     843            method:      Interpolation method when correcting from a table.
     844                         Values are  "nearest", "linear" (default), "cubic"
     845                         and "spline"
     846            insitu:      if False a new scantable is returned.
     847                         Otherwise, the scaling is done in-situ
     848                         The default is taken from .asaprc (False)
     849            allaxes:     If True apply to all spectra. Otherwise
     850                         apply only to the selected (beam/pol/if) spectra only
     851                         The default is taken from .asaprc (True if none)
     852        """
     853
     854        if allaxes is None: allaxes = rcParams['scantable.allaxes']
     855        if insitu is None: insitu = rcParams['insitu']
     856        varlist = vars()
     857        if poly is None:
     858           poly = ()
     859        from os.path import expandvars
     860        filename = expandvars(filename)
     861        if not insitu:
     862            from asap._asap import gainel as _gainEl
     863            s = scantable(_gainEl(self, poly, filename, method, allaxes))
     864            s._add_history("gain_el", varlist)
     865            return s
     866        else:
     867            from asap._asap import gainel_insitu as _gainEl
     868            _gainEl(self, poly, filename, method, allaxes)
     869            self._add_history("gain_el", varlist)
     870            return
     871   
     872    def freq_align(self, reftime=None, method='cubic', perif=False,
     873                   insitu=None):
     874        """
     875        Return a scan where all rows have been aligned in frequency/velocity.
     876        The alignment frequency frame (e.g. LSRK) is that set by function
     877        set_freqframe.
     878        Parameters:
     879            reftime:     reference time to align at. By default, the time of
     880                         the first row of data is used.
     881            method:      Interpolation method for regridding the spectra.
     882                         Choose from "nearest", "linear", "cubic" (default)
     883                         and "spline"
     884            perif:       Generate aligners per freqID (no doppler tracking) or
     885                         per IF (scan-based doppler tracking)
     886            insitu:      if False a new scantable is returned.
     887                         Otherwise, the scaling is done in-situ
     888                         The default is taken from .asaprc (False)
     889        """
     890        if insitu is None: insitu = rcParams['insitu']
     891        varlist = vars()
     892        if reftime is None: reftime = ''
     893        perfreqid = not perif
     894        if not insitu:
     895            from asap._asap import freq_align as _align
     896            s = scantable(_align(self, reftime, method, perfreqid))
     897            s._add_history("freq_align", varlist)
     898            return s
     899        else:
     900            from asap._asap import freq_align_insitu as _align
     901            _align(self, reftime, method, perfreqid)
     902            self._add_history("freq_align", varlist)
     903            return
     904
     905    def opacity(self, tau, insitu=None, allaxes=None):
     906        """
     907        Apply an opacity correction. The data
     908        and Tsys are multiplied by the correction factor.
     909        Parameters:
     910            tau:         Opacity from which the correction factor is
     911                         exp(tau*ZD)
     912                         where ZD is the zenith-distance
     913            insitu:      if False a new scantable is returned.
     914                         Otherwise, the scaling is done in-situ
     915                         The default is taken from .asaprc (False)
     916            allaxes:     if True apply to all spectra. Otherwise
     917                         apply only to the selected (beam/pol/if)spectra only
     918                         The default is taken from .asaprc (True if none)
     919        """
     920        if allaxes is None: allaxes = rcParams['scantable.allaxes']
     921        if insitu is None: insitu = rcParams['insitu']
     922        varlist = vars()
     923        if not insitu:
     924            from asap._asap import opacity as _opacity
     925            s = scantable(_opacity(self, tau, allaxes))
     926            s._add_history("opacity", varlist)
     927            return s
     928        else:
     929            from asap._asap import opacity_insitu as _opacity
     930            _opacity(self, tau, allaxes)
     931            self._add_history("opacity", varlist)
     932            return
     933
     934    def bin(self, width=5, insitu=None):
     935        """
     936        Return a scan where all spectra have been binned up.
     937            width:       The bin width (default=5) in pixels
     938            insitu:      if False a new scantable is returned.
     939                         Otherwise, the scaling is done in-situ
     940                         The default is taken from .asaprc (False)
     941        """
     942        if insitu is None: insitu = rcParams['insitu']
     943        varlist = vars()
     944        if not insitu:
     945            from asap._asap import bin as _bin
     946            s = scantable(_bin(self, width))
     947            s._add_history("bin",varlist)
     948            return s
     949        else:
     950            from asap._asap import bin_insitu as _bin
     951            _bin(self, width)
     952            self._add_history("bin",varlist)
     953            return
     954
     955   
     956    def resample(self, width=5, method='cubic', insitu=None):
     957        """
     958        Return a scan where all spectra have been binned up
     959            width:       The bin width (default=5) in pixels
     960            method:      Interpolation method when correcting from a table.
     961                         Values are  "nearest", "linear", "cubic" (default)
     962                         and "spline"
     963            insitu:      if False a new scantable is returned.
     964                         Otherwise, the scaling is done in-situ
     965                         The default is taken from .asaprc (False)
     966        """
     967        if insitu is None: insitu = rcParams['insitu']
     968        varlist = vars()
     969        if not insitu:
     970            from asap._asap import resample as _resample
     971            s = scantable(_resample(self, method, width))
     972            s._add_history("resample",varlist)
     973            return s
     974        else:
     975            from asap._asap import resample_insitu as _resample
     976            _resample(self, method, width)
     977            self._add_history("resample",varlist)
     978            return
     979
     980    def average_pol(self, mask=None, weight='none', insitu=None):
     981        """
     982        Average the Polarisations together.
     983        The polarisation cursor of the output scan is set to 0
     984        Parameters:
     985            scan:        The scantable
     986            mask:        An optional mask defining the region, where the
     987                         averaging will be applied. The output will have all
     988                         specified points masked.
     989            weight:      Weighting scheme. 'none' (default), or
     990                         'var' (variance weighted)
     991            insitu:      if False a new scantable is returned.
     992                         Otherwise, the scaling is done in-situ
     993                         The default is taken from .asaprc (False)
     994        Example:
     995            polav = average_pols(myscan)
     996        """
     997        if insitu is None: insitu = rcParams['insitu']
     998        varlist = vars()
     999
     1000        if mask is None:
     1001            mask = ()
     1002        if not insitu:
     1003            from asap._asap import averagepol as _avpol
     1004            s = scantable(_avpol(self, mask, weight))
     1005            s._add_history("average_pol",varlist)
     1006            return s
     1007        else:
     1008            from asap._asap import averagepol_insitu as _avpol
     1009            _avpol(self, mask, weight)
     1010            self._add_history("average_pol",varlist)
     1011            return
     1012
     1013    def smooth(self, kernel="hanning", width=5.0, insitu=None, allaxes=None):
     1014        """
     1015        Smooth the spectrum by the specified kernel (conserving flux).
     1016        Parameters:
     1017            scan:       The input scan
     1018            kernel:     The type of smoothing kernel. Select from
     1019                        'hanning' (default), 'gaussian' and 'boxcar'.
     1020                        The first three characters are sufficient.
     1021            width:      The width of the kernel in pixels. For hanning this is
     1022                        ignored otherwise it defauls to 5 pixels.
     1023                        For 'gaussian' it is the Full Width Half
     1024                        Maximum. For 'boxcar' it is the full width.
     1025            insitu:     if False a new scantable is returned.
     1026                        Otherwise, the scaling is done in-situ
     1027                        The default is taken from .asaprc (False)
     1028            allaxes:    If True (default) apply to all spectra. Otherwise
     1029                        apply only to the selected (beam/pol/if)spectra only
     1030                        The default is taken from .asaprc (True if none)
     1031        Example:
     1032             none
     1033        """
     1034        if allaxes is None: allaxes = rcParams['scantable.allaxes']
     1035        if insitu is None: insitu = rcParams['insitu']
     1036        varlist = vars()
     1037        if not insitu:
     1038            from asap._asap import smooth as _smooth
     1039            s = scantable(_smooth(self,kernel,width,allaxes))
     1040            s._add_history("smooth", varlist)
     1041            return s
     1042        else:
     1043            from asap._asap import smooth_insitu as _smooth
     1044            _smooth(self,kernel,width,allaxes)
     1045            self._add_history("smooth", varlist)
     1046            return
     1047
     1048    def poly_baseline(self, mask=None, order=0, insitu=None):
     1049        """
     1050        Return a scan which has been baselined (all rows) by a polynomial.
     1051        Parameters:
     1052            scan:    a scantable
     1053            mask:    an optional mask
     1054            order:   the order of the polynomial (default is 0)
     1055            insitu:      if False a new scantable is returned.
     1056                         Otherwise, the scaling is done in-situ
     1057                         The default is taken from .asaprc (False)
     1058        Example:
     1059            # return a scan baselined by a third order polynomial,
     1060            # not using a mask
     1061            bscan = scan.poly_baseline(order=3)
     1062        """
     1063        if insitu is None: insitu = rcParams['insitu']
     1064        varlist = vars()
     1065        if mask is None:
     1066            from numarray import ones
     1067            mask = list(ones(scan.nchan()))
     1068        from asap.asapfitter import fitter
     1069        f = fitter()
     1070        f._verbose(True)
     1071        f.set_scan(self, mask)
     1072        f.set_function(poly=order)
     1073        sf = f.auto_fit(insitu)
     1074        if insitu:
     1075            self._add_history("poly_baseline", varlist)
     1076            return
     1077        else:
     1078            sf._add_history("poly_baseline", varlist)
     1079            return sf
     1080
     1081    def auto_poly_baseline(self, mask=None, edge=(0,0), order=0,
     1082                           threshold=3,insitu=None):
     1083        """
     1084        Return a scan which has been baselined (all rows) by a polynomial.
     1085        Spectral lines are detected first using linefinder and masked out
     1086        to avoid them affecting the baseline solution.
     1087
     1088        Parameters:
     1089            scan:    a scantable
     1090            mask:       an optional mask retreived from scantable
     1091            edge:       an optional number of channel to drop at
     1092                        the edge of spectrum. If only one value is
     1093                        specified, the same number will be dropped from
     1094                        both sides of the spectrum. Default is to keep
     1095                        all channels
     1096            order:      the order of the polynomial (default is 0)
     1097            threshold:  the threshold used by line finder. It is better to
     1098                        keep it large as only strong lines affect the
     1099                        baseline solution.
     1100            insitu:     if False a new scantable is returned.
     1101                        Otherwise, the scaling is done in-situ
     1102                        The default is taken from .asaprc (False)
     1103
     1104        Example:
     1105            sc2=auto_poly_baseline(order=7)
     1106        """
     1107        if insitu is None: insitu = rcParams['insitu']
     1108        varlist = vars()
     1109        from asap.asapfitter import fitter
     1110        from asap.asaplinefind import linefinder
     1111        from asap import _is_sequence_or_number as _is_valid
     1112       
     1113        if not _is_valid(edge, int):
     1114            print "Parameter 'edge' as to be an integer or a pair of integers"
     1115            return
     1116       
     1117        # setup fitter
     1118        f = fitter()
     1119        f._verbose(True)
     1120        f.set_function(poly=order)
     1121
     1122        # setup line finder
     1123        fl=linefinder()
     1124        fl.set_options(threshold=threshold)
     1125
     1126        if not insitu:
     1127            workscan=self.copy()
     1128        else:
     1129            workscan=self
     1130
     1131        vb=workscan._vb
     1132        # remember the verbose parameter and selection
     1133        workscan._vb=False
     1134        sel=workscan.get_cursor()
     1135        rows=range(workscan.nrow())
     1136        for i in range(workscan.nbeam()):
     1137            workscan.setbeam(i)
     1138            for j in range(workscan.nif()):
     1139                workscan.setif(j)
     1140                for k in range(workscan.npol()):
     1141                    workscan.setpol(k)
     1142                    if f._vb:
     1143                       print "Processing:"
     1144                       print 'Beam[%d], IF[%d], Pol[%d]' % (i,j,k)
     1145                    for iRow in rows:
     1146                       fl.set_scan(workscan,mask,edge)
     1147                       fl.find_lines(iRow)
     1148                       f.set_scan(workscan, fl.get_mask())
     1149                       f.x=workscan._getabcissa(iRow)
     1150                       f.y=workscan._getspectrum(iRow)
     1151                       f.data=None
     1152                       f.fit()
     1153                       x=f.get_parameters()
     1154                       workscan._setspectrum(f.fitter.getresidual(),iRow)
     1155        workscan.set_cursor(sel[0],sel[1],sel[2])
     1156        workscan._vb = vb
     1157        if not insitu:
     1158           return workscan
     1159
     1160    def rotate_linpolphase(self, angle, allaxes=None):
     1161        """
     1162        Rotate the phase of the complex polarization O=Q+iU correlation. 
     1163        This is always done in situ in the raw data.  So if you call this
     1164        function more than once then each call rotates the phase further.
     1165        Parameters:
     1166            angle:   The angle (degrees) to rotate (add) by.
     1167            allaxes: If True apply to all spectra. Otherwise
     1168                     apply only to the selected (beam/pol/if)spectra only.
     1169                     The default is taken from .asaprc (True if none)
     1170        Examples:
     1171            scan.rotate_linpolphase(2.3)
     1172    """
     1173        if allaxes is None: allaxes = rcParams['scantable.allaxes']
     1174        varlist = vars()
     1175        from asap._asap import _rotate_linpolphase as _rotate
     1176        _rotate(self, angle, allaxes)
     1177        self._add_history("rotate_linpolphase", varlist)
     1178        return
     1179   
     1180
     1181    def rotate_xyphase(self, angle, allaxes=None):
     1182        """
     1183        Rotate the phase of the XY correlation.  This is always done in situ
     1184        in the data.  So if you call this function more than once
     1185        then each call rotates the phase further.
     1186        Parameters:
     1187            angle:   The angle (degrees) to rotate (add) by.
     1188            allaxes: If True apply to all spectra. Otherwise
     1189                     apply only to the selected (beam/pol/if)spectra only.
     1190                     The default is taken from .asaprc (True if none)
     1191        Examples:
     1192            scan.rotate_xyphase(2.3)
     1193        """
     1194        if allaxes is None: allaxes = rcParams['scantable.allaxes']
     1195        varlist = vars()
     1196        from asap._asap import rotate_xyphase as _rotate_xyphase
     1197        _rotate_xyphase(self, angle, allaxes)
     1198        self._add_history("rotate_xyphase", varlist)
     1199        return
     1200
     1201
     1202    def add(self, offset, insitu=None, allaxes=None):
     1203        """
     1204        Return a scan where all spectra have the offset added
     1205        Parameters:
     1206            offset:      the offset
     1207            insitu:      if False a new scantable is returned.
     1208                         Otherwise, the scaling is done in-situ
     1209                         The default is taken from .asaprc (False)
     1210            allaxes:     if True apply to all spectra. Otherwise
     1211                         apply only to the selected (beam/pol/if)spectra only
     1212                         The default is taken from .asaprc (True if none)
     1213        """
     1214        if allaxes is None: allaxes = rcParams['scantable.allaxes']
     1215        if insitu is None: insitu = rcParams['insitu']
     1216        varlist = vars()
     1217        if not insitu:
     1218            from asap._asap import add as _add
     1219            s = scantable(_add(self, offset, allaxes))
     1220            s._add_history("add",varlist)
     1221            return s
     1222        else:
     1223            from asap._asap import add_insitu as _add
     1224            _add(self, offset, allaxes)
     1225            self._add_history("add",varlist)
     1226            return
     1227
     1228    def scale(self, factor, insitu=None, allaxes=None, tsys=True):
     1229        """
     1230        Return a scan where all spectra are scaled by the give 'factor'
     1231        Parameters:
     1232            factor:      the scaling factor
     1233            insitu:      if False a new scantable is returned.
     1234                         Otherwise, the scaling is done in-situ
     1235                         The default is taken from .asaprc (False)
     1236            allaxes:     if True apply to all spectra. Otherwise
     1237                         apply only to the selected (beam/pol/if)spectra only.
     1238                         The default is taken from .asaprc (True if none)
     1239            tsys:        if True (default) then apply the operation to Tsys
     1240                         as well as the data
     1241        """
     1242        if allaxes is None: allaxes = rcParams['scantable.allaxes']
     1243        if insitu is None: insitu = rcParams['insitu']
     1244        varlist = vars()
     1245        if not insitu:
     1246            from asap._asap import scale as _scale
     1247            s = scantable(_scale(self, factor, allaxes, tsys))
     1248            s._add_history("scale",varlist)
     1249            return s
     1250        else:
     1251            from asap._asap import scale_insitu as _scale
     1252            _scale(self, factor, allaxes, tsys)
     1253            self._add_history("scale",varlist)
     1254            return
     1255
     1256
     1257    def quotient(self, other, isreference=True, preserve=True):
     1258        """
     1259        Return the quotient of a 'source' (signal) scan and a 'reference' scan.
     1260        The reference can have just one row, even if the signal has many.
     1261        Otherwise they must have the same number of rows.
     1262        The cursor of the output scan is set to 0
     1263        Parameters:
     1264            source:         the 'other' scan
     1265            isreference:    if the 'other' scan is the reference (default)
     1266                            or source
     1267            preserve:       you can preserve (default) the continuum or
     1268                            remove it.  The equations used are
     1269                            preserve - Output = Tref * (sig/ref) - Tref
     1270                            remove   - Output = Tref * (sig/ref) - Tsig
     1271        Example:
     1272            # src is a scantable for an 'on' scan, ref for an 'off' scantable
     1273            q1 = src.quotient(ref)
     1274            q2 = ref.quotient(src, isreference=False)
     1275            # gives the same result
     1276        """
     1277        from asap._asap import quotient as _quot
     1278        if isreference:
     1279            return scantable(_quot(self, other, preserve))
     1280        else:
     1281            return scantable(_quot(other, self, preserve))
     1282
     1283    def __add__(self, other):
     1284        varlist = vars()
     1285        s = None
     1286        if isinstance(other, scantable):
     1287            from asap._asap import b_operate as _bop           
     1288            s = scantable(_bop(self, other, 'add', True))
     1289        elif isinstance(other, float):
     1290            from asap._asap import add as _add
     1291            s = scantable(_add(self, other, True))
     1292        else:
     1293            print "Other input is not a scantable or float value"
     1294            return
     1295        s._add_history("operator +", varlist)
     1296        return s
     1297
     1298
     1299    def __sub__(self, other):
     1300        """
     1301        implicit on all axes and on Tsys
     1302        """
     1303        varlist = vars()
     1304        s = None
     1305        if isinstance(other, scantable):
     1306            from asap._asap import b_operate as _bop           
     1307            s = scantable(_bop(self, other, 'sub', True))
     1308        elif isinstance(other, float):
     1309            from asap._asap import add as _add
     1310            s = scantable(_add(self, -other, True))
     1311        else:
     1312            print "Other input is not a scantable or float value"
     1313            return
     1314        s._add_history("operator -", varlist)
     1315        return s
     1316   
     1317    def __mul__(self, other):
     1318        """
     1319        implicit on all axes and on Tsys
     1320        """
     1321        varlist = vars()
     1322        s = None
     1323        if isinstance(other, scantable):
     1324            from asap._asap import b_operate as _bop           
     1325            s = scantable(_bop(self, other, 'mul', True))
     1326        elif isinstance(other, float):
     1327            if other == 0.0:
     1328                print "Multiplying by zero is not recommended."
     1329                return
     1330            from asap._asap import scale as _sca
     1331            s = scantable(_sca(self, other, True))
     1332        else:
     1333            print "Other input is not a scantable or float value"
     1334            return
     1335        s._add_history("operator *", varlist)
     1336        return s
     1337   
     1338
     1339    def __div__(self, other):
     1340        """
     1341        implicit on all axes and on Tsys
     1342        """
     1343        varlist = vars()
     1344        s = None
     1345        if isinstance(other, scantable):
     1346            from asap._asap import b_operate as _bop           
     1347            s = scantable(_bop(self, other, 'div', True))
     1348        elif isinstance(other, float):
     1349            if other == 0.0:
     1350                print "Dividing by zero is not recommended"
     1351                return
     1352            from asap._asap import scale as _sca
     1353            s = scantable(_sca(self, 1.0/other, True))
     1354        else:
     1355            print "Other input is not a scantable or float value"
     1356            return
     1357        s._add_history("operator /", varlist)
     1358        return s
     1359
    7321360    def _add_history(self, funcname, parameters):
    7331361        # create date
     
    7461374                        hist += 'scantable'
    7471375                    elif k2 == 'mask':
    748                         hist += str(self._zip_mask(v2))
     1376                        if isinstance(v2,list) or isinstance(v2,tuple):
     1377                            hist += str(self._zip_mask(v2))
     1378                        else:
     1379                            hist += str(v2)
    7491380                    else:
    750                         hist += str(v2)                   
     1381                        hist += str(v2)
    7511382            else:
    7521383                hist += k
     
    7551386                    hist += 'scantable'
    7561387                elif k == 'mask':
    757                     hist += str(self._zip_mask(v))
     1388                    if isinstance(v,list) or isinstance(v,tuple):
     1389                        hist += str(self._zip_mask(v))
     1390                    else:
     1391                        hist += str(v)
    7581392                else:
    7591393                    hist += str(v)
     
    7741408                j = len(mask)               
    7751409            segments.append([i,j])
    776             i = j
     1410            i = j       
    7771411        return segments
Note: See TracChangeset for help on using the changeset viewer.