Migrate to uv, fix bugs and deprecated scipy APIs#55
Migrate to uv, fix bugs and deprecated scipy APIs#55TAJD wants to merge 58 commits intomarinlauber:masterfrom
Conversation
Replace legacy setuptools build with hatchling + PEP 621 metadata. Add uv.lock for reproducible installs. Replace black+isort with ruff. Move streamlit/flask to optional dependency groups. Update Python requirement to >=3.12 for improved dependency compatibility. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace setup.py/twine with uv build and PyPI OIDC trusted publishers. Run on ubuntu-latest instead of self-hosted. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Test on Python 3.10-3.12. Use astral-sh/setup-uv action. Bump actions/checkout to v4. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rinlauber#43) Replace incorrect 'pip install requirements.txt' with correct commands. Add uv as the recommended install method. Fix hardcoded shebang in runVPP.py. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…lauber#46) String raises are invalid in Python 3 and caused TypeError. Also initialize self.upToDate = False in __init__ so the guard works when set_analysis() hasn't been called. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
interp1d was deprecated in scipy 1.10. Use make_interp_spline which returns a BSpline with the same callable interface. Filter NaN values before passing to make_interp_spline since it has stricter input validation than the deprecated interp1d. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
interp2d was deprecated in scipy 1.10 and removed in 1.14. Use RegularGridInterpolator for sail chart interpolation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Run ruff check --fix to clean up import ordering, trailing whitespace, and blank line whitespace across src/ and tests/. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Document Sail, Jib, Kite __init__ parameters and measure methods. Jib parameters (I, J, LPG, HBI) were the most requested per marinlauber#53. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Document Appendage, Keel, Rudder, Bulb, and complete Yacht parameter documentation (was missing 7 of 16 params). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Document __init__ and update() parameters for both force models. Fix typos in existing docstrings (_vce, _cf). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add modules.rst with autodoc for VPPMod, YachtMod, SailMod, AeroMod, HydroMod, and UtilsMod. Restructure index.rst with toctree. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Bump requires-python to >=3.11 (3.10 EOL Oct 2026) - Test matrix now 3.11, 3.12, 3.13 - Install --extra api in CI so test_api.py can import flask Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
nlopt 2.7.1 has no cp313 wheels. nlopt 2.9+ requires numpy>=2. Updated lower bounds to ensure compatibility with Python 3.11-3.13. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@marinlauber - was able to get this one off, please lmk what you think, I think it covers main feedback points plus upgrades CI I'm going to probably do some hobby modelling of the Daring yacht class (one design in cowes) to model the impact of potential sail changes but hard to find time ofc |
Allow per-yacht configuration of GZ righting arm curves via an optional GZ parameter in the Yacht constructor. When provided, uses the supplied curve instead of loading from the global righting_moment.json file, maintaining backward compatibility. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add conftest.py with matplotlib Agg backend so plt.show() is a no-op during tests. Update test_vpp.py to save plots to tmp_path and assert the files exist. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Create Daring yacht definition with published specifications from classicsailboats.org and estimated hydrodynamic parameters. Includes: - righting_moment.json with GZ curve for ~50% ballast ratio, GM ~0.70m - test_daring.py with comprehensive VPP tests (solve, speed sanity, polars/sail chart) - runDaring.py script to generate polars and sail charts across 4-22 knots All 3 tests pass and script runs successfully. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
9 wind speeds (4-20 kts), 31 TWA angles, main+jib and main+kite. Sanity checked: max speed ~6.7 kts at 10 kts TWS, VMG up ~4.7 kts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of hardcoding flat=1.0 and RED=2.0, resid() now accepts them as parameters with defaults that preserve existing behavior. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allow users to specify a heel angle limit when setting up the analysis. Defaults to 35.0 degrees to preserve existing behavior. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add _depower_solve() that flattens sails (flat: 1.0 -> 0.62) then reefs/furls (RED: 2.0 -> 0.5) when heel exceeds phi_max. Uses bounded least_squares solver to enforce the heel constraint during depowering. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ensure least_squares initial guess stays within bounds when the unconstrained solve produces out-of-range values. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…t model comment Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New page lets users set up two configurations side by side and compare: - Overlaid polar plots (blue vs orange) - VMG comparison table (upwind/downwind angles and speeds) - Full speed delta table with absolute and percentage differences Also extracts PRESETS into shared demos/presets.py module. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Short Keel vs Fin Keel — Physics Differences for Daring VPPThe Daring has a short/integrated keel, not a modern separated fin. The current 1. GeometryA short keel is defined by its fore-aft length along the hull and depth below the canoe body, not root/tip chord of a separated trapezoid. Aspect ratio is much lower (0.2–0.5 vs 1.0–2.0 for a fin). 2. Lift EfficiencyAt very low aspect ratio, the Prandtl correction ( 3. Form DragHigher than a fin ( 4. Residuary ResistanceA short keel's wave-making is largely captured by the hull's ORC resistance surface (since it's integrated with the hull). The separate appendage residuary term from ImpactThese differences compound — the Daring model currently over-predicts side force (too little leeway), under-predicts form drag, and may double-count residuary resistance. A |
- Replace fixed two-column layout with numbered tabs (Config 1, 2, ...) - Add/remove configs dynamically (up to 6) - Highlight fields that differ from Config 1 below each tab - Use distinct colours and markers per config on overlaid polars - VMG and delta tables scale to N configs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Jones low-AR lift formula (pi*AR/2) replaces Prandtl correction for short/integrated keels like the Daring 5.5m class. Higher form drag factor, zero appendage residuary resistance (captured by hull), and reduced wall-effect multiplier. - Add ShortKeel class to YachtMod.py - Support keel_type in API (fin/short) - Switch Daring preset and runDaring to ShortKeel - Add keel type selector to Streamlit UI - Add unit tests for Jones formula, zero Rr, and lift comparison Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Show Cu/Cl/Span for fin keels and Length/Depth/Tc_ratio for short keels, with sensible defaults when switching between types. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract keel type selector + field swapping into utils.render_keel_inputs so both the single VPP page and the comparison page show the correct inputs (Cu/Cl/Span for fin, Length/Depth/Tc_ratio for short). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move run_vpp, render_environment_inputs, and validate_ranges into demos/utils.py so both the VPP and Compare pages use the same code. Removes ~40 lines of duplication across the two pages. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
It does - I think merge in #51 and then I'll rebase can continue |
- Remove max(0, leeway) clamp in HydroMod.update that silently zeroed negative leeway values, breaking solver convergence when the optimizer explored the valid [-2, 6] degree range - Replace confusing `leeway / 180.0 * np.pi` with `np.radians(leeway)` for clarity (same result, clearer intent) - Remove unused Appendage._cl() method — side force is computed directly in HydroMod._get_Ri() via cla * np.radians(leeway) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The bounded solver pins heel at phi_max, so `phi <= phi_max` was always true after the first flat step. Added 1-degree margin check so depowering continues until heel genuinely drops below the limit. Also finer step sizes: flat 0.02 (was 0.05), RED 0.1 (was 0.2). Impact on Daring at 27kts/40TWA: Vb 3.3→6.0 kts, flat 0.95→0.62, RED 2.0→0.9, leeway 6.0→2.6 degrees. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Streamlit widget state can cause the type field to be missing or inconsistent with the actual keel parameters. Fall back to checking for 'Length' key to detect short keel payloads. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cover three keel type dispatch paths: explicit type='short', key-based detection (no type field), and explicit type='fin'. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…icients
- Remove nlopt dependency, add scipy SLSQP 5-DOF constrained optimizer
that simultaneously optimizes [vb, phi, leeway, flat, red]
- Add method parameter to VPP.run() ("iterative" or "5dof")
- Upgrade sail coefficient interpolation from linear interp1d to cubic
B-splines (make_interp_spline k=3), with NaN filtering and k=1 fallback
- Add pluggable data_source parameter (dat/{source}/) with backward compat
- Add user-loadable sail polars via cl_data/cd_data dicts
- API accepts method and data_source parameters
- Streamlit UI: solver method and data source selectboxes on both pages
- Copy existing sail data to dat/orc/ subdirectory
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…l polar plots - _get_cross() now accepts a pad parameter; speed plot (j=0) keeps pad=2 for visual overlap, heel/leeway (j>0) use pad=0 to avoid discontinuities - Legend is now rendered on all axes, not just the speed plot Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The three sail combinations (e.g. MN1+J1, MN1+A2, MN1+A5) each have a distinct colour but were unlabelled. Add a "Sail set" legend on the centre (heel) axis; TWS legends remain on the speed and leeway axes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each plot keeps its own TWS legend; a shared "Sail set" legend with colour-coded sail combinations sits along the bottom centre. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@TAJD I'm going through those slowly, as there is a lot of stuff. I'm testing as I go, and everything looks nice. |
|
Good to hear! Any concerns just shout, as you can see I'm using Claude and whilst I'm adding tests and thinking through the logic I'm not checking all the code line by line yet. |
New data files from ORC VPP documentation: - sym_kite.dat: symmetric spinnaker (peak CL 1.456) - asym_cl_kite.dat: asymmetric spinnaker, centerline tack (peak CL 1.513) - asym_pole_kite.dat: asymmetric spinnaker, pole tack (peak CL 1.548) - main_low.dat: mainsail low-performance rig variant - jib_low.dat: jib low-performance rig variant Add sail_type parameter to Main, Jib, Kite constructors to select coefficient variant (e.g. sail_type="sym_kite"). API passes through sail_type from JSON payload per sail section. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add sail_type selectboxes for main (main/main_low), jib (jib/jib_low), and kite (kite/sym_kite/asym_cl_kite/asym_pole_kite) to both VPP and Compare Streamlit pages - Wire sail_types through run_vpp() to API payload per sail section - Add API tests for sym_kite and low-performance sail_type parameters Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…it tests - ITTC 1978 surface roughness allowance in HydroMod - Bretschneider wave spectrum added resistance model - Match racing simulation engine (RaceMod) with tactical rules, wind shadow model, and Monte Carlo runner - Pluggable wind model API (WindMod): constant, Brownian, mean-reverting - Pre-computed polar caches for YD41 and Daring - Match Race UI page with full parameter controls - Popover explainers across all Streamlit pages - Streamlit AppTest suite (25 tests) for UI verification - Finer TWA grid (39 points) and environment parameter sliders Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two changes to break perfect symmetry between identical boats: - Random start-line offset (0.5-2 boat lengths lateral, 0-0.5 along-course) models winning the pin at a real start - Fractional mark-crossing time interpolation gives sub-second precision instead of rounding to integer timesteps Draw rate drops from 100% to 0% even with identical boats, constant wind, and zero noise. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Distinct colours (blue/orange) and markers (circle/triangle) per boat - Dashed line for boat B vs solid for boat A (colourblind accessible) - Mark/buoy positions shown as black diamonds on course trace - Course corridor boundaries drawn as dotted lines - Start positions marked with larger symbols - Grid lines, cleaner spines, higher DPI (120) across all plots - Win probability bar uses cleaner styling with hidden spines
- Analytical wind triangle (law of cosines) replacing scipy fsolve - LRU caching for wind_triangle() and sail coefficient deduplication - Parallel TWS/TWA grid computation via ProcessPoolExecutor - TWS sensitivity sweep and parameter sensitivity analysis for match racing - Per-leg race breakdown with timing and leg type tracking - Tactical statistics: shadow tracking and encounter counting - Field help tooltips on all VPP, Compare, and Match Race UI inputs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace plain-text parameter labels (Lwl, Vol, Bwl, etc.) with proper
LaTeX notation ($L_{wl}$, $\nabla$, $B_{wl}$, etc.) across all
Streamlit pages. Adds FIELD_LABELS mapping and field_label() helper in
utils.py. Also formats environment sliders and match race parameters
with Greek symbols for sigma, kappa, tau, and theta.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ht, UI improvements - Replace matplotlib polar plot on Compare page with interactive Plotly Scatterpolar (hover tooltips, zoom, legend toggle) - Replace manual st.progress callback with built-in st.status on VPP and Compare pages - Move hull roughness from environment to per-yacht (number_input with guidance tooltip), applied per-config on Compare and per-boat on Match Race - Add run_vpp_direct() to bypass Flask and call solver directly - Add progress_callback parameter to VPP.run() for future use - Improve Compare page change summary: use mathematical field labels, section titles, and collapse to expander when >4 changes - VMG tables now stacked vertically with percentage deltas - Add plotly dependency Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add per-TWS progress updates via st.status on VPP and Compare pages (shows each wind speed as it completes per config) - Make TWS and TWA slider ranges inclusive of the end value - Add seconds-per-nautical-mile delta column to VMG comparison tables - Simplify VPP.run() progress_callback to fire at TWS level Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
setup.py+requirements.txttopyproject.toml(hatchling) +uv.lockastral-sh/setup-uvwith Python 3.11/3.12 matrix; publish workflow usesuv build+ PyPI trusted publishers (OIDC)raise "string"is invalid Python 3, replaced withRuntimeError(fixes if not self.upToDate in run does not work since the excpetion is not derived from a BaseException #46)pip install requirements.txtreplaced withpip install -e ".[dev]"anduv sync(fixes fix incorrect dependency install instructions in readme #43)interp1d→make_interp_spline,interp2d→RegularGridInterpolator(addresses Update dependencies to latest versions #36)src/andtests/phi_max), makingflatandREDtuneable parametersIssues addressed
Supersedes PR #51 and PR #41.
Test plan
runVPP.pyruns end-to-end producing correct outputNotes
requires-pythonset to>=3.11(CI tests 3.11-3.12)flaskandstreamlitmoved to base dependencies (needed for Streamlit Cloud)ruffreplacesblack+isort(faster, single tool)🤖 Generated with Claude Code