Restructure package for domain-driven design

Reorganise package structure to improve separation of concerns:
- instruments/ - SCPI, transport, drivers, interfaces, factory
- simulation/ - physics engine, virtual instruments, server
- framework/ - test runner, logger, limits, context
- tests/ - thermal/, electrical/ (DVT test implementations)
- data/ - repository, models
- reporting/ - generator, templates
- app/ - CLI, config, dashboard

This structure enables:
- Reusable instruments package for other test suites
- Clear separation of simulation (dev) vs production code
- Domain-focused package organisation

Updated documentation to reflect new paths.
This commit is contained in:
2025-02-10 12:06:22 +00:00
parent 154352e92f
commit ed2515bca7
29 changed files with 332 additions and 361 deletions

View File

@@ -214,7 +214,7 @@ For **why** decisions were made, see `03_architecture_decisions.md`.
### 2.1 Directory Layout ### 2.1 Directory Layout
``` ```
thermaulate/ py_dvt_ate/
├── pyproject.toml # Project metadata and dependencies ├── pyproject.toml # Project metadata and dependencies
├── README.md # Project overview and quick start ├── README.md # Project overview and quick start
├── CHANGELOG.md # Version history ├── CHANGELOG.md # Version history
@@ -222,205 +222,163 @@ thermaulate/
├── docs/ ├── docs/
│ ├── 01_requirements.md # Business Requirements │ ├── 01_requirements.md # Business Requirements
│ ├── 02_technical_specification.md # Technical Design (this doc) │ ├── 02_technical_specification.md # Technical Design (this doc)
── 03_architecture_decisions.md # Architecture Decisions ── 03_architecture_decisions.md # Architecture Decisions
│ └── 04_development_plan.md # Sprint breakdown
├── src/ ├── src/py_dvt_ate/
── thermaulate/ ── __init__.py # Package version
│ ├── py.typed # PEP 561 marker
│ │
│ ├── instruments/ # INSTRUMENT CONTROL (reusable)
│ │ ├── __init__.py
│ │ ├── interfaces.py # IThermalChamber, IPowerSupply, IMultimeter
│ │ ├── scpi.py # SCPI parser (shared protocol)
│ │ ├── factory.py # Creates instrument sets from config
│ │ ├── transport/ # Connection layer
│ │ │ ├── __init__.py
│ │ │ ├── base.py # Transport protocol
│ │ │ ├── tcp.py # TCP socket transport
│ │ │ └── visa.py # PyVISA transport (future)
│ │ └── drivers/ # SCPI driver implementations
│ │ ├── __init__.py
│ │ ├── base.py # Base driver
│ │ ├── chamber.py # Thermal chamber driver
│ │ ├── power_supply.py # PSU driver
│ │ └── multimeter.py # DMM driver
│ │
│ ├── simulation/ # PHYSICS SIMULATION (dev/test only)
│ │ ├── __init__.py
│ │ ├── server.py # TCP server hosting virtual instruments
│ │ ├── physics/ # Physics engine
│ │ │ ├── __init__.py
│ │ │ ├── engine.py # Main simulation loop
│ │ │ ├── thermal.py # Thermal calculations
│ │ │ └── models/ # DUT models
│ │ │ ├── __init__.py
│ │ │ ├── base.py # DUT protocol
│ │ │ └── ldo.py # LDO model
│ │ └── virtual/ # Virtual instrument implementations
│ │ ├── __init__.py
│ │ ├── base.py # Base virtual instrument
│ │ ├── chamber.py # Virtual thermal chamber
│ │ ├── power_supply.py # Virtual PSU
│ │ └── multimeter.py # Virtual DMM
│ │
│ ├── framework/ # TEST FRAMEWORK (reusable)
│ │ ├── __init__.py
│ │ ├── runner.py # Test sequencer
│ │ ├── context.py # Runtime context
│ │ ├── logger.py # Measurement logging
│ │ ├── limits.py # Pass/fail evaluation
│ │ └── models.py # Framework models
│ │
│ ├── tests/ # DVT TEST IMPLEMENTATIONS
│ │ ├── __init__.py
│ │ ├── base.py # Base test class
│ │ ├── thermal/ # Thermal characterisation tests
│ │ │ ├── __init__.py
│ │ │ └── tempco.py # Temperature coefficient test
│ │ └── electrical/ # Electrical characterisation tests
│ │ ├── __init__.py
│ │ └── load_regulation.py # Load regulation test
│ │
│ ├── data/ # DATA PERSISTENCE (shared)
│ │ ├── __init__.py
│ │ ├── repository.py # Data access layer
│ │ └── models.py # Data models
│ │
│ ├── reporting/ # REPORT GENERATION (standalone)
│ │ ├── __init__.py
│ │ ├── generator.py # Report generator
│ │ └── templates/ # Report templates
│ │
│ └── app/ # APPLICATION ENTRY POINTS
│ ├── __init__.py │ ├── __init__.py
│ ├── py.typed # PEP 561 marker │ ├── cli.py # Command-line interface
├── config.py # YAML loading
── physics/ # Physics simulation engine ── dashboard/ # Streamlit dashboard
│ │ ├── __init__.py
│ │ ├── engine.py # Main physics loop
│ │ ├── thermal.py # Thermal domain model
│ │ ├── electrical.py # Electrical domain model
│ │ └── dut/
│ │ ├── __init__.py
│ │ ├── base.py # DUT base class
│ │ └── ldo.py # LDO voltage regulator model
│ │
│ ├── instruments/ # Virtual instrument implementations
│ │ ├── __init__.py
│ │ ├── base.py # Instrument base class
│ │ ├── scpi_parser.py # SCPI command parser
│ │ ├── thermal_chamber.py # Thermal chamber simulator
│ │ ├── power_supply.py # Power supply simulator
│ │ └── multimeter.py # DMM simulator
│ │
│ ├── server/ # Simulation server
│ │ ├── __init__.py
│ │ ├── tcp_server.py # Async TCP server
│ │ └── main.py # Server entry point
│ │
│ ├── transport/ # Communication layer
│ │ ├── __init__.py
│ │ ├── base.py # Transport protocol
│ │ ├── tcp.py # TCP/IP implementation
│ │ └── async_tcp.py # Async TCP implementation
│ │
│ ├── drivers/ # Instrument SCPI drivers
│ │ ├── __init__.py
│ │ ├── base.py # Driver base class
│ │ ├── thermal_chamber.py # Chamber SCPI driver
│ │ ├── power_supply.py # PSU SCPI driver
│ │ └── multimeter.py # DMM SCPI driver
│ │
│ ├── hal/ # Hardware Abstraction Layer
│ │ ├── __init__.py
│ │ ├── interfaces.py # Protocol definitions
│ │ ├── factory.py # Instrument factory
│ │ └── impl/ # HAL implementations
│ │ ├── __init__.py
│ │ ├── thermal_chamber.py
│ │ ├── power_supply.py
│ │ └── multimeter.py
│ │
│ ├── executive/ # Test execution framework
│ │ ├── __init__.py
│ │ ├── sequencer.py # Test sequencer
│ │ ├── context.py # Test context
│ │ ├── logger.py # Test logger
│ │ ├── limits.py # Limit checker
│ │ └── models.py # Domain models
│ │
│ ├── tests/ # DVT test implementations
│ │ ├── __init__.py
│ │ ├── base.py # Test base class
│ │ ├── tempco.py # TempCo characterisation
│ │ └── load_regulation.py # Load regulation test
│ │
│ ├── data/ # Data persistence
│ │ ├── __init__.py
│ │ ├── repository.py # Data access layer
│ │ ├── models.py # Data models
│ │ └── migrations/ # Schema migrations
│ │
│ ├── reporting/ # Report generation (Phase 3)
│ │ ├── __init__.py
│ │ ├── generator.py # Report generator
│ │ ├── pdf.py # PDF output
│ │ ├── html.py # HTML output
│ │ └── templates/ # Report templates
│ │
│ ├── api/ # REST API (Phase 2)
│ │ ├── __init__.py
│ │ ├── main.py # FastAPI app
│ │ └── routes/
│ │ ├── __init__.py
│ │ ├── instruments.py
│ │ ├── tests.py
│ │ └── runs.py
│ │
│ ├── dashboard/ # Streamlit dashboard
│ │ ├── __init__.py
│ │ ├── app.py # Main Streamlit app
│ │ ├── pages/ # Multi-page app
│ │ │ ├── 01_instruments.py
│ │ │ ├── 02_run_test.py
│ │ │ └── 03_results.py
│ │ └── components/ # Reusable UI components
│ │ ├── __init__.py
│ │ └── instrument_panel.py
│ │
│ ├── cli/ # Command-line interface
│ │ ├── __init__.py
│ │ └── main.py # Typer CLI app
│ │
│ └── config/ # Configuration handling
│ ├── __init__.py │ ├── __init__.py
── models.py # Pydantic config models ── app.py # Main Streamlit app
│ └── loader.py # Config file loader
├── tests/ # Test suite ├── tests/ # pytest test suite
│ ├── conftest.py # pytest fixtures │ ├── conftest.py # pytest fixtures
│ ├── unit/ │ ├── unit/ # Unit tests
│ ├── test_physics_engine.py └── integration/ # Integration tests
│ │ ├── test_scpi_parser.py
│ │ ├── test_thermal_model.py
│ │ └── ...
│ └── integration/
│ ├── test_instrument_communication.py
│ ├── test_tempco_sequence.py
│ └── ...
├── config/ # Configuration files ├── config/ # Configuration files
── default.yaml # Default configuration ── default.yaml # Default configuration
│ └── example_pyvisa.yaml # Example for real hardware
── docker/ ── docker/ # Docker deployment
├── Dockerfile.server # Simulation server image ├── Dockerfile.server # Simulation server image
├── Dockerfile.app # Test application image ├── Dockerfile.app # Test application image
└── docker-compose.yml # Full stack orchestration └── docker-compose.yml # Full stack orchestration
└── scripts/
├── demo.py # Demo script
└── run_tempco.py # Example test execution
``` ```
### 2.2 Package Dependencies ### 2.2 Package Dependencies
``` ```
thermaulate/ Dependency Graph:
├── cli/ ──────────────────────────────────────────────┐
├── api/ ──────────────────────────────────────────────┤
├── dashboard/ ──────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ PRESENTATION │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
├── executive/ ◄───────────────────────────────────────────────┤
├── tests/ ◄───────────────────────────────────────────────┤
├── reporting/ ◄───────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ APPLICATION │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
├── hal/interfaces ◄───────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ DOMAIN (Abstractions) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ implements│ │
│ ▼ │
├── hal/impl ◄───────────────────────────────────────────────┤
├── drivers/ ◄───────────────────────────────────────────────┤
├── transport/ ◄───────────────────────────────────────────────┤
├── data/ ◄───────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ INFRASTRUCTURE │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
SIMULATION SERVER (Separate Process): app/ ──────────────▶ framework/ ──────────────▶ instruments/
├── physics/ ◄─── Pure domain logic, no external dependencies │ │ │
├── instruments/ ◄─── Depends on physics │ ▼ │
└── server/ ◄─── Depends on instruments │ data/ ◀────────────────────────┘
│ ▲
▼ │
reporting/ ──────────────┘
simulation/ ─────────────────────────────────▶ instruments/
Key:
- app/ : CLI, dashboard, config loading (PRESENTATION)
- framework/ : Test runner, logger, limits (APPLICATION)
- instruments/ : Interfaces, drivers, transport, SCPI (DOMAIN)
- data/ : Persistence layer (INFRASTRUCTURE)
- reporting/ : Report generation (standalone)
- simulation/ : Physics engine, virtual instruments (DEVELOPMENT)
``` ```
--- ---
## 3. Module Specifications ## 3. Module Specifications
### 3.1 Physics Module ### 3.1 Instruments Package
**Responsibility**: Simulate coupled thermal-electrical behaviour. **Responsibility**: Everything about talking to lab instruments.
**Key Components**: **Key Components**:
| Component | File | Purpose | | Component | File | Purpose |
|-----------|------|---------| |-----------|------|---------|
| PhysicsEngine | `engine.py` | Main simulation loop, state management | | Interfaces | `instruments/interfaces.py` | IThermalChamber, IPowerSupply, IMultimeter protocols |
| ThermalModel | `thermal.py` | Heat transfer calculations | | SCPIParser | `instruments/scpi.py` | Parse SCPI command strings |
| ElectricalModel | `electrical.py` | Current/voltage relationships | | Factory | `instruments/factory.py` | Create instrument sets from config |
| DUTBase | `dut/base.py` | Abstract DUT interface | | Transport | `instruments/transport/` | TCP, VISA connection layer |
| LDOModel | `dut/ldo.py` | LDO voltage regulator implementation | | Drivers | `instruments/drivers/` | SCPI command implementations |
**Command Processing Flow**:
```
High-level call → Driver → SCPI command → Transport → Instrument
```
---
### 3.2 Simulation Package
**Responsibility**: Physics simulation for development without real hardware.
**Key Components**:
| Component | File | Purpose |
|-----------|------|---------|
| Server | `simulation/server.py` | TCP server hosting virtual instruments |
| PhysicsEngine | `simulation/physics/engine.py` | Main simulation loop |
| ThermalModel | `simulation/physics/thermal.py` | Heat transfer calculations |
| DUTBase | `simulation/physics/models/base.py` | Abstract DUT interface |
| LDOModel | `simulation/physics/models/ldo.py` | LDO voltage regulator model |
| VirtualChamber | `simulation/virtual/chamber.py` | Virtual thermal chamber |
| VirtualPSU | `simulation/virtual/power_supply.py` | Virtual power supply |
| VirtualDMM | `simulation/virtual/multimeter.py` | Virtual multimeter |
**State Management**: **State Management**:
- Engine maintains global simulation time - Engine maintains global simulation time
@@ -429,108 +387,68 @@ SIMULATION SERVER (Separate Process):
--- ---
### 3.2 Instruments Module ### 3.3 Framework Package
**Responsibility**: SCPI-compliant virtual instrument behaviour. **Responsibility**: Test execution infrastructure.
**Key Components**: **Key Components**:
| Component | File | Purpose | | Component | File | Purpose |
|-----------|------|---------| |-----------|------|---------|
| InstrumentBase | `base.py` | Common instrument functionality | | TestRunner | `framework/runner.py` | Sequences test steps |
| SCPIParser | `scpi_parser.py` | Parse SCPI command strings | | TestContext | `framework/context.py` | Runtime context |
| ThermalChamberSim | `thermal_chamber.py` | Chamber simulation | | TestLogger | `framework/logger.py` | Measurement logging |
| PowerSupplySim | `power_supply.py` | PSU simulation | | LimitChecker | `framework/limits.py` | Pass/fail evaluation |
| MultimeterSim | `multimeter.py` | DMM simulation | | Models | `framework/models.py` | TestStatus, TestResult, etc. |
**Command Processing Flow**:
```
SCPI String → Parser → Command Object → Instrument Handler → Response
```
--- ---
### 3.3 Transport Module ### 3.4 Data Package
**Responsibility**: Low-level communication. **Responsibility**: Data persistence for test results.
**Key Components**: **Key Components**:
| Component | File | Purpose | | Component | File | Purpose |
|-----------|------|---------| |-----------|------|---------|
| Transport Protocol | `base.py` | Abstract transport interface | | Repository | `data/repository.py` | Data access layer |
| TCPTransport | `tcp.py` | Synchronous TCP implementation | | Models | `data/models.py` | TestRun, Measurement dataclasses |
| AsyncTCPTransport | `async_tcp.py` | Async TCP implementation |
--- ---
### 3.4 Drivers Module ### 3.5 Reporting Package
**Responsibility**: Instrument-specific SCPI command sets. **Responsibility**: Report generation from stored data.
**Key Components**: **Key Components**:
| Component | File | Purpose | | Component | File | Purpose |
|-----------|------|---------| |-----------|------|---------|
| DriverBase | `base.py` | Common driver functionality | | Generator | `reporting/generator.py` | Creates reports from data |
| ThermalChamberDriver | `thermal_chamber.py` | Chamber SCPI commands | | Templates | `reporting/templates/` | Report templates |
| PowerSupplyDriver | `power_supply.py` | PSU SCPI commands |
| MultimeterDriver | `multimeter.py` | DMM SCPI commands |
--- ---
### 3.5 HAL Module ### 3.6 App Package
**Responsibility**: Hardware abstraction interfaces. **Responsibility**: Application entry points.
**Key Components**: **Key Components**:
| Component | File | Purpose | | Component | File | Purpose |
|-----------|------|---------| |-----------|------|---------|
| Protocols | `interfaces.py` | Abstract interfaces | | CLI | `app/cli.py` | Command-line interface (Typer) |
| InstrumentFactory | `factory.py` | Creates instrument sets from config | | Config | `app/config.py` | YAML loading, instance creation |
| HAL Implementations | `impl/*.py` | Concrete HAL classes | | Dashboard | `app/dashboard/app.py` | Streamlit application |
---
### 3.6 Executive Module
**Responsibility**: Test execution orchestration.
**Key Components**:
| Component | File | Purpose |
|-----------|------|---------|
| TestSequencer | `sequencer.py` | Run test sequences |
| TestContext | `context.py` | Runtime context |
| TestLogger | `logger.py` | Measurement logging |
| LimitChecker | `limits.py` | Pass/fail evaluation |
| Domain Models | `models.py` | Measurement, Result, etc. |
---
### 3.7 Dashboard Module
**Responsibility**: Real-time visualisation via Streamlit.
**Key Components**:
| Component | File | Purpose |
|-----------|------|---------|
| Main App | `app.py` | Streamlit application entry point |
| Instruments Page | `pages/01_instruments.py` | Live instrument status |
| Run Test Page | `pages/02_run_test.py` | Test execution interface |
| Results Page | `pages/03_results.py` | Historical results viewer |
| Instrument Panel | `components/instrument_panel.py` | Reusable instrument display |
--- ---
## 4. Interface Definitions ## 4. Interface Definitions
### 4.1 HAL Interfaces ### 4.1 Instrument Interfaces
```python ```python
# thermaulate/hal/interfaces.py # py_dvt_ate/instruments/interfaces.py
from typing import Protocol, runtime_checkable from typing import Protocol, runtime_checkable
@@ -664,7 +582,7 @@ class ITestLogger(Protocol):
### 4.2 Transport Interface ### 4.2 Transport Interface
```python ```python
# thermaulate/transport/base.py # py_dvt_ate/instruments/transport/base.py
from typing import Protocol from typing import Protocol
@@ -701,7 +619,7 @@ class Transport(Protocol):
### 4.3 Test Interface ### 4.3 Test Interface
```python ```python
# thermaulate/executive/models.py # py_dvt_ate/framework/models.py
from dataclasses import dataclass, field from dataclasses import dataclass, field
from datetime import datetime from datetime import datetime
@@ -778,12 +696,12 @@ class ITest(Protocol):
### 4.4 Factory Interface ### 4.4 Factory Interface
```python ```python
# thermaulate/hal/factory.py # py_dvt_ate/instruments/factory.py
from dataclasses import dataclass from dataclasses import dataclass
from typing import Literal from typing import Literal
from thermaulate.hal.interfaces import IThermalChamber, IPowerSupply, IMultimeter from py_dvt_ate.instruments.interfaces import IThermalChamber, IPowerSupply, IMultimeter
@dataclass @dataclass
@@ -827,22 +745,19 @@ class InstrumentFactory:
@staticmethod @staticmethod
def _create_simulated(config: InstrumentConfig) -> InstrumentSet: def _create_simulated(config: InstrumentConfig) -> InstrumentSet:
"""Create simulated instruments.""" """Create simulated instruments."""
from thermaulate.transport.tcp import TCPTransport from py_dvt_ate.instruments.transport.tcp import TCPTransport
from thermaulate.drivers.thermal_chamber import ThermalChamberDriver from py_dvt_ate.instruments.drivers.chamber import ThermalChamberDriver
from thermaulate.drivers.power_supply import PowerSupplyDriver from py_dvt_ate.instruments.drivers.power_supply import PowerSupplyDriver
from thermaulate.drivers.multimeter import MultimeterDriver from py_dvt_ate.instruments.drivers.multimeter import MultimeterDriver
from thermaulate.hal.impl.thermal_chamber import ThermalChamberHAL
from thermaulate.hal.impl.power_supply import PowerSupplyHAL
from thermaulate.hal.impl.multimeter import MultimeterHAL
chamber_transport = TCPTransport(config.simulator_host, config.chamber_port) chamber_transport = TCPTransport(config.simulator_host, config.chamber_port)
psu_transport = TCPTransport(config.simulator_host, config.psu_port) psu_transport = TCPTransport(config.simulator_host, config.psu_port)
dmm_transport = TCPTransport(config.simulator_host, config.dmm_port) dmm_transport = TCPTransport(config.simulator_host, config.dmm_port)
return InstrumentSet( return InstrumentSet(
chamber=ThermalChamberHAL(ThermalChamberDriver(chamber_transport)), chamber=ThermalChamberDriver(chamber_transport),
psu=PowerSupplyHAL(PowerSupplyDriver(psu_transport)), psu=PowerSupplyDriver(psu_transport),
dmm=MultimeterHAL(MultimeterDriver(dmm_transport)), dmm=MultimeterDriver(dmm_transport),
) )
@staticmethod @staticmethod
@@ -954,7 +869,7 @@ All instruments implement these standard commands:
### 5.5 SCPI Parser Specification ### 5.5 SCPI Parser Specification
```python ```python
# thermaulate/instruments/scpi_parser.py # py_dvt_ate/instruments/scpi.py
from dataclasses import dataclass from dataclasses import dataclass
@@ -1071,7 +986,7 @@ P_diss = (V_in - V_out) × I_load + V_in × I_q
### 6.3 Physics Engine Implementation ### 6.3 Physics Engine Implementation
```python ```python
# thermaulate/physics/engine.py # py_dvt_ate/simulation/physics/engine.py
from dataclasses import dataclass from dataclasses import dataclass
@@ -1256,7 +1171,7 @@ Schema:
### 7.3 Data Repository Interface ### 7.3 Data Repository Interface
```python ```python
# thermaulate/data/repository.py # py_dvt_ate/data/repository.py (interface)
from typing import Protocol from typing import Protocol
from uuid import UUID from uuid import UUID
@@ -1366,14 +1281,14 @@ dut:
# Data storage paths # Data storage paths
data: data:
database_path: "./data/thermaulate.db" database_path: "./data/py_dvt_ate.db"
measurements_dir: "./data/measurements" measurements_dir: "./data/measurements"
reports_dir: "./data/reports" reports_dir: "./data/reports"
# Logging configuration # Logging configuration
logging: logging:
level: INFO level: INFO
file: "./data/logs/thermaulate.log" file: "./data/logs/py_dvt_ate.log"
format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s" format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
# Dashboard (Streamlit) # Dashboard (Streamlit)
@@ -1391,7 +1306,7 @@ api:
### 8.2 Pydantic Configuration Models ### 8.2 Pydantic Configuration Models
```python ```python
# thermaulate/config/models.py # py_dvt_ate/app/config.py (config models)
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from typing import Literal from typing import Literal
@@ -1449,14 +1364,14 @@ class DUTConfig(BaseModel):
class DataConfig(BaseModel): class DataConfig(BaseModel):
database_path: str = "./data/thermaulate.db" database_path: str = "./data/py_dvt_ate.db"
measurements_dir: str = "./data/measurements" measurements_dir: str = "./data/measurements"
reports_dir: str = "./data/reports" reports_dir: str = "./data/reports"
class LoggingConfig(BaseModel): class LoggingConfig(BaseModel):
level: str = "INFO" level: str = "INFO"
file: str = "./data/logs/thermaulate.log" file: str = "./data/logs/py_dvt_ate.log"
format: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s" format: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
@@ -1612,7 +1527,7 @@ class AppConfig(BaseModel):
```toml ```toml
[project] [project]
name = "thermaulate" name = "py_dvt_ate"
version = "0.1.0" version = "0.1.0"
description = "Coupled Physics DVT Simulation Platform" description = "Coupled Physics DVT Simulation Platform"
requires-python = ">=3.11" requires-python = ">=3.11"
@@ -1648,9 +1563,9 @@ dev = [
] ]
[project.scripts] [project.scripts]
thermaulate = "thermaulate.cli.main:app" py_dvt_ate = "py_dvt_ate.cli.main:app"
thermaulate-server = "thermaulate.server.main:main" py_dvt_ate-server = "py_dvt_ate.server.main:main"
thermaulate-dashboard = "thermaulate.dashboard.app:main" py_dvt_ate-dashboard = "py_dvt_ate.dashboard.app:main"
[build-system] [build-system]
requires = ["hatchling"] requires = ["hatchling"]

