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.