haniwers.v1.cli.threshold#
Threshold management commands.
This module provides commands for writing threshold values to OSECHI detector channels using a unified configuration interface.
Commands: write: Write threshold values to detector channels (single or multi-channel) fit: Placeholder for threshold fitting functionality optimize: Placeholder for optimal threshold optimization list: Placeholder for listing current threshold configurations
Dependencies: - ConfigLoader: Load configuration from TOML files - Device: Serial communication with detector - apply_thresholds: High-level batch threshold application with retry and logging - SensorConfig: Configuration model for detector channels - parse_thresholds: Parse and validate threshold configuration strings
Module Contents#
Functions#
Apply overrides to configuration object |
|
Count events where each channel has value >0 |
|
Get current threshold values for all channels. |
|
Write threshold values to detector channels. |
|
Run serial threshold scanning for detector characterization. |
|
Run parallel threshold scanning for detector characterization. |
|
Parse fit parameters in global or per-channel format. |
|
Calculate optimal thresholds from scan data using error function fitting. |
Data#
API#
- haniwers.v1.cli.threshold.app#
‘Typer(…)’
- haniwers.v1.cli.threshold._apply_overrides(config, overrides: dict) None#
Apply overrides to configuration object
Args: config: Configuration object to override (e.g. cfg.device) overrides: Dict of {attribute_name: value}
- haniwers.v1.cli.threshold.count_hits_by_channel(events: list[haniwers.v1.daq.model.RawEvent]) dict[str, int]#
Count events where each channel has value >0
- haniwers.v1.cli.threshold.get_all_thresholds(sensors: dict[str, haniwers.v1.config.model.SensorConfig]) dict[str, int | None]#
Get current threshold values for all channels.
- haniwers.v1.cli.threshold.write(ctx: typer.Context, config: Optional[pathlib.Path] = ConfigOptions.config, port: Optional[str] = DeviceOptions.port, baudrate: Optional[int] = DeviceOptions.baudrate, timeout: Optional[float] = DeviceOptions.timeout, thresholds: str = ThresholdOptions.thresholds, max_retry: int = ThresholdOptions.max_retry, history: pathlib.Path = ThresholdOptions.history, workspace: pathlib.Path = OutputOptions.workspace, filename_prefix: Optional[str] = OutputOptions.filename_prefix, filename_suffix: Optional[str] = OutputOptions.filename_suffix, events_per_file: Optional[int] = SamplerOptions.events_per_file, number_of_files: Optional[int] = SamplerOptions.number_of_files, stream_mode: bool = SamplerOptions.stream_mode, mode: Optional[str] = SamplerOptions.mode, duration: Optional[float] = SamplerOptions.duration, mock: bool = TestingOptions.mock, load_from: Optional[pathlib.Path] = TestingOptions.load_from, speed: float = TestingOptions.speed, shuffle: bool = TestingOptions.shuffle, jitter: float = TestingOptions.jitter, loop: bool = TestingOptions.loop, verbose: bool = LoggerOptions.verbose, logfile: str = LoggerOptions.logfile) None#
Write threshold values to detector channels.
This command writes threshold values to the three detector layers (top, middle, bottom). The threshold determines the detector’s sensitivity to cosmic ray signals.
Supports single-channel or multi-channel configuration using the unified –thresholds option. Includes automatic retry logic on communication failures and audit trail logging to CSV file.
Args: thresholds: Threshold configuration as ‘channel:value;channel:value;…’ Examples: - Single channel: ‘1:280’ - All channels: ‘1:290;2:320;3:298’
Output: For each channel, displays: - Status icon: ✓ (success) or ✗ (failed) - Channel number and status - Threshold value written (vth) - Number of attempts (1 = immediate success, >1 = retried)
Examples: Write to single channel: $ haniwers-v1 threshold write --port /dev/tty.usbserial --thresholds 1:280
Write to multiple channels: $ haniwers-v1 threshold write --port /dev/tty.usbserial --thresholds '1:290;2:320;3:298' With custom workspace and max retries: $ haniwers-v1 threshold write --port /dev/tty.usbserial --thresholds '1:280' \ --workspace data --max-retry 5Note: The device must be powered on and connected before running this command. Logs are automatically created in YYYYMMDD directory matching DAQ structure. Each threshold write is logged to CSV with timestamp for audit trail.
- haniwers.v1.cli.threshold.serial(ctx: typer.Context, config: Optional[pathlib.Path] = ConfigOptions.config, port: Optional[str] = DeviceOptions.port, baudrate: Optional[int] = DeviceOptions.baudrate, timeout: Optional[float] = DeviceOptions.timeout, thresholds: str = ThresholdOptions.thresholds, suppress_threshold: int = ThresholdOptions.suppress_threshold, max_retry: int = ThresholdOptions.max_retry, history: pathlib.Path = ThresholdOptions.history, workspace: Optional[pathlib.Path] = OutputOptions.workspace, filename_prefix: Optional[str] = OutputOptions.filename_prefix, filename_suffix: Optional[str] = OutputOptions.filename_suffix, events_per_file: Optional[int] = SamplerOptions.events_per_file, number_of_files: Optional[int] = SamplerOptions.number_of_files, stream_mode: bool = SamplerOptions.stream_mode, mode: Optional[str] = SamplerOptions.mode, duration: Optional[float] = SamplerOptions.duration, nsteps: int = ScanOptions.nsteps, step: int = ScanOptions.step, mock: bool = TestingOptions.mock, load_from: Optional[pathlib.Path] = TestingOptions.load_from, speed: float = TestingOptions.speed, shuffle: bool = TestingOptions.shuffle, jitter: float = TestingOptions.jitter, loop: bool = TestingOptions.loop, verbose: bool = LoggerOptions.verbose, logfile: str = LoggerOptions.logfile) None#
Run serial threshold scanning for detector characterization.
Scans one or more detector channels across a range of threshold values, collecting cosmic ray event data at each threshold level. Results are saved to CSV files for analysis.
Threshold operations are logged to threshold_operations.csv in the workspace directory for complete audit trail and reproducibility. Each threshold write (suppress and measurement) is recorded with timestamp, channel, value, success status, and retry count.
This command is useful for:
Measuring detector sensitivity curves
Comparing channel responses
Characterizing detector behavior
Example commands:
Single-channel scan with mock device: $ haniwers-v1 threshold serial --thresholds "1:250" \ --nsteps 5 --step 10 --duration 2 --mock Multi-channel scan with TOML config: $ haniwers-v1 threshold serial --config config.toml Override TOML parameters with CLI: $ haniwers-v1 threshold serial --config config.toml \ --thresholds "1:300;2:320" --duration 3Output files (saved in workspace/YYYYMMDD/):
scan_results_ch1.csv, scan_results_ch2.csv, …: Threshold scan data
threshold_operations.csv: Audit log of all threshold changes (timestamp, id, vth, success, attempts)
Note: Requires a TOML configuration file with sensor definitions, unless all parameters are provided via CLI options.
- haniwers.v1.cli.threshold.parallel(ctx: typer.Context, config: Optional[pathlib.Path] = ConfigOptions.config, port: Optional[str] = DeviceOptions.port, baudrate: Optional[int] = DeviceOptions.baudrate, timeout: Optional[float] = DeviceOptions.timeout, device_label: Optional[str] = DeviceOptions.device_label, thresholds: str = ThresholdOptions.thresholds, max_retry: int = ThresholdOptions.max_retry, history: pathlib.Path = ThresholdOptions.history, nsteps: int = ScanOptions.nsteps, step: int = ScanOptions.step, duration: Optional[float] = SamplerOptions.duration, workspace: Optional[pathlib.Path] = OutputOptions.workspace, filename_prefix: Optional[str] = OutputOptions.filename_prefix, filename_suffix: Optional[str] = OutputOptions.filename_suffix, events_per_file: Optional[int] = SamplerOptions.events_per_file, number_of_files: Optional[int] = SamplerOptions.number_of_files, stream_mode: bool = SamplerOptions.stream_mode, mock: bool = TestingOptions.mock, verbose: bool = LoggerOptions.verbose, logfile: str = LoggerOptions.logfile) None#
Run parallel threshold scanning for detector characterization.
Scans all detector channels across a range of threshold values in parallel. All channels step together at each measurement point, with all active during data collection (unlike serial mode). This provides 3x speedup vs serial scan.
Threshold operations are logged to threshold_operations.csv in the workspace directory for complete audit trail and reproducibility. Each threshold write is recorded with timestamp, channel, value, success status, and retry count. Unlike serial mode, parallel mode has no suppress phase.
Results are saved to CSV files for analysis, one per channel.
This command is useful for:
Fast threshold characterization of all channels simultaneously
Collecting synchronized measurements from multiple channels
Comparing detector responses in parallel
Example commands:
Parallel scan with mock device (all channels step together): $ haniwers-v1 threshold parallel --nsteps 5 --step 10 --duration 2 --mock Multi-channel parallel scan with TOML config: $ haniwers-v1 threshold parallel --config config.toml Override TOML parameters with CLI: $ haniwers-v1 threshold parallel --config config.toml \ --thresholds "1:300;2:320;3:298" --duration 3Output files (saved in workspace/YYYYMMDD/):
scan_results_ch1.csv, scan_results_ch2.csv, …: Threshold scan data
threshold_operations.csv: Audit log of all threshold changes (timestamp, id, vth, success, attempts)
Note: Requires a TOML configuration file with sensor definitions, unless all parameters are provided via CLI options. All channels must have matching nsteps and step_size values.
- haniwers.v1.cli.threshold._parse_fit_parameters(parameters: Optional[str]) dict#
Parse fit parameters in global or per-channel format.
Supports two formats:
Global: “10,300,1,1” (height,mean,sigma,offset for all channels)
Per-channel: “1:10,300,1,1;2:10,300,1,1”
Args: parameters: Parameter string in one of the two formats above. If None, uses default global parameters.
Returns: Dictionary with channel number as key and parameter list as value. Example: {1: [10, 300, 1, 1], 2: [10, 300, 1, 1], 3: [10, 300, 1, 1]}
Raises: ValueError: If parameters format is invalid or values are out of range.
- haniwers.v1.cli.threshold.fit(read_from: pathlib.Path = typer.Argument(..., help='Directory containing threshold scan result CSV files'), pattern: str = typer.Option('*.csv', '--pattern', '-p', help='Filename pattern to search for scan data'), parameters: Optional[str] = typer.Option(None, '--parameters', help="Initial fit parameters. Two formats supported:\n 1. Global: '10,300,1,1' (height,mean,sigma,offset for all channels)\n 2. Per-channel: '1:10,300,1,1;2:10,300,1,1' (channel:height,mean,sigma,offset)"), verify: bool = typer.Option(False, '--verify', help='Perform verification checks on fit results (data quality, reasonableness)'), plot: bool = typer.Option(False, '--plot', help='Generate and save interactive hvplot visualizations of fit results'), workspace: Optional[pathlib.Path] = OutputOptions.workspace, verbose: bool = LoggerOptions.verbose, logfile: str = LoggerOptions.logfile) None#
Calculate optimal thresholds from scan data using error function fitting.
Analyzes threshold scan result data to estimate optimal threshold values using complementary error function (erfc) fitting. Results are saved to CSV files for use by other commands.
The fitting process:
Reads ThresholdScanResult CSV files from the specified directory
Fits error function curves to event rate vs threshold data for each channel
Calculates optimal thresholds at multiple sigma levels (0σ, 1σ, 3σ, 5σ)
Saves results to CSV files for analysis and use by threshold write command
Args: read_from: Directory containing threshold scan result CSV files pattern: Filename pattern for scan result files (default: “*.csv”) parameters: Initial fit parameters in two formats: - Global: “10,300,1,1” for all channels - Per-channel: “1:10,300,1,1;2:10,300,1,1” (default: “10,300,1,1” for all channels) workspace: Output directory for results (default: current directory) verbose: Enable verbose logging logfile: Log file path
Output files: -
threshold_fit_results.csv: Latest fit results for use by other commandsExamples: Fit scan results with default settings:
$ haniwers-v1 threshold fit ./scan_data With custom filename pattern: $ haniwers-v1 threshold fit ./scan_data --pattern "serial_*.csv" With per-channel fit parameters: $ haniwers-v1 threshold fit ./scan_data \ --parameters "1:5,280,2,0.5;2:5,310,2,0.5" Save to specific workspace: $ haniwers-v1 threshold fit ./scan_data --workspace ./resultsNotes: - Scan data must be in ThresholdScanResult CSV format - The 3σ level is typically used as the optimal threshold value - Results are saved with ISO8601 timestamps for audit trail