Skip to content

Commit 304c98a

Browse files
RFingAdamclaude
andcommitted
chore: post-review quick wins — deps slimming, TRP docstring, dead-code removal
Safe S-effort fixes from the 2026-05 multi-perspective review (docs/REVIEW_2026-05.md): - deps: move openai to the [ai] extra; drop keyring + cryptography from core (imported nowhere after the v5.0.0 AI removal); remove pyinstaller from the runtime requirements.txt (it's in the [exe] extra). Closes #16, #17. - numpy: raise the ceiling <2.0.0 -> <3.0.0; the suite already runs green on numpy 2.2.4 and uses no 2.0-removed APIs. Closes #18. - calculations.calculate_trp: clarify the docstring — the per-angle input is EIRP and the 1/(4pi) is the canonical CTIA discrete TRP (an isotropic 0 dBm EIRP pattern integrates to ~0 dBm, NOT -11 dB). Prevents future false-alarm "bugs". Closes #11. - groupdelay: remove the dead, undefined-name-referencing variance/std block; the real metric is tracked in #8. No behavior change; full suite 327 passed / 148 skipped. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 65f9c94 commit 304c98a

4 files changed

Lines changed: 27 additions & 32 deletions

File tree

plot_antenna/calculations.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,23 @@
66

77
def calculate_trp(power_dBm_2d, theta_angles_rad, inc_theta, inc_phi):
88
"""
9-
Calculate Total Radiated Power (TRP) using IEEE-correct solid angle integration.
9+
Calculate Total Radiated Power (TRP) using the CTIA/IEEE-149 discrete
10+
solid-angle integration.
1011
11-
The TRP is calculated by integrating radiated power density over a closed sphere:
12-
TRP = (1/4π) ∫∫ P(θ,φ) · sin(θ) dθ dφ
12+
The per-angle input is EIRP — the isotropic-referenced power measured in
13+
each direction (after path-loss calibration). For EIRP, TRP is the
14+
sphere average of EIRP, i.e. the standard CTIA discrete form:
1315
14-
For discrete measurements, this becomes:
15-
TRP = Σ P(θ,φ) · sin(θ) · Δθ · Δφ / (4π)
16+
TRP = (1/4π) ∫∫ EIRP(θ,φ) · sin(θ) dθ dφ
17+
≈ Σ EIRP(θ,φ) · sin(θ) · Δθ · Δφ / (4π)
18+
19+
The 1/(4π) is correct *because the input is EIRP*, not radiation intensity
20+
U (W/sr); for an isotropic radiator with EIRP = P0 in every direction this
21+
integrates back to TRP = P0 (verified by the golden-reference test). Do not
22+
remove the 1/(4π) — see docs/REVIEW_2026-05.md (finding R7/R8).
1623
1724
Parameters:
18-
power_dBm_2d: 2D array of power values in dBm (theta x phi)
25+
power_dBm_2d: 2D array of per-angle EIRP in dBm (theta x phi)
1926
theta_angles_rad: 1D array of theta angles in radians
2027
inc_theta: Theta increment in degrees
2128
inc_phi: Phi increment in degrees

plot_antenna/groupdelay.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -155,15 +155,10 @@ def plot_group_delay_error(data_dict, min_freq=None, max_freq=None):
155155
difference_data.append(difference_at_freq * 1e12)
156156
error_at_freq = (difference_at_freq) * 29979245800
157157
error_data.append(error_at_freq)
158-
"""
159-
# TODO Calculate the variance in picoseconds
160-
variance_at_freq = np.var(group_delays_at_freq_ps)
161-
variance_data.append(variance_at_freq)
162-
163-
# TODO Calculate the standard deviation
164-
std_dev_at_freq = np.std(group_delays_at_freq_ps)
165-
std_dev_data.append(std_dev_at_freq)
166-
"""
158+
# NOTE: per-frequency group-delay variance/std across theta is a planned
159+
# metric (tracked issue: group-delay dispersion). The previous dead
160+
# block referenced an undefined name and is removed to avoid confusion;
161+
# implement it with a dedicated test alongside group-delay test coverage.
167162
# Plot Group Delay difference
168163
plt.figure(figsize=(10, 6))
169164
plt.plot(freq_points, difference_data, label="Max Group Delay Difference over Theta")

pyproject.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,15 @@ classifiers = [
2828
]
2929

3030
dependencies = [
31-
"numpy>=1.26.0,<2.0.0",
31+
"numpy>=1.26.0,<3.0.0",
3232
"scipy>=1.14.0,<2.0.0",
3333
"matplotlib>=3.10.0,<4.0.0",
3434
"pandas>=2.0.0,<3.0.0",
3535
"python-docx>=1.2.0,<2.0.0",
36-
"openai>=1.38.0,<2.0.0",
37-
"keyring>=25.0.0,<26.0.0",
3836
"python-dotenv>=1.0.0,<2.0.0",
3937
"tqdm>=4.65.0,<5.0.0",
4038
"requests>=2.31.0,<3.0.0",
4139
"Pillow>=10.0.0,<11.0.0",
42-
"cryptography>=43.0.0,<44.0.0",
4340
]
4441

4542
[project.optional-dependencies]
@@ -52,7 +49,10 @@ dev = [
5249
"mypy>=1.8.0",
5350
"bump2version>=1.0.0",
5451
]
52+
# Optional: only needed if you wire RFlect's data into an external LLM yourself.
53+
# RFlect's own report/analysis path is fully deterministic and needs none of these.
5554
ai = [
55+
"openai>=1.38.0,<2.0.0",
5656
"anthropic>=0.40.0",
5757
"ollama>=0.4.0",
5858
]

requirements.txt

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1+
# RFlect runtime dependencies (deterministic core — no LLM/API key needed).
2+
# Optional extras live in pyproject.toml: [ai] (openai/anthropic/ollama),
3+
# [dev] (pytest/black/flake8/mypy), [exe] (pyinstaller).
4+
15
# Core scientific computing
2-
numpy>=1.26.0,<2.0.0
6+
numpy>=1.26.0,<3.0.0
37
scipy>=1.14.0,<2.0.0
48
matplotlib>=3.10.0,<4.0.0
59
pandas>=2.0.0,<3.0.0
610

711
# Document generation
812
python-docx>=1.2.0,<2.0.0
913

10-
# AI/ML integration
11-
openai>=1.38.0,<2.0.0
12-
13-
# Security & configuration
14-
keyring>=25.0.0,<26.0.0
14+
# Configuration
1515
python-dotenv>=1.0.0,<2.0.0
1616

1717
# CLI utilities
@@ -20,10 +20,3 @@ requests>=2.31.0,<3.0.0
2020

2121
# Image processing (for logo display)
2222
Pillow>=10.0.0,<11.0.0
23-
24-
# Encryption (for API key storage)
25-
cryptography>=43.0.0,<44.0.0
26-
27-
# PyInstaller for executable builds
28-
pyinstaller>=6.18.0,<7.0.0
29-
pyinstaller-hooks-contrib>=2026.0

0 commit comments

Comments
 (0)