Establish one invariant across the Drawable hierarchy: x is always a
numpy ndarray, y is always a list of per-channel ndarrays, and empty
data is the same types with zero length.
- Drawable: x starts as empty ndarray; min/max helpers return 0 on
empty data instead of raising; drop contradictory isinstance(self.y,
list) branches
- ADC_Result/Accumulation: empty constructors build ndarray x; full
constructors coerce x/y/y_square with numpy.asarray; Accumulation
get_ydata/get_yerr return empty ndarrays and no longer crash on
empty statistics-less accumulations
- MeasurementResult: fix get_lineplotdata to return the accumulated
means (previously the never-populated self.y, so the GUI line plot
could never draw); remove dead float/int branches in CSV and HDF
writers
- Error_Result: get_xdata/get_ydata return ndarrays
Add unittest coverage for the invariant, empty-state accessors,
constructor coercion, line plot data, CSV output and HDF round-trip.
Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
time_period is list[datetime] | None at runtime (None from old-format
HDF5 files, [] from the constructor), but several sites subscripted
it unguarded and crashed with TypeError/IndexError.
- annotate time_period as list[datetime.datetime] | None
- copy paths (get_accu_by_index, __iadd__ self-empty) use the guarded
pattern already present in _copy_provenance
- merges in __add__/__iadd__ only combine min/max when both sides carry
time information; otherwise the result is None (provenance unknown)
- write_to_tecmag raises ValueError when no time information is
available instead of crashing while writing the header
Clears all remaining time_period pyrefly errors (72 -> 63). Unit tests
reproduce the crashes and pass with the fix.
Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
Accumulation.__neg__ passed y_2 = numpy.array(self.y_square), storing a
2D ndarray. A later __iadd__ on an accumulation with ndarray y_square
crashed with AttributeError at the y_square.append sites (992, 1064).
- __neg__ now passes a per-channel copy (values unchanged: sums of
squares are invariant under negation)
- __init__ normalizes ndarray y_2 to a list, so external callers cannot
reintroduce the bug
- y_square annotated as _YChannels
Clears the remaining pyrefly errors at Accumulation.py:992 and :1064
(74 -> 72). Unit tests reproduce both crashes and pass with the fix.
Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
- raise instead of silent None for unsupported operands and empty negation
- validate before acquiring lock in Accumulation operators (no RLock leak)
- Accumulation._copy_provenance helper, ADC_Result._copy_metadata for all result paths
- shared _sandbox_stdout_redirect contextmanager for sandboxed scripts
- TemperatureMonitor dead code removal (gtk helper, traceback, unused properties)
- new unit tests incl. lock-freedom regression test
- gitignore sphinx generated doc/_autosummary/ and doc/damaris/
phase() overwrote the underlying channel arrays (y[i] *= -1) and returned
self, so rotated copies aliased the original object and negative phase
angles garbled shared data. It now returns a copy with new arrays and
uses numpy.deg2rad for arbitrary angles.
Add unittests for phase() including negative angles and non-mutation.
operations in the experiments.
- Identified and fixed multiple logic and syntax errors in the `Accumulation` class similar to those recently found in `ADC_Result`.
- Implemented missing arithmetic operators (`*`, `/`, `//`) and their inplace/reverse counterparts for the `Accumulation` class.
- Verified that all arithmetic operations correctly maintain statistical data (sum of squares) where mathematically possible.