fullwave25 1.4.2.dev4__tar.gz → 1.5.0.dev0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (428) hide show
  1. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/.bumpversion.toml +15 -2
  2. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/.gitignore +1 -0
  3. fullwave25-1.5.0.dev0/CONTRIBUTING.md +28 -0
  4. fullwave25-1.5.0.dev0/PKG-INFO +350 -0
  5. fullwave25-1.5.0.dev0/README.md +305 -0
  6. fullwave25-1.5.0.dev0/docs/claude_skill/fullwave25/SKILL.md +253 -0
  7. fullwave25-1.5.0.dev0/docs/fullwave2_ultra.md +33 -0
  8. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/__init__.py +1 -1
  9. fullwave25-1.5.0.dev0/fullwave/beamformer/__init__.py +6 -0
  10. fullwave25-1.5.0.dev0/fullwave/beamformer/mach_beamformer.py +533 -0
  11. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/grid.py +15 -0
  12. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/medium.py +43 -21
  13. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/medium_builder/presets/__init__.py +8 -1
  14. fullwave25-1.5.0.dev0/fullwave/medium_builder/presets/combined_phantom_map.py +146 -0
  15. fullwave25-1.5.0.dev0/fullwave/medium_builder/presets/domain_combined_phantom.py +316 -0
  16. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/binary_manager.py +1 -1
  17. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/binary_markers.py +29 -0
  18. fullwave25-1.5.0.dev0/fullwave/solver/bins/database/relaxation_params_database_num_relax=4_20261102_1540.mat +0 -0
  19. fullwave25-1.5.0.dev0/fullwave/solver/bins/database/relaxation_params_database_num_relax=4_20261102_1540_invalid_cells.json +4096 -0
  20. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/input_file_writer.py +25 -0
  21. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/pml_builder.py +2 -0
  22. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/shipped_database.py +1 -1
  23. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/solver.py +149 -52
  24. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/source_type.py +27 -0
  25. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/source.py +39 -1
  26. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/transducer.py +122 -10
  27. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/ultra/backend.py +47 -60
  28. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/ultra/backend_2d.py +23 -12
  29. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/ultra/binary.py +4 -0
  30. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/ultra/dat_io.py +15 -0
  31. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/ultra/writer_2d.py +38 -0
  32. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/ultra/writer_3d.py +37 -0
  33. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/utils/plot_utils.py +158 -4
  34. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/utils/relaxation_parameters.py +193 -21
  35. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/pyproject.toml +7 -1
  36. fullwave25-1.5.0.dev0/references/2604.06257v1.pdf +0 -0
  37. fullwave25-1.5.0.dev0/references/signed.gif +0 -0
  38. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/uv.lock +10 -2
  39. fullwave25-1.4.2.dev4/.claude/.gitignore +0 -1
  40. fullwave25-1.4.2.dev4/.claude/20260911_1813_dead-code.md +0 -162
  41. fullwave25-1.4.2.dev4/.claude/20260916_1311_commit_message_of_the_input_generation_speedup.md +0 -13
  42. fullwave25-1.4.2.dev4/.claude/20260916_1311_pull_request_of_the_input_generation_speedup.md +0 -31
  43. fullwave25-1.4.2.dev4/.claude/20260916_1405_commit_message_of_the_relaxation_memory_estimate.md +0 -10
  44. fullwave25-1.4.2.dev4/.claude/20260916_1405_pull_request_of_the_relaxation_memory_estimate.md +0 -24
  45. fullwave25-1.4.2.dev4/.claude/20260916_2152_commit_message_of_the_cuda_version_choice.md +0 -10
  46. fullwave25-1.4.2.dev4/.claude/20260916_2152_pull_request_of_the_cuda_version_choice.md +0 -25
  47. fullwave25-1.4.2.dev4/.claude/20260916_2203_commit_message_of_the_cuda_version_tests.md +0 -10
  48. fullwave25-1.4.2.dev4/.claude/20260916_2213_commit_message_of_the_blackwell_version_choice.md +0 -9
  49. fullwave25-1.4.2.dev4/.claude/20260916_2213_pull_request_of_the_blackwell_version_choice.md +0 -23
  50. fullwave25-1.4.2.dev4/.claude/CLAUDE.md +0 -286
  51. fullwave25-1.4.2.dev4/.claude/matrix_imaging/20260909_1844_acquire_the_reflection_matrix.py +0 -55
  52. fullwave25-1.4.2.dev4/.claude/matrix_imaging/20260909_1900_test_on_a_synthetic_acquisition.py +0 -139
  53. fullwave25-1.4.2.dev4/.claude/matrix_imaging/20260909_1913_analyze_the_reflection_matrix.py +0 -111
  54. fullwave25-1.4.2.dev4/.claude/matrix_imaging/20260909_2107_redraw_the_figures_of_an_analysis.py +0 -48
  55. fullwave25-1.4.2.dev4/.claude/matrix_imaging/20260909_2121_write_the_result_tables.py +0 -177
  56. fullwave25-1.4.2.dev4/.claude/matrix_imaging/20260910_1126_synthesize_plane_waves_from_the_multistatic_matrix.py +0 -132
  57. fullwave25-1.4.2.dev4/.claude/matrix_imaging/20260910_1137_scan_the_speed_of_sound.py +0 -531
  58. fullwave25-1.4.2.dev4/.claude/matrix_imaging/20260910_1141_compare_the_laws_with_the_truth.py +0 -490
  59. fullwave25-1.4.2.dev4/.claude/matrix_imaging/20260910_1146_evaluate_the_reverberation_filter.py +0 -525
  60. fullwave25-1.4.2.dev4/.claude/matrix_imaging/20260910_1208_compare_plane_waves_with_the_synthesis.py +0 -143
  61. fullwave25-1.4.2.dev4/.claude/matrix_imaging/figures.py +0 -521
  62. fullwave25-1.4.2.dev4/.claude/matrix_imaging/ground_truth.py +0 -394
  63. fullwave25-1.4.2.dev4/.claude/matrix_imaging/matrix_imaging.py +0 -1346
  64. fullwave25-1.4.2.dev4/.claude/matrix_imaging/pipeline.py +0 -534
  65. fullwave25-1.4.2.dev4/.claude/matrix_imaging/reflection_matrix.py +0 -370
  66. fullwave25-1.4.2.dev4/.claude/matrix_imaging/speed_of_sound.py +0 -417
  67. fullwave25-1.4.2.dev4/.claude/matrix_imaging/synthetic.py +0 -166
  68. fullwave25-1.4.2.dev4/.claude/scratch/20260821_0206_band_anchor_cross_check.py +0 -137
  69. fullwave25-1.4.2.dev4/.claude/scratch/20260821_0233_delivered_power_law_end_to_end.py +0 -125
  70. fullwave25-1.4.2.dev4/.claude/scratch/20260821_0317_reword_deliver_in_the_library.py +0 -59
  71. fullwave25-1.4.2.dev4/.claude/scratch/20260821_1220_relaxation_low_frequency_rolloff.py +0 -246
  72. fullwave25-1.4.2.dev4/.claude/scratch/20260825_1937_what_fails_the_pml_golden_tests.py +0 -103
  73. fullwave25-1.4.2.dev4/.claude/scratch/20260825_2329_does_the_wrapper_read_the_record.py +0 -112
  74. fullwave25-1.4.2.dev4/.claude/scratch/20260826_0002_what_the_new_default_table_holds.py +0 -92
  75. fullwave25-1.4.2.dev4/.claude/scratch/20260828_1422_what_the_candidate_tables_hold.py +0 -101
  76. fullwave25-1.4.2.dev4/.claude/scratch/20260828_1427_what_the_deployment_needs.py +0 -249
  77. fullwave25-1.4.2.dev4/.claude/scratch/20260828_1510_where_the_unstretched_ramp_reaches.py +0 -218
  78. fullwave25-1.4.2.dev4/.claude/scratch/20260828_1517_the_blast_radius_of_the_ramp.py +0 -237
  79. fullwave25-1.4.2.dev4/.claude/scratch/20260830_1458_the_3d_region_trimmed_kernel_against_the_reference.py +0 -196
  80. fullwave25-1.4.2.dev4/.claude/scratch/20260830_1505_the_multi_node_kernel_against_the_multi_gpu_one.py +0 -179
  81. fullwave25-1.4.2.dev4/.claude/scratch/20260830_1631_the_3d_multi_node_against_the_multi_gpu_one.py +0 -119
  82. fullwave25-1.4.2.dev4/.claude/scratch/20260830_1642_the_selective_absorbing_layer.py +0 -176
  83. fullwave25-1.4.2.dev4/.claude/scratch/20260830_1728_the_layer_against_the_taper.py +0 -312
  84. fullwave25-1.4.2.dev4/.claude/scratch/20260830_1757_what_the_margin_outside_the_layer_does.py +0 -286
  85. fullwave25-1.4.2.dev4/.claude/scratch/20260830_1808_the_layer_in_3d_and_on_the_multi_node_builds.py +0 -446
  86. fullwave25-1.4.2.dev4/.claude/scratch/20260830_1832_where_the_3d_residual_sits.py +0 -324
  87. fullwave25-1.4.2.dev4/.claude/scratch/20260830_1837_inside_the_layer_at_the_corner.py +0 -294
  88. fullwave25-1.4.2.dev4/.claude/scratch/20260830_1840_inside_the_3d_layer_at_the_corner.py +0 -292
  89. fullwave25-1.4.2.dev4/.claude/scratch/20260830_1912_both_absorbers_on_one_method.py +0 -326
  90. fullwave25-1.4.2.dev4/.claude/scratch/20260830_1922_the_layer_on_the_reflection_method.py +0 -443
  91. fullwave25-1.4.2.dev4/.claude/scratch/20260830_2011_whole_domain_animation.py +0 -327
  92. fullwave25-1.4.2.dev4/.claude/scratch/20260830_2032_the_example_source_kind.py +0 -168
  93. fullwave25-1.4.2.dev4/.claude/scratch/20260830_2148_drive_scale_of_the_strong_beta_cells.py +0 -71
  94. fullwave25-1.4.2.dev4/.claude/scratch/20260830_2159_profile_the_input_map_build.py +0 -250
  95. fullwave25-1.4.2.dev4/.claude/scratch/20260830_2201_build_then_extend_equivalence.py +0 -201
  96. fullwave25-1.4.2.dev4/.claude/scratch/20260830_2304_the_transmit_methods_launch_what_they_say.py +0 -208
  97. fullwave25-1.4.2.dev4/.claude/scratch/20260830_2322_the_unscaled_added_drive_follows_the_courant_number.py +0 -239
  98. fullwave25-1.4.2.dev4/.claude/scratch/20260831_0033_the_three_dimensional_arrays.py +0 -249
  99. fullwave25-1.4.2.dev4/.claude/scratch/20260831_0054_the_elevation_lens_of_a_linear_array.py +0 -276
  100. fullwave25-1.4.2.dev4/.claude/scratch/20260831_0115_run_every_example.sh +0 -21
  101. fullwave25-1.4.2.dev4/.claude/scratch/20260831_0124_move_the_notebooks_to_the_transmit_interface.py +0 -274
  102. fullwave25-1.4.2.dev4/.claude/scratch/20260831_0137_the_air_region_at_four_mechanisms.py +0 -314
  103. fullwave25-1.4.2.dev4/.claude/scratch/20260831_0148_the_element_records_its_own_transmit.py +0 -202
  104. fullwave25-1.4.2.dev4/.claude/scratch/20260831_0150_the_absorbing_layer_of_a_point_source.py +0 -235
  105. fullwave25-1.4.2.dev4/.claude/scratch/20260831_0152_the_exponential_absorbing_layer_against_its_thickness.py +0 -213
  106. fullwave25-1.4.2.dev4/.claude/scratch/20260831_0202_the_rebuilt_exponential_absorbing_layer.py +0 -267
  107. fullwave25-1.4.2.dev4/.claude/scratch/20260831_0216_where_the_three_dimensional_layer_leaks.py +0 -258
  108. fullwave25-1.4.2.dev4/.claude/scratch/20260831_0222_the_absorbing_layer_away_from_the_source.py +0 -266
  109. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1037_where_the_near_field_brightness_comes_from.py +0 -276
  110. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1040_the_aperture_transit_wedge_in_the_channel_data.py +0 -296
  111. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1043_the_transmit_in_the_recorded_trace_and_its_removal.py +0 -460
  112. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1048_the_receive_row_against_the_reference_subtraction.py +0 -491
  113. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1052_the_backing_behind_the_array_face.py +0 -495
  114. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1056_the_transmit_beam_with_the_air_backing.py +0 -233
  115. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1105_the_shipped_transducer_stack_in_the_solver.py +0 -485
  116. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1119_where_the_stack_puts_the_source_and_what_it_costs_the_depth.py +0 -446
  117. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1121_the_depth_the_image_reads_with_the_stack.py +0 -451
  118. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1123_the_depth_the_beamformer_puts_one_point_at.py +0 -353
  119. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1142_the_transmit_offset_the_beamformer_needs.py +0 -367
  120. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1145_the_depth_shift_the_offset_fix_makes.py +0 -183
  121. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1154_the_two_offset_rules_on_the_same_recording.py +0 -231
  122. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1212_what_the_pinned_release_carries.py +0 -141
  123. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1228_the_low_cut_against_the_near_field_haze.py +0 -490
  124. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1301_run_the_beamforming_notebooks.py +0 -50
  125. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1432_point_dataset_generator_at_the_local_fullwave.py +0 -92
  126. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1437_the_aperture_width_the_reference_geometry_reports.py +0 -79
  127. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1454_calibrate_the_ats539_plane_wave.py +0 -367
  128. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1508_show_the_b_mode_in_the_hdf5.py +0 -315
  129. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1534_the_comet_behind_each_wire.py +0 -241
  130. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1547_read_the_calibration_trials.py +0 -226
  131. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1605_what_the_medium_holds_in_the_near_field.py +0 -195
  132. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1607_sweep_one_generator_knob.py +0 -322
  133. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1715_assert_the_ats539_rate_chain.py +0 -166
  134. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1717_measure_every_layer_of_the_stack.py +0 -151
  135. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1720_where_the_trailing_energy_lands.py +0 -201
  136. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1725_offer_the_requested_absorption_to_the_backing.py +0 -119
  137. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1727_let_a_sweep_carry_a_switch.py +0 -105
  138. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1731_expose_the_exponential_absorbing_layer.py +0 -121
  139. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1746_point_the_solver_at_an_older_binary.py +0 -95
  140. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1756_measure_the_point_targets.py +0 -154
  141. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1802_rederive_the_near_field_bounce.py +0 -106
  142. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1810_does_the_shelf_move_with_depth.py +0 -199
  143. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1812_find_the_repeat_delay_in_the_raw_rf.py +0 -168
  144. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1937_give_each_source_row_its_own_launch_delay.py +0 -88
  145. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1943_baffle_the_element_plane.py +0 -103
  146. fullwave25-1.4.2.dev4/.claude/scratch/20260831_1952_take_the_cell_size_from_the_grid.py +0 -70
  147. fullwave25-1.4.2.dev4/.claude/scratch/20260831_2058_run_the_ats539_through_the_batched_solver.py +0 -120
  148. fullwave25-1.4.2.dev4/.claude/scratch/20260831_2105_queue_the_remaining_candidates.py +0 -143
  149. fullwave25-1.4.2.dev4/.claude/scratch/20260831_2122_the_simulator_asks_for_a_clamped_source.py +0 -111
  150. fullwave25-1.4.2.dev4/.claude/scratch/20260831_2126_rename_the_source_types_to_hard_and_soft.py +0 -98
  151. fullwave25-1.4.2.dev4/.claude/scratch/20260831_2140_bind_the_source_type_to_its_entrance.py +0 -224
  152. fullwave25-1.4.2.dev4/.claude/scratch/20260831_2225_how_redundant_are_the_absorbing_layer_files.py +0 -166
  153. fullwave25-1.4.2.dev4/.claude/scratch/20260831_2239_skip_the_constant_absorbing_layer_maps.py +0 -171
  154. fullwave25-1.4.2.dev4/.claude/scratch/20260831_2246_count_the_files_a_run_writes.py +0 -144
  155. fullwave25-1.4.2.dev4/.claude/scratch/20260831_2352_run_the_map_tiers_end_to_end.py +0 -243
  156. fullwave25-1.4.2.dev4/.claude/scratch/20260831_2355_draw_the_absorbing_layer_map_cost.py +0 -170
  157. fullwave25-1.4.2.dev4/.claude/scratch/20260901_1502_can_the_transmit_reach_the_harmonic_band.py +0 -173
  158. fullwave25-1.4.2.dev4/.claude/scratch/20260901_1504_contrast_harmonic_imaging.py +0 -896
  159. fullwave25-1.4.2.dev4/.claude/scratch/20260901_1507_where_each_band_puts_its_largest_sample.py +0 -139
  160. fullwave25-1.4.2.dev4/.claude/scratch/20260901_1519_is_the_harmonic_tail_cumulative.py +0 -280
  161. fullwave25-1.4.2.dev4/.claude/scratch/20260901_1537_does_the_cancellation_work.py +0 -202
  162. fullwave25-1.4.2.dev4/.claude/scratch/20260901_1612_does_a_sparse_bubble_cloud_localize.py +0 -232
  163. fullwave25-1.4.2.dev4/.claude/scratch/20260901_1619_calibrate_the_bubble_scatter_range.py +0 -310
  164. fullwave25-1.4.2.dev4/.claude/scratch/20260901_1622_draw_the_sweep_b_modes.py +0 -168
  165. fullwave25-1.4.2.dev4/.claude/scratch/20260901_1654_where_the_bright_region_sits.py +0 -367
  166. fullwave25-1.4.2.dev4/.claude/scratch/20260901_1701_where_one_bubble_images.py +0 -301
  167. fullwave25-1.4.2.dev4/.claude/scratch/20260901_1702_does_the_portable_example_reproduce_the_evaluation.py +0 -115
  168. fullwave25-1.4.2.dev4/.claude/scratch/20260901_1753_does_the_ported_solver_still_march_the_same.py +0 -212
  169. fullwave25-1.4.2.dev4/.claude/scratch/20260901_1755_do_the_ranks_agree_on_the_bubbles.py +0 -385
  170. fullwave25-1.4.2.dev4/.claude/scratch/20260901_1817_does_the_air_region_reach_every_solver.py +0 -331
  171. fullwave25-1.4.2.dev4/.claude/scratch/20260901_1818_does_the_air_region_reach_every_rank.py +0 -285
  172. fullwave25-1.4.2.dev4/.claude/scratch/20260902_1317_what_the_abdomen_volume_holds.py +0 -129
  173. fullwave25-1.4.2.dev4/.claude/scratch/20260902_1319_art_wave_in_the_abdomen.py +0 -584
  174. fullwave25-1.4.2.dev4/.claude/scratch/20260902_1324_art_figures_from_the_field.py +0 -2176
  175. fullwave25-1.4.2.dev4/.claude/scratch/20260902_1744_art_final_animations.py +0 -266
  176. fullwave25-1.4.2.dev4/.claude/scratch/20260904_1216_art_wire_visibility.py +0 -426
  177. fullwave25-1.4.2.dev4/.claude/scratch/20260904_2327_b_mode_of_the_abdomen.py +0 -1494
  178. fullwave25-1.4.2.dev4/.claude/scratch/20260905_0038_two_against_three_dimensions.py +0 -529
  179. fullwave25-1.4.2.dev4/.claude/scratch/20260909_1934_probe_the_reverberation_filter_on_speckle.py +0 -93
  180. fullwave25-1.4.2.dev4/.claude/scratch/20260909_1939_probe_the_ideal_profile_on_speckle.py +0 -86
  181. fullwave25-1.4.2.dev4/.claude/scratch/20260909_2044_probe_the_correction_bases_on_a_flat_speckle.py +0 -59
  182. fullwave25-1.4.2.dev4/.claude/scratch/20260909_2342_measure_the_wall_delay_screen.py +0 -85
  183. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1134_find_the_first_non_finite_value_of_the_plane_wave_correction.py +0 -98
  184. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1234_print_the_summaries_of_analyses.py +0 -100
  185. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/a_maps_checks.py +0 -75
  186. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/b_effective_frequency.py +0 -55
  187. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/c_composed_steps.py +0 -46
  188. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/check_element_centers.py +0 -77
  189. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/check_plane_wave_law.py +0 -248
  190. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/d2_gate_quarter_period.py +0 -52
  191. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/d_gate_cases.py +0 -52
  192. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/e_plate_crash.py +0 -63
  193. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/f_patch_grid.py +0 -17
  194. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/g_frequency_scan.py +0 -29
  195. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/gouy_check.py +0 -87
  196. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/h_pulse_and_wires.py +0 -23
  197. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/i_phase_slope.py +0 -28
  198. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a0200910_001.sh +0 -1
  199. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a0200910_002.sh +0 -6
  200. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a0200910_003.sh +0 -5
  201. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a0200910_004.sh +0 -10
  202. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a0200910_005.sh +0 -8
  203. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_001.sh +0 -6
  204. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_002.sh +0 -13
  205. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_003.sh +0 -12
  206. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_004.sh +0 -9
  207. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_005.sh +0 -13
  208. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_006.sh +0 -13
  209. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_007.sh +0 -16
  210. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_008.sh +0 -10
  211. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_009.sh +0 -34
  212. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_010.sh +0 -39
  213. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a3e03828_001.sh +0 -14
  214. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a3e03828_002.sh +0 -10
  215. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a3e03828_003.sh +0 -10
  216. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a3e03828_004.sh +0 -8
  217. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a3e03828_005.sh +0 -9
  218. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_001.sh +0 -1
  219. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_002.sh +0 -9
  220. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_003.sh +0 -7
  221. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_004.sh +0 -13
  222. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_005.sh +0 -14
  223. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_006.sh +0 -2
  224. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_007.sh +0 -39
  225. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_008.sh +0 -12
  226. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_47c5d913-2f0_a86c7568_001.sh +0 -10
  227. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_001.sh +0 -10
  228. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_002.sh +0 -20
  229. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_003.sh +0 -18
  230. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_004.sh +0 -24
  231. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_005.sh +0 -36
  232. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_006.sh +0 -18
  233. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_007.sh +0 -50
  234. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_008.sh +0 -32
  235. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_009.sh +0 -7
  236. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_001.sh +0 -1
  237. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_002.sh +0 -23
  238. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_003.sh +0 -6
  239. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_004.sh +0 -8
  240. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_005.sh +0 -1
  241. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_006.sh +0 -7
  242. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_007.sh +0 -12
  243. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_001.sh +0 -1
  244. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_002.sh +0 -9
  245. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_003.sh +0 -17
  246. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_004.sh +0 -16
  247. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_005.sh +0 -6
  248. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_006.sh +0 -13
  249. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_007.sh +0 -8
  250. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_008.sh +0 -13
  251. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_009.sh +0 -11
  252. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_010.sh +0 -19
  253. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_011.sh +0 -16
  254. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_012.sh +0 -19
  255. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_013.sh +0 -17
  256. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_014.sh +0 -7
  257. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_015.sh +0 -6
  258. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_016.sh +0 -20
  259. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/instrumented_guard_run.py +0 -108
  260. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/instrumented_plane_wave_nan.py +0 -71
  261. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/j_wires_in_wall.py +0 -27
  262. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/origin_checks.py +0 -76
  263. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/origin_das.py +0 -95
  264. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/quick_checks.py +0 -52
  265. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/scan_checks.py +0 -140
  266. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/scan_checks_2.py +0 -133
  267. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/scan_checks_3.py +0 -110
  268. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/scan_checks_4.py +0 -74
  269. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/toy_plane_wave.py +0 -161
  270. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1241_check_that_the_records_load.py +0 -58
  271. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1241_locate_the_non_finite_values_of_an_analysis.py +0 -43
  272. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1241_measure_the_wire_depth_against_the_time_origin.py +0 -61
  273. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1241_print_the_time_origin_scans.py +0 -48
  274. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1241_test_the_entropy_the_antisymmetry_and_the_filter_linearity.py +0 -88
  275. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1247_time_the_phase_reversal_per_patch_against_batched.py +0 -92
  276. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1248_compare_the_synthesis_on_the_card_and_the_host.py +0 -61
  277. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1250_save_and_compare_the_local_laws_of_a_subset.py +0 -113
  278. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1254_analyze_the_2.5mhz_stage_2.sh +0 -58
  279. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1256_print_the_per_depth_curves_of_a_reverberation_test.py +0 -48
  280. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1302_print_the_durations_of_a_chain_log.py +0 -43
  281. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1314_print_the_gouy_points_of_a_speed_of_sound_scan.py +0 -49
  282. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1445_fit_the_moveout_speed_of_the_point_sources.py +0 -307
  283. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1456_fit_the_depth_offset_of_the_reference_arrivals.py +0 -224
  284. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1502_print_the_laws_and_gates_of_an_analysis.py +0 -56
  285. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1503_analyze_with_the_ramp_removal_off_or_every_law_one.py +0 -144
  286. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1504_measure_the_anti_diagonal_share_of_the_clean_clutter.py +0 -203
  287. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1508_estimate_the_speed_with_smaller_windows.py +0 -138
  288. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1553_focus_the_clutter_records_in_sub_bands.py +0 -142
  289. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1553_print_the_band_and_the_screens_of_the_records.py +0 -87
  290. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1554_predict_the_phase_speed_of_the_stencil.py +0 -168
  291. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1556_compute_the_moveout_truth_with_an_eikonal_solver.py +0 -502
  292. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1556_fit_the_height_offset_on_three_grids.py +0 -252
  293. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1600_measure_the_flat_and_the_screen_correction_on_point_targets.py +0 -490
  294. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1604_predict_the_arrivals_from_the_stencil.py +0 -236
  295. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1604_prototype_the_broadband_correction.py +0 -508
  296. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1605_scan_the_time_origin_with_other_element_planes.py +0 -198
  297. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1607_measure_the_local_far_field_structure_of_the_clutter.py +0 -393
  298. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1608_score_the_speed_scans_against_the_eikonal_truth.py +0 -245
  299. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1610_compare_the_unwrapped_law_delays_with_the_truth.py +0 -186
  300. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1611_compare_the_arrival_models_at_the_point_sources.py +0 -364
  301. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1613_compare_the_sensor_pixel_with_the_element_center.py +0 -117
  302. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1613_measure_the_order_of_the_clutter_from_the_contrast_scaling.py +0 -365
  303. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1613_scan_the_speed_of_sound_at_one_time_origin.py +0 -167
  304. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1615_locate_the_source_and_sensor_pixels_of_the_array.py +0 -167
  305. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1617_check_the_data_level_correction_and_the_pulse_band.py +0 -340
  306. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1617_test_local_and_notch_filters_on_the_clutter.py +0 -388
  307. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1621_compute_the_moveout_truth_with_a_chosen_arrival_model.py +0 -304
  308. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1622_measure_the_tilt_spread_of_the_wall_interfaces.py +0 -235
  309. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1623_tabulate_the_broadband_correction_runs.py +0 -135
  310. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1626_measure_the_ghost_depths_of_the_plate.py +0 -134
  311. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1626_score_the_product_of_the_transducer_laws.py +0 -150
  312. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1630_test_the_local_filter_with_padded_windows.py +0 -127
  313. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1632_fit_the_time_origin_and_the_speed_of_the_phantom_scans.py +0 -170
  314. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1634_fit_the_reference_speed_at_the_sensor_row.py +0 -106
  315. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1646_split_the_clutter_into_orders_and_predict_its_floor.py +0 -248
  316. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1652_tabulate_the_pulse_band_check.py +0 -42
  317. fullwave25-1.4.2.dev4/.claude/scratch/20260910_1659_check_the_plane_wave_transform_of_the_elements.py +0 -69
  318. fullwave25-1.4.2.dev4/.claude/scratch/20260916_1103_compare_two_b_mode_roots.py +0 -38
  319. fullwave25-1.4.2.dev4/.claude/scratch/20260916_1214_binary_cache_lookup_order.py +0 -86
  320. fullwave25-1.4.2.dev4/.claude/scratch/20260916_1253_signal_of_old_against_new.py +0 -74
  321. fullwave25-1.4.2.dev4/.claude/scratch/20260916_1300_read_the_numexpr_pool_limit.py +0 -18
  322. fullwave25-1.4.2.dev4/.claude/scratch/20260916_1332_gpu_memory_of_the_relaxation_kernel.py +0 -72
  323. fullwave25-1.4.2.dev4/.claude/scratch/20260916_1401_relaxation_regions_against_the_kernel.py +0 -65
  324. fullwave25-1.4.2.dev4/.claude/scratch/20260916_1420_released_binary_carries_the_fix.py +0 -37
  325. fullwave25-1.4.2.dev4/.claude/scratch/20260916_1601_stable_courant_number_of_the_stencil_table.py +0 -199
  326. fullwave25-1.4.2.dev4/.claude/scratch/20260916_1602_fast_layer_in_a_small_3d_run.py +0 -162
  327. fullwave25-1.4.2.dev4/.claude/scratch/20260916_1719_p4_1_pulse_energy_above_the_trace_nyquist.py +0 -58
  328. fullwave25-1.4.2.dev4/.claude/scratch/20260916_1933_l7_4_run_at_8_ppw_stability_and_trace_sampling.py +0 -73
  329. fullwave25-1.4.2.dev4/.claude/scratch/20260916_1946_l7_4_trace_sampling_by_field_modulus.py +0 -70
  330. fullwave25-1.4.2.dev4/.claude/scratch/20260916_2004_pulse_bands_of_the_two_abdomen_arrays.py +0 -79
  331. fullwave25-1.4.2.dev4/.claude/scratch/20260916_2155_cuda_version_choice_before_and_after.py +0 -90
  332. fullwave25-1.4.2.dev4/.claude/scratch/20260916_2155_gpu_architectures_in_cached_binaries.py +0 -64
  333. fullwave25-1.4.2.dev4/.claude/scratch/20260916_2155_mutation_check_of_the_cuda_version_tests.py +0 -82
  334. fullwave25-1.4.2.dev4/.claude/scratch/20260916_2155_verify_the_cuda_version_test_findings.py +0 -89
  335. fullwave25-1.4.2.dev4/.claude/scratch/20260916_2212_mutation_check_of_the_blackwell_version_choice.py +0 -111
  336. fullwave25-1.4.2.dev4/.claude/scratch/20260925_1321_selected_cuda_tag.py +0 -7
  337. fullwave25-1.4.2.dev4/.claude/scratch/20260925_1326_release_binary_bit_identity.py +0 -459
  338. fullwave25-1.4.2.dev4/.claude/scratch/20260925_1331_summarize_release_check.py +0 -18
  339. fullwave25-1.4.2.dev4/.claude/settings.local.json +0 -20
  340. fullwave25-1.4.2.dev4/.claude/skills/fullwave25/SKILL.md +0 -119
  341. fullwave25-1.4.2.dev4/.claude/three_dimensional/convex_transducer_3d.py +0 -127
  342. fullwave25-1.4.2.dev4/.claude/three_dimensional/linear_transducer_3d.py +0 -140
  343. fullwave25-1.4.2.dev4/.claude/three_dimensional/matrix_transducer_3d.py +0 -135
  344. fullwave25-1.4.2.dev4/.claude/three_dimensional/patch.py +0 -523
  345. fullwave25-1.4.2.dev4/.claude/three_dimensional/ruff.toml +0 -40
  346. fullwave25-1.4.2.dev4/.claude/three_dimensional/superseded/convex_transducer_3d.py +0 -126
  347. fullwave25-1.4.2.dev4/.claude/three_dimensional/superseded/linear_transducer_3d.py +0 -138
  348. fullwave25-1.4.2.dev4/.claude/three_dimensional/superseded/matrix_transducer_3d.py +0 -134
  349. fullwave25-1.4.2.dev4/.claude/three_dimensional/test_patch.py +0 -178
  350. fullwave25-1.4.2.dev4/.claude/transducer_stack/README.md +0 -70
  351. fullwave25-1.4.2.dev4/.claude/transducer_stack/superseded/full_synthetic_aperture_with_stack.py +0 -438
  352. fullwave25-1.4.2.dev4/.claude/transducer_stack/superseded/plane_wave_compounding_with_stack.py +0 -433
  353. fullwave25-1.4.2.dev4/CONTRIBUTING.md +0 -24
  354. fullwave25-1.4.2.dev4/PKG-INFO +0 -514
  355. fullwave25-1.4.2.dev4/README.md +0 -473
  356. fullwave25-1.4.2.dev4/fullwave/beamformer/__init__.py +0 -5
  357. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/.pre-commit-config.yaml +0 -0
  358. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/.python-version +0 -0
  359. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/20260120_0844.log +0 -0
  360. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/CITATION.cff +0 -0
  361. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/LICENSE +0 -0
  362. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/Makefile +0 -0
  363. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/attenuation.png +0 -0
  364. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/beamformer.m +0 -0
  365. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/debug_solver_bin/fullwave2_2d_2_relax_multi_gpu_cuda124 +0 -0
  366. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/debug_solver_bin/fullwave2_2d_exponential_attenuation_multi_gpu +0 -0
  367. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/debug_solver_bin/fullwave2_2d_exponential_attenuation_multi_gpu_cuda124 +0 -0
  368. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/debug_solver_bin/fullwave2_2d_exponential_attenuation_multi_gpu_cuda124_ +0 -0
  369. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/debug_solver_bin/fullwave2_3d_exponential_attenuation_multi_gpu_cuda124 +0 -0
  370. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/debug_solver_bin/fullwave2_3d_exponential_attenuation_multi_gpu_cuda124_ +0 -0
  371. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/docker/Dockerfile +0 -0
  372. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/docker/Dockerfile.dockerignore +0 -0
  373. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/docker/README.md +0 -0
  374. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/experiments/__init__.py +0 -0
  375. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/experiments/exp_scatterer_diameter.py +0 -0
  376. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/beamformer/beamformer.py +0 -0
  377. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/constants/__init__.py +0 -0
  378. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/constants/material_properties.py +0 -0
  379. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/medium_builder/__init__.py +0 -0
  380. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/medium_builder/domain.py +0 -0
  381. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/medium_builder/medium_builder.py +0 -0
  382. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/medium_builder/presets/data/.keep +0 -0
  383. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/medium_builder/presets/data/abdominal_wall/i2365f_etfw1.mat +0 -0
  384. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/medium_builder/presets/domain_abdominal_wall.py +0 -0
  385. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/medium_builder/presets/domain_background.py +0 -0
  386. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/medium_builder/presets/domain_scatterer.py +0 -0
  387. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/medium_builder/presets/domain_simple.py +0 -0
  388. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/medium_builder/presets/domain_water_gel.py +0 -0
  389. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/sensor.py +0 -0
  390. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/__init__.py +0 -0
  391. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda118 +0 -0
  392. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda124 +0 -0
  393. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda129 +0 -0
  394. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda130 +0 -0
  395. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda118 +0 -0
  396. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda124 +0 -0
  397. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda129 +0 -0
  398. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda130 +0 -0
  399. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/bins/database/relaxation_params_database_num_relax=3_20260828_1513.mat +0 -0
  400. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/bins/database/relaxation_params_database_num_relax=3_20260828_1513_invalid_cells.json +0 -0
  401. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/bins/database/relaxation_params_database_num_relax=4_20260828_1456.mat +0 -0
  402. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/bins/database/relaxation_params_database_num_relax=4_20260828_1456_invalid_cells.json +0 -0
  403. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/cuda_utils.py +0 -0
  404. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/launcher.py +0 -0
  405. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/solver/utils.py +0 -0
  406. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/transmit.py +0 -0
  407. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/ultra/__init__.py +0 -0
  408. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/ultra/attenuation_parameters.py +0 -0
  409. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/ultra/dat_io_3d.py +0 -0
  410. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/ultra/errors.py +0 -0
  411. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/ultra/factory.py +0 -0
  412. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/ultra/medium_to_aexp.py +0 -0
  413. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/ultra/stencil.py +0 -0
  414. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/ultra/time_axis.py +0 -0
  415. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/utils/__init__.py +0 -0
  416. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/utils/check_functions.py +0 -0
  417. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/utils/coordinates.py +0 -0
  418. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/utils/gpu_memory.py +0 -0
  419. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/utils/memory_tempfile.py +0 -0
  420. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/utils/numerical.py +0 -0
  421. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/utils/pulse.py +0 -0
  422. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/utils/scatterer.py +0 -0
  423. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/utils/signal_filter.py +0 -0
  424. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/fullwave/utils/signal_process.py +0 -0
  425. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/logs/20260815_0356_sweep.log +0 -0
  426. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/ruff.log +0 -0
  427. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/ruff.toml +0 -0
  428. {fullwave25-1.4.2.dev4 → fullwave25-1.5.0.dev0}/signal_filter_example.png +0 -0
