use super::map::StarlightMap;
use super::output::StarlightOutputs;
use super::photometry::scale_outputs;
#[cfg(nsb_bundled_production_starlight)]
use super::validated::ValidatedStarlightMap;
#[cfg(nsb_bundled_production_starlight)]
use crate::data::bundled::{
BUNDLED_PRODUCTION_STARLIGHT_MANIFEST, BUNDLED_PRODUCTION_STARLIGHT_MAP,
};
use crate::error::{NsbError, Result};
use crate::evaluator::Target;
use crate::units::ScaleFactors;
use siderust::coordinates::spherical::direction;
use siderust::coordinates::transform::TransformFrame;
use std::sync::Arc;
#[derive(Debug, Clone)]
pub(crate) struct Starlight {
map: Arc<StarlightMap>,
scale: ScaleFactors,
}
impl Starlight {
#[cfg(nsb_bundled_production_starlight)]
pub(crate) fn bundled_production_model() -> Result<Self> {
static MAP: std::sync::OnceLock<std::result::Result<Arc<StarlightMap>, String>> =
std::sync::OnceLock::new();
let map = MAP.get_or_init(|| {
ValidatedStarlightMap::from_bytes_and_manifest(
BUNDLED_PRODUCTION_STARLIGHT_MAP,
BUNDLED_PRODUCTION_STARLIGHT_MANIFEST,
)
.map(|validated| validated.shared_map())
.map_err(|err| err.to_string())
});
match map {
Ok(map) => Ok(Self::with_shared_map(Arc::clone(map))),
Err(message) => Err(NsbError::InvalidMap {
message: message.clone(),
}),
}
}
#[cfg(not(nsb_bundled_production_starlight))]
pub(crate) fn bundled_production_model() -> Result<Self> {
Err(missing_bundled_production_asset())
}
pub(crate) fn with_shared_map(map: Arc<StarlightMap>) -> Self {
Self {
map,
scale: ScaleFactors::new(1.0),
}
}
pub(crate) fn compute(&self, target: Target) -> Result<StarlightOutputs> {
if !self.scale.is_finite() || self.scale < ScaleFactors::new(0.0) {
return Err(NsbError::OutOfRange(
"starlight scale must be finite and non-negative".to_string(),
));
}
let galactic: direction::Galactic = target.to_frame();
Ok(scale_outputs(
self.map.lookup(galactic.to_cartesian()),
self.scale,
))
}
pub(crate) fn map(&self) -> &StarlightMap {
&self.map
}
}
#[cfg(not(nsb_bundled_production_starlight))]
fn missing_bundled_production_asset() -> NsbError {
NsbError::DataMissing {
file: "data/manifest.toml",
message: concat!(
"bundled production starlight asset is not registered; generate and commit ",
"the Gaia DR3 XP nside=128 compact release map and runtime manifest, then register both ",
"as runtime_embedded production assets"
)
.to_string(),
}
}
#[cfg(test)]
pub(super) mod test_support {
use super::{ScaleFactors, Starlight};
pub(in crate::components::starlight) fn with_scale(
mut model: Starlight,
scale: ScaleFactors,
) -> Starlight {
model.scale = scale;
model
}
}