Source code for coronalyze.analysis.yields

"""Simplified analysis tools for yield modeling and noise floor estimation.

Implements 'Faux-RDI' and related tools for yield calculations where we assume
perfect knowledge of the background model (stellar speckles + disk).
"""

import jax
import jax.numpy as jnp


[docs] def get_perfect_residuals( observation: jnp.ndarray, expectation_model: jnp.ndarray, ) -> jnp.ndarray: """Calculate residuals assuming perfect subtraction of static structure. This simulates 'Faux-RDI': we subtract the exact expectation value of the star and disk. The residual contains only the fundamental noise (photon + read noise) and any signals not in the model (planets). Args: observation: The noisy data (Data = Poisson(Model) + ReadNoise). expectation_model: The noiseless expectation of background sources (stellar PSF + disk, excluding planets). Returns: Residual image containing noise + unmodeled signals (planets). """ return observation - expectation_model
[docs] def get_photon_noise_map( expectation_rate: jnp.ndarray, exposure_time: float, read_noise: float = 0.0, ) -> jnp.ndarray: """Calculate the theoretical 1-sigma noise map in rate units. Properly converts between rate and count units to combine photon noise with read noise. Returns noise in the same units as input (counts/sec). Formula: Sigma_rate = sqrt(Rate * t + RN^2) / t Args: expectation_rate: Expected count rate image (counts/sec). exposure_time: Integration time in seconds. read_noise: Read noise in electrons (per pixel). Default 0. Returns: 1-sigma noise map in rate units (counts/sec), same shape as input. """ # Convert rate to counts for proper Poisson statistics total_counts = jnp.maximum(expectation_rate, 0.0) * exposure_time # Variance in counts: Poisson variance + read noise^2 variance_counts = total_counts + read_noise**2 # Convert back to rate units sigma_counts = jnp.sqrt(variance_counts) return sigma_counts / exposure_time
[docs] def simulate_observation( clean_signal: jnp.ndarray, background_model: jnp.ndarray, exposure_time: float = 1.0, rng_key: jax.Array = None, ) -> jnp.ndarray: """Generate a noisy realization of the scene for yield tests. Applies Poisson noise to the combined scene (signal + background). Returns data in rate units (counts/sec). Args: clean_signal: Planet image (counts/sec). background_model: Star + Disk expectation (counts/sec). exposure_time: Integration time (seconds). rng_key: JAX PRNG Key. If None, uses key 0. Returns: Noisy image in units of counts/sec (Poisson noise added in counts, then divided back by exposure time). """ if rng_key is None: rng_key = jax.random.PRNGKey(0) # Total rate total_flux = (clean_signal + background_model) * exposure_time # Poisson draw (expects non-negative rates) counts = jax.random.poisson(rng_key, jnp.maximum(total_flux, 0.0)) # Return to rate units return counts / exposure_time