View File

@@ -38,7 +38,7 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
**Vertical Slice Strategy:** **Vertical Slice Strategy:**
- Sprints 1-3: Foundation + Physics Engine (the core simulation) - Sprints 1-3: Foundation + Physics Engine (the core simulation)
- Sprint 4: Dashboard (see the physics working!) - Sprint 4: Dashboard (see the physics working!)
- Sprints 5-11: Infrastructure/Plumbing (SCPI, TCP, HAL) - Sprints 5-11: Infrastructure/Plumbing (SCPI, TCP, Instruments)
- Sprints 12-17: Test Framework, CLI, Polish - Sprints 12-17: Test Framework, CLI, Polish
--- ---
@@ -79,20 +79,18 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
**Goal:** Define physics interfaces and data structures. **Goal:** Define physics interfaces and data structures.
### Task 2.1: Define thermal state dataclasses ### Task 2.1: Define thermal state dataclasses
- Create src/py_dvt_ate/physics/__init__.py - Create src/py_dvt_ate/simulation/physics/models.py
- Create src/py_dvt_ate/physics/models.py
- Define ThermalState (frozen dataclass) - Define ThermalState (frozen dataclass)
- Define ElectricalState (frozen dataclass) - Define ElectricalState (frozen dataclass)
- **Commit:** "Add physics state dataclasses" - **Commit:** "Add physics state dataclasses"
### Task 2.2: Define DUT base protocol ### Task 2.2: Define DUT base protocol
- Create src/py_dvt_ate/physics/dut/__init__.py - Create src/py_dvt_ate/simulation/physics/models/base.py
- Create src/py_dvt_ate/physics/dut/base.py
- Define DUTModel Protocol with method signatures - Define DUTModel Protocol with method signatures
- **Commit:** "Add DUT model protocol" - **Commit:** "Add DUT model protocol"
### Task 2.3: Create physics engine stub ### Task 2.3: Create physics engine stub
- Create src/py_dvt_ate/physics/engine.py - Create src/py_dvt_ate/simulation/physics/engine.py
- Define PhysicsEngine class with stub methods - Define PhysicsEngine class with stub methods
- Methods return placeholder values - Methods return placeholder values
- **Commit:** "Add physics engine stub" - **Commit:** "Add physics engine stub"
@@ -109,13 +107,13 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
**Goal:** Implement working physics simulation. **Goal:** Implement working physics simulation.
### Task 3.1: Implement thermal calculations ### Task 3.1: Implement thermal calculations
- Create src/py_dvt_ate/physics/thermal.py - Create src/py_dvt_ate/simulation/physics/thermal.py
- Implement first-order thermal response calculations - Implement first-order thermal response calculations
- Pure functions, no state - Pure functions, no state
- **Commit:** "Implement thermal calculation functions" - **Commit:** "Implement thermal calculation functions"
### Task 3.2: Implement LDO DUT model ### Task 3.2: Implement LDO DUT model
- Create src/py_dvt_ate/physics/dut/ldo.py - Create src/py_dvt_ate/simulation/physics/models/ldo.py
- Implement LDOModel class - Implement LDOModel class
- Temperature-dependent Vout, Iq calculations - Temperature-dependent Vout, Iq calculations
- Power dissipation calculation - Power dissipation calculation
@@ -140,8 +138,8 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
**Goal:** Visualise physics engine directly - see something working! **Goal:** Visualise physics engine directly - see something working!
### Task 4.1: Create dashboard app skeleton ### Task 4.1: Create dashboard app skeleton
- Create src/py_dvt_ate/dashboard/__init__.py - Create src/py_dvt_ate/app/dashboard/__init__.py
- Create src/py_dvt_ate/dashboard/app.py - Create src/py_dvt_ate/app/dashboard/app.py
- Basic Streamlit page with title - Basic Streamlit page with title
- **Commit:** "Add Streamlit dashboard skeleton" - **Commit:** "Add Streamlit dashboard skeleton"
@@ -173,7 +171,7 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
### Task 5.1: Define SCPI command dataclass ### Task 5.1: Define SCPI command dataclass
- Create src/py_dvt_ate/instruments/__init__.py - Create src/py_dvt_ate/instruments/__init__.py
- Create src/py_dvt_ate/instruments/scpi_parser.py - Create src/py_dvt_ate/instruments/scpi.py
- Define SCPICommand dataclass - Define SCPICommand dataclass
- **Commit:** "Add SCPI command dataclass" - **Commit:** "Add SCPI command dataclass"
@@ -196,13 +194,13 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
**Goal:** Create first virtual instrument. **Goal:** Create first virtual instrument.
### Task 6.1: Define instrument base class ### Task 6.1: Define instrument base class
- Create src/py_dvt_ate/instruments/base.py - Create src/py_dvt_ate/simulation/virtual/base.py
- Define BaseInstrument with common functionality - Define BaseInstrument with common functionality
- Command dispatch mechanism - Command dispatch mechanism
- **Commit:** "Add base instrument class" - **Commit:** "Add base instrument class"
### Task 6.2: Create thermal chamber simulator stub ### Task 6.2: Create thermal chamber simulator stub
- Create src/py_dvt_ate/instruments/thermal_chamber.py - Create src/py_dvt_ate/simulation/virtual/chamber.py
- Define ThermalChamberSim class - Define ThermalChamberSim class
- Stub SCPI command handlers - Stub SCPI command handlers
- **Commit:** "Add thermal chamber simulator stub" - **Commit:** "Add thermal chamber simulator stub"
@@ -224,7 +222,7 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
**Goal:** Complete instrument simulators. **Goal:** Complete instrument simulators.
### Task 7.1: Create power supply simulator ### Task 7.1: Create power supply simulator
- Create src/py_dvt_ate/instruments/power_supply.py - Create src/py_dvt_ate/simulation/virtual/power_supply.py
- Implement PSU SCPI commands - Implement PSU SCPI commands
- VOLT, CURR, OUTP, MEAS commands - VOLT, CURR, OUTP, MEAS commands
- **Commit:** "Add power supply simulator" - **Commit:** "Add power supply simulator"
@@ -234,7 +232,7 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
- **Commit:** "Add power supply simulator tests" - **Commit:** "Add power supply simulator tests"
### Task 7.3: Create DMM simulator ### Task 7.3: Create DMM simulator
- Create src/py_dvt_ate/instruments/multimeter.py - Create src/py_dvt_ate/simulation/virtual/multimeter.py
- Implement DMM SCPI commands - Implement DMM SCPI commands
- MEAS:VOLT:DC?, CONF commands - MEAS:VOLT:DC?, CONF commands
- **Commit:** "Add multimeter simulator" - **Commit:** "Add multimeter simulator"
@@ -250,8 +248,8 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
**Goal:** Expose instruments over network. **Goal:** Expose instruments over network.
### Task 8.1: Create async TCP server foundation ### Task 8.1: Create async TCP server foundation
- Create src/py_dvt_ate/server/__init__.py - Create src/py_dvt_ate/simulation/__init__.py
- Create src/py_dvt_ate/server/tcp_server.py - Create src/py_dvt_ate/simulation/tcp_server.py
- Define InstrumentServer class with asyncio - Define InstrumentServer class with asyncio
- **Commit:** "Add async TCP server foundation" - **Commit:** "Add async TCP server foundation"
@@ -261,7 +259,7 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
- **Commit:** "Implement TCP client handling" - **Commit:** "Implement TCP client handling"
### Task 8.3: Create server main entry point ### Task 8.3: Create server main entry point
- Create src/py_dvt_ate/server/main.py - Create src/py_dvt_ate/simulation/server.py
- Wire up physics engine and instruments - Wire up physics engine and instruments
- Add CLI command to start server - Add CLI command to start server
- **Commit:** "Add simulation server entry point" - **Commit:** "Add simulation server entry point"
@@ -278,13 +276,13 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
**Goal:** Create client-side communication. **Goal:** Create client-side communication.
### Task 9.1: Define transport protocol ### Task 9.1: Define transport protocol
- Create src/py_dvt_ate/transport/__init__.py - Create src/py_dvt_ate/instruments/transport/__init__.py
- Create src/py_dvt_ate/transport/base.py - Create src/py_dvt_ate/instruments/transport/base.py
- Define Transport Protocol class - Define Transport Protocol class
- **Commit:** "Add transport protocol definition" - **Commit:** "Add transport protocol definition"
### Task 9.2: Implement TCP transport ### Task 9.2: Implement TCP transport
- Create src/py_dvt_ate/transport/tcp.py - Create src/py_dvt_ate/instruments/transport/tcp.py
- Implement TCPTransport class - Implement TCPTransport class
- connect(), write(), read(), query() methods - connect(), write(), read(), query() methods
- **Commit:** "Implement TCP transport" - **Commit:** "Implement TCP transport"
@@ -301,19 +299,19 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
**Goal:** Create instrument drivers using transport. **Goal:** Create instrument drivers using transport.
### Task 10.1: Define driver base class ### Task 10.1: Define driver base class
- Create src/py_dvt_ate/drivers/__init__.py - Create src/py_dvt_ate/instruments/drivers/__init__.py
- Create src/py_dvt_ate/drivers/base.py - Create src/py_dvt_ate/instruments/drivers/base.py
- Define BaseDriver with transport dependency - Define BaseDriver with transport dependency
- **Commit:** "Add driver base class" - **Commit:** "Add driver base class"
### Task 10.2: Implement thermal chamber driver ### Task 10.2: Implement thermal chamber driver
- Create src/py_dvt_ate/drivers/thermal_chamber.py - Create src/py_dvt_ate/instruments/drivers/chamber.py
- Methods map to SCPI commands - Methods map to SCPI commands
- **Commit:** "Add thermal chamber driver" - **Commit:** "Add thermal chamber driver"
### Task 10.3: Implement PSU and DMM drivers ### Task 10.3: Implement PSU and DMM drivers
- Create src/py_dvt_ate/drivers/power_supply.py - Create src/py_dvt_ate/instruments/drivers/power_supply.py
- Create src/py_dvt_ate/drivers/multimeter.py - Create src/py_dvt_ate/instruments/drivers/multimeter.py
- **Commit:** "Add PSU and DMM drivers" - **Commit:** "Add PSU and DMM drivers"
### Task 10.4: Add driver tests ### Task 10.4: Add driver tests
@@ -323,32 +321,30 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
--- ---
## Sprint 11: Hardware Abstraction Layer ## Sprint 11: Instrument Interfaces
**Goal:** Create HAL interfaces and implementations. **Goal:** Create instrument protocol interfaces and factory.
### Task 11.1: Define HAL protocols ### Task 11.1: Define instrument interface protocols
- Create src/py_dvt_ate/hal/__init__.py - Create src/py_dvt_ate/instruments/interfaces.py
- Create src/py_dvt_ate/hal/interfaces.py - Define IThermalChamber, IPowerSupply, IMultimeter protocols
- Define IThermalChamber, IPowerSupply, IMultimeter - **Commit:** "Add instrument interface protocols"
- **Commit:** "Add HAL protocol definitions"
### Task 11.2: Implement HAL wrappers ### Task 11.2: Ensure drivers implement interfaces
- Create src/py_dvt_ate/hal/impl/__init__.py - Update drivers to satisfy Protocol interfaces
- Create HAL implementation classes - Add type hints for interface compliance
- Wrap drivers with HAL interface - **Commit:** "Implement instrument interfaces in drivers"
- **Commit:** "Add HAL implementations"
### Task 11.3: Create instrument factory ### Task 11.3: Create instrument factory
- Create src/py_dvt_ate/hal/factory.py - Create src/py_dvt_ate/instruments/factory.py
- InstrumentSet dataclass - InstrumentSet dataclass
- InstrumentFactory.create() method - InstrumentFactory.create() method
- **Commit:** "Add instrument factory" - **Commit:** "Add instrument factory"
### Task 11.4: Add HAL tests ### Task 11.4: Add instrument interface tests
- Create tests/unit/test_hal.py - Create tests/unit/test_instruments.py
- Test factory creates correct types - Test factory creates correct types
- **Commit:** "Add HAL unit tests" - **Commit:** "Add instrument interface tests"
--- ---
@@ -357,13 +353,12 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
**Goal:** YAML-based configuration. **Goal:** YAML-based configuration.
### Task 12.1: Define config models ### Task 12.1: Define config models
- Create src/py_dvt_ate/config/__init__.py - Create src/py_dvt_ate/app/config.py
- Create src/py_dvt_ate/config/models.py - Define Pydantic models for all config sections
- Pydantic models for all config sections
- **Commit:** "Add configuration Pydantic models" - **Commit:** "Add configuration Pydantic models"
### Task 12.2: Implement config loader ### Task 12.2: Implement config loader
- Create src/py_dvt_ate/config/loader.py - Add load_config() function to src/py_dvt_ate/app/config.py
- Load YAML, validate with Pydantic - Load YAML, validate with Pydantic
- Environment variable overrides - Environment variable overrides
- **Commit:** "Implement configuration loader" - **Commit:** "Implement configuration loader"
@@ -410,25 +405,25 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
**Goal:** Test execution orchestration. **Goal:** Test execution orchestration.
### Task 14.1: Define test interface and models ### Task 14.1: Define test interface and models
- Create src/py_dvt_ate/executive/__init__.py - Create src/py_dvt_ate/framework/__init__.py
- Create src/py_dvt_ate/executive/models.py - Create src/py_dvt_ate/framework/context.py
- TestStatus enum, TestContext, ITest protocol - TestStatus enum, TestContext, ITest protocol
- **Commit:** "Add test executive models" - **Commit:** "Add test framework models"
### Task 14.2: Implement test logger ### Task 14.2: Implement test logger
- Create src/py_dvt_ate/executive/logger.py - Create src/py_dvt_ate/framework/logger.py
- Log measurements and events - Log measurements and events
- **Commit:** "Implement test logger" - **Commit:** "Implement test logger"
### Task 14.3: Implement limit checker ### Task 14.3: Implement limit checker
- Create src/py_dvt_ate/executive/limits.py - Create src/py_dvt_ate/framework/limits.py
- Evaluate pass/fail against limits - Evaluate pass/fail against limits
- **Commit:** "Implement limit checker" - **Commit:** "Implement limit checker"
### Task 14.4: Implement test sequencer ### Task 14.4: Implement test runner
- Create src/py_dvt_ate/executive/sequencer.py - Create src/py_dvt_ate/framework/runner.py
- Run tests, collect results - Run tests, collect results
- **Commit:** "Implement test sequencer" - **Commit:** "Implement test runner"
--- ---
@@ -443,7 +438,7 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
- **Commit:** "Add DVT test base class" - **Commit:** "Add DVT test base class"
### Task 15.2: Implement TempCo test ### Task 15.2: Implement TempCo test
- Create src/py_dvt_ate/tests/tempco.py - Create src/py_dvt_ate/tests/thermal/tempco.py
- Temperature sweep logic - Temperature sweep logic
- Vout measurement at each temperature - Vout measurement at each temperature
- TempCo calculation - TempCo calculation
@@ -517,40 +512,38 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
## File Dependencies Map ## File Dependencies Map
``` ```
physics/models.py → (none) simulation/physics/models.py → (none)
physics/dut/base.py → models.py simulation/physics/models/base.py → models.py
physics/dut/ldo.py → base.py, models.py simulation/physics/models/ldo.py → base.py, models.py
physics/thermal.py → models.py simulation/physics/thermal.py → models.py
physics/engine.py → models.py, thermal.py, dut/base.py simulation/physics/engine.py → models.py, thermal.py, models/base.py
dashboard/app.py physics/engine.py (Sprint 4, direct connection) app/dashboard/app.py → simulation/physics/engine.py (Sprint 4)
instruments/scpi_parser.py → (none) instruments/scpi.py → (none)
instruments/base.py → scpi_parser.py simulation/virtual/base.py → instruments/scpi.py
instruments/*_sim.py → base.py, physics/engine.py simulation/virtual/*.py → base.py, simulation/physics/engine.py
transport/base.py → (none) instruments/transport/base.py → (none)
transport/tcp.py → base.py instruments/transport/tcp.py → base.py
drivers/base.py → transport/base.py instruments/drivers/base.py → instruments/transport/base.py
drivers/*.py → base.py instruments/drivers/*.py → base.py
hal/interfaces.py → (none) instruments/interfaces.py → (none)
hal/impl/*.py → interfaces.py, drivers/*.py instruments/factory.py → interfaces.py, drivers/*.py
hal/factory.py → interfaces.py, impl/*.py
config/models.py → (none) app/config.py → (none)
config/loader.py → models.py
data/models.py → (none) data/models.py → (none)
data/repository.py → models.py data/repository.py → models.py
executive/models.py → hal/interfaces.py framework/context.py → instruments/interfaces.py
executive/*.py → models.py, data/repository.py framework/*.py → context.py, data/repository.py
tests/*.py → executive/models.py, hal/interfaces.py tests/*.py → framework/context.py, instruments/interfaces.py
dashboard/app.py → hal/factory.py (Sprint 17, upgraded) app/dashboard/app.py → instruments/factory.py (Sprint 17, upgraded)
``` ```
--- ---
@@ -578,7 +571,7 @@ MAJOR.MINOR.PATCH[-PRERELEASE]
| 3 | `v0.1.0-alpha.1` | Physics engine working | Pre-release | | 3 | `v0.1.0-alpha.1` | Physics engine working | Pre-release |
| 4 | `v0.1.0-alpha.2` | Visual demo (dashboard) | Pre-release | | 4 | `v0.1.0-alpha.2` | Visual demo (dashboard) | Pre-release |
| 8 | `v0.1.0-alpha.3` | Network ready (TCP server) | Pre-release | | 8 | `v0.1.0-alpha.3` | Network ready (TCP server) | Pre-release |
| 11 | `v0.1.0-beta.1` | HAL complete | Pre-release | | 11 | `v0.1.0-beta.1` | Interfaces complete | Pre-release |
| 15 | `v0.1.0-beta.2` | First DVT test runs | Pre-release | | 15 | `v0.1.0-beta.2` | First DVT test runs | Pre-release |
| 17 | `v0.1.0` | **MVP Complete** | Release | | 17 | `v0.1.0` | **MVP Complete** | Release |
@@ -644,7 +637,7 @@ Maintain `CHANGELOG.md` following [Keep a Changelog](https://keepachangelog.com/
| 4 | `v0.1.0-alpha.2` | **Visual Demo!** | Interactive Streamlit showing physics | | 4 | `v0.1.0-alpha.2` | **Visual Demo!** | Interactive Streamlit showing physics |
| 7 | - | Instruments Done | SCPI simulators respond to commands | | 7 | - | Instruments Done | SCPI simulators respond to commands |
| 8 | `v0.1.0-alpha.3` | Network Ready | TCP server accepts connections | | 8 | `v0.1.0-alpha.3` | Network Ready | TCP server accepts connections |
| 11 | `v0.1.0-beta.1` | HAL Complete | Abstraction layer swappable | | 11 | `v0.1.0-beta.1` | Interfaces Complete | Instrument layer swappable |
| 15 | `v0.1.0-beta.2` | First Test | TempCo characterisation runs | | 15 | `v0.1.0-beta.2` | First Test | TempCo characterisation runs |
| 17 | `v0.1.0` | **MVP Complete** | Full end-to-end workflow | | 17 | `v0.1.0` | **MVP Complete** | Full end-to-end workflow |

View File

@@ -40,9 +40,9 @@ dev = [
] ]
[project.scripts] [project.scripts]
py-dvt-ate = "py_dvt_ate.cli.main:app" py-dvt-ate = "py_dvt_ate.app.cli:app"
py-dvt-ate-server = "py_dvt_ate.server.main:main" py-dvt-ate-server = "py_dvt_ate.simulation.server:main"
py-dvt-ate-dashboard = "py_dvt_ate.dashboard.app:main" py-dvt-ate-dashboard = "py_dvt_ate.app.dashboard.app:main"
[build-system] [build-system]
requires = ["hatchling"] requires = ["hatchling"]

View File

@@ -0,0 +1,5 @@
"""Application entry points.
Contains CLI, dashboard, and configuration loading for the
py_dvt_ate application.
"""

View File

@@ -0,0 +1,5 @@
"""Streamlit dashboard for real-time monitoring.
Provides visualisation of instrument status, test progress,
and historical results.
"""

View File

@@ -1 +0,0 @@
"""Command-line interface."""

View File

@@ -1 +0,0 @@
"""Configuration handling."""

View File

@@ -1 +0,0 @@
"""Streamlit dashboard."""

View File

@@ -1 +0,0 @@
"""Instrument SCPI drivers."""

View File

@@ -1 +0,0 @@
"""Test execution framework."""

View File

@@ -0,0 +1,5 @@
"""Test execution framework.
Provides test sequencing, measurement logging, limit checking,
and runtime context management for DVT characterisation tests.
"""

View File

@@ -1 +0,0 @@
"""Hardware Abstraction Layer."""

View File

@@ -1 +0,0 @@
"""HAL implementations."""

View File

@@ -1 +1,9 @@
"""Virtual instrument implementations.""" """Instrument control package.
This package provides everything needed to communicate with lab instruments:
- Protocol interfaces (IThermalChamber, IPowerSupply, IMultimeter)
- SCPI command parsing
- Transport layer (TCP, VISA)
- Instrument drivers
- Factory for creating configured instrument sets
"""

View File

@@ -0,0 +1,5 @@
"""SCPI driver implementations for lab instruments.
Each driver translates high-level operations into SCPI commands
and handles responses from instruments.
"""

View File

@@ -0,0 +1,6 @@
"""Transport layer for instrument communication.
Provides connection abstractions for different backends:
- TCP sockets (for simulation server)
- PyVISA (for real instruments)
"""

View File

@@ -1 +0,0 @@
"""Physics simulation engine."""

View File

@@ -1 +0,0 @@
"""Device Under Test models."""

View File

@@ -0,0 +1,5 @@
"""Report generation.
Generates test reports from stored data in various formats
including PDF and HTML.
"""

View File

@@ -1 +0,0 @@
"""Simulation server."""

View File

@@ -0,0 +1,5 @@
"""Physics simulation package.
Provides virtual instruments backed by a coupled thermal-electrical
physics engine. Used for development and testing without real hardware.
"""

View File

@@ -0,0 +1,5 @@
"""Physics engine for thermal-electrical simulation.
Implements coupled thermal and electrical domain models with
realistic time constants and temperature-dependent behaviour.
"""

View File

@@ -0,0 +1,5 @@
"""Device Under Test (DUT) models.
Provides thermal and electrical models for various device types
including LDO regulators, op-amps, and other components.
"""

View File

@@ -0,0 +1,5 @@
"""Virtual instrument implementations.
SCPI-compliant virtual instruments that respond like real hardware
but are backed by the physics simulation engine.
"""

View File

@@ -1 +1,6 @@
"""DVT test implementations.""" """DVT test implementations.
Contains characterisation test suites organised by category:
- thermal/ - Temperature-related tests (TempCo, etc.)
- electrical/ - Electrical tests (load regulation, etc.)
"""

View File

@@ -0,0 +1,5 @@
"""Electrical characterisation tests.
Tests for electrical performance including load regulation,
line regulation, and output accuracy.
"""

View File

@@ -0,0 +1,5 @@
"""Thermal characterisation tests.
Tests related to temperature behaviour including temperature
coefficient (TempCo) measurements and thermal stability.
"""

View File

@@ -1 +0,0 @@
"""Communication layer."""