| 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
 | 
|---|
| 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', 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 |         
 | 
|---|
| 222 | class _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 |             
 | 
|---|