source: trunk/python/asapgrid.py @ 2678

Last change on this file since 2678 was 2678, checked in by Takeshi Nakazato, 12 years ago

New Development: No

JIRA Issue: Yes CAS-4429

Ready for Test: Yes

Interface Changes: No

What Interface Changed: Please list interface changes

Test Programs: List test programs

Put in Release Notes: Yes/No?

Module(s): Module Names change impacts.

Description: Describe your changes here...

Added new parameter to asapgrid.setFunc(). Also, default behavior
of STGrid is changed.


File size: 22.8 KB
Line 
1import numpy
2from asap import rcParams
3from asap.scantable import scantable
4from asap.selector import selector
5from asap._asap import stgrid, stgrid2
6import pylab as pl
7from logging import asaplog
8
9class asapgrid:
10    """
11    The asapgrid class is defined to convolve data onto regular
12    spatial grid. Typical usage is as follows:
13
14       # create asapgrid instance with two input data
15       g = asapgrid( ['testimage1.asap','testimage2.asap'] )
16       # set IFNO if necessary
17       g.setIF( 0 )
18       # set POLNOs if necessary
19       g.setPolList( [0,1] )
20       # set SCANNOs if necessary
21       g.setScanList( [22,23,24] )
22       # define image with full specification
23       # you can skip some parameters (see help for defineImage)
24       g.defineImage( nx=12, ny=12, cellx='10arcsec', celly='10arcsec',
25                      center='J2000 10h10m10s -5d05m05s' )
26       # set convolution function
27       g.setFunc( func='sf', width=3 )
28       # enable min/max clipping
29       g.enableClip()
30       # or, disable min/max clipping
31       #g.disableClip()
32       # actual gridding
33       g.grid()
34       # save result
35       g.save( outfile='grid.asap' )
36       # plot result
37       g.plot( plotchan=1246, plotpol=-1, plotgrid=True, plotobs=True )
38    """
39    def __init__( self, infile ):
40        """
41        Create asapgrid instance.
42
43        infile -- input data as a string or string list if you want
44                  to grid more than one data at once. 
45        """
46        self.outfile = None
47        self.ifno = None
48        self.gridder = stgrid()
49        self.setData( infile )
50
51    def setData( self, infile ):
52        """
53        Set data to be processed.
54
55        infile -- input data as a string or string list if you want
56                  to grid more than one data at once. 
57        """
58        if isinstance( infile, str ):
59            self.gridder._setin( infile )
60        else:
61            self.gridder._setfiles( infile )
62        self.infile = infile
63
64    def setIF( self, ifno ):
65        """
66        Set IFNO to be processed. Currently, asapgrid allows to process
67        only one IFNO for one gridding run even if the data contains
68        multiple IFs. If you didn't specify IFNO, default value, which
69        is IFNO in the first spectrum, will be processed.
70
71        ifno -- IFNO to be processed.
72        """
73        self.ifno = ifno
74        self.gridder._setif( self.ifno )
75
76    def setPolList( self, pollist ):
77        """
78        Set list of polarization components you want to process.
79        If not specified, all POLNOs will be processed.
80
81        pollist -- list of POLNOs.
82        """
83        self.gridder._setpollist( pollist )
84
85    def setScanList( self, scanlist ):
86        """
87        Set list of scans you want to process. If not specified, all
88        scans will be processed.
89
90        scanlist -- list of SCANNOs.
91        """
92        self.gridder._setscanlist( scanlist )
93
94    def defineImage( self, nx=-1, ny=-1, cellx='', celly='', center='' ):
95        """
96        Define spatial grid.
97
98        First two parameters, nx and ny, define number of pixels of
99        the grid. If which of those is not specified, it will be set
100        to the same value as the other. If none of them are specified,
101        it will be determined from map extent and cell size.
102
103        Next two parameters, cellx and celly, define size of pixel.
104        You should set those parameters as string, which is constructed
105        numerical value and unit, e.g. '0.5arcmin', or numerical value.
106        If those values are specified as numerical value, their units
107        will be assumed to 'arcsec'. If which of those is not specified,
108        it will be set to the same value as the other. If none of them
109        are specified, it will be determined from map extent and number
110        of pixels, or set to '1arcmin' if neither nx nor ny is set.
111
112        The last parameter, center, define the central coordinate of
113        the grid. You should specify its value as a string, like,
114
115           'J2000 05h08m50s -16d23m30s'
116
117        or
118
119           'J2000 05:08:50 -16.23.30'
120
121        You can omit equinox when you specify center coordinate. In that
122        case, J2000 is assumed. If center is not specified, it will be
123        determined from the observed positions of input data.
124
125        nx -- number of pixels along x (R.A.) direction.
126        ny -- number of pixels along y (Dec.) direction.
127        cellx -- size of pixel in x (R.A.) direction.
128        celly -- size of pixel in y (Dec.) direction.
129        center -- central position of the grid.
130        """
131        if not isinstance( cellx, str ):
132            cellx = '%sarcsec'%(cellx)
133        if not isinstance( celly, str ):
134            celly = '%sarcsec'%(celly)
135        self.gridder._defineimage( nx, ny, cellx, celly, center )
136
137    def setFunc( self, func='box', convsupport=-1, truncate="-1", gwidth="-1", jwidth="-1" ):
138        """
139        Set convolution function. Possible options are 'box' (Box-car,
140        default), 'sf' (prolate spheroidal), and 'gauss' (Gaussian).
141        Width of convolution function can be set using width parameter.
142        By default (-1), width is automatically set depending on each
143        convolution function. Default values for width are:
144
145           'box': 1 pixel
146           'sf': 3 pixels
147           'gauss': 1 pixel (width is used as HWHM)
148
149        func -- Function type ('box', 'sf', 'gauss').
150        width -- Width of convolution function. Default (-1) is to
151                 choose pre-defined value for each convolution function.
152        """
153        self.gridder._setfunc(func,
154                              convsupport=convsupport,
155                              truncate=truncate,
156                              gwidth=gwidth,
157                              jwidth=jwidth)
158##         fname = func.upper()
159##         if fname == 'GAUSS' or fname == 'GJINC':
160##             gw = str(gwidth)
161##             jw = str(jwidth)
162##             w = str(width)
163##             #if len(w) > 0 and w[0] == '-':
164##             #    w = ''
165##             #self.gridder._setfunc(fname, -1, w, gw, jw)
166##             self.gridder._setfunc(fname,convsupport=-1,gwidth=gw,jwidth=jw,truncate=w)
167##         else:
168##             #if isinstance(width,str):
169##             #    w = -1
170##             #else:
171##             #    w = width
172##             self.gridder._setfunc( func, convsupport=width )
173
174    def setWeight( self, weightType='uniform' ):
175        """
176        Set weight type. Possible options are 'uniform' (default),
177        'tint' (weight by integration time), 'tsys' (weight by
178        Tsys: 1/Tsys**2), and 'tintsys' (weight by integration time
179        as well as Tsys: tint/Tsys**2).
180
181        weightType -- weight type ('uniform', 'tint', 'tsys', 'tintsys')
182        """
183        self.gridder._setweight( weightType )
184
185    def enableClip( self ):
186        """
187        Enable min/max clipping.
188
189        By default, min/max clipping is disabled so that you should
190        call this method before actual gridding if you want to do
191        clipping.
192        """
193        self.gridder._enableclip()
194
195    def disableClip( self ):
196        """
197        Disable min/max clipping.
198        """
199        self.gridder._disableclip()
200
201    def grid( self ):
202        """
203        Actual gridding which will be done based on several user inputs.
204        """
205        self.gridder._grid()
206
207    def save( self, outfile='' ):
208        """
209        Save result. By default, output data name will be constructed
210        from first element of input data name list (e.g. 'input.asap.grid').
211
212        outfile -- output data name.
213        """
214        self.outfile = self.gridder._save( outfile )
215
216    def plot( self, plotchan=-1, plotpol=-1, plotobs=False, plotgrid=False ):
217        """
218        Plot gridded data.
219
220        plotchan -- Which channel you want to plot. Default (-1) is
221                    to average all the channels.
222        plotpol -- Which polarization component you want to plot.
223                   Default (-1) is to average all the polarization
224                   components.
225        plotobs -- Also plot observed position if True. Default
226                   is False. Setting True for large amount of spectra
227                   might be time consuming.
228        plotgrid -- Also plot grid center if True. Default is False.
229                    Setting True for large number of grids might be
230                    time consuming.
231        """
232        import time
233        t0=time.time()
234        # to load scantable on disk
235        storg = rcParams['scantable.storage']
236        rcParams['scantable.storage'] = 'disk'
237        plotter = _SDGridPlotter( self.infile, self.outfile, self.ifno )
238        plotter.plot( chan=plotchan, pol=plotpol, plotobs=plotobs, plotgrid=plotgrid )
239        # back to original setup
240        rcParams['scantable.storage'] = storg
241        t1=time.time()
242        asaplog.push('plot: elapsed time %s sec'%(t1-t0))
243        asaplog.post('DEBUG','asapgrid.plot')
244
245    def plotFunc(self, clear=True):
246        """
247        Support function to see the shape of current grid function.
248
249        clear -- clear panel if True. Default is True.
250        """
251        pl.figure(11)
252        if clear:
253            pl.clf()
254        f = self.gridder._getfunc()
255        convsampling = 100
256        a = numpy.arange(0,len(f)/convsampling,1./convsampling,dtype=float)
257        pl.plot(a,f,'.-')
258        pl.xlabel('pixel')
259        pl.ylabel('convFunc')
260       
261class asapgrid2:
262    """
263    The asapgrid class is defined to convolve data onto regular
264    spatial grid. Typical usage is as follows:
265
266       # create asapgrid instance with input scantable
267       s = scantable( 'testimage1.asap', average=False )
268       g = asapgrid( s )
269       # set IFNO if necessary
270       g.setIF( 0 )
271       # set POLNOs if necessary
272       g.setPolList( [0,1] )
273       # set SCANNOs if necessary
274       g.setScanList( [22,23,24] )
275       # define image with full specification
276       # you can skip some parameters (see help for defineImage)
277       g.defineImage( nx=12, ny=12, cellx='10arcsec', celly='10arcsec',
278                      center='J2000 10h10m10s -5d05m05s' )
279       # set convolution function
280       g.setFunc( func='sf', width=3 )
281       # enable min/max clipping
282       g.enableClip()
283       # or, disable min/max clipping
284       #g.disableClip()
285       # actual gridding
286       g.grid()
287       # get result as scantable
288       sg = g.getResult()
289    """
290    def __init__( self, scantab ):
291        """
292        Create asapgrid instance.
293
294        scantab -- input data as a scantable or a list of scantables
295                   to grid more than one data at once. 
296        """
297        self.outfile = None
298        self.ifno = None
299        self.gridder = stgrid2()
300        self.setData( scantab )
301
302    def setData( self, scantab ):
303        """
304        Set data to be processed.
305
306        scantab -- input data as a scantable or a list of scantables
307                   to grid more than one data at once. 
308        """
309        if isinstance( scantab, scantable ):
310            self.gridder._setin( scantab )
311        else:
312            self.gridder._setfiles( scantab )
313        self.scantab = scantab
314
315    def setIF( self, ifno ):
316        """
317        Set IFNO to be processed. Currently, asapgrid allows to process
318        only one IFNO for one gridding run even if the data contains
319        multiple IFs. If you didn't specify IFNO, default value, which
320        is IFNO in the first spectrum, will be processed.
321
322        ifno -- IFNO to be processed.
323        """
324        self.ifno = ifno
325        self.gridder._setif( self.ifno )
326
327    def setPolList( self, pollist ):
328        """
329        Set list of polarization components you want to process.
330        If not specified, all POLNOs will be processed.
331
332        pollist -- list of POLNOs.
333        """
334        self.gridder._setpollist( pollist )
335
336    def setScanList( self, scanlist ):
337        """
338        Set list of scans you want to process. If not specified, all
339        scans will be processed.
340
341        scanlist -- list of SCANNOs.
342        """
343        self.gridder._setscanlist( scanlist )
344
345    def defineImage( self, nx=-1, ny=-1, cellx='', celly='', center='' ):
346        """
347        Define spatial grid.
348
349        First two parameters, nx and ny, define number of pixels of
350        the grid. If which of those is not specified, it will be set
351        to the same value as the other. If none of them are specified,
352        it will be determined from map extent and cell size.
353
354        Next two parameters, cellx and celly, define size of pixel.
355        You should set those parameters as string, which is constructed
356        numerical value and unit, e.g. '0.5arcmin', or numerical value.
357        If those values are specified as numerical value, their units
358        will be assumed to 'arcsec'. If which of those is not specified,
359        it will be set to the same value as the other. If none of them
360        are specified, it will be determined from map extent and number
361        of pixels, or set to '1arcmin' if neither nx nor ny is set.
362
363        The last parameter, center, define the central coordinate of
364        the grid. You should specify its value as a string, like,
365
366           'J2000 05h08m50s -16d23m30s'
367
368        or
369
370           'J2000 05:08:50 -16.23.30'
371
372        You can omit equinox when you specify center coordinate. In that
373        case, J2000 is assumed. If center is not specified, it will be
374        determined from the observed positions of input data.
375
376        nx -- number of pixels along x (R.A.) direction.
377        ny -- number of pixels along y (Dec.) direction.
378        cellx -- size of pixel in x (R.A.) direction.
379        celly -- size of pixel in y (Dec.) direction.
380        center -- central position of the grid.
381        """
382        if not isinstance( cellx, str ):
383            cellx = '%sarcsec'%(cellx)
384        if not isinstance( celly, str ):
385            celly = '%sarcsec'%(celly)
386        self.gridder._defineimage( nx, ny, cellx, celly, center )
387
388    def setFunc( self, func='box', width=-1 ):
389        """
390        Set convolution function. Possible options are 'box' (Box-car,
391        default), 'sf' (prolate spheroidal), and 'gauss' (Gaussian).
392        Width of convolution function can be set using width parameter.
393        By default (-1), width is automatically set depending on each
394        convolution function. Default values for width are:
395
396           'box': 1 pixel
397           'sf': 3 pixels
398           'gauss': 1 pixel (width is used as HWHM)
399
400        func -- Function type ('box', 'sf', 'gauss').
401        width -- Width of convolution function. Default (-1) is to
402                 choose pre-defined value for each convolution function.
403        """
404        fname = func.upper()
405        if fname == 'GAUSS' or fname == 'GJINC':
406            gw = str(gwidth)
407            jw = str(jwidth)
408            w = str(width)
409            if w[0] == '-': w = ''
410            #self.gridder._setfunc(fname, -1, w, gw, jw)
411            self.gridder._setfunc(fname,convsupport=-1,gwidth=gw,jwidth=jw,truncate=w)
412        else:
413            self.gridder._setfunc( func, convsupport=width )
414
415    def setWeight( self, weightType='uniform' ):
416        """
417        Set weight type. Possible options are 'uniform' (default),
418        'tint' (weight by integration time), 'tsys' (weight by
419        Tsys: 1/Tsys**2), and 'tintsys' (weight by integration time
420        as well as Tsys: tint/Tsys**2).
421
422        weightType -- weight type ('uniform', 'tint', 'tsys', 'tintsys')
423        """
424        self.gridder._setweight( weightType )
425
426    def enableClip( self ):
427        """
428        Enable min/max clipping.
429
430        By default, min/max clipping is disabled so that you should
431        call this method before actual gridding if you want to do
432        clipping.
433        """
434        self.gridder._enableclip()
435
436    def disableClip( self ):
437        """
438        Disable min/max clipping.
439        """
440        self.gridder._disableclip()
441
442    def grid( self ):
443        """
444        Actual gridding which will be done based on several user inputs.
445        """
446        self.gridder._grid()
447
448    def getResult( self ):
449        """
450        Return gridded data as a scantable.
451        """
452        tp = 0 if rcParams['scantable.storage']=='memory' else 1
453        return scantable( self.gridder._get( tp ), average=False )
454   
455    def plotFunc(self, clear=True):
456        """
457        Support function to see the shape of current grid function.
458
459        clear -- clear panel if True. Default is True.
460        """
461        pl.figure(11)
462        if clear:
463            pl.clf()
464        f = self.gridder._getfunc()
465        convsampling = 100
466        a = numpy.arange(0,len(f)/convsampling,1./convsampling,dtype=float)
467        pl.plot(a,f,'.-')
468        pl.xlabel('pixel')
469        pl.ylabel('convFunc')
470
471class _SDGridPlotter:
472    def __init__( self, infile, outfile=None, ifno=-1 ):
473        if isinstance( infile, str ):
474            self.infile = [infile]
475        else:
476            self.infile = infile
477        self.outfile = outfile
478        if self.outfile is None:
479            self.outfile = self.infile[0].rstrip('/')+'.grid'
480        self.nx = -1
481        self.ny = -1
482        self.nchan = 0
483        self.npol = 0
484        self.pollist = []
485        self.cellx = 0.0
486        self.celly = 0.0
487        self.center = [0.0,0.0]
488        self.nonzero = [[0.0],[0.0]]
489        self.ifno = ifno
490        self.tablein = None
491        self.nrow = 0
492        self.blc = None
493        self.trc = None
494        self.get()
495
496    def get( self ):
497        s = scantable( self.outfile, average=False )
498        self.nchan = len(s._getspectrum(0))
499        nrow = s.nrow()
500        pols = numpy.ones( nrow, dtype=int )
501        for i in xrange(nrow):
502            pols[i] = s.getpol(i)
503        self.pollist, indices = numpy.unique( pols, return_inverse=True )
504        self.npol = len(self.pollist)
505        self.pollist = self.pollist[indices[:self.npol]]
506        #print 'pollist=',self.pollist
507        #print 'npol=',self.npol
508        #print 'nrow=',nrow
509
510        idx = 1
511        d0 = s.get_direction( 0 ).split()[-2]
512        d = s.get_direction(self.npol*idx)
513        while( d is not None \
514               and d.split()[-2] != d0):
515            idx += 1
516            d = s.get_direction(self.npol*idx)
517       
518        self.nx = idx
519        self.ny = nrow / (self.npol * idx )
520        #print 'nx,ny=',self.nx,self.ny
521
522        self.blc = s.get_directionval( 0 )
523        self.trc = s.get_directionval( nrow-self.npol )
524        #print self.blc
525        #print self.trc
526        if nrow > 1:
527            incrx = s.get_directionval( self.npol )
528            incry = s.get_directionval( self.nx*self.npol )
529        else:
530            incrx = [0.0,0.0]
531            incry = [0.0,0.0]
532        self.cellx = abs( self.blc[0] - incrx[0] )
533        self.celly = abs( self.blc[1] - incry[1] )
534        #print 'cellx,celly=',self.cellx,self.celly
535
536    def plot( self, chan=-1, pol=-1, plotobs=False, plotgrid=False ):
537        if pol < 0:
538            opt = 'averaged over pol'
539        else:
540            opt = 'pol %s'%(pol)
541        if type(chan) is list:
542            opt += ', averaged over channel %s-%s'%(chan[0],chan[1])
543        elif chan < 0:
544            opt += ', averaged over channel'
545        else:
546            opt += ', channel %s'%(chan)
547        data = self.getData( chan, pol )
548        #data = numpy.fliplr( data )
549        title = 'Gridded Image (%s)'%(opt)
550        pl.figure(10)
551        pl.clf()
552        # plot grid position
553        if plotgrid:
554            x = numpy.arange(self.blc[0],self.trc[0]+0.5*self.cellx,self.cellx,dtype=float)
555            #print 'len(x)=',len(x)
556            #print 'x=',x
557            ybase = numpy.ones(self.nx,dtype=float)*self.blc[1]
558            #print 'len(ybase)=',len(ybase)
559            incr = self.celly
560            for iy in xrange(self.ny):
561                y = ybase + iy * incr
562                #print y
563                pl.plot(x,y,',',color='blue')
564        # plot observed position
565        if plotobs:
566            for i in xrange(len(self.infile)):
567                self.createTableIn( self.infile[i] )
568                irow = 0
569                while ( irow < self.nrow ):
570                    chunk = self.getPointingChunk( irow )
571                    #print chunk
572                    pl.plot(chunk[0],chunk[1],',',color='green')
573                    irow += chunk.shape[1]
574                    #print irow
575        # show image
576        extent=[self.trc[0]+0.5*self.cellx,
577                self.blc[0]-0.5*self.cellx,
578                self.blc[1]-0.5*self.celly,
579                self.trc[1]+0.5*self.celly]
580        deccorr = 1.0/numpy.cos(0.5*(self.blc[1]+self.trc[1]))
581        pl.imshow(data,extent=extent,origin='lower',interpolation='nearest')
582        pl.colorbar()
583        pl.xlabel('R.A. [rad]')
584        pl.ylabel('Dec. [rad]')
585        ax = pl.axes()
586        ax.set_aspect(deccorr)
587        pl.title( title )
588
589    def createTableIn( self, tab ):
590        del self.tablein
591        self.tablein = scantable( tab, average=False )
592        if self.ifno < 0:
593            ifno = self.tablein.getif(0)
594            #print 'ifno=',ifno
595        else:
596            ifno = self.ifno
597        sel = selector()
598        sel.set_ifs( ifno )
599        self.tablein.set_selection( sel )
600        self.nchan = len(self.tablein._getspectrum(0))
601        self.nrow = self.tablein.nrow()
602        del sel
603       
604
605    def getPointingChunk( self, irow ):
606        numchunk = 1000
607        nrow = min( self.nrow-irow, numchunk )
608        #print 'nrow=',nrow
609        v = numpy.zeros( (2,nrow), dtype=float )
610        idx = 0
611        for i in xrange(irow,irow+nrow):
612            d = self.tablein.get_directionval( i )
613            v[0,idx] = d[0]
614            v[1,idx] = d[1]
615            idx += 1
616        return v
617
618    def getData( self, chan=-1, pol=-1 ):
619        if type(chan) == list:
620            spectra = self.__chanAverage(start=chan[0],end=chan[1])
621        elif chan == -1:
622            spectra = self.__chanAverage()
623        else:
624            spectra = self.__chanIndex( chan )
625        data = spectra.reshape( (self.npol,self.ny,self.nx) )
626        if pol == -1:
627            retval = data.mean(axis=0)
628        else:
629            retval = data[pol]
630        return retval
631
632    def __chanAverage( self, start=-1, end=-1 ):
633        s = scantable( self.outfile, average=False )
634        nrow = s.nrow()
635        spectra = numpy.zeros( (self.npol,nrow/self.npol), dtype=float )
636        irow = 0
637        sp = [0 for i in xrange(self.nchan)]
638        if start < 0:
639            start = 0
640        if end < 0:
641            end = self.nchan
642        for i in xrange(nrow/self.npol):
643            for ip in xrange(self.npol):
644                sp = s._getspectrum( irow )[start:end]
645                spectra[ip,i] = numpy.mean( sp )
646                irow += 1
647           
648        return spectra
649
650    def __chanIndex( self, idx ):
651        s = scantable( self.outfile, average=False )
652        nrow = s.nrow()
653        spectra = numpy.zeros( (self.npol,nrow/self.npol), dtype=float )
654        irow = 0
655        sp = [0 for i in xrange(self.nchan)]
656        for i in xrange(nrow/self.npol):
657            for ip in xrange(self.npol):
658                sp = s._getspectrum( irow )
659                spectra[ip,i] = sp[idx]
660                irow += 1
661        return spectra
662       
663           
Note: See TracBrowser for help on using the repository browser.