Skip to content

followup - Lookup Table Functions

Calculate exposure information using pre-computed lookup tables via interpolation.

get_exposure(
delay: u.Quantity,
source_filepath: Path | str | None = None,
lookup_df: pd.DataFrame | Path | str | None = None,
sensitivity_curve: list | None = None,
photon_flux_curve: list | None = None,
redshift: float | None = None,
radius: u.Quantity = 3.0 * u.deg,
min_energy: u.Quantity = 0.02 * u.TeV,
max_energy: u.Quantity = 10 * u.TeV,
target_precision: u.Quantity = 1 * u.s,
max_time: u.Quantity = 12 * u.h,
sensitivity_mode: Literal["sensitivity", "photon_flux"] = "sensitivity",
n_time_steps: int = 10,
other_info: list[str] = ["long", "lat" "dist"],
delay_column: str = "obs_delay",
obs_time_column: str = "obs_time",
**filters: str | float | int | bool,
) -> dict
ParameterTypeDescription
delayu.QuantityObservation delay from event onset
source_filepathPath | str | NonePath to source file. Required if lookup_df is None
lookup_dfpd.DataFrame | Path | str | NoneOptional DataFrame or path to parquet file containing pre-computed observation times or sensitivity data. If provided, uses lookup mode
sensitivity_curvelist | NoneOptional list of sensitivity values
photon_flux_curvelist | NoneOptional list of photon flux values
redshiftfloat | NoneOptional redshift value for EBL calculations
radiusu.QuantityExtraction radius (default: 3.0 deg)
min_energyu.QuantityMinimum energy (default: 0.02 TeV)
max_energyu.QuantityMaximum energy (default: 10 TeV)
target_precisionu.QuantityPrecision for rounding observation times (default: 1 s)
max_timeu.QuantityMaximum allowed observation time (default: 12 h)
sensitivity_modeLiteral["sensitivity", "photon_flux"]Detection calculation mode (default: "sensitivity")
n_time_stepsintNumber of time steps for observation calculation (default: 10)
other_infolist[str]List of column names to include in the returned dictionary when using lookup mode. These are extracted from the lookup dataframe.
delay_columnstrName of the column containing observation delays (default: "obs_delay")
obs_time_columnstrName of the column containing observation times (default: "obs_time")
**filtersstr | float | int | boolAny custom column-value pairs to filter dataframes. Common filters:
- event_id: Event identifier (if present in lookup table)
- irf_site: Observatory site ("north" or "south")
- irf_zenith: Zenith angle in degrees
- irf_ebl: Boolean indicating if EBL is used (True/False)
- irf_ebl_model: EBL model name (e.g., “franceschini”, “dominguez11”)
- irf_config: Telescope configuration (default: "alpha")
- irf_duration: IRF duration in seconds (default: 1800)

Dictionary with keys:

  • obs_time: Required observation time (u.Quantity)
  • seen: Whether detection is possible (bool)
  • start_time, end_time: Observation window
  • ebl_model: EBL model used
  • min_energy, max_energy: Energy range
  • Any metadata columns you request via other_info, for example; long, lat, dist, etc.
  • error_message: Error details if not detectable
from sensipy import followup
import astropy.units as u
import pandas as pd
lookup_df = pd.read_parquet("./O5_gammapy_observations_v4.parquet")
result = followup.get_exposure(
delay=30 * u.min,
lookup_df=lookup_df,
event_id=42,
irf_site="south",
irf_zenith=20,
irf_ebl_model="franceschini",
)
if result['seen']:
print(f"Observation time: {result['obs_time']}")

Retrieve a specific row from the lookup table matching given criteria.

get_row(
lookup_df: pd.DataFrame,
**filters: str | float | int | bool,
) -> pd.Series
ParameterTypeDescription
lookup_dfpd.DataFrameDataFrame containing lookup data
**filtersstr | float | int | boolColumn-value pairs to filter the dataframe. Keyword arguments should be column names, values should be the values to match. This allows filtering on any column in the dataframe.

pandas.Series: The first matching row from the dataframe.

  • ValueError: If no row matches all the specified criteria, if no filters are provided, or if a specified column does not exist in the dataframe.
