source: trunk/python/asapmath.py @ 2818

Last change on this file since 2818 was 2818, checked in by Malte Marquarding, 11 years ago

Issue #291: added scantable.set_sourcename to overwrite sourcename to allow freq_align to work. Exposed 'SOURCE' averaging to python api. Added some logging to freq_align refering to the sources it aligns to

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 37.8 KB
Line 
1from asap.scantable import scantable
2from asap.parameters import rcParams
3from asap.logging import asaplog, asaplog_post_dec
4from asap.selector import selector
5from asap.asapplotter import new_asaplot
6from matplotlib import rc as rcp
7
8@asaplog_post_dec
9def average_time(*args, **kwargs):
10    """
11    Return the (time) average of a scan or list of scans. [in channels only]
12    The cursor of the output scan is set to 0
13    Parameters:
14        one scan or comma separated  scans or a list of scans
15        mask:     an optional mask (only used for 'var' and 'tsys' weighting)
16        scanav:   True averages each scan separately.
17                  False (default) averages all scans together,
18        weight:   Weighting scheme.
19                    'none'     (mean no weight)
20                    'var'      (1/var(spec) weighted)
21                    'tsys'     (1/Tsys**2 weighted)
22                    'tint'     (integration time weighted)
23                    'tintsys'  (Tint/Tsys**2)
24                    'median'   ( median averaging)
25        align:    align the spectra in velocity before averaging. It takes
26                  the time of the first spectrum in the first scantable
27                  as reference time.
28        compel:   True forces to average overwrapped IFs.
29    Example:
30        # return a time averaged scan from scana and scanb
31        # without using a mask
32        scanav = average_time(scana,scanb)
33        # or equivalent
34        # scanav = average_time([scana, scanb])
35        # return the (time) averaged scan, i.e. the average of
36        # all correlator cycles
37        scanav = average_time(scan, scanav=True)
38    """
39    scanav = False
40    if kwargs.has_key('scanav'):
41       scanav = kwargs.get('scanav')
42    weight = 'tint'
43    if kwargs.has_key('weight'):
44       weight = kwargs.get('weight')
45    mask = ()
46    if kwargs.has_key('mask'):
47        mask = kwargs.get('mask')
48    align = False
49    if kwargs.has_key('align'):
50        align = kwargs.get('align')
51    compel = False
52    if kwargs.has_key('compel'):
53        compel = kwargs.get('compel')
54    varlist = vars()
55    if isinstance(args[0],list):
56        lst = args[0]
57    elif isinstance(args[0],tuple):
58        lst = list(args[0])
59    else:
60        lst = list(args)
61
62    del varlist["kwargs"]
63    varlist["args"] = "%d scantables" % len(lst)
64    # need special formatting here for history...
65
66    from asap._asap import stmath
67    stm = stmath()
68    for s in lst:
69        if not isinstance(s,scantable):
70            msg = "Please give a list of scantables"
71            raise TypeError(msg)
72    if scanav: scanav = "SCAN"
73    else: scanav = "NONE"
74    alignedlst = []
75    if align:
76        refepoch = lst[0].get_time(0)
77        for scan in lst:
78            alignedlst.append(scan.freq_align(refepoch,insitu=False))
79    else:
80        alignedlst = lst
81    if weight.upper() == 'MEDIAN':
82        # median doesn't support list of scantables - merge first
83        merged = None
84        if len(alignedlst) > 1:
85            merged = merge(alignedlst)
86        else:
87            merged = alignedlst[0]
88        s = scantable(stm._averagechannel(merged, 'MEDIAN', scanav))
89        del merged
90    else:
91        #s = scantable(stm._average(alignedlst, mask, weight.upper(), scanav))
92        s = scantable(stm._new_average(alignedlst, compel, mask,
93                                       weight.upper(), scanav))
94    s._add_history("average_time",varlist)
95
96    return s
97
98@asaplog_post_dec
99def quotient(source, reference, preserve=True):
100    """
101    Return the quotient of a 'source' (signal) scan and a 'reference' scan.
102    The reference can have just one scan, even if the signal has many. Otherwise
103    they must have the same number of scans.
104    The cursor of the output scan is set to 0
105    Parameters:
106        source:        the 'on' scan
107        reference:     the 'off' scan
108        preserve:      you can preserve (default) the continuum or
109                       remove it.  The equations used are
110                       preserve:  Output = Toff * (on/off) - Toff
111                       remove:    Output = Toff * (on/off) - Ton
112    """
113    varlist = vars()
114    from asap._asap import stmath
115    stm = stmath()
116    stm._setinsitu(False)
117    s = scantable(stm._quotient(source, reference, preserve))
118    s._add_history("quotient",varlist)
119    return s
120
121@asaplog_post_dec
122def dototalpower(calon, caloff, tcalval=0.0):
123    """
124    Do calibration for CAL on,off signals.
125    Adopted from GBTIDL dototalpower
126    Parameters:
127        calon:         the 'cal on' subintegration
128        caloff:        the 'cal off' subintegration
129        tcalval:       user supplied Tcal value
130    """
131    varlist = vars()
132    from asap._asap import stmath
133    stm = stmath()
134    stm._setinsitu(False)
135    s = scantable(stm._dototalpower(calon, caloff, tcalval))
136    s._add_history("dototalpower",varlist)
137    return s
138
139@asaplog_post_dec
140def dosigref(sig, ref, smooth, tsysval=0.0, tauval=0.0):
141    """
142    Calculate a quotient (sig-ref/ref * Tsys)
143    Adopted from GBTIDL dosigref
144    Parameters:
145        sig:         on source data
146        ref:         reference data
147        smooth:      width of box car smoothing for reference
148        tsysval:     user specified Tsys (scalar only)
149        tauval:      user specified Tau (required if tsysval is set)
150    """
151    varlist = vars()
152    from asap._asap import stmath
153    stm = stmath()
154    stm._setinsitu(False)
155    s = scantable(stm._dosigref(sig, ref, smooth, tsysval, tauval))
156    s._add_history("dosigref",varlist)
157    return s
158
159@asaplog_post_dec
160def calps(scantab, scannos, smooth=1, tsysval=0.0, tauval=0.0, tcalval=0.0, verify=False):
161    """
162    Calibrate GBT position switched data
163    Adopted from GBTIDL getps
164    Currently calps identify the scans as position switched data if source
165    type enum is pson or psoff. The data must contains 'CAL' signal
166    on/off in each integration. To identify 'CAL' on state, the source type
167    enum of poncal and poffcal need to be present.
168
169    Parameters:
170        scantab:       scantable
171        scannos:       list of scan numbers
172        smooth:        optional box smoothing order for the reference
173                       (default is 1 = no smoothing)
174        tsysval:       optional user specified Tsys (default is 0.0,
175                       use Tsys in the data)
176        tauval:        optional user specified Tau
177        tcalval:       optional user specified Tcal (default is 0.0,
178                       use Tcal value in the data)
179        verify:        Verify calibration if true
180    """
181    varlist = vars()
182    # check for the appropriate data
183##    s = scantab.get_scan('*_ps*')
184##     if s is None:
185##         msg = "The input data appear to contain no position-switch mode data."
186##         raise TypeError(msg)
187    s = scantab.copy()
188    from asap._asap import srctype
189    sel = selector()
190    sel.set_types( srctype.pson )
191    try:
192        scantab.set_selection( sel )
193    except Exception, e:
194        msg = "The input data appear to contain no position-switch mode data."
195        raise TypeError(msg)
196    s.set_selection()
197    sel.reset()
198    ssub = s.get_scan(scannos)
199    if ssub is None:
200        msg = "No data was found with given scan numbers!"
201        raise TypeError(msg)
202    #ssubon = ssub.get_scan('*calon')
203    #ssuboff = ssub.get_scan('*[^calon]')
204    sel.set_types( [srctype.poncal,srctype.poffcal] )
205    ssub.set_selection( sel )
206    ssubon = ssub.copy()
207    ssub.set_selection()
208    sel.reset()
209    sel.set_types( [srctype.pson,srctype.psoff] )
210    ssub.set_selection( sel )
211    ssuboff = ssub.copy()
212    ssub.set_selection()
213    sel.reset()
214    if ssubon.nrow() != ssuboff.nrow():
215        msg = "mismatch in numbers of CAL on/off scans. Cannot calibrate. Check the scan numbers."
216        raise TypeError(msg)
217    cals = dototalpower(ssubon, ssuboff, tcalval)
218    #sig = cals.get_scan('*ps')
219    #ref = cals.get_scan('*psr')
220    sel.set_types( srctype.pson )
221    cals.set_selection( sel )
222    sig = cals.copy()
223    cals.set_selection()
224    sel.reset()
225    sel.set_types( srctype.psoff )
226    cals.set_selection( sel )
227    ref = cals.copy()
228    cals.set_selection()
229    sel.reset()
230    if sig.nscan() != ref.nscan():
231        msg = "mismatch in numbers of on/off scans. Cannot calibrate. Check the scan numbers."
232        raise TypeError(msg)
233
234    #for user supplied Tsys
235    if tsysval>0.0:
236        if tauval<=0.0:
237            msg = "Need to supply a valid tau to use the supplied Tsys"
238            raise TypeError(msg)
239        else:
240            sig.recalc_azel()
241            ref.recalc_azel()
242            #msg = "Use of user specified Tsys is not fully implemented yet."
243            #raise TypeError(msg)
244            # use get_elevation to get elevation and
245            # calculate a scaling factor using the formula
246            # -> tsys use to dosigref
247
248    #ress = dosigref(sig, ref, smooth, tsysval)
249    ress = dosigref(sig, ref, smooth, tsysval, tauval)
250    ###
251    if verify:
252        # get data
253        import numpy
254        precal={}
255        postcal=[]
256        keys=['ps','ps_calon','psr','psr_calon']
257        types=[srctype.pson,srctype.poncal,srctype.psoff,srctype.poffcal]
258        ifnos=list(ssub.getifnos())
259        polnos=list(ssub.getpolnos())
260        sel=selector()
261        for i in range(2):
262            #ss=ssuboff.get_scan('*'+keys[2*i])
263            ll=[]
264            for j in range(len(ifnos)):
265                for k in range(len(polnos)):
266                    sel.set_ifs(ifnos[j])
267                    sel.set_polarizations(polnos[k])
268                    sel.set_types(types[2*i])
269                    try:
270                        #ss.set_selection(sel)
271                        ssuboff.set_selection(sel)
272                    except:
273                        continue
274                    #ll.append(numpy.array(ss._getspectrum(0)))
275                    ll.append(numpy.array(ssuboff._getspectrum(0)))
276                    sel.reset()
277                    ssuboff.set_selection()
278            precal[keys[2*i]]=ll
279            #del ss
280            #ss=ssubon.get_scan('*'+keys[2*i+1])
281            ll=[]
282            for j in range(len(ifnos)):
283                for k in range(len(polnos)):
284                    sel.set_ifs(ifnos[j])
285                    sel.set_polarizations(polnos[k])
286                    sel.set_types(types[2*i+1])
287                    try:
288                        #ss.set_selection(sel)
289                        ssubon.set_selection(sel)
290                    except:
291                        continue
292                    #ll.append(numpy.array(ss._getspectrum(0)))
293                    ll.append(numpy.array(ssubon._getspectrum(0)))
294                    sel.reset()
295                    ssubon.set_selection()
296            precal[keys[2*i+1]]=ll
297            #del ss
298        for j in range(len(ifnos)):
299            for k in range(len(polnos)):
300                sel.set_ifs(ifnos[j])
301                sel.set_polarizations(polnos[k])
302                try:
303                    ress.set_selection(sel)
304                except:
305                    continue
306                postcal.append(numpy.array(ress._getspectrum(0)))
307                sel.reset()
308                ress.set_selection()
309        del sel
310        # plot
311        asaplog.post()
312        asaplog.push('Plot only first spectrum for each [if,pol] pairs to verify calibration.')
313        asaplog.post('WARN')
314        p=new_asaplot()
315        rcp('lines', linewidth=1)
316        #nr=min(6,len(ifnos)*len(polnos))
317        nr=len(ifnos)*len(polnos)
318        titles=[]
319        btics=[]
320        if nr<4:
321            p.set_panels(rows=nr,cols=2,nplots=2*nr,ganged=False)
322            for i in range(2*nr):
323                b=False
324                if i >= 2*nr-2:
325                    b=True
326                btics.append(b)
327        elif nr==4:
328            p.set_panels(rows=2,cols=4,nplots=8,ganged=False)
329            for i in range(2*nr):
330                b=False
331                if i >= 2*nr-4:
332                    b=True
333                btics.append(b)
334        elif nr<7:
335            p.set_panels(rows=3,cols=4,nplots=2*nr,ganged=False)
336            for i in range(2*nr):
337                if i >= 2*nr-4:
338                    b=True
339                btics.append(b)
340        else:
341            asaplog.post()
342            asaplog.push('Only first 6 [if,pol] pairs are plotted.')
343            asaplog.post('WARN')
344            nr=6
345            for i in range(2*nr):
346                b=False
347                if i >= 2*nr-4:
348                    b=True
349                btics.append(b)
350            p.set_panels(rows=3,cols=4,nplots=2*nr,ganged=False)
351        for i in range(nr):
352            p.subplot(2*i)
353            p.color=0
354            title='raw data IF%s POL%s' % (ifnos[int(i/len(polnos))],polnos[i%len(polnos)])
355            titles.append(title)
356            #p.set_axes('title',title,fontsize=40)
357            ymin=1.0e100
358            ymax=-1.0e100
359            nchan=s.nchan(ifnos[int(i/len(polnos))])
360            edge=int(nchan*0.01)
361            for j in range(4):
362                spmin=min(precal[keys[j]][i][edge:nchan-edge])
363                spmax=max(precal[keys[j]][i][edge:nchan-edge])
364                ymin=min(ymin,spmin)
365                ymax=max(ymax,spmax)
366            for j in range(4):
367                if i==0:
368                    p.set_line(label=keys[j])
369                else:
370                    p.legend()
371                p.plot(precal[keys[j]][i])
372            p.axes.set_ylim(ymin-0.1*abs(ymin),ymax+0.1*abs(ymax))
373            if not btics[2*i]:
374                p.axes.set_xticks([])
375            p.subplot(2*i+1)
376            p.color=0
377            title='cal data IF%s POL%s' % (ifnos[int(i/len(polnos))],polnos[i%len(polnos)])
378            titles.append(title)
379            #p.set_axes('title',title)
380            p.legend()
381            ymin=postcal[i][edge:nchan-edge].min()
382            ymax=postcal[i][edge:nchan-edge].max()
383            p.plot(postcal[i])
384            p.axes.set_ylim(ymin-0.1*abs(ymin),ymax+0.1*abs(ymax))
385            if not btics[2*i+1]:
386                p.axes.set_xticks([])
387        for i in range(2*nr):
388            p.subplot(i)
389            p.set_axes('title',titles[i],fontsize='medium')
390        x=raw_input('Accept calibration ([y]/n): ' )
391        if x.upper() == 'N':
392            p.quit()
393            del p
394            return scabtab
395        p.quit()
396        del p
397    ###
398    ress._add_history("calps", varlist)
399    return ress
400
401@asaplog_post_dec
402def calnod(scantab, scannos=[], smooth=1, tsysval=0.0, tauval=0.0, tcalval=0.0, verify=False):
403    """
404    Do full (but a pair of scans at time) processing of GBT Nod data
405    calibration.
406    Adopted from  GBTIDL's getnod
407    Parameters:
408        scantab:     scantable
409        scannos:     a pair of scan numbers, or the first scan number of the pair
410        smooth:      box car smoothing order
411        tsysval:     optional user specified Tsys value
412        tauval:      optional user specified tau value (not implemented yet)
413        tcalval:     optional user specified Tcal value
414        verify:       Verify calibration if true
415    """
416    varlist = vars()
417    from asap._asap import stmath
418    from asap._asap import srctype
419    stm = stmath()
420    stm._setinsitu(False)
421
422    # check for the appropriate data
423##     s = scantab.get_scan('*_nod*')
424##     if s is None:
425##         msg = "The input data appear to contain no Nod observing mode data."
426##         raise TypeError(msg)
427    s = scantab.copy()
428    sel = selector()
429    sel.set_types( srctype.nod )
430    try:
431        s.set_selection( sel )
432    except Exception, e:
433        msg = "The input data appear to contain no Nod observing mode data."
434        raise TypeError(msg)
435    sel.reset()
436    del sel
437    del s
438
439    # need check correspondance of each beam with sig-ref ...
440    # check for timestamps, scan numbers, subscan id (not available in
441    # ASAP data format...). Assume 1st scan of the pair (beam 0 - sig
442    # and beam 1 - ref...)
443    # First scan number of paired scans or list of pairs of
444    # scan numbers (has to have even number of pairs.)
445
446    #data splitting
447    scan1no = scan2no = 0
448
449    if len(scannos)==1:
450        scan1no = scannos[0]
451        scan2no = scannos[0]+1
452        pairScans = [scan1no, scan2no]
453    else:
454        #if len(scannos)>2:
455        #    msg = "calnod can only process a pair of nod scans at time."
456        #    raise TypeError(msg)
457        #
458        #if len(scannos)==2:
459        #    scan1no = scannos[0]
460        #    scan2no = scannos[1]
461        pairScans = list(scannos)
462
463    if tsysval>0.0:
464        if tauval<=0.0:
465            msg = "Need to supply a valid tau to use the supplied Tsys"
466            raise TypeError(msg)
467        else:
468            scantab.recalc_azel()
469    resspec = scantable(stm._donod(scantab, pairScans, smooth, tsysval,tauval,tcalval))
470    ###
471    if verify:
472        # get data
473        import numpy
474        precal={}
475        postcal=[]
476        keys=['','_calon']
477        types=[srctype.nod,srctype.nodcal]
478        ifnos=list(scantab.getifnos())
479        polnos=list(scantab.getpolnos())
480        sel=selector()
481        ss = scantab.copy()
482        for i in range(2):
483            #ss=scantab.get_scan('*'+keys[i])
484            ll=[]
485            ll2=[]
486            for j in range(len(ifnos)):
487                for k in range(len(polnos)):
488                    sel.set_ifs(ifnos[j])
489                    sel.set_polarizations(polnos[k])
490                    sel.set_scans(pairScans[0])
491                    sel.set_types(types[i])
492                    try:
493                        ss.set_selection(sel)
494                    except:
495                        continue
496                    ll.append(numpy.array(ss._getspectrum(0)))
497                    sel.reset()
498                    ss.set_selection()
499                    sel.set_ifs(ifnos[j])
500                    sel.set_polarizations(polnos[k])
501                    sel.set_scans(pairScans[1])
502                    sel.set_types(types[i])
503                    try:
504                        ss.set_selection(sel)
505                    except:
506                        ll.pop()
507                        continue
508                    ll2.append(numpy.array(ss._getspectrum(0)))
509                    sel.reset()
510                    ss.set_selection()
511            key='%s%s' %(pairScans[0],keys[i])
512            precal[key]=ll
513            key='%s%s' %(pairScans[1],keys[i])
514            precal[key]=ll2
515            #del ss
516        keys=precal.keys()
517        for j in range(len(ifnos)):
518            for k in range(len(polnos)):
519                sel.set_ifs(ifnos[j])
520                sel.set_polarizations(polnos[k])
521                sel.set_scans(pairScans[0])
522                try:
523                    resspec.set_selection(sel)
524                except:
525                    continue
526                postcal.append(numpy.array(resspec._getspectrum(0)))
527                sel.reset()
528                resspec.set_selection()
529        del sel
530        # plot
531        asaplog.post()
532        asaplog.push('Plot only first spectrum for each [if,pol] pairs to verify calibration.')
533        asaplog.post('WARN')
534        p=new_asaplot()
535        rcp('lines', linewidth=1)
536        #nr=min(6,len(ifnos)*len(polnos))
537        nr=len(ifnos)*len(polnos)
538        titles=[]
539        btics=[]
540        if nr<4:
541            p.set_panels(rows=nr,cols=2,nplots=2*nr,ganged=False)
542            for i in range(2*nr):
543                b=False
544                if i >= 2*nr-2:
545                    b=True
546                btics.append(b)
547        elif nr==4:
548            p.set_panels(rows=2,cols=4,nplots=8,ganged=False)
549            for i in range(2*nr):
550                b=False
551                if i >= 2*nr-4:
552                    b=True
553                btics.append(b)
554        elif nr<7:
555            p.set_panels(rows=3,cols=4,nplots=2*nr,ganged=False)
556            for i in range(2*nr):
557                if i >= 2*nr-4:
558                    b=True
559                btics.append(b)
560        else:
561            asaplog.post()
562            asaplog.push('Only first 6 [if,pol] pairs are plotted.')
563            asaplog.post('WARN')
564            nr=6
565            for i in range(2*nr):
566                b=False
567                if i >= 2*nr-4:
568                    b=True
569                btics.append(b)
570            p.set_panels(rows=3,cols=4,nplots=2*nr,ganged=False)
571        for i in range(nr):
572            p.subplot(2*i)
573            p.color=0
574            title='raw data IF%s POL%s' % (ifnos[int(i/len(polnos))],polnos[i%len(polnos)])
575            titles.append(title)
576            #p.set_axes('title',title,fontsize=40)
577            ymin=1.0e100
578            ymax=-1.0e100
579            nchan=scantab.nchan(ifnos[int(i/len(polnos))])
580            edge=int(nchan*0.01)
581            for j in range(4):
582                spmin=min(precal[keys[j]][i][edge:nchan-edge])
583                spmax=max(precal[keys[j]][i][edge:nchan-edge])
584                ymin=min(ymin,spmin)
585                ymax=max(ymax,spmax)
586            for j in range(4):
587                if i==0:
588                    p.set_line(label=keys[j])
589                else:
590                    p.legend()
591                p.plot(precal[keys[j]][i])
592            p.axes.set_ylim(ymin-0.1*abs(ymin),ymax+0.1*abs(ymax))
593            if not btics[2*i]:
594                p.axes.set_xticks([])
595            p.subplot(2*i+1)
596            p.color=0
597            title='cal data IF%s POL%s' % (ifnos[int(i/len(polnos))],polnos[i%len(polnos)])
598            titles.append(title)
599            #p.set_axes('title',title)
600            p.legend()
601            ymin=postcal[i][edge:nchan-edge].min()
602            ymax=postcal[i][edge:nchan-edge].max()
603            p.plot(postcal[i])
604            p.axes.set_ylim(ymin-0.1*abs(ymin),ymax+0.1*abs(ymax))
605            if not btics[2*i+1]:
606                p.axes.set_xticks([])
607        for i in range(2*nr):
608            p.subplot(i)
609            p.set_axes('title',titles[i],fontsize='medium')
610        x=raw_input('Accept calibration ([y]/n): ' )
611        if x.upper() == 'N':
612            p.quit()
613            del p
614            return scabtab
615        p.quit()
616        del p
617    ###
618    resspec._add_history("calnod",varlist)
619    return resspec
620
621@asaplog_post_dec
622def calfs(scantab, scannos=[], smooth=1, tsysval=0.0, tauval=0.0, tcalval=0.0, verify=False):
623    """
624    Calibrate GBT frequency switched data.
625    Adopted from GBTIDL getfs.
626    Currently calfs identify the scans as frequency switched data if source
627    type enum is fson and fsoff. The data must contains 'CAL' signal
628    on/off in each integration. To identify 'CAL' on state, the source type
629    enum of foncal and foffcal need to be present.
630
631    Parameters:
632        scantab:       scantable
633        scannos:       list of scan numbers
634        smooth:        optional box smoothing order for the reference
635                       (default is 1 = no smoothing)
636        tsysval:       optional user specified Tsys (default is 0.0,
637                       use Tsys in the data)
638        tauval:        optional user specified Tau
639        verify:        Verify calibration if true
640    """
641    varlist = vars()
642    from asap._asap import stmath
643    from asap._asap import srctype
644    stm = stmath()
645    stm._setinsitu(False)
646
647#    check = scantab.get_scan('*_fs*')
648#    if check is None:
649#        msg = "The input data appear to contain no Nod observing mode data."
650#        raise TypeError(msg)
651    s = scantab.get_scan(scannos)
652    del scantab
653
654    resspec = scantable(stm._dofs(s, scannos, smooth, tsysval,tauval,tcalval))
655    ###
656    if verify:
657        # get data
658        ssub = s.get_scan(scannos)
659        #ssubon = ssub.get_scan('*calon')
660        #ssuboff = ssub.get_scan('*[^calon]')
661        sel = selector()
662        sel.set_types( [srctype.foncal,srctype.foffcal] )
663        ssub.set_selection( sel )
664        ssubon = ssub.copy()
665        ssub.set_selection()
666        sel.reset()
667        sel.set_types( [srctype.fson,srctype.fsoff] )
668        ssub.set_selection( sel )
669        ssuboff = ssub.copy()
670        ssub.set_selection()
671        sel.reset()
672        import numpy
673        precal={}
674        postcal=[]
675        keys=['fs','fs_calon','fsr','fsr_calon']
676        types=[srctype.fson,srctype.foncal,srctype.fsoff,srctype.foffcal]
677        ifnos=list(ssub.getifnos())
678        polnos=list(ssub.getpolnos())
679        for i in range(2):
680            #ss=ssuboff.get_scan('*'+keys[2*i])
681            ll=[]
682            for j in range(len(ifnos)):
683                for k in range(len(polnos)):
684                    sel.set_ifs(ifnos[j])
685                    sel.set_polarizations(polnos[k])
686                    sel.set_types(types[2*i])
687                    try:
688                        #ss.set_selection(sel)
689                        ssuboff.set_selection(sel)
690                    except:
691                        continue
692                    ll.append(numpy.array(ss._getspectrum(0)))
693                    sel.reset()
694                    #ss.set_selection()
695                    ssuboff.set_selection()
696            precal[keys[2*i]]=ll
697            #del ss
698            #ss=ssubon.get_scan('*'+keys[2*i+1])
699            ll=[]
700            for j in range(len(ifnos)):
701                for k in range(len(polnos)):
702                    sel.set_ifs(ifnos[j])
703                    sel.set_polarizations(polnos[k])
704                    sel.set_types(types[2*i+1])
705                    try:
706                        #ss.set_selection(sel)
707                        ssubon.set_selection(sel)
708                    except:
709                        continue
710                    ll.append(numpy.array(ss._getspectrum(0)))
711                    sel.reset()
712                    #ss.set_selection()
713                    ssubon.set_selection()
714            precal[keys[2*i+1]]=ll
715            #del ss
716        #sig=resspec.get_scan('*_fs')
717        #ref=resspec.get_scan('*_fsr')
718        sel.set_types( srctype.fson )
719        resspec.set_selection( sel )
720        sig=resspec.copy()
721        resspec.set_selection()
722        sel.reset()
723        sel.set_type( srctype.fsoff )
724        resspec.set_selection( sel )
725        ref=resspec.copy()
726        resspec.set_selection()
727        sel.reset()
728        for k in range(len(polnos)):
729            for j in range(len(ifnos)):
730                sel.set_ifs(ifnos[j])
731                sel.set_polarizations(polnos[k])
732                try:
733                    sig.set_selection(sel)
734                    postcal.append(numpy.array(sig._getspectrum(0)))
735                except:
736                    ref.set_selection(sel)
737                    postcal.append(numpy.array(ref._getspectrum(0)))
738                sel.reset()
739                resspec.set_selection()
740        del sel
741        # plot
742        asaplog.post()
743        asaplog.push('Plot only first spectrum for each [if,pol] pairs to verify calibration.')
744        asaplog.post('WARN')
745        p=new_asaplot()
746        rcp('lines', linewidth=1)
747        #nr=min(6,len(ifnos)*len(polnos))
748        nr=len(ifnos)/2*len(polnos)
749        titles=[]
750        btics=[]
751        if nr>3:
752            asaplog.post()
753            asaplog.push('Only first 3 [if,pol] pairs are plotted.')
754            asaplog.post('WARN')
755            nr=3
756        p.set_panels(rows=nr,cols=3,nplots=3*nr,ganged=False)
757        for i in range(3*nr):
758            b=False
759            if i >= 3*nr-3:
760                b=True
761            btics.append(b)
762        for i in range(nr):
763            p.subplot(3*i)
764            p.color=0
765            title='raw data IF%s,%s POL%s' % (ifnos[2*int(i/len(polnos))],ifnos[2*int(i/len(polnos))+1],polnos[i%len(polnos)])
766            titles.append(title)
767            #p.set_axes('title',title,fontsize=40)
768            ymin=1.0e100
769            ymax=-1.0e100
770            nchan=s.nchan(ifnos[2*int(i/len(polnos))])
771            edge=int(nchan*0.01)
772            for j in range(4):
773                spmin=min(precal[keys[j]][i][edge:nchan-edge])
774                spmax=max(precal[keys[j]][i][edge:nchan-edge])
775                ymin=min(ymin,spmin)
776                ymax=max(ymax,spmax)
777            for j in range(4):
778                if i==0:
779                    p.set_line(label=keys[j])
780                else:
781                    p.legend()
782                p.plot(precal[keys[j]][i])
783            p.axes.set_ylim(ymin-0.1*abs(ymin),ymax+0.1*abs(ymax))
784            if not btics[3*i]:
785                p.axes.set_xticks([])
786            p.subplot(3*i+1)
787            p.color=0
788            title='sig data IF%s POL%s' % (ifnos[2*int(i/len(polnos))],polnos[i%len(polnos)])
789            titles.append(title)
790            #p.set_axes('title',title)
791            p.legend()
792            ymin=postcal[2*i][edge:nchan-edge].min()
793            ymax=postcal[2*i][edge:nchan-edge].max()
794            p.plot(postcal[2*i])
795            p.axes.set_ylim(ymin-0.1*abs(ymin),ymax+0.1*abs(ymax))
796            if not btics[3*i+1]:
797                p.axes.set_xticks([])
798            p.subplot(3*i+2)
799            p.color=0
800            title='ref data IF%s POL%s' % (ifnos[2*int(i/len(polnos))+1],polnos[i%len(polnos)])
801            titles.append(title)
802            #p.set_axes('title',title)
803            p.legend()
804            ymin=postcal[2*i+1][edge:nchan-edge].min()
805            ymax=postcal[2*i+1][edge:nchan-edge].max()
806            p.plot(postcal[2*i+1])
807            p.axes.set_ylim(ymin-0.1*abs(ymin),ymax+0.1*abs(ymax))
808            if not btics[3*i+2]:
809                p.axes.set_xticks([])
810        for i in range(3*nr):
811            p.subplot(i)
812            p.set_axes('title',titles[i],fontsize='medium')
813        x=raw_input('Accept calibration ([y]/n): ' )
814        if x.upper() == 'N':
815            p.quit()
816            del p
817            return scabtab
818        p.quit()
819        del p
820    ###
821    resspec._add_history("calfs",varlist)
822    return resspec
823
824@asaplog_post_dec
825def merge(*args):
826    """
827    Merge a list of scanatables, or comma-sperated scantables into one
828    scnatble.
829    Parameters:
830        A list [scan1, scan2] or scan1, scan2.
831    Example:
832        myscans = [scan1, scan2]
833        allscans = merge(myscans)
834        # or equivalent
835        sameallscans = merge(scan1, scan2)
836    """
837    varlist = vars()
838    if isinstance(args[0],list):
839        lst = tuple(args[0])
840    elif isinstance(args[0],tuple):
841        lst = args[0]
842    else:
843        lst = tuple(args)
844    varlist["args"] = "%d scantables" % len(lst)
845    # need special formatting her for history...
846    from asap._asap import stmath
847    stm = stmath()
848    for s in lst:
849        if not isinstance(s,scantable):
850            msg = "Please give a list of scantables"
851            raise TypeError(msg)
852    s = scantable(stm._merge(lst))
853    s._add_history("merge", varlist)
854    return s
855
856@asaplog_post_dec
857def calibrate( scantab, scannos=[], calmode='none', verify=None ):
858    """
859    Calibrate data.
860
861    Parameters:
862        scantab:       scantable
863        scannos:       list of scan number
864        calmode:       calibration mode
865        verify:        verify calibration
866    """
867    import re
868    antname = scantab.get_antennaname()
869    if ( calmode == 'nod' ):
870        asaplog.push( 'Calibrating nod data.' )
871        scal = calnod( scantab, scannos=scannos, verify=verify )
872    elif ( calmode == 'quotient' ):
873        asaplog.push( 'Calibrating using quotient.' )
874        scal = scantab.auto_quotient( verify=verify )
875    elif ( calmode == 'ps' ):
876        asaplog.push( 'Calibrating %s position-switched data.' % antname )
877        if ( antname.find( 'APEX' ) != -1 ):
878            scal = apexcal( scantab, scannos, calmode, verify )
879        elif ( antname.find( 'ALMA' ) != -1 or antname.find( 'OSF' ) != -1
880               or re.match('DV[0-9][0-9]$',antname) is not None
881               or re.match('PM[0-9][0-9]$',antname) is not None
882               or re.match('CM[0-9][0-9]$',antname) is not None
883               or re.match('DA[0-9][0-9]$',antname) is not None ):
884            scal = almacal( scantab, scannos, calmode, verify )
885        else:
886            scal = calps( scantab, scannos=scannos, verify=verify )
887    elif ( calmode == 'fs' or calmode == 'fsotf' ):
888        asaplog.push( 'Calibrating %s frequency-switched data.' % antname )
889        if ( antname.find( 'APEX' ) != -1 ):
890            scal = apexcal( scantab, scannos, calmode, verify )
891        elif ( antname.find( 'ALMA' ) != -1 or antname.find( 'OSF' ) != -1 ):
892            scal = almacal( scantab, scannos, calmode, verify )
893        else:
894            scal = calfs( scantab, scannos=scannos, verify=verify )
895    elif ( calmode == 'otf' ):
896        asaplog.push( 'Calibrating %s On-The-Fly data.' % antname )
897        scal = almacal( scantab, scannos, calmode, verify )
898    else:
899        asaplog.push( 'No calibration.' )
900        scal = scantab.copy()
901
902    return scal
903
904def apexcal( scantab, scannos=[], calmode='none', verify=False ):
905    """
906    Calibrate APEX data
907
908    Parameters:
909        scantab:       scantable
910        scannos:       list of scan number
911        calmode:       calibration mode
912
913        verify:        verify calibration
914    """
915    from asap._asap import stmath
916    stm = stmath()
917    antname = scantab.get_antennaname()
918    selection=selector()
919    selection.set_scans(scannos)
920    orig = scantab.get_selection()
921    scantab.set_selection(orig+selection)
922##     ssub = scantab.get_scan( scannos )
923##     scal = scantable( stm.cwcal( ssub, calmode, antname ) )
924    scal = scantable( stm.cwcal( scantab, calmode, antname ) )
925    scantab.set_selection(orig)
926    return scal
927
928def almacal( scantab, scannos=[], calmode='none', verify=False ):
929    """
930    Calibrate ALMA data
931
932    Parameters:
933        scantab:       scantable
934        scannos:       list of scan number
935        calmode:       calibration mode
936
937        verify:        verify calibration
938    """
939    from asap._asap import stmath
940    stm = stmath()
941    selection=selector()
942    selection.set_scans(scannos)
943    orig = scantab.get_selection()
944    scantab.set_selection(orig+selection)
945##     ssub = scantab.get_scan( scannos )
946##     scal = scantable( stm.almacal( ssub, calmode ) )
947    scal = scantable( stm.almacal( scantab, calmode ) )
948    scantab.set_selection(orig)
949    return scal
950
951@asaplog_post_dec
952def splitant(filename, outprefix='',overwrite=False, getpt=True, freq_tolsr=False):
953    """
954    Split Measurement set by antenna name, save data as a scantables,
955    and return a list of filename.
956    Notice this method can only be available from CASA.
957    Prameter
958       filename:    the name of Measurement set to be read.
959       outprefix:   the prefix of output scantable name.
960                    the names of output scantable will be
961                    outprefix.antenna1, outprefix.antenna2, ....
962                    If not specified, outprefix = filename is assumed.
963       overwrite    If the file should be overwritten if it exists.
964                    The default False is to return with warning
965                    without writing the output. USE WITH CARE.
966       getpt        Whether to import direction from MS/POINTING
967                    table or not. Default is True (import direction).
968       freq_tolsr   Whether to convert frequency frame information
969                    to LSRK or not. Default is False (import as is).
970
971    """
972    # Import the table toolkit from CASA
973    from casac import casac
974    from asap.scantable import is_ms
975    tb = casac.table()
976    # Check the input filename
977    if isinstance(filename, str):
978        import os.path
979        filename = os.path.expandvars(filename)
980        filename = os.path.expanduser(filename)
981        if not os.path.exists(filename):
982            s = "File '%s' not found." % (filename)
983            raise IOError(s)
984        # check if input file is MS
985        #if not os.path.isdir(filename) \
986        #       or not os.path.exists(filename+'/ANTENNA') \
987        #       or not os.path.exists(filename+'/table.f1'):
988        if not is_ms(filename):
989            s = "File '%s' is not a Measurement set." % (filename)
990            raise IOError(s)
991    else:
992        s = "The filename should be string. "
993        raise TypeError(s)
994    # Check out put file name
995    outname=''
996    if len(outprefix) > 0: prefix=outprefix+'.'
997    else:
998        prefix=filename.rstrip('/')
999    # Now do the actual splitting.
1000    outfiles=[]
1001    tb.open(tablename=filename,nomodify=True)
1002    ant1=tb.getcol('ANTENNA1',0,-1,1)
1003    #anttab=tb.getkeyword('ANTENNA').split()[-1]
1004    anttab=tb.getkeyword('ANTENNA').lstrip('Table: ')
1005    tb.close()
1006    #tb.open(tablename=filename+'/ANTENNA',nomodify=True)
1007    tb.open(tablename=anttab,nomodify=True)
1008    nant=tb.nrows()
1009    antnames=tb.getcol('NAME',0,nant,1)
1010    tb.close()
1011    tmpname='asapmath.splitant.tmp'
1012    for antid in set(ant1):
1013        tb.open(tablename=filename,nomodify=True)
1014        tbsel=tb.query('ANTENNA1 == %s && ANTENNA2 == %s'%(antid,antid),tmpname)
1015        scan=scantable(tmpname,average=False,antenna=int(antid),getpt=getpt,freq_tolsr=freq_tolsr,)
1016        outname=prefix+antnames[antid]+'.asap'
1017        scan.save(outname,format='ASAP',overwrite=overwrite)
1018        tbsel.close()
1019        tb.close()
1020        del tbsel
1021        del scan
1022        outfiles.append(outname)
1023        os.system('rm -rf '+tmpname)
1024    del tb
1025    return outfiles
1026
1027@asaplog_post_dec
1028def _array2dOp( scan, value, mode="ADD", tsys=False, insitu=None):
1029    """
1030    This function is workaround on the basic operation of scantable
1031    with 2 dimensional float list.
1032
1033    scan:    scantable operand
1034    value:   float list operand
1035    mode:    operation mode (ADD, SUB, MUL, DIV)
1036    tsys:    if True, operate tsys as well
1037    insitu:  if False, a new scantable is returned.
1038             Otherwise, the array operation is done in-sitsu.
1039    """
1040    if insitu is None: insitu = rcParams['insitu']
1041    nrow = scan.nrow()
1042    s = None
1043    from asap._asap import stmath
1044    stm = stmath()
1045    stm._setinsitu(insitu)
1046    if len( value ) == 1:
1047        s = scantable( stm._arrayop( scan, value[0], mode, tsys ) )
1048    elif len( value ) != nrow:
1049        raise ValueError( 'len(value) must be 1 or conform to scan.nrow()' )
1050    else:
1051        from asap._asap import stmath
1052        if not insitu:
1053            s = scan.copy()
1054        else:
1055            s = scan
1056        # insitu must be True as we go row by row on the same data
1057        stm._setinsitu( True )
1058        basesel = s.get_selection()
1059        # generate a new selector object based on basesel
1060        sel = selector(basesel)
1061        for irow in range( nrow ):
1062            sel.set_rows( irow )
1063            s.set_selection( sel )
1064            if len( value[irow] ) == 1:
1065                stm._unaryop( s, value[irow][0], mode, tsys )
1066            else:
1067                #stm._arrayop( s, value[irow], mode, tsys, 'channel' )
1068                stm._arrayop( s, value[irow], mode, tsys )
1069        s.set_selection(basesel)
1070    return s
Note: See TracBrowser for help on using the repository browser.