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

87 make hdf datasets always be float64 unless they are pcap bits #93

6 changes: 1 addition & 5 deletions src/pandablocks/hdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,11 +198,7 @@ def mean_callable(data):
return (data[column_name] * field.scale / gate_duration) + field.offset

return mean_callable
elif (
raw
and not field.is_pcap_bits_or_samples
and (field.scale != 1 or field.offset != 0)
):
elif raw and field.has_scale_or_offset:
return lambda data: data[column_name] * field.scale + field.offset
else:
return lambda data: data[column_name]
Expand Down
36 changes: 19 additions & 17 deletions src/pandablocks/responses.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from dataclasses import dataclass
from dataclasses import dataclass, field
from enum import Enum
from typing import Dict, List, Optional, Tuple

Expand Down Expand Up @@ -238,29 +238,31 @@ class FieldCapture:
name: str
type: np.dtype
capture: str
scale: Optional[float]
offset: Optional[float]
units: Optional[str]
scale: Optional[float] = field(default=None)
offset: Optional[float] = field(default=None)
units: Optional[str] = field(default=None)

@property
def raw_mode_dataset_dtype(self) -> np.dtype:
"""We use double for all dtypes,
unless the field is a PCAP.BITS or PCAP.SAMPLES."""

if self.is_pcap_bits_or_samples:
return self.type

if None in (self.scale, self.offset, self.units):
def __post_init__(self):
sou = (self.scale, self.offset, self.units)
if sou != (None, None, None) and None in sou:
raise ValueError(
"If any of `scale`, `offset`, or `units` is set, all must be set"
f"If any of `scale={self.scale}`, `offset={self.offset}`"
f", or `units={self.units}` is set, all must be set."
)

return np.dtype("float64")
@property
def raw_mode_dataset_dtype(self) -> np.dtype:
"""We use double for all dtypes that have scale and offset."""
if self.scale is not None and self.offset is not None:
return np.dtype("float64")
return self.type

@property
def is_pcap_bits_or_samples(self) -> bool:
def has_scale_or_offset(self) -> bool:
"""Return True if this field is a PCAP.BITS or PCAP.SAMPLES field"""
return self.scale is None and self.offset is None and self.units is None
return (self.scale is not None and self.offset is not None) and (
self.scale != 1 or self.offset != 0
)


class Data:
Expand Down
64 changes: 50 additions & 14 deletions tests/test_hdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,36 +71,72 @@ def test_field_capture_pcap_bits():
units=None,
)

assert pcap_bits_frame_data.is_pcap_bits_or_samples
assert not pcap_bits_frame_data.has_scale_or_offset
assert pcap_bits_frame_data.raw_mode_dataset_dtype is np.dtype("uint32")

some_other_frame_data = FieldCapture(
name="some_other_frame_data",
frame_data_without_scale_offset = FieldCapture(
name="frame_data_without_scale_offset",
type=np.dtype("uint32"),
capture="Value",
scale=1.0,
offset=0.0,
units="",
)

assert not some_other_frame_data.is_pcap_bits_or_samples
assert some_other_frame_data.raw_mode_dataset_dtype is np.dtype("float64")
assert not frame_data_without_scale_offset.has_scale_or_offset
assert frame_data_without_scale_offset.raw_mode_dataset_dtype is np.dtype("float64")

malformed_frame_data = FieldCapture(
name="malformed_frame_data",
with pytest.raises(
ValueError,
match=(
"If any of `scale=None`, `offset=0.0`, or "
"`units=` is set, all must be set"
),
):
_ = FieldCapture(
name="malformed_frame_data",
type=np.dtype("uint32"),
capture="Value",
scale=None,
offset=0.0,
units="",
)

frame_data_with_offset = FieldCapture(
name="frame_data_with_offset",
type=np.dtype("uint32"),
capture="Value",
scale=None,
scale=1.0,
offset=1.0,
units="",
)
frame_data_with_scale = FieldCapture(
name="frame_data_with_scale",
type=np.dtype("uint32"),
capture="Value",
scale=1.1,
offset=0.0,
units="",
)

assert not some_other_frame_data.is_pcap_bits_or_samples
with pytest.raises(
ValueError,
match="If any of `scale`, `offset`, or `units` is set, all must be set",
):
assert malformed_frame_data.raw_mode_dataset_dtype is np.dtype("float64")
assert frame_data_with_offset.has_scale_or_offset
assert frame_data_with_offset.raw_mode_dataset_dtype is np.dtype("float64")
assert frame_data_with_scale.has_scale_or_offset
assert frame_data_with_scale.raw_mode_dataset_dtype is np.dtype("float64")

frame_data_with_scale_and_offset = FieldCapture(
name="frame_data_with_scale_and_offset",
type=np.dtype("uint32"),
evalott100 marked this conversation as resolved.
Show resolved Hide resolved
capture="Value",
scale=1.1,
offset=0.0,
units="",
)

assert frame_data_with_scale_and_offset.has_scale_or_offset
assert frame_data_with_scale_and_offset.raw_mode_dataset_dtype is np.dtype(
"float64"
)


@pytest.mark.parametrize(
Expand Down
Loading