@@ -248,7 +248,7 @@ def uvw_to_dict(self):
248248 else :
249249 self .uvbins [uv ] = [uv ]
250250
251- def uv_weights (self , u , v ):
251+ def uv_weights (self , u , v , spatial_function = "triangle" ):
252252 """Compute weights for arbitrary baseline on a gridded UV plane.
253253
254254 uv must be in units of pixels.
@@ -259,19 +259,32 @@ def uv_weights(self, u, v):
259259 # weights = np.exp( - abs(uv - grid)/(np.diff(grid)[0]))
260260 _range = np .arange (self .uv_size ) - (self .uv_size - 1 ) / 2.0
261261 _range *= self .uv_delta
262- x , y = np .meshgrid (_range , _range )
263- x .shape += (1 ,)
264- y .shape += (1 ,)
265- x = u - x
266- y = v - y
267- dists = np .linalg .norm ([x , y ], axis = 0 )
268- weights = 1.0 - dists / self .wavelength_scale
269- weights = np .ma .masked_less_equal (weights , 0 ).filled (0 )
270- weights /= np .sum (weights , axis = (0 , 1 ))
271- weights = np .transpose (weights , [2 , 0 , 1 ])
262+ match spatial_function .casefold ():
263+ case "triangle" :
264+ x , y = np .meshgrid (_range , _range )
265+ x .shape += (1 ,)
266+ y .shape += (1 ,)
267+ x = u - x
268+ y = v - y
269+ dists = np .linalg .norm ([x , y ], axis = 0 )
270+ weights = 1.0 - dists / self .wavelength_scale
271+ weights = np .ma .masked_less_equal (weights , 0 ).filled (0 )
272+ weights /= np .sum (weights , axis = (0 , 1 ))
273+ weights = np .transpose (weights , [2 , 0 , 1 ])
274+ case "nearest" :
275+ u_index = np .argmin (np .abs (u - _range ))
276+ v_index = np .argmin (np .abs (v - _range ))
277+ print (f"{ u_index = :} , { v_index = :} " )
278+ weights = np .zeros ((1 , self .uv_size , self .uv_size ), dtype = complex )
279+ weights [0 , u_index , v_index ] = 1.0
280+ case _:
281+ raise ValueError (
282+ f"Unknown value for 'spatial_function': { spatial_function } "
283+ )
284+
272285 return weights
273286
274- def __sum_uv__ (self , uv_key ):
287+ def __sum_uv__ (self , uv_key , spatial_function = "triangle" ):
275288 """Convert uvbin dictionary to a UV-plane."""
276289 uvbin = self .uvbins [uv_key ]
277290 nbls = len (uvbin )
@@ -280,10 +293,10 @@ def __sum_uv__(self, uv_key):
280293 v /= self .wavelength
281294 _beam = np .zeros ((self .freqs .size , self .uv_size , self .uv_size ), dtype = complex )
282295 # Create interpolation weights based on grid size and sampling
283- _beam += self .uv_weights (u , v )
296+ _beam += self .uv_weights (u , v , spatial_function = spatial_function )
284297 self .uvf_cube += nbls * _beam
285298
286- def grid_uvw (self ):
299+ def grid_uvw (self , convolve_beam = True , spatial_function = "triangle" ):
287300 """Create UV coverage from object data."""
288301 self .uv_size = (
289302 int (np .round (self .bl_len_max / self .wavelength / self .uv_delta ).max () * 1.1 )
@@ -294,27 +307,40 @@ def grid_uvw(self):
294307 (self .freqs .size , self .uv_size , self .uv_size ), dtype = complex
295308 )
296309 for uv_key in self .uvbins .keys ():
297- self .__sum_uv__ (uv_key )
310+ self .__sum_uv__ (uv_key , spatial_function = spatial_function )
298311 beam_array = self .get_uv_beam ()
299312 # if only one beam was given, use that beam for all freqs
300313 if np .shape (beam_array )[0 ] < self .freqs .size :
301314 beam_array = np .tile (beam_array [0 ], (self .freqs .size , 1 , 1 ))
302- for _fq in range (self .freqs .size ):
303- beam = beam_array [_fq ]
304- self .uvf_cube [_fq ] = fftconvolve (self .uvf_cube [_fq ], beam , mode = "same" )
305315
306- def calc_all (self , refresh_all = True ):
316+ if convolve_beam :
317+ for _fq in range (self .freqs .size ):
318+ beam = beam_array [_fq ]
319+ self .uvf_cube [_fq ] = fftconvolve (self .uvf_cube [_fq ], beam , mode = "same" )
320+
321+ def calc_all (
322+ self , refresh_all = True , convolve_beam = True , spatial_function = "triangle"
323+ ):
307324 """Calculate all necessary info.
308325
309326 Perform All calculations:
310327 Convert uvw_array to dict (uvw_to_dict())
311328 Grid uvw to plane (grid_uvw())
312- refresh_all : boolean, if true, recalculate the uvbins
329+
330+ Parameters
331+ -----------
332+ refresh_all : boolean,
333+ if true, recalculate the uvbins
334+ convolve_beam: bool
335+ when set to true, perform an FFT convolution with the supplied beam
336+ spatial_function: string
337+ must be one of ["nearest", "triangle"]. Nearest modes performs delta function like assignment into a uv-bin
338+ triangle performs simple distance based weighting of uv-bins based on self.wavelength_scale slope
313339 """
314340 if refresh_all :
315341 self .uvbins = {}
316342 self .uvf_cube = None
317343 if self .n_obs > 1 :
318344 self .simulate_observation ()
319345 self .uvw_to_dict ()
320- self .grid_uvw ()
346+ self .grid_uvw (convolve_beam = convolve_beam , spatial_function = spatial_function )
0 commit comments