from sensipy.followup import get_row
# Filter using any column names as keyword arguments
row = get_row(
lookup_df=lookup_df,
event_id=42,
irf_site="south",
irf_zenith=20,
irf_ebl=True,
irf_config="alpha",
irf_duration=1800,
)
print(row)
# You can filter on any columns in the dataframe
row = get_row(
lookup_df=lookup_df,
event_id=42,
custom_column="value",
another_column=123,
)

Low-level interpolation function for observation times.

extrapolate_obs_time(
delay: u.Quantity,
lookup_df: pd.DataFrame,
filters: dict[str, str | float | int] = {},
other_info: list[str] = [],
delay_column: str = "obs_delay",
obs_time_column: str = "obs_time",
) -> dict
  • delay: Observation delay
  • lookup_df: Lookup table
  • filters: Dictionary of column-value pairs to filter the dataframe. All filters must match for a row to be included.
  • other_info: Additional fields to include in output (list)
  • delay_column: Name of the column containing observation delays (default: “obs_delay”)
  • obs_time_column: Name of the column containing observation times (default: “obs_time”)
from sensipy.followup import extrapolate_obs_time
import astropy.units as u
result = extrapolate_obs_time(
delay=100 * u.s,
lookup_df=lookup_df,
filters={'event_id': 42, 'irf_site': 'south', 'irf_zenith': 20},
other_info=['long', 'lat', 'eiso'],
)

Create a Sensitivity object from lookup table data or directly provided curves.

get_sensitivity(
lookup_df: pd.DataFrame | None = None,
sensitivity_curve: list[float] | None = None,
photon_flux_curve: list[float] | None = None,
observatory: str | None = None,
radius: u.Quantity = 3.0 * u.deg,
min_energy: u.Quantity = 0.02 * u.TeV,
max_energy: u.Quantity = 10 * u.TeV,
**filters: str | float | int | bool,
) -> Sensitivity
ParameterTypeDescription
lookup_dfpd.DataFrame | NoneOptional DataFrame containing pre-computed sensitivity data. If provided, sensitivity_curve and photon_flux_curve must be None.
sensitivity_curvelist[float] | NoneOptional list of sensitivity values in erg cm⁻² s⁻¹. Must be provided with photon_flux_curve if lookup_df is None.
photon_flux_curvelist[float] | NoneOptional list of photon flux values in cm⁻² s⁻¹. Must be provided with sensitivity_curve if lookup_df is None.
observatorystr | NoneObservatory name (e.g., “ctao_north”, “ctao_south”, “hess”, “magic”). Must be one of the valid observatory locations from gammapy.data.observatory_locations. Required if lookup_df is None. If lookup_df is provided and observatory is None, will attempt to construct from “irf_site” in filters (e.g., “north” -> “ctao_north”).
radiusu.QuantityAngular radius of the observation region. Defaults to 3.0 degrees.
min_energyu.QuantityMinimum energy for the sensitivity calculation. Defaults to 0.02 TeV.
max_energyu.QuantityMaximum energy for the sensitivity calculation. Defaults to 10 TeV.
**filtersstr | float | int | boolColumn-value pairs to filter the dataframe when lookup_df is provided. Keyword arguments should be column names, values should be the values to match. This allows filtering on any column in the dataframe.
from sensipy.followup import get_sensitivity
import astropy.units as u
# Using lookup_df with filters
sens = get_sensitivity(
lookup_df=lookup_df,
event_id=42,
irf_zenith=20,
irf_ebl=True,
irf_config="alpha",
irf_duration=1800,
observatory="ctao_south", # Can provide directly
radius=3.0 * u.deg,
)
# Or construct from irf_site
sens = get_sensitivity(
lookup_df=lookup_df,
event_id=42,
irf_site="south", # Will construct "ctao_south" automatically
irf_zenith=20,
)
# Using curves directly
sens = get_sensitivity(
sensitivity_curve=[1e-10, 1e-11, 1e-12],
photon_flux_curve=[1e-9, 1e-10, 1e-11],
observatory="ctao_north",
)