haniwers.v1.cli.daq

haniwers.v1.cli.daq#

Data acquisition command.

This module provides the ‘daq’ command for collecting cosmic ray event data from the OSECHI detector. It handles configuration loading, CLI option overrides, validation, directory creation, and initiates the data acquisition session.

Features: - Load configuration from TOML files or environment variables - Override config settings via CLI options (precedence: CLI > env > config) - Validate all settings before starting DAQ - Support CLI-only mode (no config file required) - Support config file mode with partial CLI overrides

Architecture: Clear & Unified Flow

┌─────────────────────────────────────┐ │ Config File (TOML) │ └──────────────┬──────────────────────┘ ↓ ┌─────────────────────────────────────┐ │ ConfigLoader │ └──────────────┬──────────────────────┘ ↓ ┌─────────────────────────────────────┐ │ cfg = HaniwersConfig │ │ ├── device → DeviceConfig │ │ └── sampler → SamplerConfig ◄──────┼─── PRIMARY FOR DAQ └──────────────┬──────────────────────┘ ↓ ┌─────────────────────────────────────┐ │ CLI Overrides (only cfg.sampler) │ └──────────────┬──────────────────────┘ ↓ ┌─────────────────────────────────────┐ │ Validation │ └──────────────┬──────────────────────┘ ↓ ┌─────────────────────────────────────┐ │ Device.connect() │ └──────────────┬──────────────────────┘ ↓ ┌─────────────────────────────────────┐ │ Create timestamped workspace │ └──────────────┬──────────────────────┘ ↓ ┌─────────────────────────────────────┐ │ Sampler(device, cfg.sampler) │ │ sampler.run(files=…) │ └──────────────┬──────────────────────┘ ↓ ┌─────────────────────────────────────┐ │ Device.disconnect() │ └─────────────────────────────────────┘

Module Contents#

Functions#

daq

Run data acquisition to collect cosmic ray events.

API#

haniwers.v1.cli.daq.daq(ctx: typer.Context, config: Optional[pathlib.Path] = typer.Option(None, '--config', help='Configuration file path (config.toml, .env.haniwers, etc). If not specified, ConfigLoader searches default locations.'), port: Optional[str] = typer.Option(None, '--port', help="Serial port path for OSECHI detector (e.g., /dev/ttyUSB0, COM3). Use 'haniwers-v1 port list' to find available ports.", rich_help_panel='Device Settings'), baudrate: Optional[int] = typer.Option(None, '--baudrate', min=1, help='Serial communication baud rate in bits per second (e.g., 9600, 115200).', rich_help_panel='Device Settings'), timeout: Optional[float] = typer.Option(None, '--timeout', min=0.1, help='Serial read timeout in seconds (e.g., 1.0, 2.0).', rich_help_panel='Device Settings'), device_label: Optional[str] = typer.Option(None, '--device-label', help='Device identifier label for logging and documentation.', rich_help_panel='Device Settings'), workspace: Optional[pathlib.Path] = typer.Option(None, '--workspace', help='Output directory for data files. Timestamped subdirectory created automatically.', rich_help_panel='Sampler Settings'), filename_prefix: Optional[str] = typer.Option(None, '--filename-prefix', help="Prefix for output file names (e.g., 'run001').", rich_help_panel='Sampler Settings'), filename_suffix: Optional[str] = typer.Option(None, '--filename-suffix', help="File extension/suffix for output files (e.g., '.csv').", rich_help_panel='Sampler Settings'), events_per_file: Optional[int] = typer.Option(None, '--events-per-file', min=1, help='Number of detector events per output file before rollover.', rich_help_panel='Sampler Settings'), number_of_files: Optional[int] = typer.Option(None, '--number-of-files', min=1, help='Maximum number of files to create in a single DAQ session.', rich_help_panel='Sampler Settings'), stream_mode: bool = typer.Option(False, '--stream-mode', help='Enable continuous streaming mode (write immediately, no buffering).', rich_help_panel='Sampler Settings'), mode: Optional[str] = typer.Option(None, '--mode', help="Data acquisition mode: 'count_based' (fixed number of events) or 'time_based' (fixed duration). If not specified, uses mode from [sampler] config section (default: count_based).", rich_help_panel='Sampler Settings'), duration: Optional[float] = typer.Option(None, '--duration', min=0.1, help='Acquisition duration in seconds for time_based mode. When specified, automatically switches to time_based mode. Overrides mode setting from config file.', rich_help_panel='Sampler Settings'), mock: bool = typer.Option(False, '--mock', help='Use RandomMocker instead of real device for testing (no hardware required).', rich_help_panel='Testing')) None#

Run data acquisition to collect cosmic ray events.

Supports three usage modes:

CLI-only (no config file): $ haniwers-v1 daq --port /dev/ttyUSB0 --workspace ./output
–filename-prefix run001 --events-per-file 1000

Config file (all settings from TOML): $ haniwers-v1 daq --config daq.toml

Config with CLI overrides (mix of both): $ haniwers-v1 daq --config daq.toml --port /dev/ttyUSB1 --workspace ./exp02

Mode Resolution (determines count_based vs time_based acquisition):

The command determines the acquisition mode through the following precedence (highest to lowest priority):

  1. Explicit --mode flag: Direct specification wins Example: haniwers-v1 daq --config config.toml --mode time_based

  2. Implicit --duration flag: Automatically switches to time_based mode Example: haniwers-v1 daq --config config.toml --duration 60 (mode is set to time_based even if config says count_based)

  3. Config [sampler] section: Uses configured mode Example: haniwers-v1 daq --config config.toml (uses mode from [sampler] mode = “count_based” or “time_based”)

  4. Default fallback: count_based mode (used when no mode specified anywhere)

Configuration precedence (highest to lowest):

  1. CLI options (–port, --workspace, etc.)

  2. Environment variables (HANIWERS_DEVICE_PORT, etc.)

  3. TOML configuration file

  4. Built-in defaults

Exit codes: 0: Success 1: Configuration error, validation failure, or DAQ runtime error 2: Serial port permission error (rare)