source: trunk/python/asapgrid.py @ 2396

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

New Development: No

JIRA Issue: Yes CAS-2816

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 min/max clipping functionality.
Introduced control parameter and methods for clipping.

File size: 13.5 KB
Line 
1import numpy
2from asap import rcParams
3from asap.scantable import scantable
4from asap.selector import selector
5from asap._asap import stgrid
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       # actual gridding
29       g.grid()
30       # save result
31       g.save( outfile='grid.asap' )
32       # plot result
33       g.plot( plotchan=1246, plotpol=-1, plotgrid=True, plotobs=True )
34    """
35    def __init__( self, infile ):
36        """
37        Create asapgrid instance.
38
39        infile -- input data as a string or string list if you want
40                  to grid more than one data at once. 
41        """
42        self.outfile = None
43        self.ifno = None
44        self.gridder = stgrid()
45        self.setData( infile )
46
47    def setData( self, infile ):
48        """
49        Set data to be processed.
50
51        infile -- input data as a string or string list if you want
52                  to grid more than one data at once. 
53        """
54        if isinstance( infile, str ):
55            self.gridder._setin( infile )
56        else:
57            self.gridder._setfiles( infile )
58        self.infile = infile
59
60    def setIF( self, ifno ):
61        """
62        Set IFNO to be processed. Currently, asapgrid allows to process
63        only one IFNO for one gridding run even if the data contains
64        multiple IFs. If you didn't specify IFNO, default value, which
65        is IFNO in the first spectrum, will be processed.
66
67        ifno -- IFNO to be processed.
68        """
69        self.ifno = ifno
70        self.gridder._setif( self.ifno )
71
72    def setPolList( self, pollist ):
73        """
74        Set list of polarization components you want to process.
75        If not specified, all POLNOs will be processed.
76
77        pollist -- list of POLNOs.
78        """
79        self.gridder._setpollist( pollist )
80
81    def setScanList( self, scanlist ):
82        """
83        Set list of scans you want to process. If not specified, all
84        scans will be processed.
85
86        scanlist -- list of SCANNOs.
87        """
88        self.gridder._setscanlist( scanlist )
89
90    def defineImage( self, nx=-1, ny=-1, cellx='', celly='', center='' ):
91        """
92        Define spatial grid.
93
94        First two parameters, nx and ny, define number of pixels of
95        the grid. If which of those is not specified, it will be set
96        to the same value as the other. If none of them are specified,
97        it will be determined from map extent and cell size.
98
99        Next two parameters, cellx and celly, define size of pixel.
100        You should set those parameters as string, which is constructed
101        numerical value and unit, e.g. '0.5arcmin', or numerical value.
102        If those values are specified as numerical value, their units
103        will be assumed to 'arcmin'. If which of those is not specified,
104        it will be set to the same value as the other. If none of them
105        are specified, it will be determined from map extent and number
106        of pixels, or set to '1arcmin' if neither nx nor ny is set.
107
108        The last parameter, center, define the central coordinate of
109        the grid. You should specify its value as a string, like,
110
111           'J2000 05h08m50s -16d23m30s'
112
113        or
114
115           'J2000 05:08:50 -16.23.30'
116
117        You can omit equinox when you specify center coordinate. In that
118        case, J2000 is assumed. If center is not specified, it will be
119        determined from the observed positions of input data.
120
121        nx -- number of pixels along x (R.A.) direction.
122        ny -- number of pixels along y (Dec.) direction.
123        cellx -- size of pixel in x (R.A.) direction.
124        celly -- size of pixel in y (Dec.) direction.
125        center -- central position of the grid.
126        """
127        if not isinstance( cellx, str ):
128            cellx = '%sarcmin'%(cellx)
129        if not isinstance( celly, str ):
130            celly = '%sarcmin'%(celly)
131        self.gridder._defineimage( nx, ny, cellx, celly, center )
132
133    def setFunc( self, func='box', width=-1 ):
134        """
135        Set convolution function. Possible options are 'box' (Box-car,
136        default), 'sf' (prolate spheroidal), and 'gauss' (Gaussian).
137        Width of convolution function can be set using width parameter.
138        By default (-1), width is automatically set depending on each
139        convolution function. Default values for width are:
140
141           'box': 1 pixel
142           'sf': 3 pixels
143           'gauss': 3 pixels (width is used as HWHM)
144
145        func -- Function type ('box', 'sf', 'gauss').
146        width -- Width of convolution function. Default (-1) is to
147                 choose pre-defined value for each convolution function.
148        """
149        self.gridder._setfunc( func, width )
150
151    def setWeight( self, weightType='uniform' ):
152        """
153        Set weight type. Possible options are 'uniform' (default),
154        'tint' (weight by integration time), 'tsys' (weight by
155        Tsys: 1/Tsys**2), and 'tintsys' (weight by integration time
156        as well as Tsys: tint/Tsys**2).
157
158        weightType -- weight type ('uniform', 'tint', 'tsys', 'tintsys')
159        """
160        self.gridder._setweight( weightType )
161
162    def enableClip( self ):
163        """
164        Enable min/max clipping.
165
166        By default, min/max clipping is disabled so that you should
167        call this method before actual gridding if you want to do
168        clipping.
169        """
170        self.gridder._enableclip()
171
172    def disableClip( self ):
173        """
174        Disable min/max clipping.
175        """
176        self.gridder._disableclip()
177
178    def grid( self ):
179        """
180        Actual gridding which will be done based on several user inputs.
181        """
182        self.gridder._grid()
183
184    def save( self, outfile='' ):
185        """
186        Save result. By default, output data name will be constructed
187        from first element of input data name list (e.g. 'input.asap.grid').
188
189        outfile -- output data name.
190        """
191        self.outfile = self.gridder._save( outfile )
192
193    def plot( self, plotchan=-1, plotpol=-1, plotobs=False, plotgrid=False ):
194        """
195        Plot gridded data.
196
197        plotchan -- Which channel you want to plot. Default (-1) is
198                    to average all the channels.
199        plotpol -- Which polarization component you want to plot.
200                   Default (-1) is to average all the polarization
201                   components.
202        plotobs -- Also plot observed position if True. Default
203                   is False. Setting True for large amount of spectra
204                   might be time consuming.
205        plotgrid -- Also plot grid center if True. Default is False.
206                    Setting True for large number of grids might be
207                    time consuming.
208        """
209        import time
210        t0=time.time()
211        # to load scantable on disk
212        storg = rcParams['scantable.storage']
213        rcParams['scantable.storage'] = 'disk'
214        plotter = _SDGridPlotter( self.infile, self.outfile, self.ifno )
215        plotter.plot( chan=plotchan, pol=plotpol, plotobs=plotobs, plotgrid=plotgrid )
216        # back to original setup
217        rcParams['scantable.storage'] = storg
218        t1=time.time()
219        asaplog.push('plot: elapsed time %s sec'%(t1-t0))
220        asaplog.post('DEBUG','asapgrid.plot')
221       
222class _SDGridPlotter:
223    def __init__( self, infile, outfile=None, ifno=-1 ):
224        if isinstance( infile, str ):
225            self.infile = [infile]
226        else:
227            self.infile = infile
228        self.outfile = outfile
229        if self.outfile is None:
230            self.outfile = self.infile[0].rstrip('/')+'.grid'
231        self.nx = -1
232        self.ny = -1
233        self.nchan = 0
234        self.npol = 0
235        self.pollist = []
236        self.cellx = 0.0
237        self.celly = 0.0
238        self.center = [0.0,0.0]
239        self.nonzero = [[0.0],[0.0]]
240        self.ifno = ifno
241        self.tablein = None
242        self.nrow = 0
243        self.blc = None
244        self.trc = None
245        self.get()
246
247    def get( self ):
248        s = scantable( self.outfile, average=False )
249        self.nchan = len(s._getspectrum(0))
250        nrow = s.nrow()
251        pols = numpy.ones( nrow, dtype=int )
252        for i in xrange(nrow):
253            pols[i] = s.getpol(i)
254        self.pollist, indices = numpy.unique( pols, return_inverse=True )
255        self.npol = len(self.pollist)
256        self.pollist = self.pollist[indices[:self.npol]]
257        #print 'pollist=',self.pollist
258        #print 'npol=',self.npol
259        #print 'nrow=',nrow
260
261        idx = 0
262        d0 = s.get_direction( 0 ).split()[-1]
263        while ( s.get_direction(self.npol*idx).split()[-1] == d0 ): 
264            idx += 1
265       
266        self.nx = idx
267        self.ny = nrow / (self.npol * idx )
268        #print 'nx,ny=',self.nx,self.ny
269
270        self.blc = s.get_directionval( 0 )
271        self.trc = s.get_directionval( nrow-self.npol )
272        #print self.blc
273        #print self.trc
274        incrx = s.get_directionval( self.npol )
275        incry = s.get_directionval( self.nx*self.npol )
276        self.cellx = abs( self.blc[0] - incrx[0] )
277        self.celly = abs( self.blc[1] - incry[1] )
278        #print 'cellx,celly=',self.cellx,self.celly
279
280    def plot( self, chan=-1, pol=-1, plotobs=False, plotgrid=False ):
281        if pol < 0:
282            opt = 'averaged over pol'
283        else:
284            opt = 'pol %s'%(pol)
285        if chan < 0:
286            opt += ', averaged over channel'
287        else:
288            opt += ', channel %s'%(chan)
289        data = self.getData( chan, pol )
290        title = 'Gridded Image (%s)'%(opt)
291        pl.figure(10)
292        pl.clf()
293        # plot grid position
294        if plotgrid:
295            x = numpy.arange(self.blc[0],self.trc[0]+0.5*self.cellx,self.cellx,dtype=float)
296            #print 'len(x)=',len(x)
297            #print 'x=',x
298            ybase = numpy.ones(self.nx,dtype=float)*self.blc[1]
299            #print 'len(ybase)=',len(ybase)
300            incr = self.celly
301            for iy in xrange(self.ny):
302                y = ybase + iy * incr
303                #print y
304                pl.plot(x,y,',',color='blue')
305        # plot observed position
306        if plotobs:
307            for i in xrange(len(self.infile)):
308                self.createTableIn( self.infile[i] )
309                irow = 0
310                while ( irow < self.nrow ):
311                    chunk = self.getPointingChunk( irow )
312                    #print chunk
313                    pl.plot(chunk[0],chunk[1],',',color='green')
314                    irow += chunk.shape[1]
315                    #print irow
316        # show image
317        extent=[self.blc[0]-0.5*self.cellx,
318                self.trc[0]+0.5*self.cellx,
319                self.blc[1]-0.5*self.celly,
320                self.trc[1]+0.5*self.celly]
321        pl.imshow(data,extent=extent,origin='lower',interpolation='nearest')
322        pl.colorbar()
323        pl.xlabel('R.A. [rad]')
324        pl.ylabel('Dec. [rad]')
325        pl.title( title )
326
327    def createTableIn( self, tab ):
328        del self.tablein
329        self.tablein = scantable( tab, average=False )
330        if self.ifno < 0:
331            ifno = self.tablein.getif(0)
332            print 'ifno=',ifno
333        else:
334            ifno = self.ifno
335        sel = selector()
336        sel.set_ifs( ifno )
337        self.tablein.set_selection( sel )
338        self.nchan = len(self.tablein._getspectrum(0))
339        self.nrow = self.tablein.nrow()
340        del sel
341       
342
343    def getPointingChunk( self, irow ):
344        numchunk = 1000
345        nrow = min( self.nrow-irow, numchunk )
346        #print 'nrow=',nrow
347        v = numpy.zeros( (2,nrow), dtype=float )
348        idx = 0
349        for i in xrange(irow,irow+nrow):
350            d = self.tablein.get_directionval( i )
351            v[0,idx] = d[0]
352            v[1,idx] = d[1]
353            idx += 1
354        return v
355
356    def getData( self, chan=-1, pol=-1 ):
357        if chan == -1:
358            spectra = self.__chanAverage()
359        else:
360            spectra = self.__chanIndex( chan )
361        data = spectra.reshape( (self.npol,self.ny,self.nx) )
362        if pol == -1:
363            retval = data.mean(axis=0)
364        else:
365            retval = data[pol]
366        return retval
367
368    def __chanAverage( self ):
369        s = scantable( self.outfile, average=False )
370        nrow = s.nrow()
371        spectra = numpy.zeros( (self.npol,nrow/self.npol), dtype=float )
372        irow = 0
373        sp = [0 for i in xrange(self.nchan)]
374        for i in xrange(nrow/self.npol):
375            for ip in xrange(self.npol):
376                sp = s._getspectrum( irow )
377                spectra[ip,i] = numpy.mean( sp )
378                irow += 1
379        return spectra
380
381    def __chanIndex( self, idx ):
382        s = scantable( self.outfile, average=False )
383        nrow = s.nrow()
384        spectra = numpy.zeros( (self.npol,nrow/self.npol), dtype=float )
385        irow = 0
386        sp = [0 for i in xrange(self.nchan)]
387        for i in xrange(nrow/self.npol):
388            for ip in xrange(self.npol):
389                sp = s._getspectrum( irow )
390                spectra[ip,i] = sp[idx]
391                irow += 1
392        return spectra
393       
394           
Note: See TracBrowser for help on using the repository browser.