Skip to content

Commit 88e3601

Browse files
jman4162claude
andcommitted
v0.6.1: Expand public API, update README for v0.6.0 features, add test fixtures
- Rich top-level exports in __init__.py (22 classes/functions importable directly) - Add py.typed marker for PEP 561 type checker support - Update README: optimization workflow, RF/digital/reliability features, new examples - Quick start examples now use top-level imports - Add shared test fixtures in conftest.py - Bump development status classifier from Alpha to Beta Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 3c9ba84 commit 88e3601

6 files changed

Lines changed: 241 additions & 10 deletions

File tree

README.md

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ Phased array antenna system design, optimization, and performance visualization
2020
- **Model-Based Workflow**: MBSE/MDAO approach from requirements through optimized designs
2121
- **Requirements-Driven**: Every evaluation produces pass/fail with margins and traceability
2222
- **Trade-Space Exploration**: DOE generation and Pareto analysis for systematic design exploration
23+
- **Design Optimization**: Scipy-based solvers (DE, dual annealing, L-BFGS-B) with constraint support
24+
- **Comprehensive Models**: Comms link budget, radar detection, RF cascade, digital beamformer, reliability
2325
- **Dual Application**: Supports both communications link budgets and radar detection scenarios
2426
- **Reproducible**: Config-driven workflow with seed control and version stamping
2527

@@ -30,14 +32,20 @@ Config (YAML/JSON) → Architecture + Scenario → DOE Generation → Batch Eval
3032
↓ ↓
3133
Requirements ───────────────────────────────────────────→ Verification
3234
33-
Reports ← Visualization ← Pareto Extraction ←──┘
35+
Pareto Extraction
36+
37+
Reports ← Visualization ← Optimization ←────────────┘
3438
```
3539

3640
## Features
3741

3842
- **Requirements as first-class objects**: Every run produces pass/fail + margins with traceability
3943
- **Trade-space exploration**: DOE + Pareto optimization over single-point designs
44+
- **Design optimization**: Scipy solvers with weighted multi-objective scalarization and constraint penalties
4045
- **Communications & Radar**: Link budget analysis and radar detection modeling
46+
- **RF cascade analysis**: Friis noise figure, IIP3, SFDR, MDS for cascaded receiver chains
47+
- **Digital beamformer models**: ADC/DAC characterization, bandwidth budgets, scheduling
48+
- **TRM reliability**: MTBF, availability, graceful degradation with failed elements
4149
- **Flat metrics dictionary**: All models return consistent `dict[str, float]` for interchange
4250
- **Config-driven reproducibility**: Stable case IDs, seed control, version stamping
4351
- **CLI and Python API**: Use from command line or integrate into scripts
@@ -59,9 +67,8 @@ pip install phased-array-systems[plotting]
5967
### Single Case Evaluation
6068

6169
```python
62-
from phased_array_systems.architecture import Architecture, ArrayConfig, RFChainConfig
63-
from phased_array_systems.scenarios import CommsLinkScenario
64-
from phased_array_systems.evaluate import evaluate_case
70+
from phased_array_systems import Architecture, ArrayConfig, RFChainConfig
71+
from phased_array_systems import CommsLinkScenario, evaluate_case
6572

