Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion imap_processing/codice/codice_l2.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
dataset = process_codice_l2(l1_filename)
"""

import datetime
import logging
from pathlib import Path

Expand Down Expand Up @@ -41,6 +42,7 @@
SW_POSITIONS,
)
from imap_processing.codice.utils import apply_replacements_to_attrs
from imap_processing.spice.time import et_to_datetime64, ttj2000ns_to_et

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -315,7 +317,19 @@ def compute_geometric_factors(
# Perform the comparison and calculate modes
# Modes will be true (reduced mode) anywhere half_spin > rgfo_half_spin otherwise
# false (full mode)
modes = half_spin_per_esa_step > rgfo_half_spin
# TODO: The mode calculation will need to be revisited after FW changes in january
# 2026. We also need to fix this on days when the sci Lut changes.
# After November 24th 2025 we need to do this step a different way.
date_switch = datetime.datetime(2025, 11, 24)
dataset_midpoint_ns = dataset["epoch"].values[dataset["epoch"].size // 2]
# Convert to datetime64 for comparison
dataset_midpoint = et_to_datetime64(ttj2000ns_to_et(dataset_midpoint_ns))
if dataset_midpoint < date_switch:
modes = (half_spin_per_esa_step > rgfo_half_spin) & (rgfo_half_spin > 0)
else:
# After November 24th, 2025, we no longer apply reduced geometric factors;
# always use the full geometric factor lookup.
modes = np.zeros_like(half_spin_per_esa_step, dtype=bool)

# Get the geometric factors based on the modes
gf = np.where(
Expand Down
44 changes: 37 additions & 7 deletions imap_processing/tests/codice/test_codice_l2.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,14 @@ def mock_half_spin_per_esa_step():
ESA steps 0–63 belong to half_spin=1
ESA steps 64–127 belong to half_spin=2
"""
return np.repeat([1, 2], 64)
return np.repeat([2, 3], 64)


def test_compute_geometric_factors_all_full_mode(mock_half_spin_per_esa_step):
# rgfo_half_spin = 3 means all half_spin values (1 or 2) are < rgfo_half_spin
# rgfo_half_spin = 4 means all half_spin values (2 or 3) are < rgfo_half_spin
dataset = xr.Dataset(
{
"rgfo_half_spin": (("epoch",), np.array([3, 3])),
"rgfo_half_spin": (("epoch",), np.array([4, 4])),
"half_spin_per_esa_step": (("esa_step",), mock_half_spin_per_esa_step),
},
)
Expand All @@ -113,11 +113,41 @@ def test_compute_geometric_factors_all_full_mode(mock_half_spin_per_esa_step):
np.testing.assert_array_equal(result, expected)


def test_compute_geometric_factors_past_nov_24th(mock_half_spin_per_esa_step):
# rgfo_half_spin = 1 means all half_spin values (>=2) are >= rgfo_half_spin
# Although the rgfo_half_spin indicates reduced mode, the date is past Nov 24th,
# 2024 so we expect full mode to be used.
dataset = xr.Dataset(
{
"rgfo_half_spin": (("epoch",), np.array([1, 1])),
"half_spin_per_esa_step": (
(
"epoch",
"esa_step",
),
np.tile(mock_half_spin_per_esa_step, (2, 1)),
),
},
)
geometric_factor_lut = {
"full": np.zeros((128, 24)),
"reduced": np.ones((128, 24)),
}
# Make sure epoch is past Nov 24th, 2024
ns_past_nov_24 = 900000000000000000
dataset = dataset.assign_coords({"epoch": np.repeat(ns_past_nov_24, 2)})
result = compute_geometric_factors(dataset, geometric_factor_lut)

# Expect "full" values everywhere
expected = np.full((2, 128, 24), 0)
np.testing.assert_array_equal(result, expected)


def test_compute_geometric_factors_all_reduced_mode(mock_half_spin_per_esa_step):
# rgfo_half_spin = 0 means all half_spin values (>=1) are >= rgfo_half_spin
# rgfo_half_spin = 1 means all half_spin values (>=2) are >= rgfo_half_spin
dataset = xr.Dataset(
{
"rgfo_half_spin": (("epoch",), np.array([0])),
"rgfo_half_spin": (("epoch",), np.array([1])),
"half_spin_per_esa_step": (("esa_step",), mock_half_spin_per_esa_step),
},
)
Expand All @@ -133,10 +163,10 @@ def test_compute_geometric_factors_all_reduced_mode(mock_half_spin_per_esa_step)


def test_compute_geometric_factors_mixed(mock_half_spin_per_esa_step):
# rgfo_half_spin = 1
# rgfo_half_spin = 2
dataset = xr.Dataset(
{
"rgfo_half_spin": (("epoch",), np.array([1])),
"rgfo_half_spin": (("epoch",), np.array([2])),
"half_spin_per_esa_step": (("esa_step",), mock_half_spin_per_esa_step),
},
)
Expand Down