yippy.performance
=================

.. py:module:: yippy.performance

.. autoapi-nested-parse::

   Coronagraph performance metric computation.

   This module provides standalone functions for computing coronagraph performance
   curves: throughput, raw contrast, core area, occulter transmission, and core
   mean intensity. Each metric has its own compute function for clarity, plus a
   ``compute_all_performance_curves`` orchestrator.

   All functions operate on a Coronagraph instance passed as the first argument,
   keeping the Coronagraph class itself slim while preserving backward-compatible
   delegation methods on it.



Classes
-------

.. autoapisummary::

   yippy.performance.OffAxisPosition


Functions
---------

.. autoapisummary::

   yippy.performance._iter_xaxis_positions
   yippy.performance._collect_and_sort
   yippy.performance._point_source_in_image
   yippy.performance._oversample_psf
   yippy.performance._threshold_mask
   yippy.performance._compute_iwa_owa
   yippy.performance.compute_radial_average
   yippy.performance.plot_performance_curve
   yippy.performance.compute_throughput_curve
   yippy.performance.compute_raw_contrast_curve
   yippy.performance.compute_core_area_curve
   yippy.performance.compute_truncation_throughput_curve
   yippy.performance.compute_truncation_core_area_curve
   yippy.performance.compute_occ_trans_curve
   yippy.performance.compute_core_mean_intensity_curve
   yippy.performance._build_perf_interps
   yippy.performance.compute_all_performance_curves


Module Contents
---------------

.. py:class:: OffAxisPosition

   Data for a single off-axis PSF position along the performance axis.


   .. py:attribute:: separation
      :type:  float


   .. py:attribute:: psf
      :type:  numpy.ndarray


   .. py:attribute:: px
      :type:  int


   .. py:attribute:: py
      :type:  int


.. py:function:: _iter_xaxis_positions(coro)

   Yield :class:`OffAxisPosition` for each valid x-offset (y ~= 0).

   Iterates over each valid x-offset position along the performance-curve
   axis. All native YIP offsets are included, even those where the nominal
   point-source location lies outside the image, because the truncation-ratio
   throughput remains meaningful as long as the translated PSF retains
   significant in-image power.


.. py:function:: _collect_and_sort(separations, values)

   Convert lists to sorted arrays by separation.


.. py:function:: _point_source_in_image(pos)

   Return True if the nominal point-source pixel lies inside the PSF image.


.. py:function:: _oversample_psf(psf, pixel_scale_arcsec, oversample)

   Oversample a PSF using flux-conserving resampling.

   Uses ``resample_flux`` from hwoutils which converts to surface brightness
   before interpolation and back to integrated flux after, guaranteeing
   per-pixel flux accuracy.

   Args:
       psf: 2D PSF image.
       pixel_scale_arcsec: Pixel scale of the input PSF (lam/D per pixel).
       oversample: Oversampling factor.

   Returns:
       Oversampled PSF with flux conserved and negative values clamped.


.. py:function:: _threshold_mask(psf_os, trunc_ratio)

   Create boolean mask of pixels exceeding ``trunc_ratio * peak``.

   Falls back to peak-only mask if no pixels exceed the threshold.


.. py:function:: _compute_iwa_owa(coro, sep, throughput)

   Compute IWA and OWA from throughput curve, storing on *coro*.


.. py:function:: compute_radial_average(image, pixel_scale_value, center = None, nbins = None)

   Compute radial average of a 2D image.

   Thin wrapper around :func:`hwoutils.radial.radial_profile` for
   backward compatibility.

   Args:
       image: 2D numpy array.
       pixel_scale_value: Pixel scale in lambda/D per pixel (float).
       center: ``(cy, cx)`` pixel coordinates of centre. Defaults to
           image centre.
       nbins: Number of radial bins. Defaults to ``floor(max_dim / 2)``.

   Returns:
       ``(separations_lod, radial_profile)`` - 1-D arrays.


.. py:function:: plot_performance_curve(x, y, title, xlabel, ylabel, marker='o-', log_scale=False, ms=4)

   Plot a single performance curve.


.. py:function:: compute_throughput_curve(coro, aperture_radius_lod = 0.7, oversample = 2)

   Compute coronagraph throughput vs separation.

   Throughput is the fraction of the total flux (planet PSF normalised to 1)
   that lands inside a photometric aperture at each off-axis position.

   Args:
       coro: Coronagraph instance.
       aperture_radius_lod: Aperture radius in lam/D.
       oversample: Oversampling factor.

   Returns:
       ``(separations, throughputs)`` - sorted 1-D arrays.


