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