Conversation
…cpp backend - @typechecker on kspaceFirstOrder() catches wrong positional arg order - Auto-convert Cartesian sensor masks to binary via cart2grid for cpp backend (python backend handles Cartesian masks natively via interpolation) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace kspaceFirstOrder2DC/3D with kspaceFirstOrder() - Remove SimulationOptions/SimulationExecutionOptions usage - Map is_gpu_simulation → device="gpu"|"cpu", save_to_disk → implicit for backend="cpp" - Drop data_cast="single" (handled internally) - Note unsupported features: pml_inside, stream_to_disk, checkpointing - Time-reversal examples keep legacy imports (TimeReversal class requires them) - checkpointing example unchanged (uses checkpoint_file/checkpoint_timesteps not yet in new API) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The new kspaceFirstOrder() API does not mutate its inputs (handles copies internally when needed), so deepcopy is never required. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All .py examples now work as interactive notebooks in VS Code/JupyterLab via percent-format cell markers. Each file has a markdown header cell with title and description, followed by logical sections. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…es README .py files with # %% markers are the source of truth. Notebooks will be auto-generated via jupytext at release time. Per-example READMEs replaced by inline markdown headers in each .py file. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
jupytext is a dev/CI dependency only (not runtime). Notebooks are generated from .py files with: jupytext --to notebook examples/**/*.py Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…es on CPU/python kspaceFirstOrder() now respects KWAVE_BACKEND and KWAVE_DEVICE env vars, allowing CI to run GPU/cpp examples with python/cpu backend. CI workflow sets these + MPLBACKEND=Agg, and excludes utility/legacy-only scripts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #668 +/- ##
==========================================
+ Coverage 74.09% 74.17% +0.07%
==========================================
Files 56 56
Lines 7925 7933 +8
Branches 1543 1544 +1
==========================================
+ Hits 5872 5884 +12
+ Misses 1435 1432 -3
+ Partials 618 617 -1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Covers KWAVE_BACKEND/KWAVE_DEVICE env override paths and cart2grid auto-conversion for cpp backend. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
NotATransducer (kSensor subclass) is used as source in transducer examples (us_bmode_phased_array). beartype rejects it without the Union[kSource, NotATransducer] annotation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…level - Revert at_focused_bowl_AS and at_circular_piston_AS to kspaceFirstOrderASC (new API doesn't support axisymmetric flag — would silently produce wrong results) - Hoist legacy imports (kspaceFirstOrder2D/3D, SimulationOptions, etc.) to top of TR examples instead of burying inside main() Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…badge On merge to master, CI generates .ipynb files from examples/*.py via jupytext and commits them to notebooks/. Colab badges link to these generated notebooks. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@greptile-app |
- run_examples.py sets KWAVE_BACKEND=python KWAVE_DEVICE=cpu MPLBACKEND=Agg - Skip utility files, report pass/fail summary - Add notebooks/.gitkeep so link checker doesn't fail on missing directory Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ectories - Move 20 example .py files from subdirectories to examples/ - Inline example_utils.py into us_bmode_linear_transducer.py - Delete now-empty subdirectories and stale MATLAB file - README.md renders below file list on GitHub (always visible) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… workflows - Fix: import kspaceFirstOrderASC from kwave.kspaceFirstOrderAS (not 2D) - generate-notebooks: flat glob, explicit push to master, contents:write permission - run-examples: exclude AS examples (legacy API), flat find with maxdepth 1 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Squeeze single-sensor data before plotting (ivp_photoacoustic_waveforms) - Fix sensor sum axis: axis=0 sums across sensors for (n_sensors, n_time) shape (sd_focussed_detector_2D, sd_focussed_detector_3D, sd_directivity_modelling_2D) - Add missing kgrid.makeTime() call (pr_3D_FFT_planar_sensor) - Use full grid size (PML inside) instead of subtracting PML (pr_3D_FFT_planar_sensor) - Skip save_only test when KWAVE_BACKEND=python (unified_entry_point_demo) 11/20 examples now pass with KWAVE_BACKEND=python. Remaining failures are in kWaveArray/transducer examples that need library-level fixes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ansducer - Remove .T on sensor_data["p"] — python backend already returns (n_sensors, n_time) (at_array_as_sensor, at_circular_piston_3D, at_focused_bowl_3D, at_focused_annular_array_3D, pr_3D_FFT_planar_sensor) - Fix PML inside: use full grid size, don't subtract 2*PML (pr_2D_FFT_line_sensor, at_circular_piston_3D) - validate_source: use getattr() for all source attributes so NotATransducer (which lacks p0, p, p_mask, u_mask) doesn't raise AttributeError 17/20 examples now pass with KWAVE_BACKEND=python. Remaining: - us_* (3): still on legacy API, need NotATransducer python backend support - at_array_as_source: ffmpeg/mp4 dependency Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CLAUDE.md: project overview, architecture, conventions, commands - release-strategy.md: detailed F-order → C-order migration plan for v1.0 with explicit boundary layers (HDF5 serialization, MATLAB interop) - Document 1-based → 0-based indexing migration path Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…nside=False When sensor=None with pml_inside=False, the grid expands (64 → 104) and all grid points become sensors. _strip_pml now strips PML rows from time-series data using an interior boolean mask on the expanded grid. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@greptile-app |
| from typing import Optional, Union | ||
|
|
||
| import numpy as np | ||
| from beartype import beartype as typechecker |
There was a problem hiding this comment.
typechecker imported but never applied
beartype as typechecker is imported but no function in this file is decorated with @typechecker. This leaves an unused import that linters will flag and could confuse readers who expect runtime type-checking to be active.
Either apply it to kspaceFirstOrder (which would enforce the Union[kSource, NotATransducer] annotation at call-time), or remove the import if it is not needed here:
| from beartype import beartype as typechecker |
(i.e. remove this line entirely, or add @typechecker before def kspaceFirstOrder(...) if enforcement is intended.)
| import sys | ||
| from pathlib import Path | ||
|
|
||
| SKIP = {"example_utils.py", "__init__.py"} |
There was a problem hiding this comment.
checkpoint.py not excluded from run_examples.py
The CI workflow (run-examples.yml) explicitly skips checkpoint.py with -not -name "checkpoint.py", but run_examples.py only skips example_utils.py and __init__.py. Because rglob("*.py") recurses into examples/checkpointing/, checkpoint.py will be executed when anyone runs python run_examples.py locally. If that script requires special conditions (e.g. a C++ binary, specific file paths, or manual cleanup), it will fail or leave artifacts.
| SKIP = {"example_utils.py", "__init__.py"} | |
| SKIP = {"example_utils.py", "__init__.py", "checkpoint.py"} |
…store @typechecker Post-merge cleanup: - Remove _is_binary_mask (superseded by _is_cartesian_mask from pml-inside branch) - Remove sensor_was_none (assigned but never read after merge resolution) - Restore @typechecker decorator on kspaceFirstOrder (catches wrong arg order) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@greptile-app |
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Remove KWAVE_BACKEND override — examples run with their specified backend (cpp or python). Only override KWAVE_DEVICE=cpu since CI has no GPU. Include all examples including legacy ones (TR, AS, checkpoint). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
| - name: Run example | ||
| env: | ||
| KWAVE_FORCE_CPU: 1 | ||
| KWAVE_DEVICE: cpu | ||
| MPLBACKEND: Agg |
There was a problem hiding this comment.
KWAVE_BACKEND not set; C++-backend examples will fail in CI
KWAVE_DEVICE: cpu is set, but KWAVE_BACKEND: python is missing. us_bmode_phased_array.py hardcodes backend="cpp" and is no longer excluded from CI discovery.
| - name: Run example | |
| env: | |
| KWAVE_FORCE_CPU: 1 | |
| KWAVE_DEVICE: cpu | |
| MPLBACKEND: Agg | |
| env: | |
| KWAVE_BACKEND: python | |
| KWAVE_DEVICE: cpu | |
| MPLBACKEND: Agg |
Greptile Summary
This PR migrates ~30 examples to the new unified
kspaceFirstOrder()API, adds CI infrastructure for running examples and auto-generating notebooks, and cleans up the old per-dimensionality solver calls. The overall direction is a clear improvement in usability and consistency.Key changes:
examples/*.py(flat) and updated to callkspaceFirstOrder()withbackend=/device=kwargs instead of separatekspaceFirstOrder2D/3Dfunctions.kspaceFirstOrder()gains@typechecker, env-var overrides (KWAVE_BACKEND,KWAVE_DEVICE), apml_inside=Truewarning, andUnion[kSource, NotATransducer]on thesourceparameter.validation.pycorrectly switches all direct attribute accesses onsourcetogetattr(...)guards soNotATransducerobjects pass validation cleanly.Issues found in this review:
source.p0 is not Noneon line 199 ofkspaceFirstOrder.pyraisesAttributeErrorfor every caller passing aNotATransducerassource; fix isgetattr(source, "p0", None).run-examples.ymlomitsKWAVE_BACKEND: python, so examples hardcodingbackend="cpp"will fail in CI.Confidence Score: 2/5
Not safe to merge — guaranteed AttributeError crash for all NotATransducer-based simulations.
P0 bug causes runtime crash in transducer examples; several prior-thread issues remain open.
kwave/kspaceFirstOrder.py line 199, .github/workflows/run-examples.yml
Important Files Changed
Comments Outside Diff (4)
kwave/kspaceFirstOrder.py, line 143-152 (link)sensor.record_start_indexsilently ignored for cpp backend — steady-state results will be wrongSeveral examples (e.g.
at_circular_piston_3D,at_focused_bowl_3D,at_circular_piston_AS,at_focused_bowl_AS,at_focused_annular_array_3D) setsensor.record_start_index = kgrid.Nt - (record_periods * ppp) + 1specifically to capture only the final steady-state window. When the cpp backend ignores this and records from time step 1,extract_amp_phaseis called on all time steps — the early transient contaminates the result and the extracted amplitude will be wrong.The warning on line 147 is not enough; the simulation produces incorrect output without user awareness. Options:
ValueErrorinstead of a warning whenrecord_start_index != 1andbackend="cpp"(breaking but safe).sensor_record_start_indexif the binary supports it.kwave/kspaceFirstOrder.py, line 206 (link)AttributeErrorwhensourceisNotATransducersource.p0is accessed directly, butNotATransducer(which inherits fromkSensor) has nop0attribute. SincekSensor.__init__never setsp0and there is no__getattr__fallback, this raisesAttributeErrorat runtime wheneversmooth_p0=True(the default) and a transducer is passed assource— for example inus_bmode_phased_array.py.The validation layer was correctly updated to use
getattr(source, "p0", None), but the guard here was not:kwave/kspaceFirstOrder.py, line 200 (link)AttributeErrorforNotATransducersource whensmooth_p0=TrueNotATransduceris a subclass ofkSensorand has nop0attribute. The direct attribute accesssource.p0here will raiseAttributeError: 'NotATransducer' object has no attribute 'p0'whenever a transducer is passed assourcewith the defaultsmooth_p0=True.us_bmode_phased_array.pypassesnot_transducer(aNotATransducer) assourcewithout overridingsmooth_p0, so this code path is hit and will fail in CI.validation.pyalready usesgetattr(source, "p0", None)to guard against exactly this case — the same pattern should be applied here:kwave/kspaceFirstOrder.py, line 199 (link)AttributeErrorwhensourceisNotATransducerNotATransducerinherits fromkSensor, notkSource, and defines nop0attribute. Withsmooth_p0=True(the default), Python evaluatessource.p0as soon as the expression is reached and raisesAttributeErrorfor every caller that passes a transducer assource(e.g.us_bmode_phased_array.py,us_bmode_linear_transducer.py).Reviews (5): Last reviewed commit: "CI: run all examples with native backend..." | Re-trigger Greptile