6673
# Define architecture
6774
arch = Architecture(
@@ -86,7 +93,7 @@ print(f"Link Margin: {metrics['link_margin_db']:.1f} dB")
8693
### DOE Trade Study
8794

8895
```python
89-
from phased_array_systems.trades import DesignSpace, generate_doe, BatchRunner, extract_pareto
96+
from phased_array_systems import DesignSpace, generate_doe, BatchRunner, extract_pareto
9097

9198
# Define design space
9299
space = (
@@ -110,12 +117,35 @@ pareto = extract_pareto(results, [
110117
])
111118
```
112119

120+
### Design Optimization
121+
122+
```python
123+
from phased_array_systems import optimize_design, DesignSpace, CommsLinkScenario
124+
125+
scenario = CommsLinkScenario(
126+
freq_hz=10e9, bandwidth_hz=10e6, range_m=100e3, required_snr_db=10.0,
127+
)
128+
space = (
129+
DesignSpace()
130+
.add_variable("array.nx", "categorical", values=[4, 8, 16])
131+
.add_variable("array.ny", "categorical", values=[4, 8, 16])
132+
.add_variable("rf.tx_power_w_per_elem", "float", low=0.5, high=3.0)
133+
)
134+
135+
result = optimize_design(
136+
space=space, scenario=scenario,
137+
objective="eirp_dbw", sense="maximize", method="de", seed=42,
138+
)
139+
print(f"Best EIRP: {result.best_metrics['eirp_dbw']:.1f} dBW")
140+
```
141+
113142
## Examples
114143

115144
See the `examples/` directory:
116145
- `01_comms_single_case.py` - Single case evaluation
117146
- `02_comms_doe_trade.py` - Full DOE trade study workflow
118147
- `03_radar_detection_trade.py` - Radar detection analysis and trade study
148+
- `05_optimization.py` - Design optimization with constraint handling
119149

120150
### Tutorial Notebook
121151

@@ -168,11 +198,14 @@ pasys run config.yaml
168198
# DOE batch study
169199
pasys doe config.yaml -n 100 --method lhs
170200

171-
# Generate report
172-
pasys report results.parquet --format html
201+
# Design optimization
202+
pasys optimize config.yaml --objective eirp_dbw --sense maximize
173203

174204
# Extract Pareto frontier
175205
pasys pareto results.parquet -x cost_usd -y eirp_dbw --plot
206+
207+
# Generate report
208+
pasys report results.parquet --format html
176209
```
177210

178211
## Documentation

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ keywords = [
2323
"optimization",
2424
]
2525
classifiers = [
26-
"Development Status :: 3 - Alpha",
26+
"Development Status :: 4 - Beta",
2727
"Intended Audience :: Science/Research",
2828
"Intended Audience :: Developers",
2929
"License :: OSI Approved :: MIT License",
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
"""Version and metadata for phased-array-systems."""
22

3-
__version__ = "0.6.0"
3+
__version__ = "0.6.1"
44
__author__ = "phased-array-systems contributors"

src/phased_array_systems/__init__.py

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,82 @@
77

88
from phased_array_systems.__about__ import __version__
99

10-
__all__ = ["__version__"]
10+
# Architecture configs
11+
from phased_array_systems.architecture import (
12+
Architecture,
13+
ArrayConfig,
14+
CostConfig,
15+
DigitalConfig,
16+
ReliabilityConfig,
17+
RFChainConfig,
18+
)
19+
20+
# Evaluation
21+
from phased_array_systems.evaluate import (
22+
evaluate_case,
23+
evaluate_case_with_report,
24+
evaluate_config,
25+
)
26+
27+
# I/O
28+
from phased_array_systems.io import (
29+
export_results,
30+
load_config,
31+
load_results,
32+
)
33+
34+
# Requirements
35+
from phased_array_systems.requirements import (
36+
Requirement,
37+
RequirementSet,
38+
VerificationReport,
39+
)
40+
41+
# Scenarios
42+
from phased_array_systems.scenarios import (
43+
CommsLinkScenario,
44+
RadarDetectionScenario,
45+
)
46+
47+
# Trade studies and optimization
48+
from phased_array_systems.trades import (
49+
BatchRunner,
50+
DesignSpace,
51+
OptimizationResult,
52+
extract_pareto,
53+
generate_doe,
54+
optimize_design,
55+
)
56+
57+
__all__ = [
58+
"__version__",
59+
# Architecture
60+
"Architecture",
61+
"ArrayConfig",
62+
"CostConfig",
63+
"DigitalConfig",
64+
"ReliabilityConfig",
65+
"RFChainConfig",
66+
# Scenarios
67+
"CommsLinkScenario",
68+
"RadarDetectionScenario",
69+
# Requirements
70+
"Requirement",
71+
"RequirementSet",
72+
"VerificationReport",
73+
# Evaluation
74+
"evaluate_case",
75+
"evaluate_case_with_report",
76+
"evaluate_config",
77+
# Trades
78+
"BatchRunner",
79+
"DesignSpace",
80+
"OptimizationResult",
81+
"extract_pareto",
82+
"generate_doe",
83+
"optimize_design",
84+
# I/O
85+
"export_results",
86+
"load_config",
87+
"load_results",
88+
]

src/phased_array_systems/py.typed

Whitespace-only changes.

tests/conftest.py

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
"""Shared test fixtures for phased-array-systems."""
2+
3+
from pathlib import Path
4+
5+
import pytest
6+
7+
from phased_array_systems.architecture import (
8+
Architecture,
9+
ArrayConfig,
10+
CostConfig,
11+
RFChainConfig,
12+
)
13+
from phased_array_systems.requirements import Requirement, RequirementSet
14+
from phased_array_systems.scenarios import CommsLinkScenario, RadarDetectionScenario
15+
from phased_array_systems.trades import DesignSpace
16+
17+
18+
@pytest.fixture
19+
def comms_scenario():
20+
"""Standard 10 GHz comms scenario at 100 km range."""
21+
return CommsLinkScenario(
22+
freq_hz=10e9,
23+
bandwidth_hz=10e6,
24+
range_m=100e3,
25+
required_snr_db=10.0,
26+
scan_angle_deg=0.0,
27+
rx_antenna_gain_db=0.0,
28+
rx_noise_temp_k=290.0,
29+
)
30+
31+
32+
@pytest.fixture
33+
def radar_scenario():
34+
"""Standard 10 GHz radar scenario at 50 km range."""
35+
return RadarDetectionScenario(
36+
freq_hz=10e9,
37+
bandwidth_hz=1e6,
38+
range_m=50e3,
39+
target_rcs_dbsm=0.0,
40+
pfa=1e-6,
41+
pd_required=0.9,
42+
n_pulses=10,
43+
integration_type="noncoherent",
44+
)
45+
46+
47+
@pytest.fixture
48+
def base_architecture():
49+
"""8x8 array with 1W/element and standard RF chain."""
50+
return Architecture(
51+
array=ArrayConfig(
52+
nx=8,
53+
ny=8,
54+
dx_lambda=0.5,
55+
dy_lambda=0.5,
56+
enforce_subarray_constraint=False,
57+
),
58+
rf=RFChainConfig(
59+
tx_power_w_per_elem=1.0,
60+
pa_efficiency=0.3,
61+
noise_figure_db=3.0,
62+
feed_loss_db=1.0,
63+
),
64+
cost=CostConfig(
65+
cost_per_elem_usd=100.0,
66+
nre_usd=10000.0,
67+
),
68+
)
69+
70+
71+
@pytest.fixture
72+
def basic_requirements():
73+
"""Simple EIRP + cost requirement set."""
74+
return RequirementSet(
75+
requirements=[
76+
Requirement(
77+
id="REQ-001",
78+
name="Minimum EIRP",
79+
metric_key="eirp_dbw",
80+
op=">=",
81+
value=30.0,
82+
severity="must",
83+
),
84+
Requirement(
85+
id="REQ-002",
86+
name="Maximum Cost",
87+
metric_key="cost_usd",
88+
op="<=",
89+
value=50000.0,
90+
severity="must",
91+
),
92+
],
93+
name="Basic Requirements",
94+
)
95+
96+
97+
@pytest.fixture
98+
def architecture_design_space():
99+
"""Design space for array sizing and RF parameters."""
100+
return (
101+
DesignSpace(name="Test Design Space")
102+
.add_variable("array.nx", type="categorical", values=[4, 8, 16])
103+
.add_variable("array.ny", type="categorical", values=[4, 8, 16])
104+
.add_variable(
105+
"array.enforce_subarray_constraint",
106+
type="categorical",
107+
values=[True],
108+
)
109+
.add_variable("array.geometry", type="categorical", values=["rectangular"])
110+
.add_variable("rf.tx_power_w_per_elem", type="float", low=0.5, high=3.0)
111+
.add_variable("rf.pa_efficiency", type="float", low=0.2, high=0.5)
112+
.add_variable("rf.noise_figure_db", type="float", low=3.0, high=3.0)
113+
.add_variable("cost.cost_per_elem_usd", type="float", low=75.0, high=150.0)
114+
)
115+
116+
117+
@pytest.fixture
118+
def configs_dir():
119+
"""Path to example config files."""
120+
return Path(__file__).parent.parent / "examples" / "configs"

0 commit comments

Comments
 (0)