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 e94c0c9e71
commit 85024f8670
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
```
thermaulate/
py_dvt_ate/
├── pyproject.toml # Project metadata and dependencies
├── README.md # Project overview and quick start
├── CHANGELOG.md # Version history
@@ -222,205 +222,163 @@ thermaulate/
├── docs/
│ ├── 01_requirements.md # Business Requirements
│ ├── 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/
── thermaulate/
├── src/py_dvt_ate/
── __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
│ ├── py.typed # PEP 561 marker
── physics/ # Physics simulation engine
│ │ ├── __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
│ ├── cli.py # Command-line interface
├── config.py # YAML loading
── dashboard/ # Streamlit dashboard
│ ├── __init__.py
── models.py # Pydantic config models
│ └── loader.py # Config file loader
── app.py # Main Streamlit app
├── tests/ # Test suite
│ ├── conftest.py # pytest fixtures
│ ├── unit/
│ ├── test_physics_engine.py
│ │ ├── test_scpi_parser.py
│ │ ├── test_thermal_model.py
│ │ └── ...
│ └── integration/
│ ├── test_instrument_communication.py
│ ├── test_tempco_sequence.py
│ └── ...
├── tests/ # pytest test suite
│ ├── conftest.py # pytest fixtures
│ ├── unit/ # Unit tests
└── integration/ # Integration tests
├── config/ # Configuration files
── default.yaml # Default configuration
│ └── example_pyvisa.yaml # Example for real hardware
├── config/ # Configuration files
── default.yaml # Default configuration
── docker/
├── Dockerfile.server # Simulation server image
├── Dockerfile.app # Test application image
└── docker-compose.yml # Full stack orchestration
└── scripts/
├── demo.py # Demo script
└── run_tempco.py # Example test execution
── docker/ # Docker deployment
├── Dockerfile.server # Simulation server image
├── Dockerfile.app # Test application image
└── docker-compose.yml # Full stack orchestration
```
### 2.2 Package Dependencies
```
thermaulate/
├── cli/ ──────────────────────────────────────────────┐
├── api/ ──────────────────────────────────────────────┤
├── dashboard/ ──────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ PRESENTATION │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
├── executive/ ◄───────────────────────────────────────────────┤
├── tests/ ◄───────────────────────────────────────────────┤
├── reporting/ ◄───────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ APPLICATION │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
├── hal/interfaces ◄───────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ DOMAIN (Abstractions) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ implements│ │
│ ▼ │
├── hal/impl ◄───────────────────────────────────────────────┤
├── drivers/ ◄───────────────────────────────────────────────┤
├── transport/ ◄───────────────────────────────────────────────┤
├── data/ ◄───────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ INFRASTRUCTURE │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Dependency Graph:
SIMULATION SERVER (Separate Process):
├── physics/ ◄─── Pure domain logic, no external dependencies
├── instruments/ ◄─── Depends on physics
└── server/ ◄─── Depends on instruments
app/ ──────────────▶ framework/ ──────────────▶ 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.1 Physics Module
### 3.1 Instruments Package
**Responsibility**: Simulate coupled thermal-electrical behaviour.
**Responsibility**: Everything about talking to lab instruments.
**Key Components**:
| Component | File | Purpose |
|-----------|------|---------|
| PhysicsEngine | `engine.py` | Main simulation loop, state management |
| ThermalModel | `thermal.py` | Heat transfer calculations |
| ElectricalModel | `electrical.py` | Current/voltage relationships |
| DUTBase | `dut/base.py` | Abstract DUT interface |
| LDOModel | `dut/ldo.py` | LDO voltage regulator implementation |
| Interfaces | `instruments/interfaces.py` | IThermalChamber, IPowerSupply, IMultimeter protocols |
| SCPIParser | `instruments/scpi.py` | Parse SCPI command strings |
| Factory | `instruments/factory.py` | Create instrument sets from config |
| Transport | `instruments/transport/` | TCP, VISA connection layer |
| 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**:
- 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**:
| Component | File | Purpose |
|-----------|------|---------|
| InstrumentBase | `base.py` | Common instrument functionality |
| SCPIParser | `scpi_parser.py` | Parse SCPI command strings |
| ThermalChamberSim | `thermal_chamber.py` | Chamber simulation |
| PowerSupplySim | `power_supply.py` | PSU simulation |
| MultimeterSim | `multimeter.py` | DMM simulation |
**Command Processing Flow**:
```
SCPI String → Parser → Command Object → Instrument Handler → Response
```
| TestRunner | `framework/runner.py` | Sequences test steps |
| TestContext | `framework/context.py` | Runtime context |
| TestLogger | `framework/logger.py` | Measurement logging |
| LimitChecker | `framework/limits.py` | Pass/fail evaluation |
| Models | `framework/models.py` | TestStatus, TestResult, etc. |
---
### 3.3 Transport Module
### 3.4 Data Package
**Responsibility**: Low-level communication.
**Responsibility**: Data persistence for test results.
**Key Components**:
| Component | File | Purpose |
|-----------|------|---------|
| Transport Protocol | `base.py` | Abstract transport interface |
| TCPTransport | `tcp.py` | Synchronous TCP implementation |
| AsyncTCPTransport | `async_tcp.py` | Async TCP implementation |
| Repository | `data/repository.py` | Data access layer |
| Models | `data/models.py` | TestRun, Measurement dataclasses |
---
### 3.4 Drivers Module
### 3.5 Reporting Package
**Responsibility**: Instrument-specific SCPI command sets.
**Responsibility**: Report generation from stored data.
**Key Components**:
| Component | File | Purpose |
|-----------|------|---------|
| DriverBase | `base.py` | Common driver functionality |
| ThermalChamberDriver | `thermal_chamber.py` | Chamber SCPI commands |
| PowerSupplyDriver | `power_supply.py` | PSU SCPI commands |
| MultimeterDriver | `multimeter.py` | DMM SCPI commands |
| Generator | `reporting/generator.py` | Creates reports from data |
| Templates | `reporting/templates/` | Report templates |
---
### 3.5 HAL Module
### 3.6 App Package
**Responsibility**: Hardware abstraction interfaces.
**Responsibility**: Application entry points.
**Key Components**:
| Component | File | Purpose |
|-----------|------|---------|
| Protocols | `interfaces.py` | Abstract interfaces |
| InstrumentFactory | `factory.py` | Creates instrument sets from config |
| HAL Implementations | `impl/*.py` | Concrete HAL classes |
---
### 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 |
| CLI | `app/cli.py` | Command-line interface (Typer) |
| Config | `app/config.py` | YAML loading, instance creation |
| Dashboard | `app/dashboard/app.py` | Streamlit application |
---
## 4. Interface Definitions
### 4.1 HAL Interfaces
### 4.1 Instrument Interfaces
```python
# thermaulate/hal/interfaces.py
# py_dvt_ate/instruments/interfaces.py
from typing import Protocol, runtime_checkable
@@ -664,7 +582,7 @@ class ITestLogger(Protocol):
### 4.2 Transport Interface
```python
# thermaulate/transport/base.py
# py_dvt_ate/instruments/transport/base.py
from typing import Protocol
@@ -701,7 +619,7 @@ class Transport(Protocol):
### 4.3 Test Interface
```python
# thermaulate/executive/models.py
# py_dvt_ate/framework/models.py
from dataclasses import dataclass, field
from datetime import datetime
@@ -778,12 +696,12 @@ class ITest(Protocol):
### 4.4 Factory Interface
```python
# thermaulate/hal/factory.py
# py_dvt_ate/instruments/factory.py
from dataclasses import dataclass
from typing import Literal
from thermaulate.hal.interfaces import IThermalChamber, IPowerSupply, IMultimeter
from py_dvt_ate.instruments.interfaces import IThermalChamber, IPowerSupply, IMultimeter
@dataclass
@@ -827,22 +745,19 @@ class InstrumentFactory:
@staticmethod
def _create_simulated(config: InstrumentConfig) -> InstrumentSet:
"""Create simulated instruments."""
from thermaulate.transport.tcp import TCPTransport
from thermaulate.drivers.thermal_chamber import ThermalChamberDriver
from thermaulate.drivers.power_supply import PowerSupplyDriver
from thermaulate.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
from py_dvt_ate.instruments.transport.tcp import TCPTransport
from py_dvt_ate.instruments.drivers.chamber import ThermalChamberDriver
from py_dvt_ate.instruments.drivers.power_supply import PowerSupplyDriver
from py_dvt_ate.instruments.drivers.multimeter import MultimeterDriver
chamber_transport = TCPTransport(config.simulator_host, config.chamber_port)
psu_transport = TCPTransport(config.simulator_host, config.psu_port)
dmm_transport = TCPTransport(config.simulator_host, config.dmm_port)
return InstrumentSet(
chamber=ThermalChamberHAL(ThermalChamberDriver(chamber_transport)),
psu=PowerSupplyHAL(PowerSupplyDriver(psu_transport)),
dmm=MultimeterHAL(MultimeterDriver(dmm_transport)),
chamber=ThermalChamberDriver(chamber_transport),
psu=PowerSupplyDriver(psu_transport),
dmm=MultimeterDriver(dmm_transport),
)
@staticmethod
@@ -954,7 +869,7 @@ All instruments implement these standard commands:
### 5.5 SCPI Parser Specification
```python
# thermaulate/instruments/scpi_parser.py
# py_dvt_ate/instruments/scpi.py
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
```python
# thermaulate/physics/engine.py
# py_dvt_ate/simulation/physics/engine.py
from dataclasses import dataclass
@@ -1256,7 +1171,7 @@ Schema:
### 7.3 Data Repository Interface
```python
# thermaulate/data/repository.py
# py_dvt_ate/data/repository.py (interface)
from typing import Protocol
from uuid import UUID
@@ -1366,14 +1281,14 @@ dut:
# Data storage paths
data:
database_path: "./data/thermaulate.db"
database_path: "./data/py_dvt_ate.db"
measurements_dir: "./data/measurements"
reports_dir: "./data/reports"
# Logging configuration
logging:
level: INFO
file: "./data/logs/thermaulate.log"
file: "./data/logs/py_dvt_ate.log"
format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
# Dashboard (Streamlit)
@@ -1391,7 +1306,7 @@ api:
### 8.2 Pydantic Configuration Models
```python
# thermaulate/config/models.py
# py_dvt_ate/app/config.py (config models)
from pydantic import BaseModel, Field
from typing import Literal
@@ -1449,14 +1364,14 @@ class DUTConfig(BaseModel):
class DataConfig(BaseModel):
database_path: str = "./data/thermaulate.db"
database_path: str = "./data/py_dvt_ate.db"
measurements_dir: str = "./data/measurements"
reports_dir: str = "./data/reports"
class LoggingConfig(BaseModel):
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"
@@ -1612,7 +1527,7 @@ class AppConfig(BaseModel):
```toml
[project]
name = "thermaulate"
name = "py_dvt_ate"
version = "0.1.0"
description = "Coupled Physics DVT Simulation Platform"
requires-python = ">=3.11"
@@ -1648,9 +1563,9 @@ dev = [
]
[project.scripts]
thermaulate = "thermaulate.cli.main:app"
thermaulate-server = "thermaulate.server.main:main"
thermaulate-dashboard = "thermaulate.dashboard.app:main"
py_dvt_ate = "py_dvt_ate.cli.main:app"
py_dvt_ate-server = "py_dvt_ate.server.main:main"
py_dvt_ate-dashboard = "py_dvt_ate.dashboard.app:main"
[build-system]
requires = ["hatchling"]

View File

@@ -38,7 +38,7 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
**Vertical Slice Strategy:**
- Sprints 1-3: Foundation + Physics Engine (the core simulation)
- 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
---
@@ -79,20 +79,18 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
**Goal:** Define physics interfaces and data structures.
### Task 2.1: Define thermal state dataclasses
- Create src/py_dvt_ate/physics/__init__.py
- Create src/py_dvt_ate/physics/models.py
- Create src/py_dvt_ate/simulation/physics/models.py
- Define ThermalState (frozen dataclass)
- Define ElectricalState (frozen dataclass)
- **Commit:** "Add physics state dataclasses"
### Task 2.2: Define DUT base protocol
- Create src/py_dvt_ate/physics/dut/__init__.py
- Create src/py_dvt_ate/physics/dut/base.py
- Create src/py_dvt_ate/simulation/physics/models/base.py
- Define DUTModel Protocol with method signatures
- **Commit:** "Add DUT model protocol"
### 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
- Methods return placeholder values
- **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.
### 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
- Pure functions, no state
- **Commit:** "Implement thermal calculation functions"
### 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
- Temperature-dependent Vout, Iq calculations
- 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!
### Task 4.1: Create dashboard app skeleton
- Create src/py_dvt_ate/dashboard/__init__.py
- Create src/py_dvt_ate/dashboard/app.py
- Create src/py_dvt_ate/app/dashboard/__init__.py
- Create src/py_dvt_ate/app/dashboard/app.py
- Basic Streamlit page with title
- **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
- 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
- **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.
### 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
- Command dispatch mechanism
- **Commit:** "Add base instrument class"
### 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
- Stub SCPI command handlers
- **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.
### 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
- VOLT, CURR, OUTP, MEAS commands
- **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"
### 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
- MEAS:VOLT:DC?, CONF commands
- **Commit:** "Add multimeter simulator"
@@ -250,8 +248,8 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
**Goal:** Expose instruments over network.
### Task 8.1: Create async TCP server foundation
- Create src/py_dvt_ate/server/__init__.py
- Create src/py_dvt_ate/server/tcp_server.py
- Create src/py_dvt_ate/simulation/__init__.py
- Create src/py_dvt_ate/simulation/tcp_server.py
- Define InstrumentServer class with asyncio
- **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"
### 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
- Add CLI command to start server
- **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.
### Task 9.1: Define transport protocol
- Create src/py_dvt_ate/transport/__init__.py
- Create src/py_dvt_ate/transport/base.py
- Create src/py_dvt_ate/instruments/transport/__init__.py
- Create src/py_dvt_ate/instruments/transport/base.py
- Define Transport Protocol class
- **Commit:** "Add transport protocol definition"
### 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
- connect(), write(), read(), query() methods
- **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.
### Task 10.1: Define driver base class
- Create src/py_dvt_ate/drivers/__init__.py
- Create src/py_dvt_ate/drivers/base.py
- Create src/py_dvt_ate/instruments/drivers/__init__.py
- Create src/py_dvt_ate/instruments/drivers/base.py
- Define BaseDriver with transport dependency
- **Commit:** "Add driver base class"
### 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
- **Commit:** "Add thermal chamber driver"
### Task 10.3: Implement PSU and DMM drivers
- Create src/py_dvt_ate/drivers/power_supply.py
- Create src/py_dvt_ate/drivers/multimeter.py
- Create src/py_dvt_ate/instruments/drivers/power_supply.py
- Create src/py_dvt_ate/instruments/drivers/multimeter.py
- **Commit:** "Add PSU and DMM drivers"
### 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
- Create src/py_dvt_ate/hal/__init__.py
- Create src/py_dvt_ate/hal/interfaces.py
- Define IThermalChamber, IPowerSupply, IMultimeter
- **Commit:** "Add HAL protocol definitions"
### Task 11.1: Define instrument interface protocols
- Create src/py_dvt_ate/instruments/interfaces.py
- Define IThermalChamber, IPowerSupply, IMultimeter protocols
- **Commit:** "Add instrument interface protocols"
### Task 11.2: Implement HAL wrappers
- Create src/py_dvt_ate/hal/impl/__init__.py
- Create HAL implementation classes
- Wrap drivers with HAL interface
- **Commit:** "Add HAL implementations"
### Task 11.2: Ensure drivers implement interfaces
- Update drivers to satisfy Protocol interfaces
- Add type hints for interface compliance
- **Commit:** "Implement instrument interfaces in drivers"
### Task 11.3: Create instrument factory
- Create src/py_dvt_ate/hal/factory.py
- Create src/py_dvt_ate/instruments/factory.py
- InstrumentSet dataclass
- InstrumentFactory.create() method
- **Commit:** "Add instrument factory"
### Task 11.4: Add HAL tests
- Create tests/unit/test_hal.py
### Task 11.4: Add instrument interface tests
- Create tests/unit/test_instruments.py
- 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.
### Task 12.1: Define config models
- Create src/py_dvt_ate/config/__init__.py
- Create src/py_dvt_ate/config/models.py
- Pydantic models for all config sections
- Create src/py_dvt_ate/app/config.py
- Define Pydantic models for all config sections
- **Commit:** "Add configuration Pydantic models"
### 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
- Environment variable overrides
- **Commit:** "Implement configuration loader"
@@ -410,25 +405,25 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
**Goal:** Test execution orchestration.
### Task 14.1: Define test interface and models
- Create src/py_dvt_ate/executive/__init__.py
- Create src/py_dvt_ate/executive/models.py
- Create src/py_dvt_ate/framework/__init__.py
- Create src/py_dvt_ate/framework/context.py
- TestStatus enum, TestContext, ITest protocol
- **Commit:** "Add test executive models"
- **Commit:** "Add test framework models"
### 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
- **Commit:** "Implement test logger"
### 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
- **Commit:** "Implement limit checker"
### Task 14.4: Implement test sequencer
- Create src/py_dvt_ate/executive/sequencer.py
### Task 14.4: Implement test runner
- Create src/py_dvt_ate/framework/runner.py
- 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"
### 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
- Vout measurement at each temperature
- TempCo calculation
@@ -517,40 +512,38 @@ Each sprint is ~1-2 days of work, producing demonstrable progress.
## File Dependencies Map
```
physics/models.py → (none)
physics/dut/base.py → models.py
physics/dut/ldo.py → base.py, models.py
physics/thermal.py → models.py
physics/engine.py → models.py, thermal.py, dut/base.py
simulation/physics/models.py → (none)
simulation/physics/models/base.py → models.py
simulation/physics/models/ldo.py → base.py, models.py
simulation/physics/thermal.py → models.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/base.py → scpi_parser.py
instruments/*_sim.py → base.py, physics/engine.py
instruments/scpi.py → (none)
simulation/virtual/base.py → instruments/scpi.py
simulation/virtual/*.py → base.py, simulation/physics/engine.py
transport/base.py → (none)
transport/tcp.py → base.py
instruments/transport/base.py → (none)
instruments/transport/tcp.py → base.py
drivers/base.py → transport/base.py
drivers/*.py → base.py
instruments/drivers/base.py → instruments/transport/base.py
instruments/drivers/*.py → base.py
hal/interfaces.py → (none)
hal/impl/*.py → interfaces.py, drivers/*.py
hal/factory.py → interfaces.py, impl/*.py
instruments/interfaces.py → (none)
instruments/factory.py → interfaces.py, drivers/*.py
config/models.py → (none)
config/loader.py → models.py
app/config.py → (none)
data/models.py → (none)
data/repository.py → models.py
data/models.py → (none)
data/repository.py → models.py
executive/models.py → hal/interfaces.py
executive/*.py → models.py, data/repository.py
framework/context.py → instruments/interfaces.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 |
| 4 | `v0.1.0-alpha.2` | Visual demo (dashboard) | 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 |
| 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 |
| 7 | - | Instruments Done | SCPI simulators respond to commands |
| 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 |
| 17 | `v0.1.0` | **MVP Complete** | Full end-to-end workflow |

View File

@@ -40,9 +40,9 @@ dev = [
]
[project.scripts]
py-dvt-ate = "py_dvt_ate.cli.main:app"
py-dvt-ate-server = "py_dvt_ate.server.main:main"
py-dvt-ate-dashboard = "py_dvt_ate.dashboard.app:main"
py-dvt-ate = "py_dvt_ate.app.cli:app"
py-dvt-ate-server = "py_dvt_ate.simulation.server:main"
py-dvt-ate-dashboard = "py_dvt_ate.app.dashboard.app:main"
[build-system]
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."""