def test__all_individual_plotter( tracer_x2_plane_7x7, sub_grid_7x7, mask_7x7, include_2d_all, plot_path, plot_patch ): tracer_plotter = aplt.TracerPlotter( tracer=tracer_x2_plane_7x7, grid=sub_grid_7x7, mat_plot_2d=aplt.MatPlot2D(output=aplt.Output(plot_path, format="png")), ) tracer_plotter.figures( image=True, source_plane=True, convergence=True, potential=True, deflections_y=True, deflections_x=True, magnification=True, ) assert path.join(plot_path, "image.png") in plot_patch.paths assert path.join(plot_path, "plane_image_of_plane_1.png") in plot_patch.paths assert path.join(plot_path, "convergence.png") in plot_patch.paths assert path.join(plot_path, "potential.png") in plot_patch.paths assert path.join(plot_path, "deflections_y.png") in plot_patch.paths assert path.join(plot_path, "deflections_x.png") in plot_patch.paths assert path.join(plot_path, "magnification.png") in plot_patch.paths tracer_x2_plane_7x7.planes[0].galaxies[0].hyper_galaxy = al.HyperGalaxy() tracer_x2_plane_7x7.planes[0].galaxies[0].hyper_model_image = al.Array2D.ones( shape_native=(7, 7), pixel_scales=0.1 ) tracer_x2_plane_7x7.planes[0].galaxies[0].hyper_galaxy_image = al.Array2D.ones( shape_native=(7, 7), pixel_scales=0.1 ) tracer_plotter.figures(contribution_map=True) assert path.join(plot_path, "contribution_map.png") in plot_patch.paths plot_patch.paths = [] tracer_plotter = aplt.TracerPlotter( tracer=tracer_x2_plane_7x7, grid=sub_grid_7x7, include_2d=include_2d_all, mat_plot_2d=aplt.MatPlot2D(output=aplt.Output(plot_path, format="png")), ) tracer_plotter.figures( image=True, source_plane=True, potential=True, magnification=True ) assert path.join(plot_path, "image.png") in plot_patch.paths assert path.join(plot_path, "plane_image_of_plane_1.png") in plot_patch.paths assert path.join(plot_path, "convergence.png") not in plot_patch.paths assert path.join(plot_path, "potential.png") in plot_patch.paths assert path.join(plot_path, "deflections_y.png") not in plot_patch.paths assert path.join(plot_path, "deflections_x.png") not in plot_patch.paths assert path.join(plot_path, "magnification.png") in plot_patch.paths
def test__figures_of_plane( tracer_x2_plane_7x7, sub_grid_2d_7x7, mask_2d_7x7, include_2d_all, plot_path, plot_patch, ): tracer_plotter = aplt.TracerPlotter( tracer=tracer_x2_plane_7x7, grid=sub_grid_2d_7x7, include_2d=include_2d_all, mat_plot_2d=aplt.MatPlot2D( output=aplt.Output(path=plot_path, format="png")), ) tracer_plotter.figures_2d_of_planes(plane_image=True, plane_grid=True) assert path.join(plot_path, "plane_image_of_plane_0.png") in plot_patch.paths assert path.join(plot_path, "plane_image_of_plane_1.png") in plot_patch.paths plot_patch.paths = [] tracer_plotter.figures_2d_of_planes(plane_image=True, plane_index=0) assert path.join(plot_path, "plane_image_of_plane_0.png") in plot_patch.paths assert path.join(plot_path, "plane_image_of_plane_1.png") not in plot_patch.paths
def test__tracer_sub_plot_output(tracer_x2_plane_7x7, sub_grid_7x7, include_2d_all, plot_path, plot_patch): tracer_plotter = aplt.TracerPlotter( tracer=tracer_x2_plane_7x7, grid=sub_grid_7x7, include_2d=include_2d_all, mat_plot_2d=aplt.MatPlot2D( output=aplt.Output(plot_path, format="png")), ) tracer_plotter.subplot_tracer() assert path.join(plot_path, "subplot_tracer.png") in plot_patch.paths
angle=60.0), intensity=3.0, effective_radius=0.4, sersic_index=1.0, ), point_0=al.ps.Point(centre=(0.0, 0.1)), ) """ Use these galaxies to setup a tracer, which will generate the image for the simulated `Imaging` dataset. """ tracer = al.Tracer.from_galaxies( galaxies=[lens_galaxy_0, lens_galaxy_1, lens_galaxy_2, source_galaxy]) """ Lets look at the tracer`s image, this is the image we'll be simulating. """ tracer_plotter = aplt.TracerPlotter(tracer=tracer, grid=grid) tracer_plotter.figures_2d(image=True) """ __Point Source__ It is common for group-scale strong lens datasets to be modeled assuming that the source is a point-source. Even if it isn't, this can be necessary due to computational run-time making it unfeasible to fit the imaging dataset outright. We will use a `PositionSolver` to locate the multiple images, using computationally slow but robust settings to ensure w e accurately locate the image-plane positions. """ solver = al.PointSolver( grid=grid, use_upscaling=True, pixel_scale_precision=0.001, upscale_factor=2,
intensity=0.3, effective_radius=1.0, sersic_index=2.5, ), ) tracer = al.Tracer.from_galaxies(galaxies=[lens_galaxy, source_galaxy]) """ Following the lensing.py example, we can make a tracer from a collection of `LightProfile`, `MassProfile` and `Galaxy` objects. We can then use the `FitImaging` object to fit this tracer to the dataset. The fit performs the necessary tasks to create the model image we fit the data with, such as blurring the tracer`s image with the `Imaging` PSF. We can see this by comparing the tracer`s image (which isn't PSF convolved) and the fit`s model image (which is). """ tracer_plotter = aplt.TracerPlotter(tracer=tracer, grid=imaging.grid) tracer_plotter.figures_2d(image=True) fit = al.FitImaging(imaging=imaging, tracer=tracer) fit_imaging_plotter = aplt.FitImagingPlotter(fit=fit) fit_imaging_plotter.figures_2d(model_image=True) """ The fit creates the following: - The residual-map: The model-image subtracted from the observed dataset`s image. - The normalized residual-map: The residual-map divided by the noise-map. - The chi-squared-map: The normalized residual-map squared. we'll plot all 3 of these, alongside a subplot containing them all.
to create the appropriate strong lens system. """ tracer = al.Tracer.from_galaxies(galaxies=[lens_galaxy, source_galaxy], cosmology=cosmo.Planck15) """ __Ray Tracing__ We can now create the image of a strong lens system! When calculating this image, the `Tracer` performs all ray-tracing for the strong lens system. This includes using the lens galaxy's total mass distribution to deflect the light-rays that are traced to the source galaxy. As a result, the source's appears as a multiply imaged and strongly lensed Einstein ring. """ image = tracer.image_2d_from(grid=grid) tracer_plotter = aplt.TracerPlotter(tracer=tracer, grid=grid) tracer_plotter.figures_2d(image=True) """ The `TracerPlotter` includes the `MassProfile` quantities we plotted previously, which can be plotted as a subplot that plots all these quantities simultaneously. """ tracer_plotter.subplot_tracer() """ The `Tracer` is composed of planes, for the system above just two planes, an image-plane (at redshift=0.5) and a source-plane (at redshift=1.0). When creating the image from a Tracer, the `MassProfile` is used to `ray-trace` the image-plane grid to the source-plane grid, via the `MassProfile`'s deflection angles. We can use the Tracer`s traced_grid method to plot the image-plane and source-plane grids. """ traced_grids = tracer.traced_grid_list_from(grid=grid)
""" __Model-Fit__ We can now begin the model-fit by passing the model and analysis object to the search, which performs a non-linear search to find which models fit the data with the highest likelihood. Checkout the output folder for live outputs of the results of the fit, including on-the-fly visualization of the best fit model! """ result = search.fit(model=model, analysis=analysis) """ __Result__ The search returns a result object, which includes: - The lens model corresponding to the maximum log likelihood solution in parameter space. - The corresponding maximum log likelihood `Tracer` object. - Information on the posterior as estimated by the `Dynesty` non-linear search. """ print(result.max_log_likelihood_instance) tracer_plotter = aplt.TracerPlotter(tracer=result.max_log_likelihood_tracer, grid=result.grid) tracer_plotter.subplot_tracer() dynesty_plotter = aplt.DynestyPlotter(samples=result.samples) dynesty_plotter.cornerplot() """ Checkout `autolens_workspace/notebooks/modeling/results.py` for a full description of the result object. """
Only the `LightProfile` centre is used by the position solver, but a light profile is used to visalize the lensed source. """ light_profile = light_profile_model.random_instance() """Setup the lens, source and _Tracer_.""" lens_galaxy = al.Galaxy(redshift=0.5, mass=mass_profile) source_galaxy = al.Galaxy(redshift=1.0, light=light_profile) tracer = al.Tracer.from_galaxies(galaxies=[lens_galaxy, source_galaxy]) """Solve for the positions via the _Tracer_.""" positions = solver.solve( lensing_obj=tracer, source_plane_coordinate=tracer.source_plane.galaxies[0].light.centre, ) """Visually inspect the positions (comment this out if you are confident the code is behaving as expected).""" visuals_2d = aplt.Visuals2D(positions=positions) tracer_plotter = aplt.TracerPlotter(tracer=tracer, grid=grid, visuals_2d=visuals_2d) tracer_plotter.figures(image=True) """Save the `Tracer` and `Positions` so they can be used for testing other `PositionsSolver` settings.""" tracer.save(file_path=pickle_path, filename=f"tracer_{str(i)}") positions.save(file_path=pickle_path, filename=f"positions_{str(i)}")
mapper_plotter = aplt.MapperPlotter( mapper=fit.inversion.linear_obj_list[0], visuals_2d=visuals_2d, include_2d=include_2d, ) mapper_plotter.subplot_image_and_mapper(image=fit.imaging.image) """ So, why is this happening? What is the mass profile physically doing to create these source plane coordinates at extremely large radial values? Towards the centre of th elliptical isothermal mass profile, the density begins to rise very sharply, it becomes extremely steep or 'cuspy'. This cuspy behaviour towards its centre can cause extremely large deflection angles to be calculated: """ tracer_plotter = aplt.TracerPlotter(tracer=fit.tracer, grid=fit.grid) tracer_plotter.figures_2d(deflections_y=True, deflections_x=True) """ Central image pixel can therefore be subjected to 'demagnification', whereby they trace to extremely large values in the source plane! Physically, this is not a problem, and it is the reason we do not see a 'central image' in most strong lenses, as the light-rays which take this path through the centre of the lens are demagnified. However, if the lens galaxy had a less steep inner mass distribution (termed a 'core') we would see the central image. Demagnification is a problem for the pixelization and inversion though, which reconstruct the flux of these demagnified pixels just like the other pixels in the image-pixel. There are two negative consequences: 1) The rectangular pixel-grid that we 'lay over' the source-plane is very larger because it expands to include the demagnified image-pixels. As a result, larger source-pixels are used to reconstruct the central regions of the source-plane (where the source galaxy is actually located), meaning we reconstruct the source-galaxy at a lower
computed. 2) These deflection angles are used to trace every image-plane coordinate to the source-plane. 3) The light of each traced source-plane coordinate is evaluated using the source plane galaxy's light profiles. """ traced_image = tracer.image_2d_from(grid=image_plane_grid) print("traced image pixel 1") print(traced_image.native[0, 0]) print("traced image pixel 2") print(traced_image.native[0, 1]) print("traced image pixel 3") print(traced_image.native[0, 2]) """ This image appears as the Einstein ring we saw in the previous tutorial. """ tracer_plotter = aplt.TracerPlotter(tracer=tracer, grid=image_plane_grid) tracer_plotter.figures_2d(image=True) """ We can also use the tracer to compute the traced grid of every plane: """ traced_grids = tracer.traced_grid_list_from(grid=image_plane_grid) """ The first traced grid corresponds to the image-plane grid (i.e. before lensing), whereas the second grid is that of the source-plane. """ print("grid image-plane (y,x) coordinate 1") print(traced_grids[0].native[0, 0]) print("grid image-plane (y,x) coordinate 2") print(traced_grids[0].native[0, 1])
search = af.DynestyStatic( path_prefix=path.join("imaging", "modeling"), name="mass[sie]_source[bulge]", unique_tag=dataset_name, nlive=50, ) analysis = al.AnalysisImaging(dataset=imaging) result = search.fit(model=model, analysis=analysis) """ Great, so we have the `Result` object we'll cover in this script. As a reminder, we can use the `max_log_likelihood_tracer` and `max_log_likelihood_fit` to plot the results of the fit: """ tracer_plotter = aplt.TracerPlotter(tracer=result.max_log_likelihood_tracer, grid=mask.masked_grid_sub_1) tracer_plotter.subplot_tracer() fit_imaging_plotter = aplt.FitImagingPlotter(fit=result.max_log_likelihood_fit) fit_imaging_plotter.subplot_fit_imaging() """ The result contains a lot more information about the model-fit. For example, its `Samples` object contains the complete set of non-linear search samples, for example every set of parameters evaluated, their log likelihoods and so on, which are used for computing information about the model-fit such as the error on every parameter. Our model-fit used the nested sampling algorithm Dynesty, so the `Samples` object returned is a `NestSamples` objct. """ samples = result.samples print("Nest Samples: \n") print(samples)
Checkout the output folder for live outputs of the results of the fit, including on-the-fly visualization of the best fit model! """ result = search.fit(model=model, analysis=analysis) """ __Result__ The search returns a result object, which includes: - The lens model corresponding to the maximum log likelihood solution in parameter space. - The corresponding maximum log likelihood `Tracer` and `FitInterferometer` objects. - Information on the posterior as estimated by the `Dynesty` non-linear search. """ print(result.max_log_likelihood_instance) tracer_plotter = aplt.TracerPlotter(tracer=result.max_log_likelihood_tracer, grid=real_space_mask.masked_grid_sub_1) tracer_plotter.subplot_tracer() fit_interferometer_plotter = aplt.FitInterferometerPlotter( fit=result.max_log_likelihood_fit) fit_interferometer_plotter.subplot_fit_interferometer() fit_interferometer_plotter.subplot_fit_dirty_images() dynesty_plotter = aplt.DynestyPlotter(samples=result.samples) dynesty_plotter.cornerplot() """ Checkout `autolens_workspace/notebooks/interferometer/modeling/results.py` for a full description of the result object. """
print(fit.tracer.image_plane.galaxies[0].mass) print() print(fit.tracer.source_plane.galaxies[0].bulge) print() print(fit.tracer.source_plane.galaxies[0].disk) print() # %% """ Using the mat_plot_2d we've used throughout this chapter, we can visualize any aspect of a fit we're interested in. For example, if we want to plot the image of the source galaxy `MassProfile`, we can do this in a variety of different ways """ # %% tracer_plotter = aplt.TracerPlotter(tracer=fit.tracer, grid=masked_imaging.grid) tracer_plotter.figures(image=True) source_plane_grid = tracer.traced_grids_of_planes_from_grid(grid=masked_imaging.grid)[1] plane_plotter = aplt.PlanePlotter(plane=tracer.source_plane, grid=source_plane_grid) plane_plotter.figures(image=True) galaxy_plotter = aplt.GalaxyPlotter( galaxy=fit.tracer.source_plane.galaxies[0], grid=source_plane_grid ) galaxy_plotter.figures(image=True) # %% """ As our fit and ray-tracing becomes more complex, it is useful to know how to decompose their different attributes to extract different things about them. For example, we made our source-galaxy above with two `LightProfile`'s, a
tracer = al.Tracer.from_galaxies(galaxies=[lens_galaxy, source_galaxy]) """ __Grid__ We also need an image-plane `Grid2D` which we'll ray-trace via the `Tracer`. """ grid = al.Grid2D.uniform(shape_native=(100, 100), pixel_scales=0.05) """ __Figures__ We now pass the tracer` and grid to a `TracerPlotter` and call various `figure_*` methods to plot different attributes. """ tracer_plotter = aplt.TracerPlotter(tracer=tracer, grid=grid) tracer_plotter.figures_2d( image=True, convergence=True, potential=True, deflections_y=True, deflections_x=True, magnification=True, ) """ __Subplots__ A subplot of the above quantaties can be plotted. """ tracer_plotter.subplot_tracer()
source_galaxy = al.Galaxy( redshift=1.0, bulge=al.lp.EllSersic( centre=(0.0, 0.0), elliptical_comps=al.convert.elliptical_comps_from(axis_ratio=0.8, angle=60.0), intensity=0.3, effective_radius=1.0, sersic_index=2.5, ), ) tracer = al.Tracer.from_galaxies(galaxies=[lens_galaxy, source_galaxy]) tracer_plotter = aplt.TracerPlotter(tracer=tracer, grid=real_space_mask.masked_grid_sub_1) tracer_plotter.figures_2d(image=True) """ __UV-Plane__ To perform uv-plane modeling, **PyAutoLens** next Fourier transforms this image from real-sapce to the uv-plane. This operation uses a *Transformer* object, of which there are multiple available in **PyAutoLens**. This includes a direct Fourier transform which performs the exact Fourier transformw without approximation. """ transformer_class = al.TransformerDFT """ However, the direct Fourier transform is inefficient. For ~10 million visibilities, it requires **thousands of seconds** to perform a single transform. To model a lens, we'll perform tens of thousands of transforms, making this approach unfeasible for high quality ALMA and radio datasets. For this reason, **PyAutoLens** supports the non-uniform fast fourier transform algorithm
mass=al.mp.SphericalIsothermal), source_galaxy=al.GalaxyModel(redshift=1.0, bulge=al.lp.SphericalExponential), ), ) result = phase.run(dataset=imaging, mask=mask) # %% """ In the previous tutorials, we saw that this result contains the maximum log likelihood tracer and fit, which provide a fast way to visualize the result. (Uncomment the line below to plot the tracer). """ tracer_plotter = aplt.TracerPlotter(tracer=result.max_log_likelihood_tracer, grid=mask.geometry.unmasked_grid) tracer_plotter.subplot_tracer() fit_imaging_plotter = aplt.FitImagingPlotter(fit=result.max_log_likelihood_fit) fit_imaging_plotter.subplot_fit_imaging() # %% """ The result contains a lot more information about the model-fit. For example, its `Samples` object contains the complete set of `NonLinearSearch` samples, for example every set of parameters evaluated, their log likelihoods and so on, which are used for computing information about the model-fit such as the error on every parameter. """ print(result.samples) print(result.samples.parameters) print(result.samples.log_likelihoods)