source: trunk/python/asapgrid.py @ 2671

Last change on this file since 2671 was 2671, 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...

Implemented gauss and gjinc gridding. Added some arguments to
pass necessary parameters for those grid functions.

Also, defined helper function that plots current grid function
against radius in pixel.


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