use crate::math::coords::standard_equatorial;
use crate::types::{PlateConstants, WcsSolution};
#[must_use]
pub fn derive_wcs(
ra_db: f64,
dec_db: f64,
plate: &PlateConstants,
width: usize,
height: usize,
) -> WcsSolution {
let cx = (width as f64 - 1.0) * 0.5;
let cy = (height as f64 - 1.0) * 0.5;
let x_std = plate.a * cx + plate.b * cy + plate.c;
let y_std = plate.d * cx + plate.e * cy + plate.f;
let (ra0, dec0) = standard_equatorial(ra_db, dec_db, x_std, y_std, 1.0);
let cd1_1 = -plate.a / 3600.0;
let cd1_2 = -plate.b / 3600.0;
let cd2_1 = plate.d / 3600.0;
let cd2_2 = plate.e / 3600.0;
let cdelt1 = -(cd1_1 * cd1_1 + cd1_2 * cd1_2).sqrt(); let cdelt2 = (cd2_1 * cd2_1 + cd2_2 * cd2_2).sqrt();
let crota2 = cd2_1.atan2(cd2_2).to_degrees();
WcsSolution {
ra0,
dec0,
crpix1: cx + 1.0,
crpix2: cy + 1.0,
cd1_1,
cd1_2,
cd2_1,
cd2_2,
cdelt1,
cdelt2,
crota2,
residual_rms: 0.0,
stars_matched: 0,
plate: plate.clone(),
mag_limit: 0.0,
search_dist_deg: 0.0,
step_distances: Vec::new(),
raw_matches: 0,
matched_stars: Vec::new(),
sip: None,
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::math::coords::ang_sep;
use core::f64::consts::PI;
fn deg(d: f64) -> f64 {
d * PI / 180.0
}
#[test]
fn identity_wcs_near_zero() {
let plate = PlateConstants {
a: 1.0,
b: 0.0,
c: 0.0,
d: 0.0,
e: 1.0,
f: 0.0,
};
let w = WcsSolution {
ra0: 0.0,
dec0: 0.0,
..derive_wcs(0.0, 0.0, &plate, 101, 101)
};
assert!(w.ra0.abs() < 1e-8, "ra0 = {}", w.ra0);
assert!(w.dec0.abs() < 1e-8, "dec0 = {}", w.dec0);
assert!(
(w.cdelt2 - 1.0 / 3600.0).abs() < 1e-10,
"cdelt2 = {}",
w.cdelt2
);
}
#[test]
fn center_ra_dec_reasonable() {
let plate = PlateConstants {
a: 1.0,
b: 0.0,
c: 0.0,
d: 0.0,
e: 1.0,
f: 0.0,
};
let ra_db = deg(45.0);
let dec_db = deg(20.0);
let wcs = derive_wcs(ra_db, dec_db, &plate, 101, 101);
let sep = ang_sep(wcs.ra0, wcs.dec0, ra_db, dec_db);
assert!(
sep < deg(0.1),
"center offset = {} arcsec",
sep * 3600.0 * 180.0 / PI
);
}
#[test]
fn crpix_is_image_center() {
let plate = PlateConstants {
a: 1.0,
b: 0.0,
c: 0.0,
d: 0.0,
e: 1.0,
f: 0.0,
};
let wcs = derive_wcs(0.0, 0.0, &plate, 200, 300);
assert!(
(wcs.crpix1 - 100.5).abs() < 1e-10,
"crpix1 = {}",
wcs.crpix1
);
assert!(
(wcs.crpix2 - 150.5).abs() < 1e-10,
"crpix2 = {}",
wcs.crpix2
);
}
}