Skip to content

Commit

Permalink
Merge pull request #421 from slwatkins/feature/add_ORRunDecoderForRun
Browse files Browse the repository at this point in the history
Add ORRunDecoderForRun to Orca decoders
  • Loading branch information
jasondet authored Jan 20, 2023
2 parents 0fd86aa + 71c79cd commit bc59d33
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/pygama/lgdo/lh5_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ def read_object(
if datatype == "scalar":
value = h5f[name][()]
if elements == "bool":
value = np.bool(value)
value = np.bool_(value)
if obj_buf is not None:
obj_buf.value = value
obj_buf.attrs.update(h5f[name].attrs)
Expand Down Expand Up @@ -631,7 +631,7 @@ def read_object(
# special handling for bools
# (c and Julia store as uint8 so cast to bool)
if elements == "bool":
nda = nda.astype(np.bool)
nda = nda.astype(np.bool_)

# Finally, set attributes and return objects
attrs = h5f[name].attrs
Expand Down
63 changes: 63 additions & 0 deletions src/pygama/raw/orca/orca_run_decoder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import logging
from typing import Any

from pygama.raw.orca.orca_base import OrcaDecoder
from pygama.raw.orca.orca_header import OrcaHeader
from pygama.raw.orca.orca_packet import OrcaPacket
from pygama.raw.raw_buffer import RawBufferLibrary

log = logging.getLogger(__name__)


class ORRunDecoderForRun(OrcaDecoder):
"""Decoder for Run Control data written by ORCA."""

def __init__(self, header: OrcaHeader = None, **kwargs) -> None:
# quickstartrun through startsubrunrecord are in order
# of increasing bit location with respect to the rightmost
# bit in data packet
self.decoded_values = {
"subrun_number": {"dtype": "uint16"},
"runstartorstop": {"dtype": "bool8"},
"quickstartrun": {"dtype": "bool8"},
"remotecontrolrun": {"dtype": "bool8"},
"heartbeatrecord": {"dtype": "bool8"},
"endsubrunrecord": {"dtype": "bool8"},
"startsubrunrecord": {"dtype": "bool8"},
"run_number": {"dtype": "int32"},
"time": {"dtype": "int32"},
}
super().__init__(header=header, **kwargs)

def get_decoded_values(self, key: int = None) -> dict[str, Any]:
return self.decoded_values

def decode_packet(
self, packet: OrcaPacket, packet_id: int, rbl: RawBufferLibrary
) -> bool:
"""
Decode the ORCA Run packet.
Format is taken from the ORCA website: `Run Control
<http://orca.physics.unc.edu/orca/Data_Chain/Run_Control.html>`_
"""

if len(rbl) != 1:
log.warning(
f"got {len(rbl)} rb's, should have only 1 (no keyed decoded values)"
)
rb = rbl[0]
tbl = rb.lgdo
ii = rb.loc

tbl["subrun_number"].nda[ii] = (packet[1] & 0xFFFF0000) >> 16
for i, k in enumerate(self.decoded_values):
if 0 < i < 7:
tbl[k].nda[ii] = (packet[1] & (1 << (i - 1))) >> (i - 1)

tbl["run_number"].nda[ii] = packet[2]
tbl["time"].nda[ii] = packet[3]

rb.loc += 1
return rb.is_full()
1 change: 1 addition & 0 deletions src/pygama/raw/orca/orca_streamer.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
ORFlashCamWaveformDecoder,
)
from pygama.raw.orca.orca_header_decoder import OrcaHeaderDecoder
from pygama.raw.orca.orca_run_decoder import ORRunDecoderForRun # noqa: F401
from pygama.raw.raw_buffer import RawBuffer, RawBufferLibrary

log = logging.getLogger(__name__)
Expand Down
12 changes: 12 additions & 0 deletions tests/raw/orca/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import pytest

from pygama.raw.orca.orca_streamer import OrcaStreamer


@pytest.fixture(scope="module")
def orca_stream(lgnd_test_data):
orstr = OrcaStreamer()
orstr.open_stream(
lgnd_test_data.get_path("orca/fc/L200-comm-20220519-phy-geds.orca")
)
return orstr
65 changes: 65 additions & 0 deletions tests/raw/orca/test_or_run_decoder_for_run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import pytest

from pygama import lgdo
from pygama.raw.orca.orca_run_decoder import ORRunDecoderForRun
from pygama.raw.raw_buffer import RawBuffer


@pytest.fixture(scope="module")
def run_rbkd(orca_stream):

decoder = ORRunDecoderForRun(header=orca_stream.header)

rbkd = {}
rbkd[0] = RawBuffer(lgdo=decoder.make_lgdo(size=1))

this_packet = orca_stream.load_packet(skip_unknown_ids=False)
orca_stream.close_stream() # avoid leaving file open

# assert correct type for ORRunDecoderForRun
assert (this_packet[0] >> 18) == 7

# assert that it worked and the buffer is full
assert decoder.decode_packet(packet=this_packet, packet_id=1, rbl=rbkd)

return rbkd, this_packet


def test_decoding(run_rbkd):
assert run_rbkd[0] != {}


def test_data_types(run_rbkd):

for _, v in run_rbkd[0].items():
tbl = v.lgdo
assert isinstance(tbl, lgdo.Struct)
assert isinstance(tbl["subrun_number"], lgdo.Array)
assert isinstance(tbl["runstartorstop"], lgdo.Array)
assert isinstance(tbl["quickstartrun"], lgdo.Array)
assert isinstance(tbl["remotecontrolrun"], lgdo.Array)
assert isinstance(tbl["heartbeatrecord"], lgdo.Array)
assert isinstance(tbl["endsubrunrecord"], lgdo.Array)
assert isinstance(tbl["startsubrunrecord"], lgdo.Array)
assert isinstance(tbl["run_number"], lgdo.Array)
assert isinstance(tbl["time"], lgdo.Array)


def test_values(run_rbkd):

this_packet = run_rbkd[1]

decoded_values = ORRunDecoderForRun().decoded_values

for _, v in run_rbkd[0].items():
loc = v.loc - 1
tbl = v.lgdo

assert tbl["subrun_number"].nda[loc] == (this_packet[1] & 0xFFFF0000) >> 16

for i, k in enumerate(decoded_values):
if 0 < i < 7:
assert tbl[k].nda[loc] == (this_packet[1] & (1 << (i - 1))) >> (i - 1)

assert tbl["run_number"].nda[loc] == this_packet[2]
assert tbl["time"].nda[loc] == this_packet[3]

0 comments on commit bc59d33

Please sign in to comment.