@@ -1,5 +1,5 @@
1
1
  [tool.bumpversion]
2
- current_version = "1.4.2-dev4"
2
+ current_version = "1.5.0-dev0"
3
3
  parse = """(?x)
4
4
  (?P<major>0|[1-9]\\d*)\\.
5
5
  (?P<minor>0|[1-9]\\d*)\\.
@@ -26,7 +26,7 @@ tag_message = "Bump version: {current_version} → {new_version}"
26
26
 
27
27
  pre_commit_hooks = [
28
28
  "uv lock",
29
- "git add uv.lock .bumpversion.toml fullwave/__init__.py pyproject.toml",
29
+ "git add uv.lock .bumpversion.toml fullwave/__init__.py pyproject.toml examples",
30
30
  ]
31
31
 
32
32
  [[tool.bumpversion.files]]
@@ -41,6 +41,19 @@ filename = "fullwave/__init__.py"
41
41
  search = '__version__ = "{current_version}"'
42
42
  replace = '__version__ = "{new_version}"'
43
43
 
44
+ [[tool.bumpversion.files]]
45
+ # Colab install cell of the example notebooks
46
+ glob = "examples/**/*.ipynb"
47
+ search = 'fullwave25=={current_version}'
48
+ replace = 'fullwave25=={new_version}'
49
+ ignore_missing_version = true
50
+
51
+ [[tool.bumpversion.files]]
52
+ glob = "examples/**/*.ipynb"
53
+ search = 'fullwave25[mach]=={current_version}'
54
+ replace = 'fullwave25[mach]=={new_version}'
55
+ ignore_missing_version = true
56
+
44
57
  [tool.bumpversion.parts.pre_l]
45
58
  values = ["dev", "rc", "final"]
46
59
  optional_value = "final"
@@ -12,3 +12,4 @@ wheels/
12
12
  temp/*
13
13
  outputs
14
14
  .env
15
+ .claude/*
@@ -0,0 +1,28 @@
1
+ # Contributing to Fullwave 2.5
2
+
3
+ Thank you for your interest in contributing to Fullwave 2.5.
4
+
5
+ ## Branches and pull requests
6
+
7
+ - Create a branch named `TYPE/BRANCH_NAME`. `TYPE` is one of `feature`, `bugfix`, `hotfix`, `docs`, `refactor`, `release`, `test` or `experiment`; `BRANCH_NAME` says what the branch does.
8
+ - Base the branch on `develop` and keep it up to date with `develop`.
9
+ - Open the pull request against `develop`. After review, `develop` is merged into `main` for a release.
10
+ - Write clear, concise commit messages.
11
+
12
+ ## Code
13
+
14
+ - Add tests for new features and bug fixes.
15
+ - Install the pre-commit hooks; `make install` does this for you:
16
+
17
+ ```sh
18
+ pre-commit install
19
+ ```
20
+
21
+ - [Ruff](https://docs.astral.sh/ruff/) checks and formats the code before each commit. If a rule gets in the way, say so in your pull request.
22
+
23
+ ## New to the tools?
24
+
25
+ - [Visual Studio Code documentation](https://code.visualstudio.com/docs) and [source control in VS Code](https://code.visualstudio.com/docs/sourcecontrol/overview)
26
+ - [Git tutorial (W3Schools)](https://www.w3schools.com/git/default.asp)
27
+ - [uv documentation](https://docs.astral.sh/uv/)
28
+ - [Connecting to GitHub with SSH](https://docs.github.com/en/authentication/connecting-to-github-with-ssh)
@@ -0,0 +1,350 @@
1
+ Metadata-Version: 2.5
2
+ Name: fullwave25
3
+ Version: 1.5.0-dev0
4
+ Summary: Fullwave 2.5: Ultrasound wave propagation simulation with heterogeneous power law attenuation modelling capabilities
5
+ Author: Masashi Sode, Gianmarco Pinton
6
+ Maintainer: Masashi Sode
7
+ License-File: LICENSE
8
+ Keywords: fdtd,finite-difference,simulation,ultrasound
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Topic :: Scientific/Engineering :: Physics
15
+ Requires-Python: >=3.10
16
+ Requires-Dist: cupy-cuda12x>=13.6.0
17
+ Requires-Dist: matplotlib>=3.10.7
18
+ Requires-Dist: numba>=0.63.1
19
+ Requires-Dist: numexpr>=2.14.1
20
+ Requires-Dist: numpy>=2.0.0
21
+ Requires-Dist: opencv-python-headless>=4.12.0.88
22
+ Requires-Dist: pillow>=12.3.0
23
+ Requires-Dist: scipy>=1.13.1
24
+ Requires-Dist: tomli>=2.3.0
25
+ Requires-Dist: tqdm>=4.67.1
26
+ Provides-Extra: dev
27
+ Requires-Dist: line-profiler>=5.0.1; extra == 'dev'
28
+ Requires-Dist: pre-commit==4.6.2; extra == 'dev'
29
+ Requires-Dist: pytest>=8.3.5; extra == 'dev'
30
+ Requires-Dist: ruff>=0.12.9; extra == 'dev'
31
+ Provides-Extra: examples
32
+ Requires-Dist: cupy-cuda12x>=13.6.0; extra == 'examples'
33
+ Requires-Dist: ipykernel>=6.28.0; extra == 'examples'
34
+ Requires-Dist: jupyter>=1.0.0; extra == 'examples'
35
+ Requires-Dist: mach-beamform>=0.0.4; extra == 'examples'
36
+ Requires-Dist: pymust>=0.1.8; extra == 'examples'
37
+ Provides-Extra: mach
38
+ Requires-Dist: cupy-cuda12x>=13.6.0; extra == 'mach'
39
+ Requires-Dist: mach-beamform>=0.0.4; extra == 'mach'
40
+ Requires-Dist: pymust>=0.1.8; extra == 'mach'
41
+ Provides-Extra: test
42
+ Requires-Dist: pytest; extra == 'test'
43
+ Requires-Dist: tomli>=2.3.0; extra == 'test'
44
+ Description-Content-Type: text/markdown
45
+
46
+ # Fullwave 2.5
47
+
48
+ **Ultrasound wave propagation simulation with heterogeneous power-law attenuation**
49
+
50
+ <a href="https://doi.org/10.5281/zenodo.17625780"><img src="https://zenodo.org/badge/DOI/10.5281/zenodo.17625780.svg" alt="DOI"></a>
51
+ <a href="https://pypi.org/project/fullwave25/"><img src="https://img.shields.io/pypi/v/fullwave25" alt="PyPI version"></a>
52
+ <a href="https://pepy.tech/projects/fullwave25"><img src="https://static.pepy.tech/personalized-badge/fullwave25?period=total&units=INTERNATIONAL_SYSTEM&left_color=GREY&right_color=BLUE&left_text=PyPI+Downloads" alt="PyPI Downloads"></a>
53
+ <a href="LICENSE"><img src="https://img.shields.io/github/license/pinton-lab/fullwave25" alt="License"></a>
54
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/pinton-lab/fullwave25/blob/main/examples/simple_plane_wave/example_simple_plane_wave.ipynb)
55
+
56
+ Fullwave 2.5 simulates nonlinear ultrasound propagation in tissue whose attenuation follows a power law $\alpha_0 f^\gamma$ **with a coefficient $\alpha_0$ and an exponent $\gamma$ that can differ in every grid cell**, together with the dispersion that the Kramers-Kronig relations give for each cell. It runs 2D and 3D simulations on multiple GPUs from a Python interface.
57
+
58
+ <p align="center">
59
+ <img src="figs/l7_4_abdomen_3d.gif" width="360" alt="3D simulation of a focused L7-4 transmit through an abdominal wall"/>
60
+ </p>
61
+ <p align="center"><em>3D simulation of a focused transmit from an L7-4 linear array through an abdominal wall. L7-4 CAD model: <a href="https://grabcad.com/library/ultrasound-probes-1">Ultrasound probes</a> by Amirhasan Qadamian (GrabCAD).</em></p>
62
+
63
+ | Medium: abdominal wall and liver (2D) | Focused transmit from an L7-4 array |
64
+ | ---------------------------------------- | -------------------------------------------------------------------------- |
65
+ | <img src="figs/medium.png" width="300"/> | <img src="figs/linear_transducer_focused_abdominal_wall.gif" width="200"/> |
66
+
67
+ ## Highlights
68
+
69
+ - **Heterogeneous power-law attenuation.** Multiple relaxation processes give the attenuation and the dispersion of $\alpha_0 f^\gamma$ for a map of $\alpha_0$ and a map of $\gamma$.
70
+ - **High-order FDTD.** Staggered-grid pressure-velocity scheme, 8th order in space and 4th order in time, with a relaxing perfectly matched layer.
71
+ - **2D and 3D, multi-GPU.** The 3D domain is split along depth across GPUs.
72
+ - **Transducers ready to use.** L7-4 linear, C5-2V curved and P4-1C phased arrays, or any geometry, with plane wave, focused, diverging and synthetic aperture transmits.
73
+ - **Transmit batches.** Several transmits on one medium run in one simulation.
74
+ - **Beamforming.** A delay-and-sum `Beamformer` on the CPU, and `MachBeamformer` on the GPU, built on [mach](https://github.com/Forest-Neurotech/mach).
75
+ - **Familiar interface.** The workflow follows [k-Wave](http://www.k-wave.org/) and [k-wave-python](https://github.com/waltsims/k-wave-python).
76
+
77
+ ## Attenuation model
78
+
79
+ The solver advances the pressure $p$ and the particle velocity $\mathbf{v}$ with
80
+
81
+ $$\nabla_1 p + \rho \cfrac{\partial {\bf{v}}}{\partial t} = 0, \qquad \nabla_2 \cdot {\bf{v}} + \kappa \cfrac{\partial p}{\partial t} = 0 .$$
82
+
83
+ in which the spatial derivatives $\nabla_1$ and $\nabla_2$ carry a set of relaxation mechanisms. fullwave25 looks up the parameters of these mechanisms in a precomputed table for the $\alpha_0$ and $\gamma$ of each cell, so that the simulated attenuation matches the power law and the phase velocity matches its Kramers-Kronig dispersion. The table spans $\alpha_0$ up to 1.0 dB/(MHz^γ cm) and $\gamma$ from 0.4 to 2.0, for frequencies from 0.1 to 20 MHz. It extends to $\alpha_0$ = 2.0 dB/(MHz^γ cm) for $\gamma$ from 0.4 to 1.6, and to $\alpha_0$ = 10 dB/(MHz^γ cm) for $\gamma$ = 1.0. A specified pair on a cell the table does not fit logs a warning.
84
+
85
+ The figure compares the target attenuation $\alpha_0 f^\gamma$ (red lines) with the simulated attenuation (black dots) for $\alpha_0 =$ 0.25, 0.5 and 0.75 dB/(MHz^γ cm) and $\gamma =$ 0.4, 0.7, 1.0, 1.3 and 1.6. Each dot is one simulation of a plane wave through a uniform medium, read at two depths.
86
+
87
+ ![Simulated against target power-law attenuation](./figs/attenuation_modeling.svg)
88
+
89
+ [attenuation_dispersion.py](examples/attenuation_dispersion/attenuation_dispersion.py) makes these measurements, so you can check the model for your own parameters.
90
+
91
+ ## Installation
92
+
93
+ Requirements: Linux (on Windows, use [WSL2](https://learn.microsoft.com/en-us/windows/wsl/install)) and an NVIDIA GPU. A 3D simulation can need several GPUs.
94
+
95
+ ```sh
96
+ pip install fullwave25
97
+ pip install "fullwave25[mach]" # optional: MachBeamformer (mach-beamform, pymust, cupy)
98
+ ```
99
+
100
+ The released solver binaries need glibc 2.34 or newer (for example Ubuntu 22.04). On an older system, use the container in [docker/README.md](docker/README.md).
101
+
102
+ The plotting functions write videos with `ffmpeg` and OpenCV (`cv2`). If they are missing, install them with your package manager:
103
+
104
+ ```sh
105
+ sudo apt install ffmpeg python3-opencv # Ubuntu/Debian; or: pip install opencv-python
106
+ ```
107
+
108
+ ### Development installation
109
+
110
+ We use [uv](https://docs.astral.sh/uv/) to manage the environment.
111
+
112
+ ```sh
113
+ curl -LsSf https://astral.sh/uv/install.sh | sh # if uv is not installed
114
+ git clone git@github.com:pinton-lab/fullwave25.git
115
+ cd fullwave25
116
+ make install-all-extras # core library, examples and development tools
117
+ make test
118
+ ```
119
+
120
+ ## Quick start
121
+
122
+ Start with the notebook [example_simple_plane_wave.ipynb](examples/simple_plane_wave/example_simple_plane_wave.ipynb), or run it in Google Colab without a local GPU: [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/pinton-lab/fullwave25/blob/main/examples/simple_plane_wave/example_simple_plane_wave.ipynb)
123
+
124
+ A simulation has five steps:
125
+
126
+ 1. Define the computational grid (`fullwave.Grid`).
127
+ 2. Define the acoustic medium (`fullwave.Medium`): sound speed, density, attenuation coefficient and exponent, nonlinearity.
128
+ 3. Define the source (`fullwave.Source`) or a transducer (`fullwave.Transducer`).
129
+ 4. Define the sensor (`fullwave.Sensor`).
130
+ 5. Run the solver (`fullwave.Solver`).
131
+
132
+ To start your own simulation, copy [simple_plane_wave.py](examples/simple_plane_wave/simple_plane_wave.py) (2D) or [simple_plane_wave_3d.py](examples/wave_3d/simple_plane_wave_3d.py) (3D) and change it.
133
+
134
+ ### Simulation guide
135
+
136
+ [docs/claude_skill/fullwave25/SKILL.md](docs/claude_skill/fullwave25/SKILL.md) is a short guide to setting up a simulation the standard way. It covers:
137
+
138
+ - the basic flow, the output shapes and the sensor order;
139
+ - scatterers, air and the discretized attenuation values;
140
+ - grid resolution, duration, the size of the record and running in memory;
141
+ - transducers, presets and beamforming;
142
+ - multi-GPU runs, the container and troubleshooting.
143
+
144
+ Read it before writing a new simulation. The same file is a [Claude Code](https://docs.anthropic.com/en/docs/claude-code) skill: to use it in Claude Code, copy the folder `docs/claude_skill/fullwave25/` to `~/.claude/skills/fullwave25/`.
145
+
146
+ ## Transducers and transmits
147
+
148
+ A named array places itself on the grid, and one call sets the transmit.
149
+
150
+ ```python
151
+ grid = fullwave.Grid(domain_size=(4.5e-2, 4.5e-2), f0=5.208e6, duration=6.7e-5, c0=1540)
152
+
153
+ transducer = fullwave.Transducer.l7_4(grid)
154
+ transducer.plane_wave(angle_deg=2.5)
155
+ maps = transducer.fill_probe_above_face(
156
+ sound_speed=sound_speed_map, density=density_map, alpha_coeff=alpha_coeff_map, alpha_power=alpha_power_map,
157
+ )
158
+ medium = fullwave.Medium(grid, beta=beta_map, **maps)
159
+
160
+ solver = fullwave.Solver(work_dir="./outputs/my_run", grid=grid, medium=medium, transducer=transducer)
161
+ sensor_output = solver.run() # [n_elements, n_t]
162
+ ```
163
+
164
+ | Array | Type | Elements | Aperture | Center frequency |
165
+ | ------- | ------------- | -------- | ------------------------------- | ---------------- |
166
+ | `l7_4` | linear | 128 | 38.09 mm | 5.208 MHz |
167
+ | `p4_1c` | linear phased | 64 | 27 mm | `grid.f0` |
168
+ | `c5_2v` | curved | 128 | 0.508 mm pitch, 49.57 mm radius | 3.7 MHz |
169
+
170
+ `fullwave.TransducerGeometry` builds any other array. The transmits are `plane_wave(angle_deg=...)`, `focus(focus_m=...)`, `diverging(virtual_source_m=...)` and `synthetic_aperture(element)`; each takes `apodization` and `pulse`. To transmit with part of the aperture, set `transducer.active_source_elements` first.
171
+
172
+ ### Linear array layout
173
+
174
+ The linear arrays (`l7_4`, `p4_1c` and `LinearTransducer`) share one layout, from the top of the grid:
175
+
176
+ | Rows | Content |
177
+ | ----------------------------- | ----------------------------------------------------------------------------------------- |
178
+ | from row 0 | source: one wavelength of rows (at least 8), with the absorbing layer directly behind it |
179
+ | next row | receiver |
180
+ | `transducer.face_row_px` | probe face, depth 0 (`transducer.face_depth_m`): the medium starts here |
181
+
182
+ The array is centered laterally, so make the grid wider than the array (for example 45 mm for the 38.09 mm L7-4). `transducer.fill_probe_above_face(...)` sets the rows above the face to a probe fill (1540 m/s, 1000 kg/m³, 0.005 dB/(MHz cm), power 1.0) across the array and to water beside it, without scatterers. Pass its result to `fullwave.Medium`, or register `transducer.probe_fill_domain()` last in a `MediumBuilder`.
183
+
184
+ `Transducer.l7_4` gives every gap between two elements exactly one pixel (`kerf_px=1`) and holds those kerf pixels at zero pressure after the drive (`hold_kerf=True`); `kerf_px=None, hold_kerf=False` gives an array without held kerfs. A held kerf needs `source_type="hard"`.
185
+
186
+ Start the tissue at the face (for an `AbdominalWallDomain`, pass `start_depth=transducer.face_depth_m`) and measure target and focus depths from it. The curved `c5_2v` keeps its own layout; `transducer.make_surface_reflective_with_air()` returns the air behind it. `transducer.apply_transducer_stack(...)` paints a backing, a matching layer, a lens and a standoff (`fullwave.TransducerStack`) onto the medium maps before the `Medium` is built.
187
+
188
+ ### Source types
189
+
190
+ | `source_type` | Behavior |
191
+ | ----------------------- | ---------------------------------------------------------------------------------------------------------- |
192
+ | `"hard"` (named arrays) | assigns the source pressure for the whole run; after the drive ends the source cells stay at 0 Pa, so the face reflects |
193
+ | `"hard_released_after"` | assigns the source pressure while the drive plays; then the source cells evolve freely |
194
+ | `"soft"` | adds the signal to the field |
195
+
196
+ Pass `source_type=` to `Transducer.l7_4`, `c5_2v`, `p4_1c` or `fullwave.Solver`.
197
+
198
+ ### Transmit batches
199
+
200
+ A transmit sequence on one medium, such as plane wave angles, focused lines or synthetic aperture elements, can run as a batch: several transmits in one simulation, which is faster than one `run` per transmit. The transmits of a batch share the medium, the sensor and the source positions, and differ only in their signals; the transmits of one transducer satisfy this.
201
+
202
+ ```python
203
+ sources = []
204
+ for angle in (-10, -5, 0, 5, 10):
205
+ transducer.plane_wave(angle_deg=angle)
206
+ sources.append(transducer.source)
207
+
208
+ sensor_output = solver.run_batch(sources) # [n_transmits, n_sensors, n_t]
209
+ ```
210
+
211
+ `run_batch` puts at most `max_members_per_run` transmits in one simulation: 32 by default, or fewer when the estimated GPU memory does not fit. A longer sequence runs as several simulations of nearly equal size, so 128 transmits run as 4 simulations of 32. In a 2D L7-4 test the time per transmit stopped falling at 16 to 32 transmits per simulation.
212
+
213
+ ### Beamforming
214
+
215
+ | Beamformer | Runs on | Purpose |
216
+ | ---------------------------------------- | ------- | ------------------------------------------------------------- |
217
+ | `fullwave.beamformer.Beamformer` | CPU | delay-and-sum for linear arrays, for teaching; not optimized for speed |
218
+ | `fullwave.beamformer.MachBeamformer` | GPU | fast delay-and-sum with [mach](https://github.com/Forest-Neurotech/mach) |
219
+
220
+ mach is an open-source GPU beamformer with an optimized delay-and-sum CUDA kernel: 1.1 trillion points per second on a consumer GPU, more than 10 times faster than other open-source GPU beamformers. `pip install "fullwave25[mach]"` installs mach-beamform, pymust and cupy; mach needs Linux and an NVIDIA driver for CUDA 12.8 or newer.
221
+
222
+ ```python
223
+ beamformer = MachBeamformer.from_transducer(
224
+ transducer, lateral_position_m=lateral_m, axial_position_m=depth_m, f_number=1.0,
225
+ )
226
+ arrival_s = [beamformer.plane_wave_arrival_s(angle_deg=a) for a in angles]
227
+ image = beamformer.beamform(np.stack(traces), tx_arrival_s=np.stack(arrival_s)) # complex [n_depth, n_lateral]
228
+ ```
229
+
230
+ `MachBeamformer` converts the traces to IQ with `pymust.rf2iq` and measures depth from the probe face. `traces` holds one `[n_elements, n_t]` array per transmit (from `post_process_sensor_output`). `focused_arrival_s(focus_m=...)` and `synthetic_aperture_arrival_s(element=...)` give the other transmits. Time zero follows from the drive and the rows between the source and the face, so it holds for every transmit of the named linear arrays. `f_number` is depth / aperture width; `Beamformer` takes the half width as depth / F, so pass `f_number / 2` to it for the same aperture. If you use `MachBeamformer`, please also cite mach (see [Citation](#citation)).
231
+
232
+ ### Imaging a phantom
233
+
234
+ `fullwave.presets.CombinedPhantomDomain` builds an imaging phantom: point targets in a column and in rows, and hypoechoic and hyperechoic cylinders, on a scattering background. [plane_wave_phantom.py](examples/linear_transducer/plane_wave_phantom.py) sends one plane wave from an L7-4 array at 5.208 MHz through it and beamforms the echoes into a B-mode with `MachBeamformer`.
235
+
236
+ | Plane wave through the phantom | B-mode, one plane wave (0 to −40 dB) |
237
+ | ------------------------------------------------------ | ------------------------------------------------------------- |
238
+ | <img src="figs/plane_wave_phantom.gif" width="200"/> | <img src="figs/plane_wave_phantom_b_mode.png" width="360"/> |
239
+
240
+ ## Examples
241
+
242
+ | Task | Example | Notebook / Colab |
243
+ | --- | --- | --- |
244
+ | 2D plane wave from a source built by hand, through an inclusion | [simple_plane_wave.py](examples/simple_plane_wave/simple_plane_wave.py) | [notebook](examples/simple_plane_wave/example_simple_plane_wave.ipynb), [![Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/pinton-lab/fullwave25/blob/main/examples/simple_plane_wave/example_simple_plane_wave.ipynb) |
245
+ | 2D plane wave through an inclusion with scattered air cells | [simple_plane_wave_air.py](examples/simple_plane_wave/simple_plane_wave_air.py) | [notebook](examples/simple_plane_wave/example_simple_plane_wave_air.ipynb), [![Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/pinton-lab/fullwave25/blob/main/examples/simple_plane_wave/example_simple_plane_wave_air.ipynb) |
246
+ | Attenuation and phase velocity of a uniform medium against the power law | [attenuation_dispersion.py](examples/attenuation_dispersion/attenuation_dispersion.py) | |
247
+ | Layered medium built with `MediumBuilder` | [medium_builder_example.py](examples/medium_builder/medium_builder_example.py) | [notebook](examples/medium_builder/medium_builder_example.ipynb), [![Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/pinton-lab/fullwave25/blob/main/examples/medium_builder/medium_builder_example.ipynb) |
248
+ | Abdominal wall built with `MediumBuilder` | [medium_builder_abdominal_example.py](examples/medium_builder/medium_builder_abdominal_example.py) | |
249
+ | L7-4 linear array: focused transmit through an abdominal wall | [linear_transducer_abdominal_wall.py](examples/linear_transducer/linear_transducer_abdominal_wall.py) | |
250
+ | L7-4 linear array: plane wave compounding B-mode | [plane_wave_compounding.py](examples/linear_transducer/plane_wave_compounding.py) | [notebook](examples/linear_transducer/plane_wave_compounding.ipynb), [![Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/pinton-lab/fullwave25/blob/main/examples/linear_transducer/plane_wave_compounding.ipynb) |
251
+ | L7-4 linear array: plane wave movie and B-mode of an imaging phantom | [plane_wave_phantom.py](examples/linear_transducer/plane_wave_phantom.py) | |
252
+ | L7-4 linear array: plane wave compounding B-mode, all angles in one transmit batch | [plane_wave_compounding_batch.py](examples/linear_transducer/plane_wave_compounding_batch.py) | |
253
+ | L7-4 linear array: plane waves and focused lines as transmit batches | [transmit_batch_basics.py](examples/transmit_batch/transmit_batch_basics.py) | |
254
+ | L7-4 linear array: full synthetic aperture B-mode | [full_synthetic_aperture.py](examples/linear_transducer/full_synthetic_aperture.py) | [notebook](examples/linear_transducer/full_synthetic_aperture.ipynb), [![Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/pinton-lab/fullwave25/blob/main/examples/linear_transducer/full_synthetic_aperture.ipynb) |
255
+ | L7-4 linear array: high-pass filter on the recorded traces | [plane_wave_with_filter.py](examples/signal_filter/plane_wave_with_filter.py) | |
256
+ | P4-1C phased array: focused transmit from half the aperture, with a movie of the field | [linear_transducer_focused_animation.py](examples/linear_transducer/linear_transducer_focused_animation.py) | |
257
+ | C5-2V curved array: full synthetic aperture acquisition | [convex_transducer_fsa.py](examples/convex_transducer/convex_transducer_fsa.py) | |
258
+ | C5-2V curved array: focused transmit through an abdominal wall | [convex_transducer_abdominal_wall.py](examples/convex_transducer/convex_transducer_abdominal_wall.py) | |
259
+ | 3D plane wave through an inclusion | [simple_plane_wave_3d.py](examples/wave_3d/simple_plane_wave_3d.py) | |
260
+ | 3D plane wave through an inclusion with scattered air cells | [simple_plane_wave_3d_with_air.py](examples/wave_3d/simple_plane_wave_3d_with_air.py) | |
261
+
262
+ ### Gallery
263
+
264
+ | Plane wave through an inclusion | P4-1C focused transmit | C5-2V through an abdominal wall |
265
+ | ------------------------------------------------- | ------------------------------------------------------ | --------------------------------------------------------------- |
266
+ | <img src="figs/simple_plane_wave.gif" width="200"/> | <img src="figs/linear_transducer_focused.gif" width="200"/> | <img src="figs/convex_transducer_abdominal_wall.gif" width="200"/> |
267
+
268
+ **3D plane wave through an inclusion, without and with scattered air cells**
269
+
270
+ | | x-y slice | x-z slice |
271
+ | ----------- | ---------------------------------------------------------- | ---------------------------------------------------------- |
272
+ | without air cells | <img src="figs/wave_propagation_x-y.gif" width="200"/> | <img src="figs/wave_propagation_x-z.gif" width="200"/> |
273
+ | with air cells | <img src="figs/wave_propagation_x-y_air.gif" width="200"/> | <img src="figs/wave_propagation_x-z_air.gif" width="200"/> |
274
+
275
+ ## Experimental: fullwave2-ultra backend
276
+
277
+ `Solver(..., use_ultra=True)` runs the simulation with the fullwave2-ultra binary, which is optimized for speed. It is experimental, its API may change, and the binaries are not part of fullwave25. See [docs/fullwave2_ultra.md](docs/fullwave2_ultra.md).
278
+
279
+ ## Notes
280
+
281
+ - **Axis order.** The grid axes are (x, y, z) = (depth, lateral, elevation). The solver splits the domain along depth across GPUs, so depth comes first.
282
+ - **Index order.** Source and sensor coordinates are in C (row-major) order inside the solver, whatever order you use. Check this when you build a source by hand.
283
+ - **GPU memory.** A 3D simulation needs much GPU memory. Reduce the grid or use more GPUs if it does not fit; `nvidia-smi` or `nvtop` shows the use. `Solver.run` estimates the memory before the run (`gpu_memory_estimate=True`, the default).
284
+ - **Multi-GPU.** 2D and 3D runs can use multiple GPUs (`cuda_device_id`); the run time scales linearly with the number of GPUs.
285
+ - **3D.** Start with the 2D version of a simulation. The 3D code is similar, runs longer, and some plot functions are 2D only.
286
+
287
+ ## Citation
288
+
289
+ Fullwave 2.5 is developed and maintained by the [Pinton Lab](https://github.com/pinton-lab) at the University of North Carolina at Chapel Hill. If you use Fullwave 2.5 in your research, please cite:
290
+
291
+ ```bibtex
292
+ @article{Sode2026-heterogeneous-attenuation,
293
+ title = {Spatially heterogeneous power-law attenuation with multiple relaxation mechanisms for ultrasound modeling},
294
+ author = {Sode, Masashi and Pinton, Gianmarco},
295
+ journal = {arXiv preprint arXiv:2606.11103},
296
+ year = {2026},
297
+ eprint = {2606.11103},
298
+ archivePrefix = {arXiv},
299
+ primaryClass = {physics.med-ph},
300
+ url = {https://arxiv.org/abs/2606.11103}
301
+ }
302
+
303
+ @article{Sode2026-fullwave2,
304
+ title = {A fullwave model of the nonlinear wave equation with multiple relaxations and relaxing perfectly matched layers for high-order numerical finite difference solutions},
305
+ author = {Sode, Masashi and Pinton, Gianmarco},
306
+ journal = {Physics in Medicine \& Biology},
307
+ publisher = {IOP Publishing},
308
+ year = {2026},
309
+ doi = {10.1088/1361-6560/ae9116},
310
+ url = {https://doi.org/10.1088/1361-6560/ae9116}
311
+ }
312
+
313
+ @software{Sode2025-fullwave25,
314
+ title = {Fullwave 2.5: Ultrasound wave propagation simulation with heterogeneous power law attenuation modelling capabilities},
315
+ author = {Sode, Masashi and Pinton, Gianmarco},
316
+ year = {2025},
317
+ doi = {10.5281/zenodo.17497689},
318
+ url = {https://github.com/pinton-lab/fullwave25}
319
+ }
320
+ ```
321
+
322
+ If you use `MachBeamformer`, please also cite mach:
323
+
324
+ ```bibtex
325
+ @article{mach,
326
+ title = {mach: ultrafast ultrasound beamforming},
327
+ author = {Guan, Charles and Rockhill, Alexander P and Sode, Masashi and Pinton, Gianmarco},
328
+ year = 2026,
329
+ journal = {Journal of Medical Imaging},
330
+ publisher = {Society of Photo-Optical Instrumentation Engineers},
331
+ volume = 13,
332
+ number = 6,
333
+ pages = {062203--062203},
334
+ doi = {10.1117/1.JMI.13.6.062203},
335
+ url = {https://github.com/Forest-Neurotech/mach}
336
+ }
337
+ ```
338
+
339
+ ## Contributing
340
+
341
+ Contributions are welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md) for the branch names, the pull request flow and the code checks.
342
+
343
+ ## Acknowledgments
344
+
345
+ The design of this repository was inspired by [k-wave-python](https://github.com/waltsims/k-wave-python). We thank the k-wave-python developers; their tools have contributed much to the ultrasound research community.
346
+
347
+ ## Authors
348
+
349
+ - Masashi Sode ([MasashiSode](https://github.com/MasashiSode)), maintainer
350
+ - Gianmarco Pinton ([gfpinton](https://github.com/gfpinton))