1- import autoarray as aa
2-
3- from autoarray .dataset import imaging
1+ import os
42
3+ from autoarray .util import array_util
4+ from autoarray .structures import grids , kernel
5+ from autoarray .dataset import imaging , interferometer
6+ from autoarray .operators import fourier_transform
57
68class ImagingSimulator (object ):
79 def __init__ (
@@ -66,7 +68,7 @@ def lsst(
6668 """Default settings for an observation with the Large Synotpic Survey Telescope.
6769
6870 This can be customized by over-riding the default input values."""
69- psf = aa . kernel .from_gaussian (
71+ psf = kernel . Kernel .from_gaussian (
7072 shape_2d = psf_shape_2d , sigma = psf_sigma , pixel_scales = pixel_scales
7173 )
7274 return ImagingSimulator (
@@ -98,7 +100,7 @@ def euclid(
98100 """Default settings for an observation with the Euclid space satellite.
99101
100102 This can be customized by over-riding the default input values."""
101- psf = aa . kernel .from_gaussian (
103+ psf = kernel . Kernel .from_gaussian (
102104 shape_2d = psf_shape_2d , sigma = psf_sigma , pixel_scales = pixel_scales
103105 )
104106 return ImagingSimulator (
@@ -130,7 +132,7 @@ def hst(
130132 """Default settings for an observation with the Hubble Space Telescope.
131133
132134 This can be customized by over-riding the default input values."""
133- psf = aa . kernel .from_gaussian (
135+ psf = kernel . Kernel .from_gaussian (
134136 shape_2d = psf_shape_2d , sigma = psf_sigma , pixel_scales = pixel_scales
135137 )
136138 return ImagingSimulator (
@@ -163,7 +165,7 @@ def hst_up_sampled(
163165 pixel-scale to better sample the PSF.
164166
165167 This can be customized by over-riding the default input values."""
166- psf = aa . kernel .from_gaussian (
168+ psf = kernel . Kernel .from_gaussian (
167169 shape_2d = psf_shape_2d , sigma = psf_sigma , pixel_scales = pixel_scales
168170 )
169171 return ImagingSimulator (
@@ -195,7 +197,7 @@ def keck_adaptive_optics(
195197 """Default settings for an observation using Keck Adaptive Optics imaging.
196198
197199 This can be customized by over-riding the default input values."""
198- psf = aa . kernel .from_gaussian (
200+ psf = kernel . Kernel .from_gaussian (
199201 shape_2d = psf_shape_2d , sigma = psf_sigma , pixel_scales = pixel_scales
200202 )
201203 return ImagingSimulator (
@@ -212,7 +214,7 @@ def keck_adaptive_optics(
212214
213215 @property
214216 def grid (self ):
215- return aa . grid .uniform (
217+ return grids . Grid .uniform (
216218 shape_2d = self .shape_2d ,
217219 pixel_scales = self .pixel_scales ,
218220 sub_size = self .sub_size ,
@@ -252,3 +254,140 @@ def from_image(self, image, name=None):
252254 noise_seed = self .noise_seed ,
253255 name = name ,
254256 )
257+
258+
259+ class InterferometerSimulator (object ):
260+ def __init__ (
261+ self ,
262+ real_space_shape_2d ,
263+ real_space_pixel_scales ,
264+ uv_wavelengths ,
265+ sub_size ,
266+ exposure_time ,
267+ background_sky_level ,
268+ primary_beam = None ,
269+ noise_sigma = 0.1 ,
270+ noise_if_add_noise_false = 0.1 ,
271+ noise_seed = - 1 ,
272+ origin = (0.0 , 0.0 ),
273+ ):
274+ """A class representing a Imaging observation, using the shape of the image, the pixel scale,
275+ psf, exposure time, etc.
276+
277+ Parameters
278+ ----------
279+ real_space_shape_2d : (int, int)
280+ The shape of the observation. Note that we do not simulator a full Imaging frame (e.g. 2000 x 2000 pixels for \
281+ Hubble imaging), but instead just a cut-out around the strong lens.
282+ real_space_pixel_scales : float
283+ The size of each pixel in arc seconds.
284+ psf : PSF
285+ An arrays describing the PSF kernel of the image.
286+ exposure_time : float
287+ The exposure time of an observation using this data_type.
288+ background_sky_level : float
289+ The level of the background sky of an observationg using this data_type.
290+ """
291+
292+ if type (real_space_pixel_scales ) is float :
293+ real_space_pixel_scales = (real_space_pixel_scales , real_space_pixel_scales )
294+
295+ self .real_space_shape_2d = real_space_shape_2d
296+ self .real_space_pixel_scales = real_space_pixel_scales
297+ self .uv_wavelengths = uv_wavelengths
298+ self .sub_size = sub_size
299+ self .origin = origin
300+ self .transformer = fourier_transform .Transformer (uv_wavelengths = self .uv_wavelengths , grid_radians = self .grid .in_1d_binned .in_radians )
301+ self .exposure_time = exposure_time
302+ self .background_sky_level = background_sky_level
303+ self .primary_beam = primary_beam
304+ self .noise_sigma = noise_sigma
305+ self .noise_if_add_noise_false = noise_if_add_noise_false
306+ self .noise_seed = noise_seed
307+
308+ @property
309+ def grid (self ):
310+ return grids .Grid .uniform (
311+ shape_2d = self .real_space_shape_2d ,
312+ pixel_scales = self .real_space_pixel_scales ,
313+ sub_size = self .sub_size ,
314+ origin = self .origin ,
315+ )
316+
317+ @classmethod
318+ def sma (
319+ cls ,
320+ real_space_shape_2d = (151 , 151 ),
321+ real_space_pixel_scales = (0.05 , 0.05 ),
322+ sub_size = 8 ,
323+ primary_beam_shape_2d = None ,
324+ primary_beam_sigma = None ,
325+ exposure_time = 100.0 ,
326+ background_sky_level = 1.0 ,
327+ noise_sigma = 0.1 ,
328+ noise_if_add_noise_false = 0.1 ,
329+ noise_seed = - 1 ,
330+ ):
331+ """Default settings for an observation with the Large Synotpic Survey Telescope.
332+
333+ This can be customized by over-riding the default input values."""
334+
335+ uv_wavelengths_path = "{}/dataset/sma_uv_wavelengths.fits" .format (
336+ os .path .dirname (os .path .realpath (__file__ )))
337+
338+ uv_wavelengths = array_util .numpy_array_1d_from_fits (file_path = uv_wavelengths_path , hdu = 0 )
339+
340+ if primary_beam_shape_2d is not None and primary_beam_sigma is not None :
341+ primary_beam = kernel .Kernel .from_gaussian (
342+ shape_2d = primary_beam_shape_2d , sigma = primary_beam_sigma , pixel_scales = real_space_pixel_scales
343+ )
344+ else :
345+ primary_beam = None
346+
347+ return InterferometerSimulator (
348+ real_space_shape_2d = real_space_shape_2d ,
349+ real_space_pixel_scales = real_space_pixel_scales ,
350+ uv_wavelengths = uv_wavelengths ,
351+ sub_size = sub_size ,
352+ primary_beam = primary_beam ,
353+ exposure_time = exposure_time ,
354+ background_sky_level = background_sky_level ,
355+ noise_sigma = noise_sigma ,
356+ noise_if_add_noise_false = noise_if_add_noise_false ,
357+ noise_seed = noise_seed ,
358+ )
359+
360+ def from_real_space_image (self , real_space_image ):
361+ """
362+ Create a realistic simulated image by applying effects to a plain simulated image.
363+
364+ Parameters
365+ ----------
366+ name
367+ real_space_image : ndarray
368+ The image before simulating (e.g. the lens and source galaxies before optics blurring and Imaging read-out).
369+ pixel_scales: float
370+ The scale of each pixel in arc seconds
371+ exposure_time_map : ndarray
372+ An arrays representing the effective exposure time of each pixel.
373+ psf: PSF
374+ An arrays describing the PSF the simulated image is blurred with.
375+ background_sky_map : ndarray
376+ The value of background sky in every image pixel (electrons per second).
377+ add_noise: Bool
378+ If True poisson noise_maps is simulated and added to the image, based on the total counts in each image
379+ pixel
380+ noise_seed: int
381+ A seed for random noise_maps generation
382+ """
383+ return interferometer .SimulatedInterferometer .simulate (
384+ real_space_image = real_space_image ,
385+ real_space_pixel_scales = self .real_space_pixel_scales ,
386+ exposure_time = self .exposure_time ,
387+ transformer = self .transformer ,
388+ primary_beam = self .primary_beam ,
389+ background_sky_level = self .background_sky_level ,
390+ noise_sigma = self .noise_sigma ,
391+ noise_if_add_noise_false = self .noise_if_add_noise_false ,
392+ noise_seed = self .noise_seed ,
393+ )
0 commit comments