source: trunk/python/asapgrid.py@ 2669

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

Use DirectionCoordinate for conversion between world and pixel.


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