Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve mission phase checks #4

Merged
merged 1 commit into from
Apr 24, 2024
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
2 changes: 1 addition & 1 deletion src/neospy/irsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def query_irsa_tap(
jd = neospy.Time(56823.933738, 'mjd').jd

# This time corresponds to this phase:
phase = neospy.wise.WISE_phase_from_jd(jd)
phase = neospy.wise.mission_phase_from_jd(jd)

# Single source table on IRSA is then: phase.source_table

Expand Down
13 changes: 9 additions & 4 deletions src/neospy/rust/fovs/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,16 @@ pub fn fov_spk_checks_py(obj_ids: Vec<isize>, fovs: FOVListLike) -> Vec<Vec<PySi
let fovs = fovs.into_sorted_vec_fov();

fovs.into_par_iter()
.map(|fov| {
let vis: Vec<_> = fov.check_spks(&obj_ids);
vis.into_iter()
.filter_map(|fov| {
let vis: Vec<_> = fov
.check_spks(&obj_ids)
.into_iter()
.filter_map(|pop| pop.map(|p| PySimultaneousStates(Box::new(p))))
.collect()
.collect();
match vis.is_empty() {
true => None,
false => Some(vis),
}
})
.collect()
}
125 changes: 99 additions & 26 deletions src/neospy/wise.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
from collections import namedtuple
from functools import lru_cache
import tempfile
from typing import Optional
import requests
import warnings
import matplotlib.pyplot as plt # type: ignore
import numpy as np
from typing import Optional

from astropy.io import fits # type: ignore
from astropy.wcs import WCS # type: ignore
Expand Down Expand Up @@ -188,52 +188,125 @@
MISSION_PHASES = dict(sorted(MISSION_PHASES.items(), key=lambda x: x[1].jd_start))


def WISE_phase_from_jd(jd: float):
def mission_phase_from_jd(jd: float):
"""
Return which mission phase is associated with the provided JD. Returns None if no
matching mission phase.

The WISE mission has different phases based on the cryogen on board and the
hibernation period, resulting in different useable bands and different locations in
the IRSA archive.

Parameters
----------
jd :
The Julian Date in TDB scaled time, this is fully sufficient to determine the
mission phase.
"""
for mission in MISSION_PHASES.values():
if mission.jd_start <= jd and jd < mission.jd_end:
return mission
return None


def WISE_phase_from_scan(scan_id: str) -> Optional[MissionPhase]:
def mission_phase_from_scan(scan_id: str) -> Optional[MissionPhase]:
"""
Return the mission phase for WISE from the provided scan id.

During reactivation, scan ids do not end on exact dates at the end of the year, and
as a result this function may return the wrong reactivation year for scan IDs near
the end of a year. However the Cryo/3-band/post-cryo phases will all be exact.

The WISE mission has different phases based on the cryogen on board and the
hibernation period, resulting in different useable bands and different locations in
the IRSA archive.

Parameters
----------
scan_id :
The scan id to be converted, this is fully sufficient to decide which mission
phase.
The scan id to be converted, this is sufficient to determine the mission phase.
"""

scan_num = int(scan_id[0:5])
if scan_id[-1] in ["r", "s", "t"]:
# late reactivation
if scan_num <= 45686: # final scan number of year 9
return MISSION_PHASES["Reactivation_2022"]
return None
else:
# first pass through the 5 digit scan number cycle
if scan_num > 40000:
# early reactivation
return MISSION_PHASES["Reactivation_2014"]
elif scan_num > 8745:
return MISSION_PHASES["Post-Cryo"]
elif scan_num <= 7101 and scan_id[-1] in "a":
letter = scan_id[-1]

if letter == "j":
return MISSION_PHASES["Cryo"]
if letter == "d":
return MISSION_PHASES["Post-Cryo"]
if letter == "c":
if scan_num <= 6217:
return MISSION_PHASES["Cryo"]
elif scan_num <= 7097 and scan_id[-1] == "b":
return MISSION_PHASES["Cryo"]
elif scan_num <= 6217 and scan_id[-1] == "c":
elif scan_num <= 8101:
return MISSION_PHASES["3-Band"]
return None
elif letter == "a":
if scan_num <= 7101:
return MISSION_PHASES["Cryo"]
elif scan_num <= 831 and scan_id[-1] == "j":
elif scan_num <= 8744:
return MISSION_PHASES["3-Band"]
elif scan_num <= 12514:
return MISSION_PHASES["Post-Cryo"]
elif scan_num <= 55858:
return MISSION_PHASES["Reactivation_2014"]
elif scan_num <= 66982:
return MISSION_PHASES["Reactivation_2015"]
elif scan_num <= 78154:
return MISSION_PHASES["Reactivation_2016"]
elif scan_num <= 89305:
return MISSION_PHASES["Reactivation_2017"]
elif scan_num <= 99799:
return MISSION_PHASES["Reactivation_2018"]
return None
elif letter == "b":
if scan_num <= 7097:
return MISSION_PHASES["Cryo"]
else:
elif scan_num <= 8741:
return MISSION_PHASES["3-Band"]
elif scan_num <= 12514:
return MISSION_PHASES["Post-Cryo"]
elif scan_num <= 55857:
return MISSION_PHASES["Reactivation_2014"]
elif scan_num <= 66981:
return MISSION_PHASES["Reactivation_2015"]
elif scan_num <= 78153:
return MISSION_PHASES["Reactivation_2016"]
elif scan_num <= 89301:
return MISSION_PHASES["Reactivation_2017"]
elif scan_num <= 99105:
return MISSION_PHASES["Reactivation_2018"]
return None

# 2018 or later
elif letter == "r":
if scan_num <= 1660:
return MISSION_PHASES["Reactivation_2018"]
elif scan_num <= 12819:
return MISSION_PHASES["Reactivation_2019"]
elif scan_num <= 24012:
return MISSION_PHASES["Reactivation_2020"]
elif scan_num <= 35181:
return MISSION_PHASES["Reactivation_2021"]
elif scan_num <= 46370:
return MISSION_PHASES["Reactivation_2022"]
elif scan_num <= 57041:
return MISSION_PHASES["Reactivation_2023"]
return None
elif letter == "s":
if scan_num <= 1615:
return MISSION_PHASES["Reactivation_2018"]
elif scan_num <= 12037:
return MISSION_PHASES["Reactivation_2019"]
elif scan_num <= 23769:
return MISSION_PHASES["Reactivation_2020"]
elif scan_num <= 34831:
return MISSION_PHASES["Reactivation_2021"]
elif scan_num <= 46369:
return MISSION_PHASES["Reactivation_2022"]
elif scan_num <= 56807:
return MISSION_PHASES["Reactivation_2023"]
return None
return None


def cache_WISE_frame(scan_id, frame_num, band=3, im_type="int"):
Expand All @@ -256,7 +329,7 @@ def cache_WISE_frame(scan_id, frame_num, band=3, im_type="int"):
if not os.path.isdir(dir_path):
os.makedirs(dir_path)

phase = WISE_phase_from_scan(scan_id)
phase = mission_phase_from_scan(scan_id)
url = f"{phase.frame_url}{scan_grp}/{scan_id}/{frame_num}/{filename}"
res = requests.get(url, timeout=30)
if res.status_code == 404:
Expand Down Expand Up @@ -298,7 +371,7 @@ def fetch_WISE_frame(scan_id, frame_num, band=3, im_type="int", cache=True):

filename = f"{scan_id}{frame_num}-{band}-{im_type}-1b.{ext}"

phase = WISE_phase_from_scan(scan_id)
phase = mission_phase_from_scan(scan_id)
url = f"{phase.frame_url}{scan_grp}/{scan_id}/{frame_num}/{filename}"
res = requests.get(url, timeout=30)

Expand Down Expand Up @@ -328,7 +401,7 @@ def plot_4band(
ecolor = [None, "blue", "green", "#ff7700", "red"]

if bands is None:
bands = WISE_phase_from_scan(scan_id).bands
bands = mission_phase_from_scan(scan_id).bands

plt.figure(dpi=120, figsize=(8, 8), facecolor="w")
plt.suptitle(f"Scan: {scan_id} Frame: {frame_num}")
Expand Down
34 changes: 18 additions & 16 deletions src/tests/test_wise.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,34 @@
from neospy.wise import (
MISSION_PHASES,
WISE_phase_from_jd,
WISE_phase_from_scan,
mission_phase_from_jd,
mission_phase_from_scan,
)


def test_WISE_phase_from_jd():
def test_mission_phase_from_jd():
for phase in MISSION_PHASES.values():
p0 = WISE_phase_from_jd(phase.jd_start)
p0 = mission_phase_from_jd(phase.jd_start)
assert p0 == phase, p0.name + " " + phase.name
p1 = WISE_phase_from_jd(phase.jd_end - 1)
p1 = mission_phase_from_jd(phase.jd_end - 1)
assert p1 == phase, p1.name + " " + phase.name

assert WISE_phase_from_jd(1000) is None
assert mission_phase_from_jd(1000) is None


def test_WISE_phase_from_scan():
for letter in "rst":
def test_mission_phase_from_scan():
for letter in "rs":
scan_id = "10000" + letter
assert WISE_phase_from_scan(scan_id) == MISSION_PHASES["Reactivation_2022"]
scan_id = "45687" + letter
assert WISE_phase_from_scan(scan_id) is None
assert mission_phase_from_scan(scan_id) == MISSION_PHASES["Reactivation_2019"]
scan_id = "57042" + letter
assert mission_phase_from_scan(scan_id) is None

scan_id = "01000a"
assert WISE_phase_from_scan(scan_id) == MISSION_PHASES["Cryo"]
scan_id = "08000k"
assert WISE_phase_from_scan(scan_id) == MISSION_PHASES["3-Band"]
assert mission_phase_from_scan(scan_id) == MISSION_PHASES["Cryo"]
scan_id = "08000b"
assert mission_phase_from_scan(scan_id) == MISSION_PHASES["3-Band"]
scan_id = "09000a"
assert WISE_phase_from_scan(scan_id) == MISSION_PHASES["Post-Cryo"]
assert mission_phase_from_scan(scan_id) == MISSION_PHASES["Post-Cryo"]
scan_id = "49000a"
assert WISE_phase_from_scan(scan_id) == MISSION_PHASES["Reactivation_2014"]
assert mission_phase_from_scan(scan_id) == MISSION_PHASES["Reactivation_2014"]
scan_id = "46000s"
assert mission_phase_from_scan(scan_id) == MISSION_PHASES["Reactivation_2022"]
Loading