Skip to content

Commit

Permalink
Prep for final WISE release (#112)
Browse files Browse the repository at this point in the history
* Prep for final WISE release

* removing time scaling from Covariance epoch
Covariances can have multiple parameters of time, it seems better to
leave time in UTC jd consistently across all cov values. The user will
have to make the conversion. This should be only a small error if
forgotten, however it would be a much larger error if only the epoch
is converted.

* fix example plotting
  • Loading branch information
dahlend authored Sep 19, 2024
1 parent 83e757d commit c396faf
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 164 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Added final SPICE kernels for the WISE mission, it now contains all positions from
all phases of operation. There is a gap for the years it was not operating.
- Updated WISE mission phases to reflect the final data products about to be released.
- Updated ZTF for the current release 22.
- Added `kete.RectangleFOV.from_wcs`, allowing the construction of a FOV from a given
Astropy WCS object.
- Added `kete.conversion.bin_data`, which allows for binning matrix data such as images.
Expand All @@ -21,11 +23,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

- Time scaling bugs when loading times from both Horizons and the MPC were fixed, these
were causing offsets of about a minute in the loaded states. However it was shifting
both the perihelion time and the epoch time by the same amount, leading to only minor
effective errors.
- Fixed a time offset in the FOV's downloaded from IRSA WISE/NEOWISE. They were offset
by 4.4 seconds.
- Fixed rotation approximation in WISE/NEOWISE field of views which was causing a small
percentage of objects to not be found during FOV checks when they were close to the
edge of the field.
- Constant for the sqrt of GMS was incorrect by a small amount, this value was fixed.
- IRSA username/password options are now being passed through correctly in WISE.

### Removed

- Removed `plot_frame` from ZTF, as a better version of this is available in kete.irsa.
- Removed `cache_WISE_frame` and `fetch_WISE_frame` deprecated functions in WISE.


## [0.3.0] - 2024 - 8 - 28
Expand Down
3 changes: 2 additions & 1 deletion src/examples/plot_comet.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,8 @@ def plot_synchrone(

# Plot the final results
plt.figure(dpi=200)
wcs = kete.ztf.plot_frame(vis.fov)
frame = kete.ztf.fetch_frame(vis.fov)
wcs = kete.irsa.plot_fits_image(frame, percentiles=None)
plt.title("Comet NEOWISE - C/2020 F3\n")

# plot syndynes
Expand Down
8 changes: 6 additions & 2 deletions src/kete/horizons.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,12 @@ def fetch(name, update_name=True, cache=True, update_cache=False, exact_name=Fal
]
if len(val) == 0:
continue
phys[kete_v] = val[0]
phys["epoch"] = float(props["orbit"]["epoch"])
if kete_v == "peri_time":
phys[kete_v] = Time(val[0], scaling="utc").jd
else:
phys[kete_v] = val[0]

phys["epoch"] = Time(float(props["orbit"]["epoch"]), scaling="utc").jd
if "moid" in props["orbit"] and props["orbit"]["moid"] is not None:
phys["moid"] = float(props["orbit"]["moid"])
if "data_arc" in props["orbit"] and props["orbit"]["data_arc"] is not None:
Expand Down
6 changes: 3 additions & 3 deletions src/kete/irsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ def query_irsa_tap(

phase_url = url.replace("results/result", "phase")

status = requests.get(phase_url, timeout=timeout)
status = requests.get(phase_url, timeout=timeout, auth=auth)
status.raise_for_status()

# Status results can have one of 4 outcomes:
Expand All @@ -164,7 +164,7 @@ def query_irsa_tap(
status.content.decode(),
)
time.sleep(delay)
status = requests.get(phase_url, timeout=timeout)
status = requests.get(phase_url, timeout=timeout, auth=auth)
status.raise_for_status()

# Increase time between queries until there is 30 seconds between.
Expand All @@ -175,7 +175,7 @@ def query_irsa_tap(
if status.content.decode().upper() != "COMPLETED":
raise ValueError("Job Failed: ", status.content.decode())

result = requests.get(url, timeout=timeout)
result = requests.get(url, timeout=timeout, auth=auth)
result.raise_for_status()
return pd.read_csv(io.StringIO(result.text))

Expand Down
4 changes: 2 additions & 2 deletions src/kete/mpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -673,8 +673,8 @@ def fetch_known_orbit_data(url=None, force_download=False):
incl=obj["i"],
lon_node=obj["Node"],
peri_arg=obj["Peri"],
peri_time=obj["Tp"],
epoch=obj["Epoch"],
peri_time=Time(obj["Tp"], scaling="utc").jd,
epoch=Time(obj["Epoch"], scaling="utc").jd,
arc_len=arc_len,
name=obj.get("Name", None),
)
Expand Down
95 changes: 37 additions & 58 deletions src/kete/wise.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@


import os
import logging
from collections import namedtuple
from functools import lru_cache, partial
from functools import lru_cache
from typing import Optional, Union
import matplotlib.pyplot as plt
import numpy as np
Expand All @@ -15,7 +16,6 @@
from .time import Time
from .vector import Vector, Frames
from .irsa import IRSA_URL, query_irsa_tap, plot_fits_image, zoom_plot, annotate_plot
from .deprecation import rename

from ._core import (
WiseCmos,
Expand All @@ -27,18 +27,20 @@
)

__all__ = [
"fetch_frame",
"plot_frames",
"MISSION_PHASES",
"mission_phase_from_jd",
"mission_phase_from_scan",
"plot_frames",
"fetch_WISE_frame",
"MissionPhase",
"w1_color_correction",
"w2_color_correction",
"w3_color_correction",
"w4_color_correction",
]

logger = logging.getLogger(__name__)

# All constants below are indexed as follows W1 = [0], W2 = [1]. W3 = [2], W4 = [3]

_COLOR_CORR = np.array(
Expand Down Expand Up @@ -88,29 +90,20 @@
# W4 is almost a constant.
# These fits perform much better than linear interpolation except near 100k.
#
# The values above were fit to polynomial equations as defined below, the results of
# which were hard-coded into the rust backend to allow for fast computation.
# These functions should not be referenced directly, as they also exist in the rust
# code and are only left here for reference to how the rust was constructed.
#
# from numpy.polynomial import Polynomial
# _COLOR_FITS = [
# Polynomial.fit(_COLOR_CORR[:, 0], 1 / _COLOR_CORR[:, 1], 4),
# Polynomial.fit(_COLOR_CORR[:, 0], 1 / _COLOR_CORR[:, 2], 4),
# Polynomial.fit(_COLOR_CORR[:, 0], 1 / _COLOR_CORR[:, 3], 4),
# Polynomial.fit(_COLOR_CORR[:, 0], 1 / _COLOR_CORR[:, 4], 4),
# ]
# The values above were fit to polynomial equations, the results of which were
# hard-coded into the rust backend to allow for fast computation.


SUN_COLOR_CORRECTION: list[float] = [1.0049, 1.0193, 1.0024, 1.0012]
"""
Flux in the reflected light model should be scaled by these values.
This corrects for the Sun's spectral difference to the calibrator.
"""

ZERO_MAGS: list[float] = [306.681, 170.663, 29.0448, 8.2839]
"""
Non-color corrected values for zero mag corrections in Janskys.
Magnitude can then be computed via -2.5 log10(flux Jy / zero_point)
"""

ZERO_MAGS_COLOR_CORRECTED: list[float] = [
Expand All @@ -119,7 +112,7 @@
1.08 * ZERO_MAGS[2],
0.96 * ZERO_MAGS[3],
]
"""Color Corrected Zero Mags in units of Jy"""
"""Color Corrected Zero Mags in units of Jy."""

BAND_WAVELENGTHS: list[float] = [3352.6, 4602.8, 11560.8, 22088.3]
"""Non-color corrected values for the effective central wavelength of the bands (nm)"""
Expand Down Expand Up @@ -212,10 +205,10 @@
frame_meta_table="neowiser_p1bs_frm",
source_table="neowiser_p1bs_psd",
),
"Reactivation_2023": MissionPhase(
name="Reactivation_2023",
jd_start=Time.from_ymd(2023, 1, 1).jd,
jd_end=Time.from_ymd(2023, 12, 13.121151733).jd,
"Reactivation_2024": MissionPhase(
name="Reactivation_2024",
jd_start=Time.from_ymd(2024, 1, 1).jd,
jd_end=Time.from_ymd(2024, 8, 1.291525).jd,
bands=(1, 2),
frame_url=IRSA_URL + "/ibe/data/wise/neowiser/p1bm_frm/",
frame_meta_table="neowiser_p1bs_frm",
Expand All @@ -224,7 +217,7 @@
}
"""Public released mission phases of WISE."""

for year in range(2015, 2023):
for year in range(2015, 2024):
MISSION_PHASES[f"Reactivation_{year}"] = MissionPhase(
name=f"Reactivation_{year}",
jd_start=Time.from_ymd(year, 1, 1).jd,
Expand Down Expand Up @@ -340,6 +333,10 @@ def mission_phase_from_scan(scan_id: str) -> Optional[MissionPhase]:
return MISSION_PHASES["Reactivation_2022"]
elif scan_num <= 57041:
return MISSION_PHASES["Reactivation_2023"]
elif scan_num <= 57626:
return MISSION_PHASES["Reactivation_2023"]
elif scan_num <= 64272:
return MISSION_PHASES["Reactivation_2024"]
return None
elif letter == "s":
if scan_num <= 1615:
Expand All @@ -352,8 +349,10 @@ def mission_phase_from_scan(scan_id: str) -> Optional[MissionPhase]:
return MISSION_PHASES["Reactivation_2021"]
elif scan_num <= 46369:
return MISSION_PHASES["Reactivation_2022"]
elif scan_num <= 56807:
elif scan_num <= 57519:
return MISSION_PHASES["Reactivation_2023"]
elif scan_num <= 64267:
return MISSION_PHASES["Reactivation_2024"]
return None
return None

Expand All @@ -376,7 +375,9 @@ def _scan_frame(scan_id, frame_num=None, band=None):
return scan_id, frame_num, band


def fetch_frame(scan_id, frame_num=None, band=None, as_fits=True, im_type="int"):
def fetch_frame(
scan_id, frame_num=None, band=None, as_fits=True, im_type="int", retry=2
):
"""
Fetch the WISE FITs frame, if it is not present in the cache, download it first.
Expand Down Expand Up @@ -413,49 +414,27 @@ def fetch_frame(scan_id, frame_num=None, band=None, as_fits=True, im_type="int")
# format the url
frame_num = f"{frame_num:03d}"
scan_group = str(scan_id[-2:])
band = f"w{band:1d}"
band_str = f"w{band:1d}"
ext = "fits" if im_type == "int" else "fits.gz"
filename = f"{scan_id}{frame_num}-{band}-{im_type}-1b.{ext}"
filename = f"{scan_id}{frame_num}-{band_str}-{im_type}-1b.{ext}"
url = f"{phase.frame_url}{scan_group}/{scan_id}/{frame_num}/{filename}"

subfolder = os.path.join("wise_frames", scan_group)

file_path = download_file(url, auto_zip=True, subfolder=subfolder)
if as_fits:
return fits.open(file_path)[0]
try:
return fits.open(file_path)[0]
except OSError as exc:
if retry == 0:
raise ValueError("Failed to fetch WISE frame.") from exc
logger.info("WISE file appears corrupted, attempting to fetch again.")
os.remove(file_path)
return fetch_frame(scan_id, frame_num, band, as_fits, im_type, retry - 1)
else:
return file_path


_frame_path = cache_path("wise_frames")
_reorg_msg = (
" The organization of wise cached frames has changed, it is recommended"
" to delete the old cache files with the shell command: \n"
f"rm {_frame_path}/*.fits"
"\nThis only has to be done once. Frames are now stored in subfolders "
"based on the scan group number. This allows for many more files to be"
" saved locally before there are filesystem issues."
)
cache_WISE_frame = partial(
rename(
fetch_frame,
additional_msg=(
"Use `as_fits=False` with as an argument in the new function." + _reorg_msg
),
deprecated_version="v0.2.4",
old_name="cache_WISE_frame",
),
as_fits=False,
)

fetch_WISE_frame = rename(
fetch_frame,
additional_msg=_reorg_msg,
deprecated_version="v0.2.4",
old_name="fetch_WISE_frame",
)


def plot_frames(
scan_id,
frame_num=None,
Expand Down Expand Up @@ -547,7 +526,7 @@ def plot_frames(
plt.title(f"W{band:1d}")


@lru_cache()
@lru_cache(maxsize=2)
def fetch_WISE_fovs(phase):
"""
Load all FOVs taken during the specified mission phase of WISE.
Expand Down
Loading

0 comments on commit c396faf

Please sign in to comment.