update to v0.21.1, thor data import successful #29
+14
-2
@@ -438,6 +438,10 @@ def read_idf_file(
|
|||||||
peak_tran = max((iv.peak_ips("Tran") for iv in intervals), default=0.0)
|
peak_tran = max((iv.peak_ips("Tran") for iv in intervals), default=0.0)
|
||||||
peak_vert = max((iv.peak_ips("Vert") for iv in intervals), default=0.0)
|
peak_vert = max((iv.peak_ips("Vert") for iv in intervals), default=0.0)
|
||||||
peak_long = max((iv.peak_ips("Long") for iv in intervals), default=0.0)
|
peak_long = max((iv.peak_ips("Long") for iv in intervals), default=0.0)
|
||||||
|
# Mic peak in psi — Thor stores per-interval mic ADC counts in the
|
||||||
|
# binary; convert the max count to psi via the per-count factor.
|
||||||
|
mic_peak_count = max((iv.peak_count("MicL") for iv in intervals), default=0)
|
||||||
|
mic_peak_psi = mic_count_to_psi(mic_peak_count) if mic_peak_count else None
|
||||||
rep = IdfReport(
|
rep = IdfReport(
|
||||||
serial_number=md.serial,
|
serial_number=md.serial,
|
||||||
event_type="Full Histogram",
|
event_type="Full Histogram",
|
||||||
@@ -451,7 +455,8 @@ def read_idf_file(
|
|||||||
vertical_ips=peak_vert,
|
vertical_ips=peak_vert,
|
||||||
longitudinal_ips=peak_long,
|
longitudinal_ips=peak_long,
|
||||||
peak_vector_sum_ips=None,
|
peak_vector_sum_ips=None,
|
||||||
mic_pspl_dbl=None,
|
mic_pspl_dbl=None, # IDFH binary doesn't carry the dB(L) value
|
||||||
|
mic_pspl_psi=mic_peak_psi,
|
||||||
)
|
)
|
||||||
event = IdfEvent(
|
event = IdfEvent(
|
||||||
serial=md.serial or "UNKNOWN",
|
serial=md.serial or "UNKNOWN",
|
||||||
@@ -489,6 +494,11 @@ def read_idf_file(
|
|||||||
arr = decoded.get(ch, [])
|
arr = decoded.get(ch, [])
|
||||||
return geo_count_to_ips(max((abs(v) for v in arr), default=0))
|
return geo_count_to_ips(max((abs(v) for v in arr), default=0))
|
||||||
|
|
||||||
|
# Mic peak psi from binary: max absolute MicL ADC count × 2.14e-6 psi/count.
|
||||||
|
mic_arr = decoded.get("MicL", [])
|
||||||
|
mic_peak_count = max((abs(v) for v in mic_arr), default=0)
|
||||||
|
mic_peak_psi = mic_count_to_psi(mic_peak_count) if mic_peak_count else None
|
||||||
|
|
||||||
peaks = IdfPeaks(
|
peaks = IdfPeaks(
|
||||||
transverse_ips=_peak_ips("Tran"),
|
transverse_ips=_peak_ips("Tran"),
|
||||||
vertical_ips=_peak_ips("Vert"),
|
vertical_ips=_peak_ips("Vert"),
|
||||||
@@ -496,7 +506,9 @@ def read_idf_file(
|
|||||||
# PVS requires aligned per-sample √(T²+V²+L²); leave None — the
|
# PVS requires aligned per-sample √(T²+V²+L²); leave None — the
|
||||||
# sidecar carries it and the bridge picks it up if present.
|
# sidecar carries it and the bridge picks it up if present.
|
||||||
peak_vector_sum_ips=None,
|
peak_vector_sum_ips=None,
|
||||||
mic_pspl_dbl=None,
|
mic_pspl_dbl=None, # binary IDFW doesn't carry the dB(L) value;
|
||||||
|
# sidecar .txt fills it via IdfReport.from_dict
|
||||||
|
mic_pspl_psi=mic_peak_psi,
|
||||||
)
|
)
|
||||||
|
|
||||||
event = IdfEvent(
|
event = IdfEvent(
|
||||||
|
|||||||
+27
-6
@@ -159,12 +159,23 @@ class IdfReport:
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class IdfPeaks:
|
class IdfPeaks:
|
||||||
"""Geophone + mic peak values for one Thor event. Native Thor units."""
|
"""Geophone + mic peak values for one Thor event. Native Thor units.
|
||||||
|
|
||||||
|
Thor stores the mic peak in two parallel forms — ``mic_pspl_dbl`` is
|
||||||
|
what the sidecar's top-level ``MicPSPL`` header field carries (dB(L)),
|
||||||
|
used in the report header. ``mic_pspl_psi`` is the psi value derived
|
||||||
|
either from the IDFW sample table / IDFH interval column 9, or from
|
||||||
|
the binary mic counts (~2.14e-6 psi/count). Needed because the
|
||||||
|
BW-shaped ``PeakValues.micl`` consumed by ``event_hdf5.write_event_hdf5``
|
||||||
|
expects psi — feeding it dB(L) makes the h5 mic-chart scale factor
|
||||||
|
blow up.
|
||||||
|
"""
|
||||||
transverse_ips: Optional[float] = None # in/s
|
transverse_ips: Optional[float] = None # in/s
|
||||||
vertical_ips: Optional[float] = None # in/s
|
vertical_ips: Optional[float] = None # in/s
|
||||||
longitudinal_ips: Optional[float] = None # in/s
|
longitudinal_ips: Optional[float] = None # in/s
|
||||||
peak_vector_sum_ips: Optional[float] = None # in/s
|
peak_vector_sum_ips: Optional[float] = None # in/s
|
||||||
mic_pspl_dbl: Optional[float] = None # dB(L)
|
mic_pspl_dbl: Optional[float] = None # dB(L)
|
||||||
|
mic_pspl_psi: Optional[float] = None # psi
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -324,10 +335,14 @@ class IdfEvent:
|
|||||||
machinery without those code paths needing to know about Thor.
|
machinery without those code paths needing to know about Thor.
|
||||||
|
|
||||||
Caveats of the bridge:
|
Caveats of the bridge:
|
||||||
- ``mic_ppv`` on the produced Event carries Thor's dB(L) value
|
- ``PeakValues.micl`` carries the mic peak in **psi** (matching
|
||||||
verbatim — the UI distinguishes via the ``device_family``
|
BW's convention) — set from :attr:`IdfPeaks.mic_pspl_psi`,
|
||||||
column (Phase 1). Don't run the BW psi→dBL converter on
|
with a dB(L)→psi fallback when only the dB(L) value is
|
||||||
Series IV rows.
|
available. This is what the h5 writer's mic-scale-factor
|
||||||
|
logic needs. The dB(L) value still flows through
|
||||||
|
``bw_report.mic.pspl_dbl`` (set by the
|
||||||
|
``idf_to_bw_report`` adapter) and the renderer reads it
|
||||||
|
from there for the report header.
|
||||||
- Many Thor-specific fields (Peak Acceleration / Displacement,
|
- Many Thor-specific fields (Peak Acceleration / Displacement,
|
||||||
sensor self-check, calibration) don't have a slot in
|
sensor self-check, calibration) don't have a slot in
|
||||||
``Event``. The full IdfReport is preserved on the
|
``Event``. The full IdfReport is preserved on the
|
||||||
@@ -349,11 +364,17 @@ class IdfEvent:
|
|||||||
minute=self.timestamp.minute,
|
minute=self.timestamp.minute,
|
||||||
second=self.timestamp.second,
|
second=self.timestamp.second,
|
||||||
)
|
)
|
||||||
|
# Resolve mic peak as psi. Priority: binary-derived mic_pspl_psi
|
||||||
|
# (set by read_idf_file) > dB(L)→psi fallback via standard formula
|
||||||
|
# (psi = 2.9e-9 × 10^(dBL/20)) > None.
|
||||||
|
mic_psi = self.peaks.mic_pspl_psi
|
||||||
|
if mic_psi is None and self.peaks.mic_pspl_dbl is not None:
|
||||||
|
mic_psi = 2.9e-9 * (10.0 ** (self.peaks.mic_pspl_dbl / 20.0))
|
||||||
pv = PeakValues(
|
pv = PeakValues(
|
||||||
tran=self.peaks.transverse_ips,
|
tran=self.peaks.transverse_ips,
|
||||||
vert=self.peaks.vertical_ips,
|
vert=self.peaks.vertical_ips,
|
||||||
long=self.peaks.longitudinal_ips,
|
long=self.peaks.longitudinal_ips,
|
||||||
micl=self.peaks.mic_pspl_dbl, # dB(L) — see caveat above
|
micl=mic_psi, # psi, matching BW's convention (h5 scaling depends on this)
|
||||||
peak_vector_sum=self.peaks.peak_vector_sum_ips,
|
peak_vector_sum=self.peaks.peak_vector_sum_ips,
|
||||||
)
|
)
|
||||||
pi = ProjectInfo(
|
pi = ProjectInfo(
|
||||||
|
|||||||
@@ -568,6 +568,16 @@ class WaveformStore:
|
|||||||
# precedence over the filename timestamp inside from_report().
|
# precedence over the filename timestamp inside from_report().
|
||||||
idf_event = IdfEvent.from_report(report_dict, source_path.name)
|
idf_event = IdfEvent.from_report(report_dict, source_path.name)
|
||||||
|
|
||||||
|
# The binary mic peak (psi) isn't carried through from_report() —
|
||||||
|
# IdfReport.from_dict only sees the .txt's dB(L) value. Pull the
|
||||||
|
# binary-derived ``mic_pspl_psi`` onto the typed IdfEvent so the
|
||||||
|
# downstream bridge can populate ``PeakValues.micl`` (psi-shaped)
|
||||||
|
# and the h5 writer's per-count mic factor lands at a sensible
|
||||||
|
# value. Without this, the h5 mic chart auto-scales against the
|
||||||
|
# dB(L) value-as-pseudo-psi and renders ~flat.
|
||||||
|
if binary_peaks is not None and binary_peaks.mic_pspl_psi is not None:
|
||||||
|
idf_event.peaks.mic_pspl_psi = binary_peaks.mic_pspl_psi
|
||||||
|
|
||||||
# Operator-supplied serial_hint wins over the binary's filename
|
# Operator-supplied serial_hint wins over the binary's filename
|
||||||
# prefix when both are present (e.g. callers passing a known-good
|
# prefix when both are present (e.g. callers passing a known-good
|
||||||
# serial that overrides a misnamed export).
|
# serial that overrides a misnamed export).
|
||||||
|
|||||||
Reference in New Issue
Block a user