Skip to content

Commit

Permalink
Merge pull request #181 from sot/maude-aca-chunks
Browse files Browse the repository at this point in the history
Use CxoTime.linspace on get_aca_images for > 3hour range
  • Loading branch information
jeanconn authored Nov 7, 2024
2 parents e20dc05 + e748730 commit e13497f
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 15 deletions.
70 changes: 55 additions & 15 deletions chandra_aca/maude_decom.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,16 @@
from struct import Struct
from struct import unpack as _unpack

import astropy.units as u
import maude
import numpy as np
from astropy.table import Table, vstack
from Chandra.Time import DateTime
from cxotime import CxoTime, CxoTimeLike

# Maude fetch limits
MAUDE_SINGLE_FETCH_LIMIT = 3.0 * u.hour
MAUDE_FETCH_LIMIT = 5 * u.day

# maximum values for frame counters (for convenience)
MAX_MJF = (2 << 16) - 1
Expand Down Expand Up @@ -764,8 +770,9 @@ def get_raw_aca_packets(start, stop, maude_result=None, **maude_kwargs):
{'flags': int, 'packets': [],
'TIME': np.array([]), 'MNF': np.array([]), 'MJF': np.array([])}
"""
date_start, date_stop = DateTime(start), DateTime(
stop
date_start, date_stop = (
DateTime(start),
DateTime(stop),
) # ensure input is proper date
stop_pad = 1.5 / 86400 # padding at the end in case of trailing partial ACA packets

Expand Down Expand Up @@ -1140,13 +1147,15 @@ def get_aca_packets(
combine = True
calibrate = True

date_start, date_stop = DateTime(start), DateTime(
stop
date_start, date_stop = (
DateTime(start),
DateTime(stop),
) # ensure input is proper date
if 24 * (date_stop - date_start) > 3:
if (CxoTime(stop) - CxoTime(start)) > MAUDE_SINGLE_FETCH_LIMIT:
raise ValueError(
f"Requested {24 * (date_stop - date_start)} hours of telemetry. "
"Maximum allowed is 3 hours at a time"
f"Requested {CxoTime(stop) - CxoTime(start)} of telemetry. "
f"Maximum allowed is {MAUDE_SINGLE_FETCH_LIMIT} at a time "
"(see MAUDE_SINGLE_FETCH_LIMIT)."
)

stop_pad = 0
Expand Down Expand Up @@ -1302,24 +1311,54 @@ def _get_aca_packets(
return table


def get_aca_images(start, stop, **maude_kwargs):
def get_aca_images(start: CxoTimeLike, stop: CxoTimeLike, **kwargs):
"""
Fetch ACA image telemetry
Fetch ACA image telemetry from MAUDE and return it as an astropy Table. With the default
settings and no additional kwargs, this calls `get_aca_packets()` in a configuration that
uses MAUDE frames, combines image data, and sets the TIME associated with each image to the
midpoint of the integration time during which that pixel data was collected (matches CXC L0
times). See `get_aca_packets()`.
Parameters
----------
start
timestamp interpreted as a Chandra.Time.DateTime
timestamp, CxoTimeLike
stop
timestamp interpreted as a Chandra.Time.DateTime
maude_kwargs
keyword args passed to maude
timestamp, CxoTimeLike. stop - start cannot be greater than MAUDE_FETCH_LIMIT
kwargs
keyword args passed to get_aca_packets
Returns
-------
astropy.table.Table
"""
return get_aca_packets(start, stop, level0=True, **maude_kwargs)
start = CxoTime(start)
stop = CxoTime(stop)
if (stop - start) > MAUDE_FETCH_LIMIT:
raise ValueError(
f"stop - start cannot be greater than {MAUDE_FETCH_LIMIT}. "
"Set module variable MAUDE_FETCH_LIMIT if needed."
)
maude_fetch_times = CxoTime.linspace(
start, stop, step_max=MAUDE_SINGLE_FETCH_LIMIT - 1 * u.s
)
packet_stack = [
get_aca_packets(
start=istart,
stop=istop,
level0=True,
**kwargs,
)
for istart, istop in zip(
maude_fetch_times[:-1], maude_fetch_times[1:], strict=False
)
]
out = vstack(packet_stack)
out.meta["times"] = maude_fetch_times
return out


######################
Expand Down Expand Up @@ -1356,8 +1395,9 @@ def get_raw_aca_blobs(start, stop, maude_result=None, **maude_kwargs):
dict
{'blobs': [], 'names': np.array([]), 'types': np.array([])}
"""
date_start, date_stop = DateTime(start), DateTime(
stop
date_start, date_stop = (
DateTime(start),
DateTime(stop),
) # ensure input is proper date
stop_pad = 1.5 / 86400 # padding at the end in case of trailing partial ACA packets

Expand Down
54 changes: 54 additions & 0 deletions chandra_aca/tests/test_maude_decom.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import os
import pickle

import astropy.units as u
import maude
import numpy as np
import pytest
from cxotime import CxoTime

from chandra_aca import maude_decom

Expand Down Expand Up @@ -272,6 +274,58 @@ def test_partial_images():
assert np.all(table[i]["IMG"].mask == mask[table[i]["IMGTYPE"]])


def test_aca_images_chunks_1():
"""Test that a fetch longer than the maude step limit works"""
single_fetch_limit = maude_decom.MAUDE_SINGLE_FETCH_LIMIT
maude_decom.MAUDE_SINGLE_FETCH_LIMIT = 1 * u.min
start = "2023:001:00:00:01.000"
stop = "2023:001:00:05:01.000"
tstart = CxoTime(start).secs
tstop = CxoTime(stop).secs
try:
imgs = maude_decom.get_aca_images(start, stop)
finally:
maude_decom.MAUDE_SINGLE_FETCH_LIMIT = single_fetch_limit

imgs.sort(["TIME", "IMGNUM"])

for slot in range(8):
# Confirm that the data is basically contiguous
ok_slot = imgs["IMGNUM"] == slot
# Confirm no duplicates by VCDUCTR
assert len(np.unique(imgs[ok_slot]["VCDUCTR"])) == len(imgs[ok_slot])
# Confirm for these 8x8 data that there's no gap > 5 seconds
assert np.max(np.diff(imgs[ok_slot]["TIME"])) < 5

# Confirm that the returned data times are within the start stop
assert imgs["TIME"][0] >= tstart
assert imgs["TIME"][-1] <= tstop

# Confirm that the beginning and end match the expected values
assert abs(imgs[0]["TIME"] - tstart) < 2
assert abs(imgs[-1]["TIME"] - tstop) < 2

imgs_start = maude_decom.get_aca_images(start, CxoTime(start) + 60 * u.s)
imgs_stop = maude_decom.get_aca_images(CxoTime(stop) - 60 * u.s, stop)
imgs_start.sort(["TIME", "IMGNUM"])
imgs_stop.sort(["TIME", "IMGNUM"])
assert np.all(imgs[0] == imgs_start[0])
assert np.all(imgs[-1] == imgs_stop[-1])

# Check the linspace times in the returned data
used_step_max = 1 * u.min - 1 * u.s
deltas_lte = [t <= used_step_max for t in np.diff(imgs.meta["times"])]
assert np.all(deltas_lte)


def test_aca_images_chunks_2():
"""Test that a fetch longer than MAUDE_FETCH_LIMIT throws a ValueError"""
start = CxoTime("2023:001:00:00:01.000")
stop = start + (maude_decom.MAUDE_FETCH_LIMIT * 1.1)
with pytest.raises(ValueError, match="stop - start cannot be greater than"):
maude_decom.get_aca_images(start, stop)


def test_vcdu_vs_level0():
from astropy.table import Table

Expand Down

0 comments on commit e13497f

Please sign in to comment.