def __init__(self, galaxies, cosmology): """An abstract plane which represents a set of galaxies at a given redshift. From a plane, the surface-density, potential and deflection angles of the galaxies can be computed, as well as \ cosmological quantities like angular diameter distances.. Parameters ----------- galaxies : [Galaxy] The list of lens galaxies in this plane. cosmology : astropy.cosmology The cosmology associated with the plane, used to convert arc-second coordinates to physical values. """ self.galaxies = galaxies if not galaxies: raise exc.RayTracingException('An empty list of galaxies was supplied to Plane') if any([redshift is not None for redshift in self.galaxy_redshifts]): if not all([galaxies[0].redshift == galaxy.redshift for galaxy in galaxies]): raise exc.RayTracingException('The galaxies supplied to A Plane have different redshifts or one galaxy ' 'does not have a redshift.') self.cosmology = cosmology
def __init__(self, redshift, galaxies, cosmology): """A plane of galaxies where all galaxies are at the same redshift. Parameters ----------- redshift : float or None The redshift of the plane. galaxies : [Galaxy] The list of galaxies in this plane. cosmology : astropy.cosmology The cosmology associated with the plane, used to convert arc-second coordinates to physical values. """ if redshift is None: if not galaxies: raise exc.RayTracingException( "A redshift and no galaxies were input to a Plane. A redshift for the Plane therefore cannot be" "determined") elif not all([ galaxies[0].redshift == galaxy.redshift for galaxy in galaxies ]): raise exc.RayTracingException( "A redshift and two or more galaxies with different redshifts were input to a Plane. A unique " "Redshift for the Plane therefore cannot be determined") else: redshift = galaxies[0].redshift self.redshift = redshift self.galaxies = galaxies self.cosmology = cosmology
def image_plane_images_for_simulation(self): if not self.has_padded_grid_stack: raise exc.RayTracingException( 'To retrieve an image plane image for the simulation, the grid_stack in the tracer_normal' 'must be padded grid_stack') return list(map(lambda image_plane_image_1d, grid_stack : grid_stack.regular.map_to_2d_keep_padded(padded_array_1d=image_plane_image_1d), self.image_plane_images_1d, self.grid_stacks))
def ordered_plane_redshifts_from_lens_source_plane_redshifts_and_slice_sizes( lens_redshifts, planes_between_lenses, source_plane_redshift): """Given a set of lens plane redshifts, the source-plane redshift and the number of planes between each, setup the \ plane redshifts using these values. A lens redshift corresponds to the 'main' lens galaxy(s), whereas the slices collect line-of-sight halos over a range of redshifts. The source-plane redshift is removed from the ordered plane redshifts that are returned, so that galaxies are not \ planed at the source-plane redshift. For example, if the main plane redshifts are [1.0, 2.0], and the bin sizes are [1,3], the following redshift \ slices for planes will be used: z=0.5 z=1.0 z=1.25 z=1.5 z=1.75 z=2.0 Parameters ----------- lens_redshifts : [float] The redshifts of the main-planes (e.g. the lens galaxy), which determine where redshift intervals are placed. planes_between_lenses : [int] The number of slices between each main plane. The first entry in this list determines the number of slices \ between Earth (redshift 0.0) and main plane 0, the next between main planes 0 and 1, etc. source_plane_redshift : float The redshift of the source-plane, which is input explicitly to ensure galaxies are not placed in the \ source-plane. """ # Check that the number of slices between lens planes is equal to the number of intervals between the lens planes. if len(lens_redshifts) != len(planes_between_lenses) - 1: raise exc.RayTracingException( "The number of lens_plane_redshifts input is not equal to the number of " "slices_between_lens_planes+1.") plane_redshifts = [] # Add redshift 0.0 and the source plane redshifit to the lens plane redshifts, so that calculation below can use # them when dividing slices. These will be removed by the return function at the end from the plane redshifts. lens_redshifts.insert(0, 0.0) lens_redshifts.append(source_plane_redshift) for lens_plane_index in range(1, len(lens_redshifts)): previous_plane_redshift = lens_redshifts[lens_plane_index - 1] plane_redshift = lens_redshifts[lens_plane_index] slice_total = planes_between_lenses[lens_plane_index - 1] plane_redshifts += list( np.linspace(previous_plane_redshift, plane_redshift, slice_total + 2))[1:] return plane_redshifts[0:-1]
def compute_deflections_at_next_plane(plane_index, total_planes): """This function determines whether the tracer should compute the deflections at the next plane. This is True if there is another plane after this plane, else it is False.. Parameters ----------- plane_index : int The index of the plane we are deciding if we should compute its deflections. total_planes : int The total number of planes.""" if plane_index < total_planes - 1: return True elif plane_index == total_planes - 1: return False else: raise exc.RayTracingException( 'A galaxy was not correctly allocated its previous / next redshifts' )
def __init__(self, lens_galaxies, image_plane_grid_stacks, borders=None, cosmology=cosmo.Planck15): """Ray tracer for a lens system with just an image-plane. As there is only 1 plane, there are no ray-tracing calculations. This class is therefore only used for fitting \ image-plane galaxies with light profiles. This tracer has a list of grid-stacks (see grid_stack.GridStack) which are all used for ray-tracing. Parameters ---------- lens_galaxies : [Galaxy] The list of lens galaxies in the image-plane. image_plane_grid_stacks : [grid_stacks.GridStack] The image-plane grid stacks which are traced. (each stack includes the regular-grid, sub-grid, \ blurring-grid, etc.). borders : [masks.RegularGridBorder] The border of each grid-stacks's regular-grid, which is used to relocate demagnified traced pixels to the \ source-plane border. cosmology : astropy.cosmology.Planck15 The cosmology of the ray-tracing calculation. """ if not lens_galaxies: raise exc.RayTracingException( 'No lens galaxies have been input into the Tracer') image_plane = plane_stack.PlaneStack( galaxies=lens_galaxies, grid_stacks=image_plane_grid_stacks, borders=borders, compute_deflections=True, cosmology=cosmology) super(TracerImagePlaneStack, self).__init__(planes=[image_plane], cosmology=cosmology)
def __init__(self, galaxies, image_plane_grid_stacks, borders=None, cosmology=cosmo.Planck15): """Ray-tracer for a lens system with any number of planes. To perform multi-plane ray-tracing, the cosmology that is input is used to rescale deflection-angles \ according to the lens-geometry of the multi-plane system. All galaxies input to the tracer must therefore \ have redshifts. This tracer has a list of grid-stacks (see grid_stack.GridStack) which are all used for ray-tracing. Parameters ---------- galaxies : [Galaxy] The list of galaxies in the ray-tracing calculation. image_plane_grid_stacks : [grid_stacks.GridStack] The image-plane grid stacks which are traced. (each stack includes the regular-grid, sub-grid, \ blurring-grid, etc.). borders : [masks.RegularGridBorder] The border of each grid-stacks's regular-grid, which is used to relocate demagnified traced pixels to the \ source-plane border. cosmology : astropy.cosmology The cosmology of the ray-tracing calculation. """ ordered_redshifts = lens_util.ordered_plane_redshifts_from_galaxies( galaxies=galaxies) galaxies_in_redshift_ordered_lists = \ lens_util.galaxies_in_redshift_ordered_planes_from_galaxies(galaxies=galaxies, plane_redshifts=ordered_redshifts) image_plane_grid_stacks = list( map( lambda grid_stack: pix. setup_image_plane_pixelization_grid_from_galaxies_and_grid_stack( galaxies=galaxies, grid_stack=grid_stack), image_plane_grid_stacks)) planes = [] for plane_index in range(0, len(ordered_redshifts)): if plane_index < len(ordered_redshifts) - 1: compute_deflections = True elif plane_index == len(ordered_redshifts) - 1: compute_deflections = False else: raise exc.RayTracingException( 'A galaxy was not correctly allocated its previous / next redshifts' ) new_grid_stacks = image_plane_grid_stacks if plane_index > 0: for previous_plane_index in range(plane_index): scaling_factor = lens_util.scaling_factor_between_redshifts_for_cosmology( z1=ordered_redshifts[previous_plane_index], z2=ordered_redshifts[plane_index], z_final=ordered_redshifts[-1], cosmology=cosmology) def scale(grid): return np.multiply(scaling_factor, grid) if planes[ previous_plane_index].deflection_stacks is not None: scaled_deflections = list( map( lambda deflection_stack: deflection_stack. apply_function(scale), planes[previous_plane_index].deflection_stacks) ) else: scaled_deflections = None if scaled_deflections is not None: def minus(grid, deflections): return grid - deflections new_grid_stacks = list( map( lambda grid, deflections: grid.map_function( minus, deflections), new_grid_stacks, scaled_deflections)) planes.append( plane_stack.PlaneStack( galaxies=galaxies_in_redshift_ordered_lists[plane_index], grid_stacks=new_grid_stacks, borders=borders, compute_deflections=compute_deflections, cosmology=cosmology)) super(TracerMultiPlanesStack, self).__init__(planes=planes, cosmology=cosmology)
def __init__(self, galaxies, image_plane_positions, cosmology=cosmo.Planck15): """Positional ray-tracer for a lens system with any number of planes. To perform multi-plane ray-tracing, a cosmology must be supplied so that deflection-angles can be rescaled \ according to the lens-geometry of the multi-plane system. Parameters ---------- galaxies : [Galaxy] The list of galaxies in the ray-tracing calculation. image_plane_positions : [[[]]] The (y,x) arc-second coordinates of image-plane pixels which (are expected to) mappers to the same location(s) \ in the final source-plane. cosmology : astropy.cosmology The cosmology of the ray-tracing calculation. """ ordered_redshifts = lens_util.ordered_plane_redshifts_from_galaxies( galaxies=galaxies) galaxies_in_redshift_ordered_lists = \ lens_util.galaxies_in_redshift_ordered_planes_from_galaxies(galaxies=galaxies, plane_redshifts=ordered_redshifts) if not galaxies: raise exc.RayTracingException( 'No galaxies have been input into the Tracer (TracerImageSourcePlanes)' ) planes = [] for plane_index in range(0, len(ordered_redshifts)): if plane_index < len(ordered_redshifts) - 1: compute_deflections = True elif plane_index == len(ordered_redshifts) - 1: compute_deflections = False else: raise exc.RayTracingException( 'A galaxy was not correctly allocated its previous / next redshifts' ) new_positions = image_plane_positions if plane_index > 0: for previous_plane_index in range(plane_index): scaling_factor = lens_util.scaling_factor_between_redshifts_for_cosmology( z1=ordered_redshifts[previous_plane_index], z2=ordered_redshifts[plane_index], z_final=ordered_redshifts[-1], cosmology=cosmology) scaled_deflections = list( map( lambda deflections: np.multiply( scaling_factor, deflections), planes[previous_plane_index].deflections)) new_positions = list( map( lambda positions, deflections: np.subtract( positions, deflections), new_positions, scaled_deflections)) planes.append( pl.PlanePositions( galaxies=galaxies_in_redshift_ordered_lists[plane_index], positions=new_positions, compute_deflections=compute_deflections)) super(TracerMultiPlanesPositions, self).__init__(planes=planes, cosmology=cosmology)