pysersic.rendering ================== .. py:module:: pysersic.rendering Attributes ---------- .. autoapisummary:: pysersic.rendering.base_profile_types pysersic.rendering.base_profile_params pysersic.rendering.__version__ Classes ------- .. autoapisummary:: pysersic.rendering.BaseRenderer pysersic.rendering.PixelRenderer pysersic.rendering.FourierRenderer pysersic.rendering.HybridRenderer Functions --------- .. autoapisummary:: pysersic.rendering.sersic1D pysersic.rendering.render_spergel_fourier pysersic.rendering.render_gaussian_fourier pysersic.rendering.render_pointsource_fourier pysersic.rendering.render_gaussian_pixel pysersic.rendering.render_sersic_2d pysersic.rendering.c_nu_approx pysersic.rendering.calculate_etas_betas pysersic.rendering.sersic_gauss_decomp Module Contents --------------- .. py:data:: base_profile_types :value: ['sersic', 'doublesersic', 'sersic_exp', 'sersic_pointsource', 'pointsource', 'exp', 'dev', 'spergel'] .. py:data:: base_profile_params .. py:class:: BaseRenderer(im_shape: Iterable, pixel_PSF: jax.numpy.array) Bases: :py:obj:`equinox.Module` .. py:attribute:: im_shape :type: tuple .. py:attribute:: psf_shape :type: tuple .. py:attribute:: fft_shape :type: tuple .. py:attribute:: pixel_PSF :type: jax.numpy.array .. py:attribute:: PSF_fft :type: jax.numpy.array .. py:attribute:: X :type: jax.numpy.array .. py:attribute:: Y :type: jax.numpy.array .. py:attribute:: FX :type: jax.numpy.array .. py:attribute:: FY :type: jax.numpy.array .. py:attribute:: x_mid :type: float .. py:attribute:: y_mid :type: float .. py:attribute:: fft_zeros :type: jax.numpy.array .. py:attribute:: img_zeros :type: jax.numpy.array .. py:method:: conv_img_and_fft(image, F_im) .. py:method:: conv_fft(F_im) .. py:method:: combine_scene(F_im, int_im, obs_im) Default implementation that naively combines all types of images even if they are known to be zero :param F_im: Sum of sources rendered in Fourier space :type F_im: Fourier image :param int_im: Sum of sources rendered in Intrinsic space :type int_im: _type_ :param obs_im: Sum of sources rendered in observed space :type obs_im: _type_ :returns: Combination of all sources to be compared to observations :rtype: Model image .. py:method:: render_sersic(params: dict) :abstractmethod: .. py:method:: render_doublesersic(params: dict) .. py:method:: render_sersic_exp(params: dict) .. py:method:: render_sersic_pointsource(params: dict) .. py:method:: render_pointsource(params: dict) :abstractmethod: .. py:method:: render_exp(params: dict) -> jax.numpy.array Thin wrapper for an exponential profile based on render_sersic :param xc: Central x position :type xc: float :param yc: Central y position :type yc: float :param flux: Total flux :type flux: float :param r_eff: Effective radius :type r_eff: float :param ellip: Ellipticity :type ellip: float :param theta: Position angle in radians :type theta: float :returns: Rendered Exponential model :rtype: jax.numpy.array .. py:method:: render_dev(params: dict) -> jax.numpy.array Thin wrapper for a De Vaucouleurs profile based on render_sersic :param xc: Central x position :type xc: float :param yc: Central y position :type yc: float :param flux: Total flux :type flux: float :param r_eff: Effective radius :type r_eff: float :param ellip: Ellipticity :type ellip: float :param theta: Position angle in radians :type theta: float :returns: Rendered Exponential model :rtype: jax.numpy.array .. py:method:: render_spergel(params: dict) .. py:method:: render_for_model(param_dict, types, suffix) .. py:method:: render_source(params: dict, profile_type: str, suffix: Optional[str] = '') -> jax.numpy.array Render an observed source of a given type and parameters :param params: Parameters specifying the source :type params: jax.numpy.array :param profile_type: Type of profile to use :type profile_type: str :returns: Rendered, observed model :rtype: jax.numpy.array .. py:class:: PixelRenderer(im_shape: Iterable, pixel_PSF: jax.numpy.array, os_pixel_size: Optional[int] = 6, num_os: Optional[int] = 12) Bases: :py:obj:`BaseRenderer` Render class based on rendering in pixel space and then convolving with the PSF .. py:attribute:: os_pixel_size :type: int .. py:attribute:: num_os :type: int .. py:attribute:: w_os :type: jax.numpy.array .. py:attribute:: x_os_lo :type: int .. py:attribute:: x_os_hi :type: int .. py:attribute:: y_os_lo :type: int .. py:attribute:: y_os_hi :type: int .. py:attribute:: X_os :type: jax.numpy.array .. py:attribute:: Y_os :type: jax.numpy.array .. py:method:: render_int_sersic(xc, yc, flux, r_eff, n, ellip, theta) .. py:method:: render_sersic(params: dict) -> jax.numpy.array Render a sersic profile :param xc: Central x position :type xc: float :param yc: Central y position :type yc: float :param flux: Total flux :type flux: float :param r_eff: Effective radius :type r_eff: float :param n: Sersic index :type n: float :param ellip: Ellipticity :type ellip: float :param theta: Position angle in radians :type theta: float :returns: Rendered Sersic model :rtype: jax.numpy.array .. py:method:: render_pointsource(params: dict) -> jax.numpy.array Render a Point source by interpolating given PSF into image. Currently jax only supports linear intepolation. :param xc: Central x position :type xc: float :param yc: Central y position :type yc: float :param flux: Total flux :type flux: float :returns: rendered pointsource model :rtype: jax.numpy.array .. py:method:: combine_scene(F_im, int_im, obs_im) Combine scene for PixelRenderer when nothing is rendered in Fourier space :param F_im: Sum of sources rendered in Fourier space :type F_im: Fourier image :param int_im: Sum of sources rendered in Intrinsic space :type int_im: _type_ :param obs_im: Sum of sources rendered in observed space :type obs_im: _type_ :returns: Combination of all sources to be compared to observations :rtype: Model image .. py:class:: FourierRenderer(im_shape: Iterable, pixel_PSF: jax.numpy.array, frac_start: Optional[float] = 0.01, frac_end: Optional[float] = 15.0, n_sigma: Optional[int] = 15, precision: Optional[int] = 10, use_interp_amps: Optional[bool] = True) Bases: :py:obj:`BaseRenderer` Class to render sources based on rendering them in Fourier space. Sersic profiles are modeled as a series of Gaussian following Shajib (2019) (https://arxiv.org/abs/1906.08263) and the implementation in lenstronomy (https://github.com/lenstronomy/lenstronomy/blob/main/lenstronomy/LensModel/Profiles/gauss_decomposition.py) .. py:attribute:: frac_start :type: float .. py:attribute:: frac_end :type: float .. py:attribute:: n_sigma :type: int .. py:attribute:: precision :type: int .. py:attribute:: use_interp_amps :type: bool .. py:attribute:: etas :type: jax.numpy.array .. py:attribute:: betas :type: jax.numpy.array .. py:attribute:: n_ax :type: jax.numpy.array .. py:attribute:: amps_n_ax :type: jax.numpy.array .. py:method:: get_amps_sigmas(flux, r_eff, n) .. py:method:: render_sersic_mog_fourier(xc, yc, flux, r_eff, n, ellip, theta) .. py:method:: render_sersic(params: dict) -> jax.numpy.array Render a Sersic profile :param xc: Central x position :type xc: float :param yc: Central y position :type yc: float :param flux: Total flux :type flux: float :param r_eff: Effective radius :type r_eff: float :param n: Sersic index :type n: float :param ellip: Ellipticity :type ellip: float :param theta: Position angle in radians :type theta: float :returns: Rendered Sersic model :rtype: jax.numpy.array .. py:method:: render_pointsource(params: dict) -> jax.numpy.array Render a Point source :param xc: Central x position :type xc: float :param yc: Central y position :type yc: float :param flux: Total flux :type flux: float :returns: rendered pointsource model :rtype: jax.numpy.array .. py:method:: combine_scene(F_im, int_im, obs_im) Combine scene for FourierRenderer where everything is rendered in Fourier space :param F_im: Sum of sources rendered in Fourier space :type F_im: Fourier image :param int_im: Sum of sources rendered in Intrinsic space :type int_im: _type_ :param obs_im: Sum of sources rendered in observed space :type obs_im: _type_ :returns: Combination of all sources to be compared to observations :rtype: Model image .. py:class:: HybridRenderer(im_shape: Iterable, pixel_PSF: jax.numpy.array, frac_start: Optional[float] = 0.01, frac_end: Optional[float] = 15.0, n_sigma: Optional[int] = 15, num_pixel_render: Optional[int] = 3, precision: Optional[int] = 10, use_interp_amps: Optional[bool] = True) Bases: :py:obj:`FourierRenderer` Class to render sources based on the hybrid rendering scheme introduced in Lang (2020). This avoids some of the artifacts introduced by rendering sources purely in Fourier space. Sersic profiles are modeled as a series of Gaussian following Shajib (2019) (https://arxiv.org/abs/1906.08263) and the implementation in lenstronomy (https://github.com/lenstronomy/lenstronomy/blob/main/lenstronomy/LensModel/Profiles/gauss_decomposition.py). Our scheme is implemented slightly differently than Lang (2020), specifically in how it chooses which gaussian components to render in Fourier vs. Real space. Lang (2020) employs a cutoff based on distance to the edge of the image. However given some of jax's limitation with dynamic shapes (see more here -> https://jax.readthedocs.io/en/latest/notebooks/Common_Gotchas_in_JAX.html#dynamic-shapes), we have not implemented that specific criterion. Instead we use a simpler version where the user must decide how many components to render in real space, starting from the largest ones. While this is not ideal in all circumstances it still overcomes many of the issues of rendering purely in fourier space discussed in Lang (2020). .. py:attribute:: num_pixel_render :type: int .. py:attribute:: w_real :type: jax.numpy.array .. py:attribute:: w_fourier :type: jax.numpy.array .. py:attribute:: sig_psf_approx :type: float .. py:method:: render_sersic_hybrid(xc, yc, flux, r_eff, n, ellip, theta) .. py:method:: render_sersic(params: dict) -> jax.numpy.array Render a Sersic profile :param xc: Central x position :type xc: float :param yc: Central y position :type yc: float :param flux: Total flux :type flux: float :param r_eff: Effective radius :type r_eff: float :param n: Sersic index :type n: float :param ellip: Ellipticity :type ellip: float :param theta: Position angle in radians :type theta: float :returns: Rendered Sersic model :rtype: jax.numpy.array .. py:method:: render_pointsource(params: dict) -> jax.numpy.array Render a Point source :param xc: Central x position :type xc: float :param yc: Central y position :type yc: float :param flux: Total flux :type flux: float :returns: rendered pointsource model :rtype: jax.numpy.array .. py:method:: combine_scene(F_im, int_im, obs_im) Combine scene for FourierRenderer where nothing is rendered in Intrinsic space :param F_im: Sum of sources rendered in Fourier space :type F_im: Fourier image :param int_im: Sum of sources rendered in Intrinsic space :type int_im: _type_ :param obs_im: Sum of sources rendered in observed space :type obs_im: _type_ :returns: Combination of all sources to be compared to observations :rtype: Model image .. py:function:: sersic1D(r: Union[float, jax.numpy.array], flux: float, re: float, n: float) -> Union[float, jax.numpy.array] Evaluate a 1D sersic profile :param r: radii to evaluate profile at :type r: float :param flux: Total flux :type flux: float :param re: Effective radius :type re: float :param n: Sersic index :type n: float :returns: Sersic profile evaluated at r :rtype: jax.numpy.array .. py:function:: render_spergel_fourier(FX: jax.numpy.array, FY: jax.numpy.array, r_eff: float, flux: float, nu_star: float, xc: float, yc: float, theta: float, q: float) -> jax.numpy.array Render Gaussian components in the Fourier domain :param FX: X frequency positions to evaluate :type FX: jax.numpy.array :param FY: Y frequency positions to evaluate :type FY: jax.numpy.array :param amps: Amplitudes of each component :type amps: jax.numpy.array :param sigmas: widths of each component :type sigmas: jax.numpy.array :param xc: Central x position :type xc: float :param yc: Central y position :type yc: float :param theta: position angle :type theta: float :param q: Axis ratio :type q: float :returns: Sum of components evaluated at FX and FY :rtype: jax.numpy.array .. py:function:: render_gaussian_fourier(FX: jax.numpy.array, FY: jax.numpy.array, amps: jax.numpy.array, sigmas: jax.numpy.array, xc: float, yc: float, theta: float, q: float) -> jax.numpy.array Render Gaussian components in the Fourier domain :param FX: X frequency positions to evaluate :type FX: jax.numpy.array :param FY: Y frequency positions to evaluate :type FY: jax.numpy.array :param amps: Amplitudes of each component :type amps: jax.numpy.array :param sigmas: widths of each component :type sigmas: jax.numpy.array :param xc: Central x position :type xc: float :param yc: Central y position :type yc: float :param theta: position angle :type theta: float :param q: Axis ratio :type q: float :returns: Sum of components evaluated at FX and FY :rtype: jax.numpy.array .. py:function:: render_pointsource_fourier(FX: jax.numpy.array, FY: jax.numpy.array, xc: float, yc: float, flux: float) -> jax.numpy.array Render a point source in the Fourier domain :param FX: X frequency positions to evaluate :type FX: jax.numpy.array :param FY: Y frequency positions to evaluate :type FY: jax.numpy.array :param xc: Central x position :type xc: float :param yc: Central y position :type yc: float :param flux: Total flux of source :type flux: float :returns: Point source evaluated at FX FY :rtype: jax.numpy.array .. py:function:: render_gaussian_pixel(X: jax.numpy.array, Y: jax.numpy.array, amps: jax.numpy.array, sigmas: jax.numpy.array, xc: float, yc: float, theta: float, q: Union[float, jax.numpy.array]) -> jax.numpy.array Render Gaussian components in pixel space :param FX: X positions to evaluate :type FX: jax.numpy.array :param FY: Y positions to evaluate :type FY: jax.numpy.array :param amps: Amplitudes of each component :type amps: jax.numpy.array :param sigmas: widths of each component :type sigmas: jax.numpy.array :param xc: Central x position :type xc: float :param yc: Central y position :type yc: float :param theta: position angle :type theta: float :param q: Axis ratio :type q: Union[float,jax.numpy.array] :returns: Sum of components evaluated at X and Y :rtype: jax.numpy.array .. py:function:: render_sersic_2d(X: jax.numpy.array, Y: jax.numpy.array, xc: float, yc: float, flux: float, r_eff: float, n: float, ellip: float, theta: float) -> jax.numpy.array Evalulate a 2D Sersic distribution at given locations :param X: x locations to evaluate at :type X: jax.numpy.array :param Y: y locations to evaluate at :type Y: jax.numpy.array :param xc: Central x position :type xc: float :param yc: Central y position :type yc: float :param flux: Total flux :type flux: float :param r_eff: Effective radius :type r_eff: float :param n: Sersic index :type n: float :param ellip: Ellipticity :type ellip: float :param theta: Position angle in radians [now measured from north] :type theta: float :returns: Sersic model evaluated at given locations :rtype: jax.numpy.array .. py:function:: c_nu_approx(nu) .. py:function:: calculate_etas_betas(precision: int) -> Tuple[jax.numpy.array, jax.numpy.array] Calculate the weights and nodes for the Gaussian decomposition described in Shajib (2019) (https://arxiv.org/abs/1906.08263) :param precision: Precision, higher number implies more precise decomposition but more nodes. Effective upper limit is 12 for 32 bit numbers, 27 for 64 bit numbers. :type precision: int :returns: etas and betas array to be use in gaussian decomposition :rtype: Tuple[jax.numpy.array, jax.numpy.array] .. py:function:: sersic_gauss_decomp(flux: float, re: float, n: float, etas: jax.numpy.array, betas: jax.numpy.array, sigma_start: float, sigma_end: float, n_comp: int) -> Tuple[jax.numpy.array, jax.numpy.array] Calculate a gaussian decomposition of a given sersic profile, following Shajib (2019) (https://arxiv.org/abs/1906.08263) :param flux: Total flux :type flux: float :param re: half light radius :type re: float :param n: Sersic index :type n: float :param etas: Weights for decomposition, can be calcualted using pysersic.rendering_utils.calculate_etas_betas :type etas: jax.numpy.array :param betas: Nodes for decomposition, can be calcualted using pysersic.rendering_utils.calculate_etas_betas :type betas: jax.numpy.array :param sigma_start: width for the smallest Gaussian component :type sigma_start: float :param sigma_end: width for the largest Gaussian component :type sigma_end: float :param n_comp: Number of Gaussian components :type n_comp: int :returns: Amplitudes and sigmas of Gaussian decomposition :rtype: Tuple[jax.numpy.array, jax.numpy.array] .. py:data:: __version__ :value: 'testBN_OLD'