diff --git a/CHANGELOG.md b/CHANGELOG.md index 32c1179..50e0c90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Horizons orbit table query now includes, M1/2, K1/2, PC, and rotation period. +### Fixed + +- NEOS Chip size calculation was slightly incorrect with regard to the placement of the + gaps between the chips. +- NEOS FOV rotation was being calculated in the ecliptic frame, whereas images will be + in the equatorial frame. Rotation is now defaulting to the equatorial frame. + ## [v1.0.3] diff --git a/src/kete/neos.py b/src/kete/neos.py index a4e10e2..acd2f77 100644 --- a/src/kete/neos.py +++ b/src/kete/neos.py @@ -1,13 +1,21 @@ import numpy as np +from .fov import NeosCmos, NeosVisit + + +__all__ = ["sunshield_rotation", "NeosCmos", "NeosVisit", "FOV_WIDTH", "FOV_HEIGHT"] + BANDS: list[float] = [4700.0, 8000.0] """Effective wavelength of the NC1 and NC2 bands in nm.""" FOV_WIDTH: float = 7.10 -"""Expected effective field of view width in degrees""" +"""Expected effective field of view width in degrees. Approximate Value.""" FOV_HEIGHT: float = 1.68 -"""Expected effective field of view height in degrees""" +"""Expected effective field of view height in degrees. Approximate Value.""" + +FOV_CHIP_GAP: float = 0.11 +"""Expected effective gap between individual chips in degrees. Approximate Value.""" ZERO_MAGS: list[float] = [170.662, 64.13] """Zero point magnitude for nc1 and nc2""" diff --git a/src/kete/rust/fovs/definitions.rs b/src/kete/rust/fovs/definitions.rs index 88cc329..e092aba 100644 --- a/src/kete/rust/fovs/definitions.rs +++ b/src/kete/rust/fovs/definitions.rs @@ -1,4 +1,4 @@ -use kete_core::fov::{self, NeosBand}; +use kete_core::fov::{self}; use kete_core::fov::{FovLike, SkyPatch}; use nalgebra::Vector3; use pyo3::{exceptions, prelude::*}; @@ -607,7 +607,7 @@ impl PyNeosCmos { subloop_id, exposure_id, cmos_id, - band.into(), + band, )) } @@ -677,11 +677,7 @@ impl PyNeosCmos { /// Band Number #[getter] pub fn band(&self) -> u8 { - match self.0.band { - NeosBand::NC1 => 1, - NeosBand::NC2 => 2, - NeosBand::Undefined => 0, - } + self.0.band } /// Rotation angle of the FOV in degrees. @@ -738,22 +734,23 @@ impl PyNeosVisit { exposure_id: u8, band: u8, ) -> Self { - let pointing = pointing.into_vector(crate::frame::PyFrames::Ecliptic); + let pointing = pointing.into_vector(crate::frame::PyFrames::Equatorial); let pointing = pointing.raw.into(); + let observer = observer.as_equatorial().unwrap().0; PyNeosVisit(fov::NeosVisit::from_pointing( x_width.to_radians(), y_width.to_radians(), gap_angle.to_radians(), pointing, rotation.to_radians(), - observer.0, + observer, side_id, stack_id, quad_id, loop_id, subloop_id, exposure_id, - band.into(), + band, )) } diff --git a/src/kete_core/src/fov/neos.rs b/src/kete_core/src/fov/neos.rs index 5585c7e..b17104b 100644 --- a/src/kete_core/src/fov/neos.rs +++ b/src/kete_core/src/fov/neos.rs @@ -6,31 +6,6 @@ use crate::prelude::*; use nalgebra::Vector3; use serde::{Deserialize, Serialize}; -/// NEOS bands -#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq)] -pub enum NeosBand { - /// No Band defined. - Undefined, - - /// NEOS NC1 Band. - NC1, - - /// NEOS NC2 Band. - NC2, -} - -/// Convert a NEOS band from u8 -/// 1 is NC1 2 is NC2, everything else is Undefined. -impl From for NeosBand { - fn from(value: u8) -> Self { - match value { - 1 => NeosBand::NC1, - 2 => NeosBand::NC2, - _ => NeosBand::Undefined, - } - } -} - /// NEOS frame data, a single detector on a single band #[derive(Debug, Clone, Deserialize, Serialize)] pub struct NeosCmos { @@ -62,7 +37,7 @@ pub struct NeosCmos { pub exposure_id: u8, /// Wavelength band - pub band: NeosBand, + pub band: u8, /// CMOS ID /// ID number of the CMOS chip, 0, 1, 2, or 3 @@ -83,7 +58,7 @@ impl NeosCmos { subloop_id: u8, exposure_id: u8, cmos_id: u8, - band: NeosBand, + band: u8, ) -> Self { let patch = OnSkyRectangle::new(pointing, rotation, NEOS_WIDTH, NEOS_HEIGHT, observer.frame); @@ -164,7 +139,7 @@ pub struct NeosVisit { pub exposure_id: u8, /// Wavelength band - pub band: NeosBand, + pub band: u8, } impl NeosVisit { @@ -235,7 +210,7 @@ impl NeosVisit { loop_id: u8, subloop_id: u8, exposure_id: u8, - band: NeosBand, + band: u8, ) -> Self { // Rotate the Z axis to match the defined rotation angle, this vector is not // orthogonal to the pointing vector, but is in the correct plane of the final @@ -250,14 +225,14 @@ impl NeosVisit { // orthogonal to the two existing vectors. let up_vec = pointing.cross(&left_vec); - // +------+-+------+-+------+-+------+ ^ - // | 1 |g| 2 |g| 3 |g| 4 | | - // | |a| |a| |a| | y - // | |p| |p| |p| | | - // +------+-+------+-+------+-+------+ _ - // <-cf-> x -> + // +-------+-+-------+-+-------+-+-------+ ^ + // | |g| |g| |g| | | + // | 1 |a| 2 |a| 3 |a| 4 | y + // | |p| |p| |p| | | + // +-------+-+-------+-+-------+-+-------+ - + // | <---- x -----> | // - // pointing vector is in the middle of the 'a' in the central gap. + // Pointing vector is in the middle of the 'a' in the central gap. // the Y direction is bounded by 2 planes, calculate them one time let y_top: Vector3 = rotate_around(&up_vec, left_vec, y_width / 2.0); @@ -265,14 +240,19 @@ impl NeosVisit { let half_gap = gap_angle / 2.0; + // chip width in the x direction: + // 4 * chip_width + 3 * gap_angle = x_width + // chip_width = (x_width - 3 * gap_angle) / 4 + let chip_width = (x_width - 3.0 * gap_angle) / 4.0; + // for each chip calculate the x bounds let chip_1_a: Vector3 = rotate_around(&left_vec, up_vec, -x_width / 2.0); - let chip_1_b: Vector3 = -rotate_around(&left_vec, up_vec, -x_width / 4.0 - half_gap); - let chip_2_a: Vector3 = rotate_around(&left_vec, up_vec, -x_width / 4.0 + half_gap); + let chip_1_b: Vector3 = -rotate_around(&left_vec, up_vec, -x_width / 2.0 + chip_width); + let chip_2_a: Vector3 = rotate_around(&left_vec, up_vec, -chip_width - half_gap); let chip_2_b: Vector3 = -rotate_around(&left_vec, up_vec, -half_gap); let chip_3_a: Vector3 = rotate_around(&left_vec, up_vec, half_gap); - let chip_3_b: Vector3 = -rotate_around(&left_vec, up_vec, x_width / 4.0 - half_gap); - let chip_4_a: Vector3 = rotate_around(&left_vec, up_vec, x_width / 4.0 + half_gap); + let chip_3_b: Vector3 = -rotate_around(&left_vec, up_vec, chip_width + half_gap); + let chip_4_a: Vector3 = rotate_around(&left_vec, up_vec, x_width / 2.0 - chip_width); let chip_4_b: Vector3 = -rotate_around(&left_vec, up_vec, x_width / 2.0); // make the patches for each chip