.. py:function:: compute_raw_contrast_curve(coro, stellar_diam=0.0 * lod, aperture_radius_lod = 0.7, oversample = 2)

   Compute raw contrast curve vs separation.

   Contrast is the ratio of stellar flux to planet flux within the same
   photometric aperture at each off-axis position.

   Args:
       coro: Coronagraph instance.
       stellar_diam: Stellar angular diameter for the on-axis PSF.
       aperture_radius_lod: Aperture radius in lam/D.
       oversample: Oversampling factor.

   Returns:
       ``(separations, contrasts)`` - sorted 1-D arrays.


.. py:function:: compute_core_area_curve(coro, aperture_radius_lod = 0.7, fit_gaussian = False, use_phot_aperture_as_min = False, oversample = 2)

   Compute core area vs separation.

   The core area represents the effective area of the PSF core.  If
   *fit_gaussian* is True a 2-D Gaussian is fitted to each PSF; otherwise a
   fixed circular aperture is used.

   Args:
       coro: Coronagraph instance.
       aperture_radius_lod: Aperture radius in lam/D.
       fit_gaussian: Whether to fit a 2-D Gaussian.
       use_phot_aperture_as_min: Use aperture area as a floor when fitting.
       oversample: Oversampling factor.

   Returns:
       ``(separations, core_areas)`` - sorted 1-D arrays, area in (lam/D)**2.


.. py:function:: compute_truncation_throughput_curve(coro, psf_trunc_ratio = 0.5, oversample = None)

   Compute throughput using a PSF-truncation-ratio aperture.

   Instead of a fixed circular aperture, selects all pixels where the
   oversampled PSF exceeds ``psf_trunc_ratio * peak``.  Throughput is the
   sum of those pixels (after flux-conserving resampling).  This
   matches the ``photap_frac`` calculation in AYO's ``load_coronagraph.pro``.

   Args:
       coro: Coronagraph instance.
       psf_trunc_ratio: Fraction of the PSF peak used as threshold
           (e.g. 0.5 keeps all pixels > 50% of the peak).
       oversample: Oversampling factor.  ``None`` uses AYO's rule:
           ``ceil(pixscale / 0.05)``.

   Returns:
       ``(separations, throughputs)`` - sorted 1-D arrays.


.. py:function:: compute_truncation_core_area_curve(coro, psf_trunc_ratio = 0.5, oversample = None)

   Compute core area using a PSF-truncation-ratio aperture.

   The core area is the solid angle (in (lam/D)**2) of all oversampled pixels
   that exceed ``psf_trunc_ratio * peak``.  This matches AYO's
   ``omega_lod`` calculation.

   Args:
       coro: Coronagraph instance.
       psf_trunc_ratio: Fraction of PSF peak used as threshold.
       oversample: Oversampling factor.  ``None`` uses AYO's rule.

   Returns:
       ``(separations, core_areas)`` - sorted 1-D arrays, area in (lam/D)^2.


.. py:function:: compute_occ_trans_curve(coro)

   Compute occulter (sky) transmission curve.

   This is the radial profile of the sky transmission mask.

   Args:
       coro: Coronagraph instance.

   Returns:
       ``(separations_lod, occ_trans)`` - 1-D arrays.


.. py:function:: compute_core_mean_intensity_curve(coro, stellar_diam_values=None)

   Compute core mean intensity curves for different stellar diameters.

   Args:
       coro: Coronagraph instance.
       stellar_diam_values:
           List of stellar diameters.  ``None`` -> use all available.

   Returns:
       ``(separations_lod, intensities_dict)`` where *intensities_dict*
       maps each stellar diameter to its radial intensity profile.


.. py:function:: _build_perf_interps(coro, sep, throughput, raw_contrast, sep_ca, core_area, interp_order)

   Assign throughput, contrast, and core area spline interpolators to *coro*.


.. py:function:: compute_all_performance_curves(coro, aperture_radius_lod = 0.7, stellar_diam=None, fit_gaussian_for_core_area = False, use_phot_aperture_as_min = False, oversample = 2, save_to_fits = True, performance_file = 'coro_perf.fits', load_from_file = None, cache_dir = None, plot = False, psf_trunc_ratio = None, interp_order = 1)

   Compute (or load) all coronagraph performance curves.

   Stores interpolators on *coro*.
   This is the main entrypoint called during ``Coronagraph.__init__``.  It
   delegates to the individual ``compute_*`` helpers above, builds spline
   interpolators, and computes IWA / OWA.

   Returns a dict of all curve data for convenience.


