fullwave25 1.4.2.dev2__tar.gz → 1.4.2.dev4__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.
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.bumpversion.toml +1 -1
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/PKG-INFO +35 -7
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/README.md +34 -6
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/__init__.py +1 -1
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/beamformer/beamformer.py +23 -5
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/input_file_writer.py +22 -5
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/solver.py +137 -14
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/transducer.py +316 -52
- fullwave25-1.4.2.dev4/fullwave/ultra/attenuation_parameters.py +215 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/ultra/backend.py +85 -5
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/ultra/backend_2d.py +45 -7
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/ultra/binary.py +28 -1
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/ultra/factory.py +4 -1
- fullwave25-1.4.2.dev4/fullwave/ultra/medium_to_aexp.py +167 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/ultra/writer_2d.py +54 -14
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/ultra/writer_3d.py +54 -14
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/utils/relaxation_parameters.py +51 -0
- fullwave25-1.4.2.dev4/fullwave/utils/signal_filter.py +126 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/pyproject.toml +1 -1
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/uv.lock +1 -1
- fullwave25-1.4.2.dev2/fullwave/ultra/medium_to_aexp.py +0 -50
- fullwave25-1.4.2.dev2/fullwave/utils/signal_filter.py +0 -161
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/.gitignore +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/20260911_1813_dead-code.md +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/20260916_1311_commit_message_of_the_input_generation_speedup.md +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/20260916_1311_pull_request_of_the_input_generation_speedup.md +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/20260916_1405_commit_message_of_the_relaxation_memory_estimate.md +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/20260916_1405_pull_request_of_the_relaxation_memory_estimate.md +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/20260916_2152_commit_message_of_the_cuda_version_choice.md +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/20260916_2152_pull_request_of_the_cuda_version_choice.md +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/20260916_2203_commit_message_of_the_cuda_version_tests.md +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/20260916_2213_commit_message_of_the_blackwell_version_choice.md +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/20260916_2213_pull_request_of_the_blackwell_version_choice.md +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/CLAUDE.md +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/matrix_imaging/20260909_1844_acquire_the_reflection_matrix.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/matrix_imaging/20260909_1900_test_on_a_synthetic_acquisition.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/matrix_imaging/20260909_1913_analyze_the_reflection_matrix.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/matrix_imaging/20260909_2107_redraw_the_figures_of_an_analysis.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/matrix_imaging/20260909_2121_write_the_result_tables.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/matrix_imaging/20260910_1126_synthesize_plane_waves_from_the_multistatic_matrix.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/matrix_imaging/20260910_1137_scan_the_speed_of_sound.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/matrix_imaging/20260910_1141_compare_the_laws_with_the_truth.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/matrix_imaging/20260910_1146_evaluate_the_reverberation_filter.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/matrix_imaging/20260910_1208_compare_plane_waves_with_the_synthesis.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/matrix_imaging/figures.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/matrix_imaging/ground_truth.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/matrix_imaging/matrix_imaging.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/matrix_imaging/pipeline.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/matrix_imaging/reflection_matrix.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/matrix_imaging/speed_of_sound.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/matrix_imaging/synthetic.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260821_0206_band_anchor_cross_check.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260821_0233_delivered_power_law_end_to_end.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260821_0317_reword_deliver_in_the_library.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260821_1220_relaxation_low_frequency_rolloff.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260825_1937_what_fails_the_pml_golden_tests.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260825_2329_does_the_wrapper_read_the_record.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260826_0002_what_the_new_default_table_holds.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260828_1422_what_the_candidate_tables_hold.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260828_1427_what_the_deployment_needs.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260828_1510_where_the_unstretched_ramp_reaches.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260828_1517_the_blast_radius_of_the_ramp.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260830_1458_the_3d_region_trimmed_kernel_against_the_reference.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260830_1505_the_multi_node_kernel_against_the_multi_gpu_one.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260830_1631_the_3d_multi_node_against_the_multi_gpu_one.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260830_1642_the_selective_absorbing_layer.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260830_1728_the_layer_against_the_taper.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260830_1757_what_the_margin_outside_the_layer_does.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260830_1808_the_layer_in_3d_and_on_the_multi_node_builds.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260830_1832_where_the_3d_residual_sits.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260830_1837_inside_the_layer_at_the_corner.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260830_1840_inside_the_3d_layer_at_the_corner.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260830_1912_both_absorbers_on_one_method.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260830_1922_the_layer_on_the_reflection_method.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260830_2011_whole_domain_animation.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260830_2032_the_example_source_kind.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260830_2148_drive_scale_of_the_strong_beta_cells.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260830_2159_profile_the_input_map_build.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260830_2201_build_then_extend_equivalence.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260830_2304_the_transmit_methods_launch_what_they_say.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260830_2322_the_unscaled_added_drive_follows_the_courant_number.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_0033_the_three_dimensional_arrays.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_0054_the_elevation_lens_of_a_linear_array.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_0115_run_every_example.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_0124_move_the_notebooks_to_the_transmit_interface.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_0137_the_air_region_at_four_mechanisms.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_0148_the_element_records_its_own_transmit.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_0150_the_absorbing_layer_of_a_point_source.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_0152_the_exponential_absorbing_layer_against_its_thickness.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_0202_the_rebuilt_exponential_absorbing_layer.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_0216_where_the_three_dimensional_layer_leaks.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_0222_the_absorbing_layer_away_from_the_source.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1037_where_the_near_field_brightness_comes_from.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1040_the_aperture_transit_wedge_in_the_channel_data.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1043_the_transmit_in_the_recorded_trace_and_its_removal.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1048_the_receive_row_against_the_reference_subtraction.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1052_the_backing_behind_the_array_face.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1056_the_transmit_beam_with_the_air_backing.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1105_the_shipped_transducer_stack_in_the_solver.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1119_where_the_stack_puts_the_source_and_what_it_costs_the_depth.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1121_the_depth_the_image_reads_with_the_stack.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1123_the_depth_the_beamformer_puts_one_point_at.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1142_the_transmit_offset_the_beamformer_needs.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1145_the_depth_shift_the_offset_fix_makes.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1154_the_two_offset_rules_on_the_same_recording.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1212_what_the_pinned_release_carries.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1228_the_low_cut_against_the_near_field_haze.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1301_run_the_beamforming_notebooks.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1432_point_dataset_generator_at_the_local_fullwave.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1437_the_aperture_width_the_reference_geometry_reports.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1454_calibrate_the_ats539_plane_wave.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1508_show_the_b_mode_in_the_hdf5.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1534_the_comet_behind_each_wire.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1547_read_the_calibration_trials.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1605_what_the_medium_holds_in_the_near_field.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1607_sweep_one_generator_knob.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1715_assert_the_ats539_rate_chain.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1717_measure_every_layer_of_the_stack.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1720_where_the_trailing_energy_lands.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1725_offer_the_requested_absorption_to_the_backing.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1727_let_a_sweep_carry_a_switch.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1731_expose_the_exponential_absorbing_layer.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1746_point_the_solver_at_an_older_binary.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1756_measure_the_point_targets.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1802_rederive_the_near_field_bounce.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1810_does_the_shelf_move_with_depth.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1812_find_the_repeat_delay_in_the_raw_rf.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1937_give_each_source_row_its_own_launch_delay.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1943_baffle_the_element_plane.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_1952_take_the_cell_size_from_the_grid.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_2058_run_the_ats539_through_the_batched_solver.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_2105_queue_the_remaining_candidates.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_2122_the_simulator_asks_for_a_clamped_source.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_2126_rename_the_source_types_to_hard_and_soft.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_2140_bind_the_source_type_to_its_entrance.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_2225_how_redundant_are_the_absorbing_layer_files.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_2239_skip_the_constant_absorbing_layer_maps.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_2246_count_the_files_a_run_writes.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_2352_run_the_map_tiers_end_to_end.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260831_2355_draw_the_absorbing_layer_map_cost.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260901_1502_can_the_transmit_reach_the_harmonic_band.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260901_1504_contrast_harmonic_imaging.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260901_1507_where_each_band_puts_its_largest_sample.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260901_1519_is_the_harmonic_tail_cumulative.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260901_1537_does_the_cancellation_work.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260901_1612_does_a_sparse_bubble_cloud_localize.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260901_1619_calibrate_the_bubble_scatter_range.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260901_1622_draw_the_sweep_b_modes.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260901_1654_where_the_bright_region_sits.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260901_1701_where_one_bubble_images.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260901_1702_does_the_portable_example_reproduce_the_evaluation.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260901_1753_does_the_ported_solver_still_march_the_same.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260901_1755_do_the_ranks_agree_on_the_bubbles.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260901_1817_does_the_air_region_reach_every_solver.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260901_1818_does_the_air_region_reach_every_rank.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260902_1317_what_the_abdomen_volume_holds.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260902_1319_art_wave_in_the_abdomen.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260902_1324_art_figures_from_the_field.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260902_1744_art_final_animations.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260904_1216_art_wire_visibility.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260904_2327_b_mode_of_the_abdomen.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260905_0038_two_against_three_dimensions.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260909_1934_probe_the_reverberation_filter_on_speckle.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260909_1939_probe_the_ideal_profile_on_speckle.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260909_2044_probe_the_correction_bases_on_a_flat_speckle.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260909_2342_measure_the_wall_delay_screen.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1134_find_the_first_non_finite_value_of_the_plane_wave_correction.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1234_print_the_summaries_of_analyses.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/a_maps_checks.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/b_effective_frequency.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/c_composed_steps.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/check_element_centers.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/check_plane_wave_law.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/d2_gate_quarter_period.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/d_gate_cases.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/e_plate_crash.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/f_patch_grid.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/g_frequency_scan.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/gouy_check.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/h_pulse_and_wires.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/i_phase_slope.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a0200910_001.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a0200910_002.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a0200910_003.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a0200910_004.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a0200910_005.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_001.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_002.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_003.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_004.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_005.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_006.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_007.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_008.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_009.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_010.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a3e03828_001.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a3e03828_002.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a3e03828_003.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a3e03828_004.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a3e03828_005.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_001.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_002.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_003.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_004.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_005.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_006.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_007.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_008.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_47c5d913-2f0_a86c7568_001.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_001.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_002.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_003.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_004.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_005.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_006.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_007.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_008.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_009.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_001.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_002.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_003.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_004.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_005.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_006.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_007.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_001.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_002.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_003.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_004.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_005.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_006.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_007.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_008.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_009.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_010.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_011.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_012.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_013.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_014.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_015.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_016.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/instrumented_guard_run.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/instrumented_plane_wave_nan.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/j_wires_in_wall.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/origin_checks.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/origin_das.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/quick_checks.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/scan_checks.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/scan_checks_2.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/scan_checks_3.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/scan_checks_4.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/toy_plane_wave.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1241_check_that_the_records_load.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1241_locate_the_non_finite_values_of_an_analysis.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1241_measure_the_wire_depth_against_the_time_origin.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1241_print_the_time_origin_scans.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1241_test_the_entropy_the_antisymmetry_and_the_filter_linearity.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1247_time_the_phase_reversal_per_patch_against_batched.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1248_compare_the_synthesis_on_the_card_and_the_host.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1250_save_and_compare_the_local_laws_of_a_subset.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1254_analyze_the_2.5mhz_stage_2.sh +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1256_print_the_per_depth_curves_of_a_reverberation_test.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1302_print_the_durations_of_a_chain_log.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1314_print_the_gouy_points_of_a_speed_of_sound_scan.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1445_fit_the_moveout_speed_of_the_point_sources.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1456_fit_the_depth_offset_of_the_reference_arrivals.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1502_print_the_laws_and_gates_of_an_analysis.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1503_analyze_with_the_ramp_removal_off_or_every_law_one.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1504_measure_the_anti_diagonal_share_of_the_clean_clutter.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1508_estimate_the_speed_with_smaller_windows.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1553_focus_the_clutter_records_in_sub_bands.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1553_print_the_band_and_the_screens_of_the_records.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1554_predict_the_phase_speed_of_the_stencil.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1556_compute_the_moveout_truth_with_an_eikonal_solver.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1556_fit_the_height_offset_on_three_grids.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1600_measure_the_flat_and_the_screen_correction_on_point_targets.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1604_predict_the_arrivals_from_the_stencil.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1604_prototype_the_broadband_correction.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1605_scan_the_time_origin_with_other_element_planes.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1607_measure_the_local_far_field_structure_of_the_clutter.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1608_score_the_speed_scans_against_the_eikonal_truth.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1610_compare_the_unwrapped_law_delays_with_the_truth.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1611_compare_the_arrival_models_at_the_point_sources.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1613_compare_the_sensor_pixel_with_the_element_center.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1613_measure_the_order_of_the_clutter_from_the_contrast_scaling.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1613_scan_the_speed_of_sound_at_one_time_origin.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1615_locate_the_source_and_sensor_pixels_of_the_array.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1617_check_the_data_level_correction_and_the_pulse_band.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1617_test_local_and_notch_filters_on_the_clutter.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1621_compute_the_moveout_truth_with_a_chosen_arrival_model.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1622_measure_the_tilt_spread_of_the_wall_interfaces.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1623_tabulate_the_broadband_correction_runs.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1626_measure_the_ghost_depths_of_the_plate.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1626_score_the_product_of_the_transducer_laws.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1630_test_the_local_filter_with_padded_windows.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1632_fit_the_time_origin_and_the_speed_of_the_phantom_scans.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1634_fit_the_reference_speed_at_the_sensor_row.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1646_split_the_clutter_into_orders_and_predict_its_floor.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1652_tabulate_the_pulse_band_check.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260910_1659_check_the_plane_wave_transform_of_the_elements.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260916_1103_compare_two_b_mode_roots.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260916_1214_binary_cache_lookup_order.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260916_1253_signal_of_old_against_new.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260916_1300_read_the_numexpr_pool_limit.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260916_1332_gpu_memory_of_the_relaxation_kernel.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260916_1401_relaxation_regions_against_the_kernel.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260916_1420_released_binary_carries_the_fix.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260916_1601_stable_courant_number_of_the_stencil_table.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260916_1602_fast_layer_in_a_small_3d_run.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260916_1719_p4_1_pulse_energy_above_the_trace_nyquist.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260916_1933_l7_4_run_at_8_ppw_stability_and_trace_sampling.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260916_1946_l7_4_trace_sampling_by_field_modulus.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260916_2004_pulse_bands_of_the_two_abdomen_arrays.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260916_2155_cuda_version_choice_before_and_after.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260916_2155_gpu_architectures_in_cached_binaries.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260916_2155_mutation_check_of_the_cuda_version_tests.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260916_2155_verify_the_cuda_version_test_findings.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260916_2212_mutation_check_of_the_blackwell_version_choice.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260925_1321_selected_cuda_tag.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260925_1326_release_binary_bit_identity.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/scratch/20260925_1331_summarize_release_check.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/settings.local.json +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/skills/fullwave25/SKILL.md +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/three_dimensional/convex_transducer_3d.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/three_dimensional/linear_transducer_3d.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/three_dimensional/matrix_transducer_3d.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/three_dimensional/patch.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/three_dimensional/ruff.toml +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/three_dimensional/superseded/convex_transducer_3d.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/three_dimensional/superseded/linear_transducer_3d.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/three_dimensional/superseded/matrix_transducer_3d.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/three_dimensional/test_patch.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/transducer_stack/README.md +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/transducer_stack/superseded/full_synthetic_aperture_with_stack.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.claude/transducer_stack/superseded/plane_wave_compounding_with_stack.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.gitignore +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.pre-commit-config.yaml +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/.python-version +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/20260120_0844.log +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/CITATION.cff +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/CONTRIBUTING.md +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/LICENSE +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/Makefile +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/attenuation.png +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/beamformer.m +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/debug_solver_bin/fullwave2_2d_2_relax_multi_gpu_cuda124 +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/debug_solver_bin/fullwave2_2d_exponential_attenuation_multi_gpu +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/debug_solver_bin/fullwave2_2d_exponential_attenuation_multi_gpu_cuda124 +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/debug_solver_bin/fullwave2_2d_exponential_attenuation_multi_gpu_cuda124_ +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/debug_solver_bin/fullwave2_3d_exponential_attenuation_multi_gpu_cuda124 +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/debug_solver_bin/fullwave2_3d_exponential_attenuation_multi_gpu_cuda124_ +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/docker/Dockerfile +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/docker/Dockerfile.dockerignore +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/docker/README.md +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/experiments/__init__.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/experiments/exp_scatterer_diameter.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/beamformer/__init__.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/constants/__init__.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/constants/material_properties.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/grid.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/medium.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/medium_builder/__init__.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/medium_builder/domain.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/medium_builder/medium_builder.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/medium_builder/presets/__init__.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/medium_builder/presets/data/.keep +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/medium_builder/presets/data/abdominal_wall/i2365f_etfw1.mat +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/medium_builder/presets/domain_abdominal_wall.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/medium_builder/presets/domain_background.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/medium_builder/presets/domain_scatterer.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/medium_builder/presets/domain_simple.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/medium_builder/presets/domain_water_gel.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/sensor.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/__init__.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/binary_manager.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/binary_markers.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda118 +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda124 +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda129 +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda130 +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda118 +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda124 +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda129 +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda130 +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/bins/database/relaxation_params_database_num_relax=3_20260828_1513.mat +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/bins/database/relaxation_params_database_num_relax=3_20260828_1513_invalid_cells.json +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/bins/database/relaxation_params_database_num_relax=4_20260828_1456.mat +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/bins/database/relaxation_params_database_num_relax=4_20260828_1456_invalid_cells.json +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/cuda_utils.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/launcher.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/pml_builder.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/shipped_database.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/source_type.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/solver/utils.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/source.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/transmit.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/ultra/__init__.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/ultra/dat_io.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/ultra/dat_io_3d.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/ultra/errors.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/ultra/stencil.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/ultra/time_axis.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/utils/__init__.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/utils/check_functions.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/utils/coordinates.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/utils/gpu_memory.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/utils/memory_tempfile.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/utils/numerical.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/utils/plot_utils.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/utils/pulse.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/utils/scatterer.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/fullwave/utils/signal_process.py +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/logs/20260815_0356_sweep.log +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/ruff.log +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/ruff.toml +0 -0
- {fullwave25-1.4.2.dev2 → fullwave25-1.4.2.dev4}/signal_filter_example.png +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: fullwave25
|
|
3
|
-
Version: 1.4.2-
|
|
3
|
+
Version: 1.4.2-dev4
|
|
4
4
|
Summary: Fullwave 2.5: Ultrasound wave propagation simulation with heterogeneous power law attenuation modelling capabilities
|
|
5
5
|
Author: Masashi Sode, Gianmarco Pinton
|
|
6
6
|
Maintainer: Masashi Sode
|
|
@@ -261,6 +261,8 @@ grid = fullwave.Grid(domain_size=(4.5e-2, 4.5e-2), f0=5.208e6, duration=6.7e-5,
|
|
|
261
261
|
|
|
262
262
|
transducer = fullwave.Transducer.l7_4(grid)
|
|
263
263
|
transducer.plane_wave(angle_deg=2.5)
|
|
264
|
+
maps = transducer.fill_probe_above_face(sound_speed=sound_speed_map, density=density_map, alpha_coeff=alpha_coeff_map, alpha_power=alpha_power_map)
|
|
265
|
+
medium = fullwave.Medium(grid, beta=beta_map, **maps)
|
|
264
266
|
|
|
265
267
|
solver = fullwave.Solver(work_dir="./outputs/my_run", grid=grid, medium=medium, transducer=transducer)
|
|
266
268
|
recorded = solver.run()
|
|
@@ -270,9 +272,11 @@ The arrays are `l7_4` (linear, 128 elements, 5.208 MHz), `c5_2v` (curved, 49.57
|
|
|
270
272
|
|
|
271
273
|
The transmits are `plane_wave(angle_deg=...)`, `focus(focus_m=...)`, `diverging(virtual_source_m=...)` and `synthetic_aperture(element)`. Each takes `apodization` and `pulse`. Set `transducer.active_source_elements` first to use part of the aperture.
|
|
272
274
|
|
|
273
|
-
The
|
|
275
|
+
The flat arrays (`l7_4`, `p4_1c`, `LinearTransducer`, `make_p4_1c_trasnducer`) share one layout. The source is one wavelength of rows (at least 8) with its first row on grid row 0, the sponge directly behind it. The receiver row is directly in front of the last source row, and the probe face (depth 0) is the row after it, where the medium starts. The array is centered in the grid, so make the grid wider than the array (the calibrated L7-4 uses 45 mm for its 38.09 mm). `transducer.fill_probe_above_face(...)` sets the cells above the face between the first and the last element edge (the source, kerf and receiver cells) to the probe fill (1540 m/s, 1000 kg/m3, attenuation 0.005 dB/MHz/cm, power 1.0), and the columns beside the array on the same rows to water (the same values with power 1.999), with no scatterers; pass its result to `fullwave.Medium`, or register `transducer.probe_fill_domain()` last in a `MediumBuilder`. `transducer.face_row_px` is the face row and `transducer.face_depth_m` its depth: start the tissue there (for an `AbdominalWallDomain`, pass `start_depth=transducer.face_depth_m`) and measure targets and focus depths from it. `Beamformer(..., face_row_px=...)` measures its depths from there. The curved `c5_2v` keeps its own layout, and `transducer.make_surface_reflective_with_air()` returns the air behind it.
|
|
274
276
|
|
|
275
|
-
`
|
|
277
|
+
The source type is `"hard"` by default for the named arrays: the transducer assigns its pressure for the whole run, so the source cells stay at zero pressure after the drive ends and the face stays reflective. `"hard_released_after"` assigns it while the drive signal plays, then the source cells evolve freely. `"soft"` adds the signal to the field. Pass `source_type=` to `Transducer.l7_4`, `c5_2v`, `p4_1c` or `fullwave.Solver`.
|
|
278
|
+
|
|
279
|
+
`transducer.apply_transducer_stack(...)` still paints a probe's backing, matching layer, lens and standoff onto the medium maps before the `Medium` is built, for a calibrated stack. `fullwave.TransducerStack` holds the values.
|
|
276
280
|
|
|
277
281
|
### Transmit batches
|
|
278
282
|
|
|
@@ -297,6 +301,7 @@ recorded = solver.run_batch(sources) # [n_transmits, n_sensors, n_t]
|
|
|
297
301
|
| I want to | example |
|
|
298
302
|
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
299
303
|
| send one plane wave | [simple_plane_wave.py](examples/simple_plane_wave/simple_plane_wave.py) |
|
|
304
|
+
| do the same with fullwave2-ultra | [simple_plane_wave_ultra.py](examples/simple_plane_wave/simple_plane_wave_ultra.py) |
|
|
300
305
|
| do the same in 3D | [simple_plane_wave_3d.py](examples/wave_3d/simple_plane_wave_3d.py) |
|
|
301
306
|
| compound plane waves into a B-mode | [plane_wave_compounding.py](examples/linear_transducer/plane_wave_compounding.py) |
|
|
302
307
|
| run a transmit sequence as batches | [transmit_batch_basics.py](examples/transmit_batch/transmit_batch_basics.py) |
|
|
@@ -395,7 +400,7 @@ Please see the following examples for more advanced usage.
|
|
|
395
400
|
|
|
396
401
|
The fullwave2-ultra backend is optimized for speed at ppw = 6 (`Grid.ppw`); a larger ppw runs, but more slowly, and gives a warning.
|
|
397
402
|
|
|
398
|
-
fullwave25 does not ship the fullwave2-ultra binaries.
|
|
403
|
+
fullwave25 does not ship the fullwave2-ultra binaries. Obtain them from the Pinton lab.
|
|
399
404
|
|
|
400
405
|
Point the solver to the binary with `path_fullwave_simulation_bin` or with the environment variable `FW2U_BATCH_BIN`. Either can be the binary file or the folder that contains it. The binary name is `bench_2d_batch` for a 2D grid and `bench_3d_opt` for a 3D grid.
|
|
401
406
|
|
|
@@ -407,7 +412,7 @@ import fullwave
|
|
|
407
412
|
solver = fullwave.Solver(
|
|
408
413
|
work_dir=Path("./outputs/ultra"),
|
|
409
414
|
grid=grid, # 2D or 3D fullwave.Grid
|
|
410
|
-
medium=medium, # fullwave.Medium
|
|
415
|
+
medium=medium, # fullwave.Medium; alpha_power other than 1 is converted to power 1 at f0
|
|
411
416
|
source=source,
|
|
412
417
|
sensor=sensor,
|
|
413
418
|
path_fullwave_simulation_bin=Path("/path/to/fullwave2-ultra/bin"),
|
|
@@ -431,17 +436,40 @@ Supported now:
|
|
|
431
436
|
- `run_batch` in 3D.
|
|
432
437
|
- Velocity sources, and sources that are not pressure sources.
|
|
433
438
|
- Sparse-grid sensors, `is_static_map`, and `record_whole_domain`.
|
|
434
|
-
- Media other than `fullwave.Medium` (exponential attenuation)
|
|
439
|
+
- Media other than `fullwave.Medium` (exponential attenuation).
|
|
435
440
|
- `use_pml=False`, `m_spatial_order` other than 8, `use_gpu=False`, and an invalid `source_type`.
|
|
436
441
|
- In 2D, a binary that does not read the files for air cells, for the additive channel, or for releasing the source (with such a binary, pad `p0` to `grid.nt`).
|
|
437
442
|
- In 3D, air cells with a binary that does not read `icczero.dat` and `nzero0.dat`, and additive sources with a binary that does not read `ncoords_add.dat` and `icmat_add.dat`.
|
|
438
443
|
|
|
439
444
|
This list will grow as the backend does.
|
|
440
445
|
|
|
441
|
-
|
|
446
|
+
Unless `ultra_attenuation_parameters` is set (below), the backend runs the exponential attenuation model (frequency-independent: the same attenuation at every frequency); a frequency-dependent attenuation is available only with `ultra_attenuation_parameters` and a compatible binary. Without it, cells with an `alpha_power` other than 1 are converted to power 1 with the same attenuation at `f0` (`alpha_coeff * f0_MHz**(alpha_power - 1)`), with one warning that names the converted range. Set the width of its absorbing sponge, in cells, with `ultra_sponge_thickness_px`; the default is 6 wavelengths in 2D and 4 wavelengths in 3D. `exponential_attenuation_pml_thickness_px` no longer sets this width with `use_ultra=True`; a script that relied on it now gets the default width until it passes `ultra_sponge_thickness_px`.
|
|
442
447
|
|
|
443
448
|
Options that only tune the native solver are ignored with a warning, once per process: `pml_layer_thickness_px`, `n_transition_layer`, `pml_alpha_entrance`, `exponential_attenuation_pml_thickness_px` (use `ultra_sponge_thickness_px` instead), `use_gpu_pml`, `save_gpu_memory`, `write_maps_the_solver_does_not_read`, `use_isotropic_relaxation=False`, and a `cuda_device_id` that lists more than one device (the run uses the first one listed). `use_exponential_attenuation=False`, the native default, also warns that the backend runs the exponential attenuation model, whose attenuation is frequency-independent, not the relaxation model, whose attenuation is frequency-dependent. Pass `use_exponential_attenuation=True` to silence it.
|
|
444
449
|
|
|
450
|
+
#### Attenuation modes
|
|
451
|
+
|
|
452
|
+
A 2D or 3D run has three attenuation modes. Each needs `use_ultra=True`; the last two need the power-law attenuation binaries from the Pinton lab and `use_exponential_attenuation=False`.
|
|
453
|
+
|
|
454
|
+
```python
|
|
455
|
+
# 1. Default: frequency-independent attenuation (as described above).
|
|
456
|
+
solver = fullwave.Solver(..., use_ultra=True, path_fullwave_simulation_bin=bin_folder)
|
|
457
|
+
|
|
458
|
+
# 2. Power-law attenuation alpha_coeff * f**alpha_power.
|
|
459
|
+
solver = fullwave.Solver(
|
|
460
|
+
...,
|
|
461
|
+
use_ultra=True,
|
|
462
|
+
use_exponential_attenuation=False,
|
|
463
|
+
path_fullwave_simulation_bin=bin_folder,
|
|
464
|
+
ultra_attenuation_parameters="centered", # or "author", or the path of a settings file
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
# 3. The same with any number of materials (more GPU memory).
|
|
468
|
+
solver = fullwave.Solver(..., ultra_attenuation_parameters="centered", ultra_unlimited_materials=True)
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
`bin_folder` is the folder of the binaries. With `ultra_attenuation_parameters` it gives the power-law build of the grid dimension; without it, `bench_2d_batch` or `bench_3d_opt`. A name looks for `attenuation_parameters_<name>_v1.dat` next to the binary, then in the `params` folder beside `bin_folder`; the error lists the places searched. "centered" is the recommended band. `UltraUnsupportedError` is raised without `use_ultra=True`, with `use_exponential_attenuation=True`, for a missing settings file, for a binary that does not read `alpha_power.dat`, and, with `ultra_unlimited_materials=True`, for a binary that does not support it. The run directory then gets `alpha_coeff.dat`, `alpha_power.dat`, `f0.dat` and a copy of the settings file as `attenuation_parameters.dat`, and `Aexp.dat` holds the sponge only. The environment variable `FW2U_BATCH_BIN` is not used in modes 2 and 3.
|
|
472
|
+
|
|
445
473
|
---
|
|
446
474
|
|
|
447
475
|
## Attention
|
|
@@ -220,6 +220,8 @@ grid = fullwave.Grid(domain_size=(4.5e-2, 4.5e-2), f0=5.208e6, duration=6.7e-5,
|
|
|
220
220
|
|
|
221
221
|
transducer = fullwave.Transducer.l7_4(grid)
|
|
222
222
|
transducer.plane_wave(angle_deg=2.5)
|
|
223
|
+
maps = transducer.fill_probe_above_face(sound_speed=sound_speed_map, density=density_map, alpha_coeff=alpha_coeff_map, alpha_power=alpha_power_map)
|
|
224
|
+
medium = fullwave.Medium(grid, beta=beta_map, **maps)
|
|
223
225
|
|
|
224
226
|
solver = fullwave.Solver(work_dir="./outputs/my_run", grid=grid, medium=medium, transducer=transducer)
|
|
225
227
|
recorded = solver.run()
|
|
@@ -229,9 +231,11 @@ The arrays are `l7_4` (linear, 128 elements, 5.208 MHz), `c5_2v` (curved, 49.57
|
|
|
229
231
|
|
|
230
232
|
The transmits are `plane_wave(angle_deg=...)`, `focus(focus_m=...)`, `diverging(virtual_source_m=...)` and `synthetic_aperture(element)`. Each takes `apodization` and `pulse`. Set `transducer.active_source_elements` first to use part of the aperture.
|
|
231
233
|
|
|
232
|
-
The
|
|
234
|
+
The flat arrays (`l7_4`, `p4_1c`, `LinearTransducer`, `make_p4_1c_trasnducer`) share one layout. The source is one wavelength of rows (at least 8) with its first row on grid row 0, the sponge directly behind it. The receiver row is directly in front of the last source row, and the probe face (depth 0) is the row after it, where the medium starts. The array is centered in the grid, so make the grid wider than the array (the calibrated L7-4 uses 45 mm for its 38.09 mm). `transducer.fill_probe_above_face(...)` sets the cells above the face between the first and the last element edge (the source, kerf and receiver cells) to the probe fill (1540 m/s, 1000 kg/m3, attenuation 0.005 dB/MHz/cm, power 1.0), and the columns beside the array on the same rows to water (the same values with power 1.999), with no scatterers; pass its result to `fullwave.Medium`, or register `transducer.probe_fill_domain()` last in a `MediumBuilder`. `transducer.face_row_px` is the face row and `transducer.face_depth_m` its depth: start the tissue there (for an `AbdominalWallDomain`, pass `start_depth=transducer.face_depth_m`) and measure targets and focus depths from it. `Beamformer(..., face_row_px=...)` measures its depths from there. The curved `c5_2v` keeps its own layout, and `transducer.make_surface_reflective_with_air()` returns the air behind it.
|
|
233
235
|
|
|
234
|
-
`
|
|
236
|
+
The source type is `"hard"` by default for the named arrays: the transducer assigns its pressure for the whole run, so the source cells stay at zero pressure after the drive ends and the face stays reflective. `"hard_released_after"` assigns it while the drive signal plays, then the source cells evolve freely. `"soft"` adds the signal to the field. Pass `source_type=` to `Transducer.l7_4`, `c5_2v`, `p4_1c` or `fullwave.Solver`.
|
|
237
|
+
|
|
238
|
+
`transducer.apply_transducer_stack(...)` still paints a probe's backing, matching layer, lens and standoff onto the medium maps before the `Medium` is built, for a calibrated stack. `fullwave.TransducerStack` holds the values.
|
|
235
239
|
|
|
236
240
|
### Transmit batches
|
|
237
241
|
|
|
@@ -256,6 +260,7 @@ recorded = solver.run_batch(sources) # [n_transmits, n_sensors, n_t]
|
|
|
256
260
|
| I want to | example |
|
|
257
261
|
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
258
262
|
| send one plane wave | [simple_plane_wave.py](examples/simple_plane_wave/simple_plane_wave.py) |
|
|
263
|
+
| do the same with fullwave2-ultra | [simple_plane_wave_ultra.py](examples/simple_plane_wave/simple_plane_wave_ultra.py) |
|
|
259
264
|
| do the same in 3D | [simple_plane_wave_3d.py](examples/wave_3d/simple_plane_wave_3d.py) |
|
|
260
265
|
| compound plane waves into a B-mode | [plane_wave_compounding.py](examples/linear_transducer/plane_wave_compounding.py) |
|
|
261
266
|
| run a transmit sequence as batches | [transmit_batch_basics.py](examples/transmit_batch/transmit_batch_basics.py) |
|
|
@@ -354,7 +359,7 @@ Please see the following examples for more advanced usage.
|
|
|
354
359
|
|
|
355
360
|
The fullwave2-ultra backend is optimized for speed at ppw = 6 (`Grid.ppw`); a larger ppw runs, but more slowly, and gives a warning.
|
|
356
361
|
|
|
357
|
-
fullwave25 does not ship the fullwave2-ultra binaries.
|
|
362
|
+
fullwave25 does not ship the fullwave2-ultra binaries. Obtain them from the Pinton lab.
|
|
358
363
|
|
|
359
364
|
Point the solver to the binary with `path_fullwave_simulation_bin` or with the environment variable `FW2U_BATCH_BIN`. Either can be the binary file or the folder that contains it. The binary name is `bench_2d_batch` for a 2D grid and `bench_3d_opt` for a 3D grid.
|
|
360
365
|
|
|
@@ -366,7 +371,7 @@ import fullwave
|
|
|
366
371
|
solver = fullwave.Solver(
|
|
367
372
|
work_dir=Path("./outputs/ultra"),
|
|
368
373
|
grid=grid, # 2D or 3D fullwave.Grid
|
|
369
|
-
medium=medium, # fullwave.Medium
|
|
374
|
+
medium=medium, # fullwave.Medium; alpha_power other than 1 is converted to power 1 at f0
|
|
370
375
|
source=source,
|
|
371
376
|
sensor=sensor,
|
|
372
377
|
path_fullwave_simulation_bin=Path("/path/to/fullwave2-ultra/bin"),
|
|
@@ -390,17 +395,40 @@ Supported now:
|
|
|
390
395
|
- `run_batch` in 3D.
|
|
391
396
|
- Velocity sources, and sources that are not pressure sources.
|
|
392
397
|
- Sparse-grid sensors, `is_static_map`, and `record_whole_domain`.
|
|
393
|
-
- Media other than `fullwave.Medium` (exponential attenuation)
|
|
398
|
+
- Media other than `fullwave.Medium` (exponential attenuation).
|
|
394
399
|
- `use_pml=False`, `m_spatial_order` other than 8, `use_gpu=False`, and an invalid `source_type`.
|
|
395
400
|
- In 2D, a binary that does not read the files for air cells, for the additive channel, or for releasing the source (with such a binary, pad `p0` to `grid.nt`).
|
|
396
401
|
- In 3D, air cells with a binary that does not read `icczero.dat` and `nzero0.dat`, and additive sources with a binary that does not read `ncoords_add.dat` and `icmat_add.dat`.
|
|
397
402
|
|
|
398
403
|
This list will grow as the backend does.
|
|
399
404
|
|
|
400
|
-
|
|
405
|
+
Unless `ultra_attenuation_parameters` is set (below), the backend runs the exponential attenuation model (frequency-independent: the same attenuation at every frequency); a frequency-dependent attenuation is available only with `ultra_attenuation_parameters` and a compatible binary. Without it, cells with an `alpha_power` other than 1 are converted to power 1 with the same attenuation at `f0` (`alpha_coeff * f0_MHz**(alpha_power - 1)`), with one warning that names the converted range. Set the width of its absorbing sponge, in cells, with `ultra_sponge_thickness_px`; the default is 6 wavelengths in 2D and 4 wavelengths in 3D. `exponential_attenuation_pml_thickness_px` no longer sets this width with `use_ultra=True`; a script that relied on it now gets the default width until it passes `ultra_sponge_thickness_px`.
|
|
401
406
|
|
|
402
407
|
Options that only tune the native solver are ignored with a warning, once per process: `pml_layer_thickness_px`, `n_transition_layer`, `pml_alpha_entrance`, `exponential_attenuation_pml_thickness_px` (use `ultra_sponge_thickness_px` instead), `use_gpu_pml`, `save_gpu_memory`, `write_maps_the_solver_does_not_read`, `use_isotropic_relaxation=False`, and a `cuda_device_id` that lists more than one device (the run uses the first one listed). `use_exponential_attenuation=False`, the native default, also warns that the backend runs the exponential attenuation model, whose attenuation is frequency-independent, not the relaxation model, whose attenuation is frequency-dependent. Pass `use_exponential_attenuation=True` to silence it.
|
|
403
408
|
|
|
409
|
+
#### Attenuation modes
|
|
410
|
+
|
|
411
|
+
A 2D or 3D run has three attenuation modes. Each needs `use_ultra=True`; the last two need the power-law attenuation binaries from the Pinton lab and `use_exponential_attenuation=False`.
|
|
412
|
+
|
|
413
|
+
```python
|
|
414
|
+
# 1. Default: frequency-independent attenuation (as described above).
|
|
415
|
+
solver = fullwave.Solver(..., use_ultra=True, path_fullwave_simulation_bin=bin_folder)
|
|
416
|
+
|
|
417
|
+
# 2. Power-law attenuation alpha_coeff * f**alpha_power.
|
|
418
|
+
solver = fullwave.Solver(
|
|
419
|
+
...,
|
|
420
|
+
use_ultra=True,
|
|
421
|
+
use_exponential_attenuation=False,
|
|
422
|
+
path_fullwave_simulation_bin=bin_folder,
|
|
423
|
+
ultra_attenuation_parameters="centered", # or "author", or the path of a settings file
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
# 3. The same with any number of materials (more GPU memory).
|
|
427
|
+
solver = fullwave.Solver(..., ultra_attenuation_parameters="centered", ultra_unlimited_materials=True)
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
`bin_folder` is the folder of the binaries. With `ultra_attenuation_parameters` it gives the power-law build of the grid dimension; without it, `bench_2d_batch` or `bench_3d_opt`. A name looks for `attenuation_parameters_<name>_v1.dat` next to the binary, then in the `params` folder beside `bin_folder`; the error lists the places searched. "centered" is the recommended band. `UltraUnsupportedError` is raised without `use_ultra=True`, with `use_exponential_attenuation=True`, for a missing settings file, for a binary that does not read `alpha_power.dat`, and, with `ultra_unlimited_materials=True`, for a binary that does not support it. The run directory then gets `alpha_coeff.dat`, `alpha_power.dat`, `f0.dat` and a copy of the settings file as `attenuation_parameters.dat`, and `Aexp.dat` holds the sponge only. The environment variable `FW2U_BATCH_BIN` is not used in modes 2 and 3.
|
|
431
|
+
|
|
404
432
|
---
|
|
405
433
|
|
|
406
434
|
## Attention
|
|
@@ -66,7 +66,7 @@ try:
|
|
|
66
66
|
__version__ = version("fullwave")
|
|
67
67
|
except PackageNotFoundError:
|
|
68
68
|
# Update via bump-my-version, not manually
|
|
69
|
-
__version__ = "1.4.2-
|
|
69
|
+
__version__ = "1.4.2-dev4"
|
|
70
70
|
|
|
71
71
|
VERSION = __version__ # for convenience
|
|
72
72
|
logger.info("Fullwave version: %s", __version__)
|
|
@@ -14,6 +14,14 @@ class Beamformer:
|
|
|
14
14
|
For faster implementations, consider using libraries such as
|
|
15
15
|
mach beamformer: https://github.com/Forest-Neurotech/mach
|
|
16
16
|
|
|
17
|
+
Conventions: ``axial_position_m`` is the depth below the probe face, so
|
|
18
|
+
depth 0 is the face row ``face_row_px`` (``Transducer.face_row_px``, the
|
|
19
|
+
first medium row, one row in front of the receiver row).
|
|
20
|
+
``transducer_coordinates`` must be the receiver positions in grid points
|
|
21
|
+
(for example from ``Transducer.element_id_to_receiver_center``). The time
|
|
22
|
+
origin is the mean receiver row, so the array depth is subtracted from the
|
|
23
|
+
two-way travel time.
|
|
24
|
+
|
|
17
25
|
References
|
|
18
26
|
----------
|
|
19
27
|
- Fullwave2 BMME890 implementation
|
|
@@ -31,6 +39,7 @@ class Beamformer:
|
|
|
31
39
|
axial_position_m: np.ndarray,
|
|
32
40
|
num_elements: int,
|
|
33
41
|
transducer_coordinates: np.ndarray,
|
|
42
|
+
face_row_px: int,
|
|
34
43
|
f_number: float = 1.0,
|
|
35
44
|
) -> None:
|
|
36
45
|
"""Initialize the beamformer with simulation and transducer parameters.
|
|
@@ -46,11 +55,14 @@ class Beamformer:
|
|
|
46
55
|
lateral_position_m : np.ndarray
|
|
47
56
|
Lateral positions (m) where the beamformed image will be computed.
|
|
48
57
|
axial_position_m : np.ndarray
|
|
49
|
-
|
|
58
|
+
Depths (m) below the probe face where the image is computed.
|
|
50
59
|
num_elements : int
|
|
51
60
|
Number of transducer elements.
|
|
52
61
|
transducer_coordinates : np.ndarray
|
|
53
|
-
|
|
62
|
+
Receiver coordinates [n_elements, 2] in grid points (row, column).
|
|
63
|
+
face_row_px : int
|
|
64
|
+
Grid row of the probe face (depth 0), for example
|
|
65
|
+
``Transducer.face_row_px``.
|
|
54
66
|
f_number : float, optional
|
|
55
67
|
F-number for aperture calculation, by default 1.0.
|
|
56
68
|
|
|
@@ -62,6 +74,7 @@ class Beamformer:
|
|
|
62
74
|
self.axial_position_m = axial_position_m
|
|
63
75
|
self.num_elements = num_elements
|
|
64
76
|
self.transducer_coordinates = transducer_coordinates
|
|
77
|
+
self.face_row_px = face_row_px
|
|
65
78
|
self.f_number = f_number
|
|
66
79
|
|
|
67
80
|
def run(self, signals: np.ndarray) -> np.ndarray:
|
|
@@ -76,13 +89,17 @@ class Beamformer:
|
|
|
76
89
|
Returns
|
|
77
90
|
-------
|
|
78
91
|
np.ndarray
|
|
79
|
-
Beamformed image. Shape: [n_axial, n_lateral, n_transmit].
|
|
92
|
+
Beamformed image. Shape: [n_axial, n_lateral, n_transmit]. Row 0
|
|
93
|
+
of the first axis is the first depth of ``axial_position_m``, which
|
|
94
|
+
is measured from the probe face.
|
|
80
95
|
|
|
81
96
|
"""
|
|
82
97
|
# signals: [n_elements, n_time, n_transmit]
|
|
83
98
|
if signals.ndim == 2:
|
|
84
99
|
signals = signals[:, :, np.newaxis]
|
|
85
100
|
n_transmit = signals.shape[2]
|
|
101
|
+
# idt_0 is the pulse arrival at the receivers, so time is measured from the array.
|
|
102
|
+
z_array = np.mean(self.transducer_coordinates[:, 0]) * self.dx
|
|
86
103
|
|
|
87
104
|
hilbert_signals = hilbert(signals, axis=1)
|
|
88
105
|
beamformed_image = np.zeros(
|
|
@@ -101,12 +118,13 @@ class Beamformer:
|
|
|
101
118
|
desc="Lateral positions",
|
|
102
119
|
total=len(self.lateral_position_m),
|
|
103
120
|
):
|
|
104
|
-
for i_axial,
|
|
121
|
+
for i_axial, depth in tqdm(
|
|
105
122
|
enumerate(self.axial_position_m),
|
|
106
123
|
desc="Axial positions",
|
|
107
124
|
total=len(self.axial_position_m),
|
|
108
125
|
leave=False,
|
|
109
126
|
):
|
|
127
|
+
axial = self.face_row_px * self.dx + depth
|
|
110
128
|
fcen = np.array(
|
|
111
129
|
[
|
|
112
130
|
int(axial / self.dx),
|
|
@@ -133,7 +151,7 @@ class Beamformer:
|
|
|
133
151
|
dd = np.round(dd / (self.dt / self.dx * self.c0)).astype(int)
|
|
134
152
|
dd = dd - dd.min()
|
|
135
153
|
|
|
136
|
-
idt = idt_0 + int(2 * axial / self.c0 / self.dt)
|
|
154
|
+
idt = idt_0 + int(2 * (axial - z_array) / self.c0 / self.dt)
|
|
137
155
|
|
|
138
156
|
# idp: 1D indices into signals flattened array
|
|
139
157
|
# we convert 2D indices to 1D indices
|
|
@@ -293,6 +293,7 @@ class InputFileWriter:
|
|
|
293
293
|
_incoords_vel,
|
|
294
294
|
)
|
|
295
295
|
self._queue_coords_write(simulation_dir / "icc.dat", self.source.incoords)
|
|
296
|
+
self._save_drive_params(simulation_dir, members)
|
|
296
297
|
self._copy_simulation_bin_file(simulation_dir)
|
|
297
298
|
|
|
298
299
|
if not self.use_exponential_attenuation:
|
|
@@ -1275,8 +1276,6 @@ class InputFileWriter:
|
|
|
1275
1276
|
"ncoords_w",
|
|
1276
1277
|
"ncoordsout",
|
|
1277
1278
|
"ncoordszero",
|
|
1278
|
-
"nTic",
|
|
1279
|
-
"hold_source",
|
|
1280
1279
|
"modT",
|
|
1281
1280
|
"modX",
|
|
1282
1281
|
"modY",
|
|
@@ -1374,6 +1373,27 @@ class InputFileWriter:
|
|
|
1374
1373
|
save_path = simulation_dir / f"{var_name}.dat"
|
|
1375
1374
|
self._queue_v_abs_write(np.float32, save_path, var)
|
|
1376
1375
|
|
|
1376
|
+
def _save_drive_params(
|
|
1377
|
+
self,
|
|
1378
|
+
simulation_dir: Path,
|
|
1379
|
+
members: Sequence[fullwave.Source] | None = None,
|
|
1380
|
+
) -> None:
|
|
1381
|
+
"""Write the drive length and the hold flag of this transmit.
|
|
1382
|
+
|
|
1383
|
+
Every transmit folder gets its own files, never a link to the shared
|
|
1384
|
+
static-map files, and a flag left by an earlier run is removed when the
|
|
1385
|
+
hold is off. The members of a batch share one length, which can exceed the
|
|
1386
|
+
length of the source, so the drive length is the one of the members.
|
|
1387
|
+
"""
|
|
1388
|
+
drive_length_file = simulation_dir / "nTic.dat"
|
|
1389
|
+
hold_flag_file = simulation_dir / "hold_source.dat"
|
|
1390
|
+
drive_length_file.unlink(missing_ok=True)
|
|
1391
|
+
hold_flag_file.unlink(missing_ok=True)
|
|
1392
|
+
drive_source = self.source if members is None else members[0]
|
|
1393
|
+
self._queue_v_abs_write(np.int32, drive_length_file, drive_source.icmat.shape[1])
|
|
1394
|
+
if self._holds_the_source:
|
|
1395
|
+
self._queue_v_abs_write(np.int32, hold_flag_file, 1)
|
|
1396
|
+
|
|
1377
1397
|
def _save_coords_params(self, simulation_dir: Path) -> None:
|
|
1378
1398
|
var_list = [
|
|
1379
1399
|
("nX", self.grid.nx),
|
|
@@ -1382,11 +1402,8 @@ class InputFileWriter:
|
|
|
1382
1402
|
("ncoords", self.source.n_sources),
|
|
1383
1403
|
("ncoordsout", self.sensor.n_sensors),
|
|
1384
1404
|
("ncoordszero", self.medium.n_air),
|
|
1385
|
-
("nTic", self.source.icmat.shape[1]),
|
|
1386
1405
|
("modT", self.sensor.sampling_modulus_time),
|
|
1387
1406
|
]
|
|
1388
|
-
if self._holds_the_source:
|
|
1389
|
-
var_list.append(("hold_source", 1))
|
|
1390
1407
|
n_sources_add = getattr(self.source, "n_sources_add", 0)
|
|
1391
1408
|
if n_sources_add > 0:
|
|
1392
1409
|
var_list.append(("ncoords_add", n_sources_add))
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""solver module."""
|
|
2
2
|
|
|
3
3
|
import contextlib
|
|
4
|
+
import copy
|
|
4
5
|
import logging
|
|
5
6
|
import os
|
|
6
7
|
import time
|
|
@@ -22,6 +23,7 @@ from fullwave.solver.source_type import (
|
|
|
22
23
|
is_hard_held,
|
|
23
24
|
is_soft,
|
|
24
25
|
)
|
|
26
|
+
from fullwave.ultra import attenuation_parameters as power_law_attenuation
|
|
25
27
|
from fullwave.ultra import backend, binary, factory
|
|
26
28
|
from fullwave.utils import (
|
|
27
29
|
check_functions,
|
|
@@ -470,10 +472,12 @@ class Solver:
|
|
|
470
472
|
verify_gpu: bool = True,
|
|
471
473
|
use_gpu_pml: bool = False,
|
|
472
474
|
pml_alpha_entrance: float | None = None,
|
|
473
|
-
source_type: str =
|
|
475
|
+
source_type: str | None = None,
|
|
474
476
|
write_maps_the_solver_does_not_read: bool = False,
|
|
475
477
|
use_ultra: bool = False,
|
|
476
478
|
ultra_sponge_thickness_px: int | None = None,
|
|
479
|
+
ultra_attenuation_parameters: str | Path | None = None,
|
|
480
|
+
ultra_unlimited_materials: bool = False,
|
|
477
481
|
) -> None:
|
|
478
482
|
"""Initialize a Solver instance for the fullwave simulation.
|
|
479
483
|
|
|
@@ -599,12 +603,14 @@ class Solver:
|
|
|
599
603
|
relaxation path. Set it to True for a solver binary that predates
|
|
600
604
|
that record. Such a binary stops with an error on kappax.dat rather
|
|
601
605
|
than returning a wrong answer.
|
|
602
|
-
source_type : str, optional
|
|
603
|
-
How the source drives the field.
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
606
|
+
source_type : str | None, optional
|
|
607
|
+
How the source drives the field. None, the default, takes the type of the
|
|
608
|
+
``transducer`` when one is given, and "hard_released_after" otherwise. A
|
|
609
|
+
value that differs from the transducer's type raises ValueError.
|
|
610
|
+
"hard_released_after" assigns the source pressure while the drive signal
|
|
611
|
+
plays, then lets the source cells evolve freely. "hard" assigns it for the
|
|
612
|
+
whole run, so the cells stay at zero pressure after the signal ends.
|
|
613
|
+
"soft" adds the signal to the field. ``use_ultra`` follows the same three values.
|
|
608
614
|
use_ultra : bool, optional
|
|
609
615
|
Experimental. Run a user-supplied fullwave2-ultra binary (not shipped; pass it
|
|
610
616
|
as ``path_fullwave_simulation_bin`` or set ``FW2U_BATCH_BIN``): ``bench_2d_batch``
|
|
@@ -620,6 +626,13 @@ class Solver:
|
|
|
620
626
|
Width of the absorbing sponge of the ``use_ultra`` backend, in cells.
|
|
621
627
|
None, the default, gives 6 wavelengths in 2D and 4 wavelengths in 3D.
|
|
622
628
|
Used only with ``use_ultra=True``.
|
|
629
|
+
ultra_attenuation_parameters : str | Path, optional
|
|
630
|
+
Power-law attenuation for the ``use_ultra`` backend. Give "centered", "author",
|
|
631
|
+
or the path of a parameter file. Needs ``use_ultra=True`` and
|
|
632
|
+
``use_exponential_attenuation=False``.
|
|
633
|
+
ultra_unlimited_materials : bool, optional
|
|
634
|
+
If True, allow any number of distinct materials (uses more GPU memory). Needs
|
|
635
|
+
``ultra_attenuation_parameters``.
|
|
623
636
|
|
|
624
637
|
Raises
|
|
625
638
|
------
|
|
@@ -630,9 +643,28 @@ class Solver:
|
|
|
630
643
|
and transducer) are defined simultaneously.
|
|
631
644
|
|
|
632
645
|
"""
|
|
646
|
+
source_type = self._resolve_source_type(source_type=source_type, transducer=transducer)
|
|
633
647
|
self.ultra = None
|
|
648
|
+
power_law_attenuation.check_unlimited_materials(
|
|
649
|
+
unlimited_materials=ultra_unlimited_materials,
|
|
650
|
+
parameters=ultra_attenuation_parameters,
|
|
651
|
+
use_ultra=use_ultra,
|
|
652
|
+
)
|
|
653
|
+
if ultra_attenuation_parameters is not None:
|
|
654
|
+
request = power_law_attenuation.check_request(
|
|
655
|
+
parameters=ultra_attenuation_parameters,
|
|
656
|
+
use_ultra=use_ultra,
|
|
657
|
+
use_exponential_attenuation=use_exponential_attenuation,
|
|
658
|
+
binary=path_fullwave_simulation_bin,
|
|
659
|
+
is_3d=grid.is_3d,
|
|
660
|
+
unlimited_materials=ultra_unlimited_materials,
|
|
661
|
+
)
|
|
662
|
+
ultra_attenuation_parameters = request.parameter_file
|
|
663
|
+
path_fullwave_simulation_bin = request.binary
|
|
634
664
|
if use_ultra:
|
|
635
665
|
self._init_ultra(
|
|
666
|
+
attenuation_parameters=ultra_attenuation_parameters,
|
|
667
|
+
unlimited_materials=ultra_unlimited_materials,
|
|
636
668
|
work_dir=work_dir,
|
|
637
669
|
grid=grid,
|
|
638
670
|
medium=medium,
|
|
@@ -813,7 +845,12 @@ class Solver:
|
|
|
813
845
|
logger.error(error_msg)
|
|
814
846
|
raise ValueError(error_msg)
|
|
815
847
|
self.source_type = source_type
|
|
816
|
-
|
|
848
|
+
source_is_the_transducers = source is None and transducer is not None
|
|
849
|
+
if is_soft(source_type) and source_is_the_transducers:
|
|
850
|
+
logger.info(
|
|
851
|
+
"source_type=%s, the transducer's source is driven by addition", source_type
|
|
852
|
+
)
|
|
853
|
+
elif is_soft(source_type) and self.source.p0_additive is not None:
|
|
817
854
|
error_msg = (
|
|
818
855
|
"this source already carries an additive signal. source_type='soft' "
|
|
819
856
|
"converts a hard source into a soft one, and this source holds no "
|
|
@@ -824,7 +861,7 @@ class Solver:
|
|
|
824
861
|
raise ValueError(error_msg)
|
|
825
862
|
if not is_soft(source_type) and self.source.p0_additive is not None:
|
|
826
863
|
self._warn_if_the_additive_signal_was_not_scaled()
|
|
827
|
-
if is_soft(source_type):
|
|
864
|
+
if is_soft(source_type) and not source_is_the_transducers:
|
|
828
865
|
self.source = as_additive_source(
|
|
829
866
|
self.source,
|
|
830
867
|
self.grid,
|
|
@@ -898,11 +935,15 @@ class Solver:
|
|
|
898
935
|
verify_gpu: bool,
|
|
899
936
|
nbdy: int | None,
|
|
900
937
|
options: dict,
|
|
938
|
+
attenuation_parameters: Path | None,
|
|
939
|
+
unlimited_materials: bool,
|
|
901
940
|
) -> None:
|
|
902
941
|
"""Set up the experimental fullwave2-ultra backend (see ``fullwave.ultra``)."""
|
|
903
942
|
backend.warn_experimental()
|
|
904
943
|
backend.warn_ppw_above_speed_optimum(ppw=grid.ppw)
|
|
905
|
-
backend.check_solver_options(
|
|
944
|
+
backend.check_solver_options(
|
|
945
|
+
**options, has_attenuation_parameters=attenuation_parameters is not None
|
|
946
|
+
)
|
|
906
947
|
binary_name = binary.BINARY_NAME_3D if grid.is_3d else binary.BINARY_NAME_2D
|
|
907
948
|
ultra_binary = binary.resolve_binary(path_fullwave_simulation_bin, name=binary_name)
|
|
908
949
|
self._check_input(grid, medium, source, sensor, transducer, ultra_binary)
|
|
@@ -924,8 +965,48 @@ class Solver:
|
|
|
924
965
|
cuda_device_id=cuda_device_id,
|
|
925
966
|
verify_gpu=verify_gpu,
|
|
926
967
|
source_type=options["source_type"],
|
|
968
|
+
attenuation_parameters=attenuation_parameters,
|
|
969
|
+
unlimited_materials=unlimited_materials,
|
|
927
970
|
)
|
|
928
971
|
|
|
972
|
+
@staticmethod
|
|
973
|
+
def _resolve_source_type(
|
|
974
|
+
*, source_type: str | None, transducer: fullwave.Transducer | None
|
|
975
|
+
) -> str:
|
|
976
|
+
"""Return the source type of the run.
|
|
977
|
+
|
|
978
|
+
Parameters
|
|
979
|
+
----------
|
|
980
|
+
source_type : str | None
|
|
981
|
+
The Solver's own argument.
|
|
982
|
+
transducer : fullwave.Transducer | None
|
|
983
|
+
The transducer that drives the run, if any.
|
|
984
|
+
|
|
985
|
+
Returns
|
|
986
|
+
-------
|
|
987
|
+
str
|
|
988
|
+
The transducer's type when the argument is None and a transducer is given,
|
|
989
|
+
the argument when it is given, and "hard_released_after" otherwise.
|
|
990
|
+
|
|
991
|
+
Raises
|
|
992
|
+
------
|
|
993
|
+
ValueError
|
|
994
|
+
If the argument differs from the transducer's type.
|
|
995
|
+
"""
|
|
996
|
+
if transducer is None:
|
|
997
|
+
return HARD_RELEASED_AFTER if source_type is None else source_type
|
|
998
|
+
if source_type is None:
|
|
999
|
+
return transducer.source_type
|
|
1000
|
+
if source_type != transducer.source_type:
|
|
1001
|
+
error_msg = (
|
|
1002
|
+
f"Solver source_type {source_type!r} differs from the transducer's "
|
|
1003
|
+
f"source_type {transducer.source_type!r}. Set the source type in one "
|
|
1004
|
+
"place, on the Transducer, and leave the Solver's source_type unset."
|
|
1005
|
+
)
|
|
1006
|
+
logger.error(error_msg)
|
|
1007
|
+
raise ValueError(error_msg)
|
|
1008
|
+
return source_type
|
|
1009
|
+
|
|
929
1010
|
def _warn_if_the_additive_signal_was_not_scaled(self) -> None:
|
|
930
1011
|
"""Say so when an additive signal was built by hand and may carry no scale.
|
|
931
1012
|
|
|
@@ -1541,8 +1622,10 @@ class Solver:
|
|
|
1541
1622
|
Parameters
|
|
1542
1623
|
----------
|
|
1543
1624
|
sources : Sequence[fullwave.Source]
|
|
1544
|
-
The transmits, in order. Each one must have the same source coordinates
|
|
1545
|
-
|
|
1625
|
+
The transmits, in order. Each one must have the same source coordinates
|
|
1626
|
+
and the same signal kinds as the Solver's source. The signals may differ in
|
|
1627
|
+
length and are padded with trailing zeros to the longest drive; with
|
|
1628
|
+
``use_ultra=True`` they must have one length.
|
|
1546
1629
|
The Solver's ``source_type`` applies to every transmit.
|
|
1547
1630
|
simulation_dir_name : str | Path
|
|
1548
1631
|
The directory name of the simulation under the work directory.
|
|
@@ -1604,7 +1687,7 @@ class Solver:
|
|
|
1604
1687
|
highpass_cutoff_mhz=highpass_cutoff_mhz,
|
|
1605
1688
|
bandpass_cutoff_mhz=bandpass_cutoff_mhz,
|
|
1606
1689
|
)
|
|
1607
|
-
members = self._batch_members(sources)
|
|
1690
|
+
members = self._batch_members(self._pad_to_longest_drive(sources))
|
|
1608
1691
|
# The sensor and the sizing below need the extended grid and medium.
|
|
1609
1692
|
self.pml_builder.run(use_pml=self.use_pml)
|
|
1610
1693
|
sensor = self._output_sensor(
|
|
@@ -1647,6 +1730,43 @@ class Solver:
|
|
|
1647
1730
|
return [path for run_paths in outputs for path in run_paths]
|
|
1648
1731
|
return np.concatenate(outputs, axis=0)
|
|
1649
1732
|
|
|
1733
|
+
def _pad_to_longest_drive(self, sources: Sequence[fullwave.Source]) -> list[fullwave.Source]:
|
|
1734
|
+
"""Return the transmits with every signal padded with zeros to the longest drive.
|
|
1735
|
+
|
|
1736
|
+
The longest drive is the longest signal among the transmits and the Solver's
|
|
1737
|
+
source. The transmits are copied; the given sources stay as they are.
|
|
1738
|
+
|
|
1739
|
+
Parameters
|
|
1740
|
+
----------
|
|
1741
|
+
sources : Sequence[fullwave.Source]
|
|
1742
|
+
The transmits, in order.
|
|
1743
|
+
|
|
1744
|
+
Returns
|
|
1745
|
+
-------
|
|
1746
|
+
list[fullwave.Source]
|
|
1747
|
+
The transmits, with signals of equal length.
|
|
1748
|
+
|
|
1749
|
+
"""
|
|
1750
|
+
names = ("p0", "p0_additive", "u0", "v0", "w0")
|
|
1751
|
+
reference = [self.source] if getattr(self, "source", None) is not None else []
|
|
1752
|
+
padded = []
|
|
1753
|
+
for source in sources:
|
|
1754
|
+
member = copy.copy(source)
|
|
1755
|
+
for name in names:
|
|
1756
|
+
signal = getattr(member, name, None)
|
|
1757
|
+
if signal is None:
|
|
1758
|
+
continue
|
|
1759
|
+
length = max(
|
|
1760
|
+
np.shape(getattr(other, name, None))[-1]
|
|
1761
|
+
for other in [*sources, *reference]
|
|
1762
|
+
if getattr(other, name, None) is not None
|
|
1763
|
+
)
|
|
1764
|
+
if np.shape(signal)[-1] < length:
|
|
1765
|
+
pad = [(0, 0)] * (np.ndim(signal) - 1) + [(0, length - np.shape(signal)[-1])]
|
|
1766
|
+
setattr(member, name, np.pad(signal, pad))
|
|
1767
|
+
padded.append(member)
|
|
1768
|
+
return padded
|
|
1769
|
+
|
|
1650
1770
|
def _batch_members(self, sources: Sequence[fullwave.Source]) -> list[fullwave.Source]:
|
|
1651
1771
|
"""Check the transmits of a batch against the Solver's source and return them.
|
|
1652
1772
|
|
|
@@ -1730,7 +1850,10 @@ class Solver:
|
|
|
1730
1850
|
return f"the {kind} signal is present in only one of them"
|
|
1731
1851
|
if expected is None:
|
|
1732
1852
|
continue
|
|
1733
|
-
if
|
|
1853
|
+
if (
|
|
1854
|
+
np.shape(found)[:-1] != np.shape(expected)[:-1]
|
|
1855
|
+
or np.shape(found)[-1] < np.shape(expected)[-1]
|
|
1856
|
+
):
|
|
1734
1857
|
return f"the {kind} signal shape {np.shape(found)} != {np.shape(expected)}"
|
|
1735
1858
|
expected_coords = getattr(self.source, coords, None)
|
|
1736
1859
|
found_coords = getattr(member, coords, None)
|