Skip to content

Commit

Permalink
Split comet magnitude phase correction into two terms (#159)
Browse files Browse the repository at this point in the history
* Comet phase correction

* changelog
  • Loading branch information
dahlend authored Nov 24, 2024
1 parent a35bf4f commit 85a3c5d
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 21 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Changed

- Comet Magnitude estimates now accepts two phase correction values instead of 1.


## [v1.0.4]

Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ keywords = ["physics", "simulation", "astronomy"]

[dependencies]
kete_core = { version = "*", path = "src/kete_core", features=["pyo3", "polars"]}
pyo3 = { version = "^0.22.1", features = ["extension-module"] }
pyo3 = { version = "^0.22.6", features = ["extension-module"] }
serde = { version = "^1.0.203", features = ["derive"] }
nalgebra = {version = "^0.33.0"}
itertools = "^0.13.0"
Expand Down
22 changes: 12 additions & 10 deletions src/kete/rust/flux/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,8 +333,8 @@ pub fn frm_thermal_py(
///
/// The model for apparent magnitudes are:
///
/// m1 + k1 * log10(sun2obj.r) + 5.0 * log10(obj2obs.r) + phase_mag_slope * phase
/// m2 + k2 * log10(sun2obj.r) + 5.0 * log10(obj2obs.r) + phase_mag_slope * phase
/// m1 + k1 * log10(sun2obj.r) + 5.0 * log10(obj2obs.r) + phase_mag_slope_1 * phase
/// m2 + k2 * log10(sun2obj.r) + 5.0 * log10(obj2obs.r) + phase_mag_slope_2 * phase
///
/// Where m1/k1 are related to total magnitudes and m2/k2 are nucleus magnitudes.
///
Expand All @@ -346,6 +346,9 @@ pub fn frm_thermal_py(
/// which are present in the wikipedia definition, this matches the definitions used by
/// JPL Horizons.
///
/// Note that this includes seperate phase magnitude slope for both the nucleus and
/// total fluxes.
///
/// This does a best effort to compute both magnitudes, if any values are missing this
/// will return None in the respective calculation.
///
Expand All @@ -365,29 +368,28 @@ pub fn frm_thermal_py(
/// and K_2 nucleus magnitude slope as a function of heliocentric distance.
/// phase_corr :
/// Magnitude variation of the comet as a function of observing phase, units are
/// Mag/Deg of phase, this defaults to 0.035 Mag/Deg.
/// Mag/Deg of phase, this defaults to 0.0 for the total magnitude, and 0.035
/// Mag/Deg for the nucleus.
///
/// Returns
/// -------
/// float
/// (Total apparent magnitude, Magnitude of the nucleus)
#[allow(clippy::too_many_arguments)]
#[pyfunction]
#[pyo3(name = "comet_apparent_mags", signature = (sun2obj, sun2obs, mk_1=None, mk_2=None, phase_corr=None))]
#[pyo3(name = "comet_apparent_mags", signature = (sun2obj, sun2obs, mk_1=None, mk_2=None, phase_corr=[0.0, 0.035]))]
pub fn comet_mags_py(
sun2obj: VectorLike,
sun2obs: VectorLike,
mk_1: Option<[f64; 2]>,
mk_2: Option<[f64; 2]>,
phase_corr: Option<f64>,
phase_corr: [f64; 2],
) -> (Option<f64>, Option<f64>) {
let sun2obj = sun2obj.into_vec(PyFrames::Ecliptic);
let sun2obs = sun2obs.into_vec(PyFrames::Ecliptic);
let corr = phase_corr.unwrap_or(0.035);
let mk_params = CometMKParams::new("".into(), mk_1, mk_2, corr);
let mk_params = CometMKParams::new("".into(), mk_1, mk_2, phase_corr);
(
mk_params.apparent_total_flux(&sun2obs, &sun2obj),
mk_params.apparent_nuclear_flux(&sun2obs, &sun2obj),
mk_params.apparent_total_mag(&sun2obs, &sun2obj),
mk_params.apparent_nuclear_mag(&sun2obs, &sun2obj),
)
}

Expand Down
4 changes: 3 additions & 1 deletion src/kete/rust/fovs/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ pub struct PyNeosCmos(pub fov::NeosCmos);
/// for chip in fov:
/// corners = chip.corners
/// corners.append(corners[0])
/// plt.plot([x.lon for x in corners], [y.lat for y in corners], c="k")
/// plt.plot([x.as_ecliptic.lon for x in corners],
/// [y.as_ecliptic.lat for y in corners],
/// c="k")
/// plt.gca().set_aspect("equal")
/// plt.gca().set_axis_off()
/// plt.annotate("0", [0.07, 0.8], xycoords="axes fraction")
Expand Down
2 changes: 1 addition & 1 deletion src/kete_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ lazy_static = "^1.5.0"
nalgebra = {version = "^0.33.0"}
polars = {version = "0.43.1", optional=true, features=["parquet", "polars-io"]}
pathfinding = "^4.10.0"
pyo3 = { version = "^0.22.1", optional=true}
pyo3 = { version = "^0.22.6", optional=true}
rayon = "^1.10.0"
serde = { version = "^1.0.203", features = ["derive"] }
sgp4 = "^2.2.0"
Expand Down
57 changes: 49 additions & 8 deletions src/kete_core/src/flux/comets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,23 @@ use serde::{Deserialize, Serialize};
///
/// <https://en.wikipedia.org/wiki/Absolute_magnitude#Cometary_magnitudes>
///
/// The model for apparent magnitudes are:
///
/// m1 + k1 * log10(sun2obj.r) + 5.0 * log10(obj2obs.r) + phase_mag_slope_1 * phase
/// m2 + k2 * log10(sun2obj.r) + 5.0 * log10(obj2obs.r) + phase_mag_slope_2 * phase
///
/// Where m1/k1 are related to total magnitudes and m2/k2 are nucleus magnitudes.
///
/// This model is based off of these:
/// <https://ssd.jpl.nasa.gov/horizons/manual.html#obsquan> (see section 9)
/// <https://en.wikipedia.org/wiki/Absolute_magnitude#Cometary_magnitudes>
///
/// Note that the above model does not include a 2.5x term attached to the K1/2 terms
/// which are present in the wikipedia definition, this matches the definitions used by
/// JPL Horizons.
///
/// This model additionally includes a correction for phase effects.
///
#[derive(Debug, Deserialize, Serialize)]
pub struct CometMKParams {
/// Designation (name) of the object.
Expand All @@ -17,8 +33,8 @@ pub struct CometMKParams {
/// M2 and K2 if defined.
pub mk_2: Option<[f64; 2]>,

/// Phase correction coefficient in units of Mag/Deg
pub phase_corr_coef: f64,
/// Phase correction coefficients in units of Mag/Deg
pub phase_corr_coef: [f64; 2],
}

impl CometMKParams {
Expand All @@ -27,19 +43,19 @@ impl CometMKParams {
desig: String,
mk_1: Option<[f64; 2]>,
mk_2: Option<[f64; 2]>,
phase_corr: f64,
phase_corr_coef: [f64; 2],
) -> Self {
Self {
desig,
mk_1,
mk_2,
phase_corr_coef: phase_corr,
phase_corr_coef,
}
}

/// Compute the apparent total flux including both coma and nucleus of the comet.
/// This includes an additional 0.035 Mag/Deg phase correction.
pub fn apparent_total_flux(
pub fn apparent_total_mag(
&self,
sun2obs: &Vector3<f64>,
sun2obj: &Vector3<f64>,
Expand All @@ -48,13 +64,13 @@ impl CometMKParams {
let obj2obs = -sun2obj + sun2obs;
let obs_dist = obj2obs.norm();
let helio_dist = sun2obj.norm();
let phase_corr = self.phase_corr_coef * obj2obs.angle(&-sun2obj).to_degrees();
let phase_corr = self.phase_corr_coef[0] * obj2obs.angle(&-sun2obj).to_degrees();
Some(m1 + k1 * helio_dist.log10() + 5.0 * obs_dist.log10() + phase_corr)
}

/// Compute the apparent nuclear flux of the comet, not including the coma.
/// This includes an additional 0.035 Mag/Deg phase correction.
pub fn apparent_nuclear_flux(
pub fn apparent_nuclear_mag(
&self,
sun2obs: &Vector3<f64>,
sun2obj: &Vector3<f64>,
Expand All @@ -63,7 +79,32 @@ impl CometMKParams {
let obj2obs = -sun2obj + sun2obs;
let obs_dist = obj2obs.norm();
let helio_dist = sun2obj.norm();
let phase_corr = self.phase_corr_coef * obj2obs.angle(&-sun2obj).to_degrees();
let phase_corr = self.phase_corr_coef[1] * obj2obs.angle(&-sun2obj).to_degrees();
Some(m2 + k2 * helio_dist.log10() + 5.0 * obs_dist.log10() + phase_corr)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_comet_mags() {
// Testing 12P against JPL horizons values.

let mk_1 = [5.0, 15.0];
let mk_2 = [11.0, 10.0];

let pos = Vector3::from([-1.154216937776, -2.385684461737, -1.893975509337]);
let obs = Vector3::from([0.469511752038, 0.868580775506, -5.2896978e-5]);

let comet_mag = CometMKParams::new("12P".into(), Some(mk_1), Some(mk_2), [0.0, 0.0]);

let nucl_mags = comet_mag.apparent_nuclear_mag(&obs, &pos).unwrap();
let total_mags = comet_mag.apparent_total_mag(&obs, &pos).unwrap();

// Horizons values: 15.757 19.192
assert!((total_mags - 15.757).abs() < 1e-3);
assert!((nucl_mags - 19.192).abs() < 1e-3);
}
}

0 comments on commit 85a3c5d

Please sign in to comment.