haniwers.v1.threshold.model#
Data models for threshold scanning operations.
This module defines immutable NamedTuple data structures for threshold scanning operations, including scan measurements, operation records, and results.
Classes: ScanDataPoint: Immutable data point from a single threshold measurement ThresholdOperation: Immutable record of a threshold write operation for audit ChannelScanResult: Immutable result from scanning one detector channel ScanResult: Immutable result from complete serial threshold scanning
Module Contents#
Classes#
Immutable data point from threshold scan measurement. |
|
Immutable record of a threshold write operation for audit logging. |
|
Immutable result from scanning a single detector channel. |
|
Immutable result from complete serial threshold scanning operation. |
API#
- class haniwers.v1.threshold.model.ScanDataPoint#
Bases:
typing.NamedTupleImmutable data point from threshold scan measurement.
What is this? A structured data point representing a single measurement during threshold scanning. Each point records the timestamp, detector channel, threshold value, and number of cosmic ray events detected at that threshold.
Why this matters? Using a NamedTuple provides several benefits: - Type-safe: IDE provides autocomplete support (point.timestamp, point.channel, etc.) - Immutable: Data can’t be accidentally modified after creation - Attribute access: Use point.channel instead of point[“channel”] - CSV-friendly: Field names match CSV column headers for direct serialization - Hashable: Can be used as dict keys if needed
Attributes: timestamp: ISO format timestamp of measurement (YYYY-MM-DDTHH:mm:ss.sssZ) channel: Detector channel number (1-3) threshold: Threshold value used for this measurement (1-1023) event_count: Number of cosmic ray events detected during collection period
Example for beginners: >>> point = ScanDataPoint( … timestamp=“2025-10-27T10:23:45.123Z”, … channel=1, … threshold=250, … event_count=1234 … ) >>> print(f"Ch{point.channel} @ {point.threshold}: {point.event_count} events") Ch1 @ 250: 1234 events
Performance note: Creating ScanDataPoint is O(1) - just tuple creation, no copying or allocation.
- timestamp: str#
None
- channel: int#
None
- threshold: int#
None
- event_count: int#
None
- class haniwers.v1.threshold.model.ThresholdOperation#
Bases:
typing.NamedTupleImmutable record of a threshold write operation for audit logging.
What is this? An immutable record of a single threshold operation executed during scanning. Used for creating an audit trail of all detector configuration changes for reproducibility and debugging.
Why this matters? Audit logging is critical for scientific reproducibility. This structure ensures: - Immutable records: Can’t be modified after creation - Typed fields: Clear distinction between channel, old/new values, and status - Hashable: Can be used in sets or as dict keys if needed - CSV-ready: Fields correspond to audit log CSV columns
Attributes: timestamp: ISO format timestamp of operation (YYYY-MM-DDTHH:mm:ss.sssZ) channel: Detector channel (1-3) old_threshold: Previous threshold value (None if unknown) new_threshold: New threshold value written (1-1023) status: Operation status (“success” or error message)
Example for beginners: >>> op = ThresholdOperation( … timestamp=“2025-10-27T10:23:45.100Z”, … channel=1, … old_threshold=None, … new_threshold=250, … status=“success” … ) >>> print(f"Ch{op.channel}: {op.old_threshold} → {op.new_threshold} ({op.status})") Ch1: None → 250 (success)
Performance note: Creating ThresholdOperation is O(1) - just tuple creation.
- timestamp: str#
None
- channel: int#
None
- old_threshold: Optional[int]#
None
- new_threshold: int#
None
- status: str#
None
- class haniwers.v1.threshold.model.ChannelScanResult#
Bases:
typing.NamedTupleImmutable result from scanning a single detector channel.
What is this? The result of scanning one detector channel across all threshold values. Contains channel ID, output files, any error, and collected data points.
Why this matters? Structured results enable: - Type safety: Clear field types and IDE autocomplete - Immutability: Results can’t be modified after creation - Composition: Can be easily combined into higher-level results - Clear semantics: Error vs. success cases are explicit
Attributes: channel: Detector channel number that was scanned (1-3) files: List of file paths created (CSV files and logs) error: Error message if scan failed, None if successful data_points: List of ScanDataPoint objects collected during scan
Example for beginners: >>> result = ChannelScanResult( … channel=1, … files=[“data/20251027/scan_results_ch1.csv”], … error=None, … data_points=[…] … ) >>> if result.error is None: … print(f"Ch{result.channel} scan complete: {len(result.files)} files")
Performance note: Creating ChannelScanResult is O(1) - just tuple creation with references to existing lists.
- channel: int#
None
- files: List[str]#
None
- error: Optional[str]#
None
- data_points: List[haniwers.v1.threshold.model.ScanDataPoint]#
None
- class haniwers.v1.threshold.model.ScanResult#
Bases:
typing.NamedTupleImmutable result from complete serial threshold scanning operation.
What is this? The complete result of running serial threshold scanning on the detector. Aggregates results from all channels, lists all output files, and records any errors encountered.
Why this matters? This result provides a comprehensive summary of the scanning operation: - Status check: Single success flag for overall operation - Channel tracking: List of channels that were scanned - File inventory: Complete list of all output files created - Error tracking: All errors encountered, even if operation partially succeeded
Attributes: success: Whether scan completed without fatal errors (True/False) scanned_channels: List of channel IDs that were successfully scanned files: Complete list of file paths created (scan results, audit logs) errors: List of error messages encountered (empty if no errors)
Example for beginners: >>> result = run_serial_threshold_scan(config, device) >>> if result.success: … print(f"Scanned channels: {result.scanned_channels}“) … print(f"Output files: {len(result.files)}”) … else: … print(f"Errors: {result.errors}")
Performance note: Creating ScanResult is O(1) - just tuple creation with references to existing lists.
- success: bool#
None
- scanned_channels: List[int]#
None
- files: List[str]#
None
- errors: List[str]#
None