[us-commits] [ehb54/ultrascan3] 041b2a: restyle the ultrascan ui for a more modern look (#...
alexsav815
noreply at github.com
Wed Sep 2 11:15:48 MDT 2026
Branch: refs/heads/alexey-dev-issue983
Home: https://github.com/ehb54/ultrascan3
Commit: 041b2a00530d6a8e9f9f5dfa4281e79ae37dbeeb
https://github.com/ehb54/ultrascan3/commit/041b2a00530d6a8e9f9f5dfa4281e79ae37dbeeb
Author: Lukas Dobler <69309597+doluk at users.noreply.github.com>
Date: 2026-08-11 (Tue, 11 Aug 2026)
Changed paths:
M doc/manual/source/config.rst
M gui/libus_gui.pro
M gui/us_associations_gui.cpp
M gui/us_extinction_gui.cpp
M gui/us_gui_settings.cpp
M gui/us_gui_settings.h
M gui/us_investigator.cpp
M gui/us_license.cpp
M gui/us_minimize.cpp
M gui/us_model_loader.cpp
M gui/us_new_spectrum.cpp
M gui/us_plot.cpp
M gui/us_predict1.cpp
M gui/us_project_gui.cpp
M gui/us_rotor_gui.cpp
A gui/us_style.cpp
A gui/us_style.h
A gui/us_theme.cpp
A gui/us_theme.h
M gui/us_widgets.cpp
M gui/us_widgets.h
M gui/us_widgets_dialog.cpp
M programs/us/us.cpp
M programs/us_config/us_color.cpp
M programs/us_config/us_color.h
M programs/us_grid_editor/us_grid_editor.cpp
M programs/us_mwl_species_fit/us_mwl_sf_plot3d.cpp
M programs/us_spectrum/us_spectrum.cpp
Log Message:
-----------
restyle the ultrascan ui for a more modern look (#505)
* restyle the ultrascan ui
Signed-off-by: doluk <69309597+doluk at users.noreply.github.com>
* restyle the ultrascan ui part 2
Signed-off-by: doluk <69309597+doluk at users.noreply.github.com>
---------
Signed-off-by: doluk <69309597+doluk at users.noreply.github.com>
Commit: bae8eb11ae00a597e0f2e59fca48dfdf174e0963
https://github.com/ehb54/ultrascan3/commit/bae8eb11ae00a597e0f2e59fca48dfdf174e0963
Author: aaron-auc <aaron at aucsolutions.com>
Date: 2026-08-13 (Thu, 13 Aug 2026)
Changed paths:
M scripts/build.ps1
Log Message:
-----------
Fix Windows nightly build by not checking out the vcpkg baseline commit
Commit: ababbdb714b89e2ad29c500c895a00eefef70dca
https://github.com/ehb54/ultrascan3/commit/ababbdb714b89e2ad29c500c895a00eefef70dca
Author: aaron-auc <95181880+aaron-auc at users.noreply.github.com>
Date: 2026-08-13 (Thu, 13 Aug 2026)
Changed paths:
M scripts/build.ps1
Log Message:
-----------
Merge pull request #513 from ehb54/fix/windows-vcpkg-baseline-checkout
Fix Windows nightly build by not checking out the vcpkg baseline commit
Commit: ecd796cb83c91e18f73a7ebb45c03b5a3f6de753
https://github.com/ehb54/ultrascan3/commit/ecd796cb83c91e18f73a7ebb45c03b5a3f6de753
Author: Lukas Dobler <69309597+doluk at users.noreply.github.com>
Date: 2026-08-14 (Fri, 14 Aug 2026)
Changed paths:
M CMakePresets.json
M gui/us_abstractrotor_gui.cpp
M gui/us_analysis_base2.h
M gui/us_analyte_gui.cpp
M gui/us_associations_gui.cpp
M gui/us_associations_gui.h
M gui/us_buffer_gui.cpp
M gui/us_choice.cpp
M gui/us_combined_plots_parms_gui.cpp
M gui/us_convert_gui.cpp
M gui/us_convert_gui.h
M gui/us_data_loader.cpp
M gui/us_edit_spectrum.cpp
M gui/us_editor.cpp
M gui/us_experiment_gui.cpp
M gui/us_extinctfitter_gui.cpp
M gui/us_extinction_gui.cpp
M gui/us_failed_gmp_run_gui.cpp
M gui/us_get_run.cpp
M gui/us_intensity.cpp
M gui/us_investigator.cpp
M gui/us_license.cpp
M gui/us_load_auc.cpp
M gui/us_minimize.cpp
M gui/us_model_gui.cpp
M gui/us_model_loader.cpp
M gui/us_new_spectrum.cpp
M gui/us_noise_loader.cpp
M gui/us_passwd.cpp
M gui/us_plot.cpp
M gui/us_plot3d.cpp
M gui/us_predict1.cpp
M gui/us_predict1.h
M gui/us_project_gui.cpp
M gui/us_properties.cpp
M gui/us_properties.h
M gui/us_report_general_gui.cpp
M gui/us_report_gui.cpp
M gui/us_rotor_gui.cpp
M gui/us_run_details2.cpp
M gui/us_sassoc.cpp
M gui/us_sassoc.h
M gui/us_scan_excl_gui.cpp
M gui/us_select_edits.cpp
M gui/us_select_item.cpp
M gui/us_select_runs.cpp
M gui/us_select_triples.cpp
M gui/us_sim_params_gui.cpp
M gui/us_solution_gui.cpp
M gui/us_table.cpp
M gui/us_tmst_plot.cpp
M gui/us_widgets.cpp
M programs/us/us.cpp
M programs/us_2dplot/us_2dplot.cpp
M programs/us_2dsa/us_2dsa.cpp
M programs/us_2dsa/us_2dsa_process.cpp
M programs/us_2dsa/us_adv_analysis_2d.cpp
M programs/us_2dsa/us_analysis_control_2d.cpp
M programs/us_2dsa/us_plot_control_2d.cpp
M programs/us_2dsa/us_resplot_2d.cpp
M programs/us_2dsa/us_show_norm.cpp
M programs/us_2dsa/us_show_norm.h
M programs/us_2dsa/us_worker_2d.cpp
M programs/us_abde/us_abde_main.cpp
M programs/us_abde/us_norm_profile.cpp
M programs/us_abde/us_norm_profile.h
M programs/us_analysis_profile/us_analysis_profile.cpp
M programs/us_astfem_sim/us_astfem_sim.cpp
M programs/us_astfem_sim/us_clipdata.cpp
M programs/us_audit_trail_gmp/us_audit_trail_gmp.cpp
M programs/us_autoflow_analysis/us_autoflow_analysis.cpp
M programs/us_autoflow_analysis/us_autoflow_analysis.h
M programs/us_buoyancy/us_buoyancy.cpp
M programs/us_colorgradient/us_colorgradient.cpp
M programs/us_com_project/us_com_project_gui.cpp
M programs/us_com_project/us_com_project_gui.h
M programs/us_combine_models/us_combine_models.cpp
M programs/us_config/us_admin.cpp
M programs/us_config/us_advanced.cpp
M programs/us_config/us_color.cpp
M programs/us_config/us_config.cpp
M programs/us_config/us_database.cpp
M programs/us_config/us_font.cpp
M programs/us_config/us_newxpnhost_db.cpp
M programs/us_config/us_xpnhost.cpp
M programs/us_config/us_xpnhost_db.cpp
M programs/us_ddist_combine/us_ddist_combine.cpp
M programs/us_ddist_combine/us_select_rundd.cpp
M programs/us_density_match/us_density_match.cpp
M programs/us_density_match/us_model_params.cpp
M programs/us_density_match/us_remove_models.cpp
M programs/us_dmga_init/us_constraints_edit.cpp
M programs/us_dmga_init/us_dmga_init.cpp
M programs/us_edit/us_edit.cpp
M programs/us_edit/us_edit.h
M programs/us_edit/us_edit_scan.cpp
M programs/us_edit/us_exclude_profile.cpp
M programs/us_edit/us_get_edit.cpp
M programs/us_edit/us_ri_noise.cpp
M programs/us_edit/us_select_lambdas.cpp
M programs/us_equiltime/us_equiltime.cpp
M programs/us_esigner_gmp/us_esigner_gmp.cpp
M programs/us_esigner_gmp/us_esigner_gmp.h
M programs/us_experiment/us_exp_utils.cpp
M programs/us_experiment/us_experiment_gui_optima.cpp
M programs/us_experiment/us_proto_ranges.cpp
M programs/us_export_legacy/us_export.cpp
M programs/us_fds_filemanager/us_fds_filemanager.cpp
M programs/us_fematch/us_adv_dmgamc.cpp
M programs/us_fematch/us_advanced_fem.cpp
M programs/us_fematch/us_fematch.cpp
M programs/us_fematch/us_plot_control_fem.cpp
M programs/us_fematch/us_resplot_fem.cpp
M programs/us_fematch/us_thread_worker.cpp
M programs/us_fit_meniscus/us_fit_meniscus.cpp
M programs/us_ga_init/us_ga_init.cpp
M programs/us_globalequil/us_eqfit_control.cpp
M programs/us_globalequil/us_eqmodel_control.cpp
M programs/us_globalequil/us_globalequil.cpp
M programs/us_globalequil/us_long_messagebox.cpp
M programs/us_globalequil/us_model_adpars.cpp
M programs/us_globalequil/us_model_select.cpp
M programs/us_grid_editor/us_grid_editor.cpp
M programs/us_helpdaemon/us_helpdaemon.cpp
M programs/us_integral/us_delete_models.cpp
M programs/us_integral/us_integral.cpp
M programs/us_manage_data/us_data_tree.cpp
M programs/us_manage_data/us_manage_data.cpp
M programs/us_modelmetrics/us_modelmetrics.cpp
M programs/us_mwl_species_fit/us_mwl_sf_plot3d.cpp
M programs/us_mwl_species_fit/us_mwl_species_fit.cpp
M programs/us_mwl_species_sim/us_mwl_species_sim.cpp
M programs/us_mwl_spectra/us_mwl_spectra.cpp
M programs/us_mwl_spectra/us_mwls_pltctl.cpp
M programs/us_mwlr_viewer/us_mwl_pltctrl.cpp
M programs/us_mwlr_viewer/us_mwl_run.cpp
M programs/us_mwlr_viewer/us_mwlr_viewer.cpp
M programs/us_pcsa/us_adv_analysis_pc.cpp
M programs/us_pcsa/us_adv_analysis_pc.h
M programs/us_pcsa/us_analysis_control_pc.cpp
M programs/us_pcsa/us_mlplot.cpp
M programs/us_pcsa/us_mrecs_loader.cpp
M programs/us_pcsa/us_pcsa_process.cpp
M programs/us_pcsa/us_plot_control_pc.cpp
M programs/us_pcsa/us_resplot_pc.cpp
M programs/us_pcsa/us_rpscan.cpp
M programs/us_predict2/us_predict2.cpp
M programs/us_protocol_dev/us_protocol_dev_gui.cpp
M programs/us_protocol_dev/us_protocol_dev_gui.h
M programs/us_pseudo3d_combine/us_remove_distros.cpp
M programs/us_pseudo_absorbance/us_add_refScan.cpp
M programs/us_pseudo_absorbance/us_convert_scan.cpp
M programs/us_pseudo_absorbance/us_pseudo_absorbance.cpp
M programs/us_pseudo_absorbance/us_remove_ri.cpp
M programs/us_query_rmsd/us_query_rmsd.cpp
M programs/us_ramp/us_experiment_gui_ra.cpp
M programs/us_ramp/us_get_dbrun_ra.cpp
M programs/us_ramp/us_intensity_ra.cpp
M programs/us_ramp/us_ramp_gui.cpp
M programs/us_ramp/us_select_triples_ra.cpp
M programs/us_reporter/us_reporter.cpp
M programs/us_reporter/us_sync_db.cpp
M programs/us_reporter_gmp/us_reporter_gmp.cpp
M programs/us_reporter_gmp/us_reporter_gmp.h
M programs/us_rotor_calibration/us_get_dbexp.cpp
M programs/us_rotor_calibration/us_rotor_calibration.cpp
M programs/us_second_moment/us_second_moment.cpp
M programs/us_tmst_viewer/us_tmst_viewer.cpp
M programs/us_vhw_combine/us_select_runid.cpp
M programs/us_vhw_combine/us_vhw_combine.cpp
M programs/us_vhw_combine/us_vhwc_pltctl.cpp
M programs/us_vhw_enhanced/us_distrib_plot.cpp
M programs/us_vhw_enhanced/us_vhw_enhanced.cpp
M programs/us_xpn_viewer/us_xpn_run_auc.cpp
M programs/us_xpn_viewer/us_xpn_run_raw.cpp
M programs/us_xpn_viewer/us_xpn_viewer_gui.cpp
M programs/us_xpn_viewer/us_xpn_viewer_gui.h
M utils/us_extern.h
M utils/us_http_post.cpp
M utils/us_link_ssl.cpp
Log Message:
-----------
Modernize connect syntax by removing old SIGNAL and SLOT macros (#499)
* Convert connects
* automatic connect conversion
* automatic connect conversion
* fix buttons in us_fematch
* Fix details
* Remove do_pltbm condition from us_resplot_fem.cpp
Removed the condition for do_pltbm variable.
* Revert changes
* Fix connects
* Fix vcpkg manifest feature in CMakePresets
* update connect
* update connect
* Remove updateSpectrogramColorScale function
Removed the updateSpectrogramColorScale function to simplify the US_Plot class.
* Remove updateSpectrogramColorScale method
Removed updateSpectrogramColorScale method declaration.
Commit: 0f92064f2d57a4d94725d66691ccad6136ff338f
https://github.com/ehb54/ultrascan3/commit/0f92064f2d57a4d94725d66691ccad6136ff338f
Author: aaron-auc <aaron at aucsolutions.com>
Date: 2026-08-15 (Sat, 15 Aug 2026)
Changed paths:
M admin/cmake/packaging/macos/MacDeploy.cmake
M admin/cmake/packaging/macos/MacHpcDeploy.cmake
M doc/manual/source/start_page-new.rst
M pkg/macos/README.md
M pkg/macos/preinstall
M programs/CMakeLists.txt
Log Message:
-----------
Keep macOS installer changes isolated
Commit: e7d7d74166bcf0202b1e1313a89ae95f28c3d867
https://github.com/ehb54/ultrascan3/commit/e7d7d74166bcf0202b1e1313a89ae95f28c3d867
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_saxs_hplc.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_options.cpp
M us_somo/develop/src/us_hydrodyn_settings.cpp
M us_somo/etc/somo.config.new
M us_somo/etc/somo.defaults.new
Log Message:
-----------
somo hplc saxs cyclic fit default
(cherry picked from commit 23217df32eb9c68071477b35b91c8fec2700f461)
Commit: 7438262147dd1359ba28bc1488a4106c04ea56bd
https://github.com/ehb54/ultrascan3/commit/7438262147dd1359ba28bc1488a4106c04ea56bd
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_dad.cpp
M us_somo/develop/src/us_hydrodyn_dad_makeiq.cpp
M us_somo/develop/src/us_hydrodyn_dad_modes.cpp
M us_somo/develop/src/us_hydrodyn_dad_options.cpp
M us_somo/develop/src/us_hydrodyn_mals.cpp
M us_somo/develop/src/us_hydrodyn_mals_makeiq.cpp
M us_somo/develop/src/us_hydrodyn_mals_modes.cpp
M us_somo/develop/src/us_hydrodyn_mals_options.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_makeiq.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_modes.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_options.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_makeiq.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_modes.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_options.cpp
Log Message:
-----------
somo smoothing -> smoothing radius
(cherry picked from commit 467b139eb8e4ea286425423605382e86abcc4d93)
Commit: f1f8287f2cd7c1abc01382a2f090b42557238179
https://github.com/ehb54/ultrascan3/commit/f1f8287f2cd7c1abc01382a2f090b42557238179
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_dad_options.cpp
M us_somo/develop/src/us_hydrodyn_mals_options.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_options.cpp
M us_somo/develop/src/us_hydrodyn_saxs.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_bl.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_options.cpp
Log Message:
-----------
somo more smoothing->smoothing radius
(cherry picked from commit 8e831017ea17956e3fa307390f41e7e0fe89092f)
Commit: e488e8dde2a2dc1ee7950f1dabe8b464995bbc43
https://github.com/ehb54/ultrascan3/commit/e488e8dde2a2dc1ee7950f1dabe8b464995bbc43
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_dad.cpp
M us_somo/develop/src/us_hydrodyn_dad_util.cpp
Log Message:
-----------
somo uv vis support alternate format loads
(cherry picked from commit 685dfdc0eed41b0d5a219a19b45829952ae8bd23)
Commit: ab91198e70eef4fb3dfe8f638456ab92d2786f86
https://github.com/ehb54/ultrascan3/commit/ab91198e70eef4fb3dfe8f638456ab92d2786f86
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_saxs.h
A us_somo/develop/include/us_hydrodyn_saxs_iqq_extrap_c0_conc.h
M us_somo/develop/include/us_hydrodyn_saxs_iqq_load_csv.h
M us_somo/develop/libus_somo.pro
A us_somo/develop/src/us_hydrodyn_saxs_iqq_extrap_c0.cpp
A us_somo/develop/src/us_hydrodyn_saxs_iqq_extrap_c0_conc.cpp
M us_somo/develop/src/us_hydrodyn_saxs_iqq_load_csv.cpp
M us_somo/develop/src/us_hydrodyn_saxs_loads.cpp
Log Message:
-----------
Add extrapolation to zero concentration for I(q) CSV load dialog
Adds a Zimm-plot-style q-pointwise linear extrapolation to zero
concentration in US_Hydrodyn_Saxs_Iqq_Load_Csv: select >=3 curves,
assign each a concentration via a new modal dialog, and add the
resulting intercept curve (with fit-derived intercept SE as error
bars) to the plot.
Co-Authored-By: Claude Sonnet 4.6 <noreply at anthropic.com>
(cherry picked from commit 72352e626deaa05e5ae3b7f742897c42960f6602)
Commit: e1446e72008b6ed2bf63412f637c439da3f91108
https://github.com/ehb54/ultrascan3/commit/e1446e72008b6ed2bf63412f637c439da3f91108
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
A us_somo/somo/doc/manual/somo/DAWN_head.png
A us_somo/somo/doc/manual/somo/MALS_angles.png
A us_somo/somo/doc/manual/somo/WyattRayleigh ratios csv.png
M us_somo/somo/doc/manual/somo/mals_parameters.html
M us_somo/somo/doc/manual/somo/mals_saxs_options.html
M us_somo/somo/doc/manual/somo/saxs_hplc_options.html
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_EMG_option.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_GaussFit1.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_GaussFit2.png
A us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_options_Min_Gauss.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_options_new.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_options_new_Gaussians.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_options_new_baseline.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian1.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian11.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian11a.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian11b.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian11c.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian12.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian2.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian3.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian4.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian5.png
A us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian6a.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian8.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian9a.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian_adv_sel.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_smoothing.png
A us_somo/somo/doc/manual/somo/somo-MALS_Concs.png
A us_somo/somo/doc/manual/somo/somo-MALS_Concs2.png
A us_somo/somo/doc/manual/somo/somo-MALS_Concs3.png
A us_somo/somo/doc/manual/somo/somo-MALS_Concs4.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss1anew.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss1bnew.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss1cnew.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss1dnew.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss1enew.png
A us_somo/somo/doc/manual/somo/somo-MALS_GaussFit.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss_all_Idash_t_selected.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gaussian_final.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gaussian_init.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gaussian_options.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gaussian_start.png
A us_somo/somo/doc/manual/somo/somo-MALS_GlobalFit_done.png
A us_somo/somo/doc/manual/somo/somo-MALS_GlobalGauss_done.png
A us_somo/somo/doc/manual/somo/somo-MALS_GlobalGauss_start_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_GlobalGaussianSDreminder.png
A us_somo/somo/doc/manual/somo/somo-MALS_GlobalGaussian_init.png
A us_somo/somo/doc/manual/somo/somo-MALS_I_hash_q_example.png
A us_somo/somo/doc/manual/somo/somo-MALS_I_starq_NoGauss_movieframe155.png
A us_somo/somo/doc/manual/somo/somo-MALS_I_starq_NoGauss_movieframe316.png
A us_somo/somo/doc/manual/somo/somo-MALS_I_starq_NoGauss_movieframe99.png
A us_somo/somo/doc/manual/somo/somo-MALS_Istarq_file_view_selected.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIdash_final.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIdash_final_kin.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIdash_final_kin_cropped.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIdash_final_kin_zoom.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIstar_final_kin.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIstar_sel_kin_dots_err.png
A us_somo/somo/doc/manual/somo/somo-MALS_Messages.png
A us_somo/somo/doc/manual/somo/somo-MALS_Movie_selected.png
A us_somo/somo/doc/manual/somo/somo-MALS_Plot_Options_demo.png
A us_somo/somo/doc/manual/somo/somo-MALS_Produced_data.png
A us_somo/somo/doc/manual/somo/somo-MALS_R_theta_csv_loaded.png
A us_somo/somo/doc/manual/somo/somo-MALS_R_theta_kin_shown.png
A us_somo/somo/doc/manual/somo/somo-MALS_R_theta_shown.png
A us_somo/somo/doc/manual/somo/somo-MALS_Residuals_twocurvesSD.png
A us_somo/somo/doc/manual/somo/somo-MALS_Residuals_twocurves_percent.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_MALS_data_loglog.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Make_scaled_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Messages.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Plot_Options_demo.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Plot_Options_demo2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Produced_data.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Produced_data_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_SAXS_common_times.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_SAXS_common_times_scroll1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_SAXS_common_times_scroll2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_SAXS_data_loading.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_bottom line.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_commons times_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_commontimes_all_dots.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_cropping_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_cropvis_results.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_cropvis_results1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_cropvis_select.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_exclude_q_vis_demo1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_exclude_q_vis_demo2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_fitting_methods.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_generating_joined_excl_q_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_initial.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_joined.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_joined_scroll.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_loadMALS.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_make_scaled.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_make_scaled_popup1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_make_scaled_popup2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_make_scaled_view_MALS_file.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_minimize_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_options.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_options1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_other_MALS_data_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_plot_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_polynomials.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_q_exclude_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_remove_panel.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale3.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale4.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale5.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale6.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale7.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale8.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scaled_MALS_generated_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scaled_SAXS_generated_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scroll_warning.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_second_set_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_second_set_buttons1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_selections_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_top_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_viewselected.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_weighting_methods.png
A us_somo/somo/doc/manual/somo/somo-MALS_SD_eval_applied.png
A us_somo/somo/doc/manual/somo/somo-MALS_SD_eval_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SD_eval_comparisonD2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SD_eval_define_1region.png
A us_somo/somo/doc/manual/somo/somo-MALS_SD_eval_define_2regions.png
A us_somo/somo/doc/manual/somo/somo-MALS_Select_Istarq_for_norm.png
A us_somo/somo/doc/manual/somo/somo-MALS_Selected_Istarq_normalized.png
A us_somo/somo/doc/manual/somo/somo-MALS_Selected_Istarq_normalized_ave.png
A us_somo/somo/doc/manual/somo/somo-MALS_Selected_normalized_ave.png
A us_somo/somo/doc/manual/somo/somo-MALS_Selected_orig_and_norm_files.png
A us_somo/somo/doc/manual/somo/somo-MALS_UV_data_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_adjust_times_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_adjust_times_pop_up2.png
A us_somo/somo/doc/manual/somo/somo-MALS_angles_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_commands1.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_chrom_Gauss_fit.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_chrom_fit_module.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_chrom_init_Gauss.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_used_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_add_MALS_data.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_loaded_data.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_pop_up2.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_pop_up3.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_repeak.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_timeshift.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_timeshift_set.png
A us_somo/somo/doc/manual/somo/somo-MALS_crop_I_dash_chromatograms.png
A us_somo/somo/doc/manual/somo/somo-MALS_cropping_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_inconsistent times_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_incorrect processing_param_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_info_panel.png
A us_somo/somo/doc/manual/somo/somo-MALS_initial.png
A us_somo/somo/doc/manual/somo/somo-MALS_main1.png
A us_somo/somo/doc/manual/somo/somo-MALS_make_Istar_q_enterparam_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_make_Istar_q_enterparam_popup1.png
A us_somo/somo/doc/manual/somo/somo-MALS_make_Istar_q_noGauss_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_no_Gaussians_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_no_conc_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_no_conc_pop_up2.png
A us_somo/somo/doc/manual/somo/somo-MALS_options.png
A us_somo/somo/doc/manual/somo/somo-MALS_options_conc_detector.png
A us_somo/somo/doc/manual/somo/somo-MALS_options_new_Gaussians.png
A us_somo/somo/doc/manual/somo/somo-MALS_options_new_misc.png
A us_somo/somo/doc/manual/somo/somo-MALS_param.png
A us_somo/somo/doc/manual/somo/somo-MALS_plot_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_processing_param_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_processing_param_pop_up2.png
A us_somo/somo/doc/manual/somo/somo-MALS_remove_panel.png
A us_somo/somo/doc/manual/somo/somo-MALS_resulting_I_starq_NoGauss.png
A us_somo/somo/doc/manual/somo/somo-MALS_scattering_angles.png
A us_somo/somo/doc/manual/somo/somo-MALS_second_set_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_selected_Ihash_EMG_GMG.png
A us_somo/somo/doc/manual/somo/somo-MALS_selections_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_set_conc_detector.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians1.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians2.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_GlobFit_Final.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_GlobFit_Init.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_GlobFit_by_q.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_GlobFit_saving_warning.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_GlobGauss.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_scroll1.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_scroll2.png
A us_somo/somo/doc/manual/somo/somo-MALS_six_Gaussians1.png
A us_somo/somo/doc/manual/somo/somo-MALS_six_Gaussians2.png
A us_somo/somo/doc/manual/somo/somo-MALS_timeshift_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_timeshift_pop_up2.png
A us_somo/somo/doc/manual/somo/somo-MALS_top_buttons.png
A us_somo/somo/doc/manual/somo/somo-mals_Residuals_twocurves.png
M us_somo/somo/doc/manual/somo/somo_mals.html
A us_somo/somo/doc/manual/somo/somo_mals_dctr.html
A us_somo/somo/doc/manual/somo/somo_mals_options.html
M us_somo/somo/doc/manual/somo/somo_mals_saxs.html
M us_somo/somo/doc/manual/somo/somo_saxs_hplc.html
M us_somo/somo/doc/manual/somo/somo_saxs_hplc_skewedGauss.html
M us_somo/somo/doc/manual/somo/somo_uv_vis.html
A us_somo/somo/doc/manual/somo_mals.html
Log Message:
-----------
updates
(cherry picked from commit 49c520dd6e3d16b673ad0910be2babff8248d06c)
Commit: 83812c32b6170758681426f592f85149c1224c39
https://github.com/ehb54/ultrascan3/commit/83812c32b6170758681426f592f85149c1224c39
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
A test_data/extrap_c0_test_iqq.csv
A test_data/extrap_c0_test_iqq_poisson.csv
A test_data/gen_extrap_c0_test_iqq.py
M us_somo/develop/src/us_hydrodyn_saxs_iqq_extrap_c0.cpp
M us_somo/develop/src/us_hydrodyn_saxs_iqq_extrap_c0_conc.cpp
Log Message:
-----------
Fix conc_csv name-key mismatch, widen conc dialog, fix cancel flow, raw test data
- do_extrap_c0: prepopulation lookup and write-back now also try the
dequoted curve name against conc_csv, fixing concentrations not being
found for curves pushed in from SAXS Hplc (to_saxs() keys conc_csv by
the bare unquoted plotted name, while curves selected via the "just
plotted curves" load path are quoted to match the CSV-row convention).
- Cancelling the concentration-assignment dialog now raises/shows the
main plot window and logs a message instead of silently returning.
- The concentration-assignment dialog is now sized to the longest
selected curve name instead of a fixed width.
- Regenerated the synthetic test CSVs to use raw, concentration-
proportional intensities (I(0) scales with c, plus a small
structure-factor-like nonlinearity) instead of pre-normalized
intensities, since load_iqq_csv curves are expected to be raw.
Co-Authored-By: Claude Sonnet 4.6 <noreply at anthropic.com>
(cherry picked from commit 1ecc8ce4ff282a725727bdc3f76ceb6b57104f78)
Commit: 453997ee9d045b0b324ae9e050aee9154f996dee
https://github.com/ehb54/ultrascan3/commit/453997ee9d045b0b324ae9e050aee9154f996dee
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_saxs_loads.cpp
Log Message:
-----------
Parse Conc:/PSV:/I0se: header tags when loading .dat/.txt/.sprr directly
load_saxs() and load_sans() (the main SAXS/SANS window's direct file
loader, used when picking individual .dat/.txt/.sprr files rather than
going through the HPLC module) never read the Conc:/PSV:/I0se: header
comment line, so conc_csv was never populated for curves loaded this
way -- do_extrap_c0's concentration pre-population had nothing to find.
Reuses the exact regexes already established in
US_Hydrodyn_Saxs_Hplc::load_file() and calls update_conc_csv() right
after the curve is plotted, keyed by the same name plot_one_iqq() uses.
Co-Authored-By: Claude Sonnet 4.6 <noreply at anthropic.com>
(cherry picked from commit e54705492a8105b4997dc81f9b3ed185ab60a43b)
Commit: 5bcec47256f2a2c9a0210a36550e3ce0086d287a
https://github.com/ehb54/ultrascan3/commit/5bcec47256f2a2c9a0210a36550e3ce0086d287a
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_saxs_iqq_extrap_c0.cpp
Log Message:
-----------
Normalize by concentration before per-q regression in do_extrap_c0
Raw SAXS intensity is dominated by a term directly proportional to
concentration, so fitting raw I(q) vs c trivially extrapolates to ~0
at c=0 -- confirmed on real asyn data, where the output curve was
just noise oscillating around zero. The standard SAXS technique (the
Zimm-plot analogue) fits I(q,c)/c against c instead; its c=0 intercept
recovers the ideal, structure-factor-free dilute-limit curve.
Concentration (x-axis) stays the real, distinct entered values --
only the intensity (y-axis) is divided by each curve's own
concentration. Curves with concentration <= 0 are excluded from the
regression (can't normalize by zero) with a warning. Output curve is
now in concentration-normalized units, noted in the summary message.
Validated against the 6 real asyn .dat files: the normalized
intercept now produces a smooth, positive, Guinier-shaped curve
instead of near-zero noise.
Co-Authored-By: Claude Sonnet 4.6 <noreply at anthropic.com>
(cherry picked from commit 2d5bca3b5b3a7110db6eefcdb28ef3ff644fad9c)
Commit: e6dd622e498cb0737196bd2d3b2759cd3202e3ed
https://github.com/ehb54/ultrascan3/commit/e6dd622e498cb0737196bd2d3b2759cd3202e3ed
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_saxs_iqq_extrap_c0.cpp
Log Message:
-----------
Tag extrap_c0 output curve as concentration-normalized (Conc:1)
The extrapolated curve is I(q)/c extrapolated to c=0, i.e. already
concentration-normalized -- mark it conc=1 in conc_csv per SOMO's
existing Conc:1-means-normalized convention, so anything downstream
that respects conc_csv (e.g. selecting it for a further extrapolation)
treats it correctly rather than as a raw curve with concentration 1.
Co-Authored-By: Claude Sonnet 4.6 <noreply at anthropic.com>
(cherry picked from commit 0df3387554c95a4ed1d6c69615a7e992e584a4ef)
Commit: f0de9a1a24aabf066eb46de10d36c9eb4dd2d2ff
https://github.com/ehb54/ultrascan3/commit/f0de9a1a24aabf066eb46de10d36c9eb4dd2d2ff
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_saxs_iqq_load_csv.cpp
Log Message:
-----------
Don't clear the plot before extrapolate-to-zero-conc has been confirmed
load_iqq_csv() clears the entire plot right after the load dialog
closes, whenever "Clear plot" is checked (the default) -- this
happened unconditionally before the new concentration-assignment
dialog even opened, so cancelling that dialog left the user with an
empty plot and no way to recover the previously plotted curves.
run_ift already avoids this exact problem by force-disabling "Clear
plot" while it's active; set_extrapolate_c0() now does the same, so
the plot is left untouched until/unless the extrapolation actually
completes.
Co-Authored-By: Claude Sonnet 4.6 <noreply at anthropic.com>
(cherry picked from commit 243154e9c162112ff1cc51a473c9da664e041c38)
Commit: b0d1074b4720e6b91e0e9ec9cd3be69ea4a08210
https://github.com/ehb54/ultrascan3/commit/b0d1074b4720e6b91e0e9ec9cd3be69ea4a08210
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_saxs_hplc.h
M us_somo/develop/src/us_hydrodyn_saxs.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc.cpp
Log Message:
-----------
Propagate concentrations when pushing curves from SOMO SAS to HPLC
US_Hydrodyn_Saxs::saxs_hplc() (the "Hplc/Saxs" button in SOMO SAS) added
curves to the HPLC window via add_plot() with no concentration at all,
so f_conc in HPLC was always 0/unknown for curves arriving this way --
the reverse direction of the to_saxs() push, which already carried
concentration across.
- US_Hydrodyn_Saxs_Hplc::add_plot() (both overloads) gains an optional
trailing conc parameter (default -1, meaning "not specified", fully
backward compatible with existing callers); when >= 0 it's written to
f_conc, overriding the previous "preserve existing or default 0e0"
fallback.
- saxs_hplc() now looks up each plotted curve's concentration via the
SAXS window's own get_conc_csv_values() and passes it through.
- update_csv_conc() (HPLC's own "Solution Concentrations" table) now
backfills new rows from f_conc instead of seeding them blank, so a
propagated concentration is also visible in that window, not just
used internally.
Co-Authored-By: Claude Sonnet 4.6 <noreply at anthropic.com>
(cherry picked from commit 5e5d55ff38ee408d8bfb00d765599dbcf1acdb7f)
Commit: a5b477eb4e1da534c8e3be3e8193c785b55fe1a2
https://github.com/ehb54/ultrascan3/commit/a5b477eb4e1da534c8e3be3e8193c785b55fe1a2
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_dad_conc.cpp
M us_somo/develop/src/us_hydrodyn_dad_conc_load.cpp
M us_somo/develop/src/us_hydrodyn_mals_conc.cpp
M us_somo/develop/src/us_hydrodyn_mals_conc_load.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_conc.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_conc_load.cpp
M us_somo/develop/src/us_hydrodyn_saxs_buffer_conc.cpp
M us_somo/develop/src/us_hydrodyn_saxs_buffer_conc_load.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_conc.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_conc_load.cpp
Log Message:
-----------
Fix "No such signal QHeaderView::released(int)" warning in conc dialogs
QHeaderView::released(int) is a Qt3/Qt4 signal name that doesn't exist
in Qt5 (it's the column/row header click handler in the various
"Concentrations" table dialogs across DAD, MALS, MALS+SAXS, SAXS,
SAXS buffer, and SAXS Hplc/Kin). The connect() silently failed at
runtime with a console warning, and the header-click slot (col/row
_header_released) never fired.
us_hydrodyn_saxs_conc.cpp already had the correct fix, properly guarded
behind #if QT_VERSION < 0x040000 / #else sectionClicked(int) / #endif --
the other 10 copy-pasted variants of this dialog never got that fix and
had the broken signal name unconditionally. Replaced with
sectionClicked(int) (the Qt5 equivalent) in all of them, matching the
already-proven-working pattern.
Co-Authored-By: Claude Sonnet 4.6 <noreply at anthropic.com>
(cherry picked from commit c7ebdda2f2175331c0231fbc2fe4e7cc9eebbeda)
Commit: 8b7f2758868445e7176e7a99d00f8e15e417e826
https://github.com/ehb54/ultrascan3/commit/8b7f2758868445e7176e7a99d00f8e15e417e826
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
R test_data/extrap_c0_test_iqq.csv
R test_data/extrap_c0_test_iqq_poisson.csv
R test_data/gen_extrap_c0_test_iqq.py
Log Message:
-----------
Remove test data from top-level test_data/
Synthetic CSV fixtures and the generator script do not belong committed
to the repo, least of all in a top-level directory.
(cherry picked from commit 7f1178ad2883095f6ddaee0b8da45ee644b1d378)
Commit: fc4a2ca4b6d0f2ae5ea4069dc8363d34bc497347
https://github.com/ehb54/ultrascan3/commit/fc4a2ca4b6d0f2ae5ea4069dc8363d34bc497347
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_dad_fit.h
M us_somo/develop/include/us_hydrodyn_dad_options.h
M us_somo/develop/include/us_hydrodyn_mals_fit.h
M us_somo/develop/include/us_hydrodyn_mals_options.h
M us_somo/develop/include/us_hydrodyn_mals_saxs_fit.h
M us_somo/develop/include/us_hydrodyn_mals_saxs_options.h
M us_somo/develop/src/us_hydrodyn_dad.cpp
M us_somo/develop/src/us_hydrodyn_dad_fit.cpp
M us_somo/develop/src/us_hydrodyn_dad_options.cpp
M us_somo/develop/src/us_hydrodyn_dad_util.cpp
M us_somo/develop/src/us_hydrodyn_mals.cpp
M us_somo/develop/src/us_hydrodyn_mals_fit.cpp
M us_somo/develop/src/us_hydrodyn_mals_options.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_fit.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_options.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_util.cpp
M us_somo/develop/src/us_hydrodyn_mals_util.cpp
Log Message:
-----------
Roll out per-amplitude Gaussian minimum to dad/mals/mals_saxs fit modules
HPLC's Gaussian fit split its single amplitude-and-width floor
(hplc_ampl_width_min) into two independent minimums: the pre-existing
one continues to bound width, while the new hplc_ampl_min bounds
amplitude. The sibling dad/mals/mals_saxs SAXS fit modules were never
updated to match, so their amplitude clamp (in setup_run and
lock_zeros) still reuses the combined width_min value.
Add the same ampl_min gparam, options-dialog widget, and fit-module
member to dad, mals, and mals_saxs, and repoint their amplitude clamp
logic at it, mirroring hplc_fit.cpp/hplc_options.cpp/hplc.cpp exactly.
(cherry picked from commit 768ca91ff963992cfbb912f512740052402f1fac)
Commit: a8b09fc57895d9cdee9a8f7d13937c15c0cbf9be
https://github.com/ehb54/ultrascan3/commit/a8b09fc57895d9cdee9a8f7d13937c15c0cbf9be
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_saxs_hplc.cpp
Log Message:
-----------
Fix SIGSEGV in HPLC SAXS get_peak: use file, not wheel_file, for end-range clamp
get_peak() operates on its `file` argument, but the gauss-fit-end range
clamp compared the typed value against f_qs[ wheel_file ].back() instead
of f_qs[ file ].back(). During Repeak, wheel_file is stale or empty (it is
never set in repeak()), so f_qs[ wheel_file ] default-inserts an empty
vector and .back() dereferences nullptr-8 (0xfffffffffffffff8), crashing.
The check is now symmetric with the start-range clamp above and with its
own body on the next line, both of which key on `file`.
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
(cherry picked from commit f087cb2f504871f6f79df846004b7ea6f0926d57)
Commit: 60e7a3010157adf3e83d93001aac6ddde8941eb0
https://github.com/ehb54/ultrascan3/commit/60e7a3010157adf3e83d93001aac6ddde8941eb0
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_saxs_hplc_ciq.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_options.cpp
M us_somo/somo/doc/manual/somo/saxs_hplc_ciq.html
M us_somo/somo/doc/manual/somo/somo_saxs_hplc.html
Log Message:
-----------
HPLC/KIN Make I(q): clarify the top-% peak average retains concentration
Relabel the "average and normalize" checkbox to "average", add a tooltip,
and update the manual, to make explicit that the existing per-peak "_avg"
curve is scaled to the mean concentration of the averaged frames (the
concentration-scaled result, for Guinier/MW) while "_avg_n" is normalized
to concentration 1.0. No change to the averaging computation.
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit c48d229f1006f0bd3360ff1fdf821482d198087d)
Commit: 11b1c559a69cc8667517e7b2ba9262e5db4d5b16
https://github.com/ehb54/ultrascan3/commit/11b1c559a69cc8667517e7b2ba9262e5db4d5b16
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_saxs_hplc_ciq.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_options.cpp
Log Message:
-----------
Format Make I(q) average tooltip with HTML line breaks
Qt renders the tooltip as rich text, so split the single run-on line into
per-suffix lines with <br> for readability.
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit 36a225651effc35e6944ed6c878c58c8ba575af1)
Commit: 72cdaaa4b996bff8a55e29257e8c19be52ae60ce
https://github.com/ehb54/ultrascan3/commit/72cdaaa4b996bff8a55e29257e8c19be52ae60ce
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_vector.h
M us_somo/develop/src/us_hydrodyn_dad_util.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_util.cpp
M us_somo/develop/src/us_hydrodyn_mals_util.cpp
M us_somo/develop/src/us_hydrodyn_saxs_buffer.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_util.cpp
M us_somo/develop/src/us_vector.cpp
M us_somo/somo/doc/manual/somo/somo_mals.html
M us_somo/somo/doc/manual/somo/somo_mals_saxs.html
M us_somo/somo/doc/manual/somo/somo_saxs_hplc.html
M us_somo/somo/doc/manual/somo/somo_uv_vis.html
Log Message:
-----------
Fix Crop Common dropping points due to 6-sig-fig q rounding
Crop Common built the shared grid via US_Vector::intersection(), which
matches q values by exact double equality. Because .dat files store q to
6 significant figures, the same physical q point is rounded slightly
differently between files (e.g. 0.00547318 vs 0.00547317), so those
points missed the exact match and were dropped, leaving "holes" in the
common grid. On a set of 7 AlphaSyn HPLC curves this cut the common grid
from ~1053 points to 803.
Add US_Vector::canonical_map(), which clusters q values whose relative
gap is <= reltol (1e-4) and maps each to a canonical representative. A
cluster/tolerance merge (rather than fixed-grid rounding) is used so that
near-identical values never straddle a bin boundary. crop_common() snaps
the grids through this map before intersecting and uses the same map for
the per-curve filter; retained points keep their original q/I/sd values.
Applied to all five crop_common paths: SAXS HPLC/KIN, MALS, DAD (UV/Vis),
MALS-SAXS, and SAXS Buffer. Manual pages updated accordingly. On the 7
test curves the common grid is restored to 1045 points with no
over-merging (min real relative gap 8.3e-4, well above the 1e-4 tol).
Fixes ehb54/ultrascan-tickets#962
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit e4097b6c1c59016b3be6e5cce40619c1bbbe0689)
Commit: 67a51f95783c0c068a3103a4ef0ec219d9ec5ea9
https://github.com/ehb54/ultrascan3/commit/67a51f95783c0c068a3103a4ef0ec219d9ec5ea9
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_saxs_util.h
M us_somo/develop/src/us_saxs_util_static.cpp
Log Message:
-----------
Add US_Saxs_Util::recompute_errors: standalone I(q) error reassessment
Reproduces the spirit of BayesApp's error-assessment stage (Larsen &
Pedersen, J. Appl. Cryst. 2021) without a BIFT fit. A local weighted
quadratic smoother of I(q) supplies residuals and an effective DoF
(hat-trace); a reduced chi-square and two-sided chi-square p-value
(clean-room regularized incomplete gamma) drive the same significance +
>10% gate as bift.f. Rescales sigma in three modes: constant, non-constant
(per-bin, triangular-smoothed) and intensity-dependent.
Standalone approximation only: no p(r) model, no Ng, no Dmax. Documented
as such in the header.
Implements ehb54/ultrascan-tickets#966
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
(cherry picked from commit 0febd2d9418b15f336c31d64e3a6dba485aa3bdb)
Commit: 594fe20f9823a2ff9fc847e5f33fce4498a03424
https://github.com/ehb54/ultrascan3/commit/594fe20f9823a2ff9fc847e5f33fce4498a03424
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_saxs_util.h
M us_somo/develop/src/us_saxs_util_static.cpp
Log Message:
-----------
Guard recompute_errors mode 'I' against negative/zero-crossing intensities
On background-subtracted or extrapolated curves I(q) crosses zero, and the
signed intensity term sigma+a*I could go negative, blowing up the a search
and emitting negative sigma (observed factors -13..1087 on real data). Use
sigma+a*|I| so the term is always >= sigma > 0. Add a general safety clamp
so no mode ever writes a non-positive or non-finite sigma (degenerate factor
falls back to 1). Modes C and N are unchanged.
Implements ehb54/ultrascan-tickets#966
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
(cherry picked from commit 17b63846933b108cf79aa0781ecab9fe533859f5)
Commit: f35defbfd26be62b9c001bc8336309dae4823817
https://github.com/ehb54/ultrascan3/commit/f35defbfd26be62b9c001bc8336309dae4823817
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_saxs_hplc.h
M us_somo/develop/src/us_hydrodyn_saxs_hplc_gui.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_modes.cpp
Log Message:
-----------
Add "SD rescale" button to HPLC/KIN s.d.util mode
Third button in the s.d.util row (alongside "SD eval."/"SD apply") that runs
US_Saxs_Util::recompute_errors on the selected curves. Prompts for the mode
(constant / non-constant / intensity-dependent) via US_Static::getItem (avoids
the OSX QInputDialog-in-slot bug), rescales each curve's SD in place, and logs
the verdict/chi2r/p per curve.
Undo: one full-restore crop_undo_data record per invocation, so the existing
"Crop undo" restores the original SDs. Enabled only for selected q-space curves
that already carry usable errors (all_selected_have_errors: count + matching
size + is_nonzero_vector). Curves lacking usable SDs are skipped with a message.
Implements ehb54/ultrascan-tickets#966
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
(cherry picked from commit 1e0ed9e1faa70de51dffaff5c11c397b7fa02903)
Commit: 8b271168f96e0b1880eaba2c710b8f868c6d492e
https://github.com/ehb54/ultrascan3/commit/8b271168f96e0b1880eaba2c710b8f868c6d492e
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_saxs_hplc.h
M us_somo/develop/src/us_hydrodyn_saxs_hplc_modes.cpp
Log Message:
-----------
Relax SD rescale gate: accept curves with some zero SDs
recompute_errors already excludes individual zero/negative points, so the
gate need only reject all-zero (placeholder) error vectors. Replace the strict
is_nonzero_vector (all non-zero) test with sd_has_usable_errors (at least one
positive value) in both the enable helper and the per-curve skip. Curves with
a few masked/zero-error points are now processed instead of skipped wholesale.
Implements ehb54/ultrascan-tickets#966
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
(cherry picked from commit 5a703361099d4bb8304d7a5477af0bfbc32fb3d7)
Commit: a6023d9d7b3b7d99436d7db24fa924bffb141d5c
https://github.com/ehb54/ultrascan3/commit/a6023d9d7b3b7d99436d7db24fa924bffb141d5c
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_saxs_hplc_modes.cpp
Log Message:
-----------
Show applied scale factor in SD rescale log
The per-curve log now reports the applied factor, not just reduced chi-square:
"factor X" for constant mode (X = sqrt(chi2r)), or "factor median X (min..max)"
for the per-point non-constant / intensity modes. Captures scale_factors from
recompute_errors for the summary.
Implements ehb54/ultrascan-tickets#966
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
(cherry picked from commit b29844fdcf97dde3af2de461f20571d1663441dc)
Commit: 8edd07ed0f01d08dde239c8a5e099d4ca3251666
https://github.com/ehb54/ultrascan3/commit/8edd07ed0f01d08dde239c8a5e099d4ca3251666
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_saxs_hplc_modes.cpp
Log Message:
-----------
Display SD rescale p-value as fixed-point (3 decimals)
Fixed-point 'f' with 3 decimals instead of 'g' scientific notation, so tiny
p-values read as 0.000 rather than e.g. 8.71e-31, while keeping the 0.003
significance threshold legible.
Implements ehb54/ultrascan-tickets#966
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
(cherry picked from commit 7a16b4d8ffd418112c7a52a607c5d2da07f36e88)
Commit: af6583836254ecf8e8d892046d513c1efa43298c
https://github.com/ehb54/ultrascan3/commit/af6583836254ecf8e8d892046d513c1efa43298c
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/somo/doc/manual/somo/somo_saxs_hplc.html
Log Message:
-----------
Document "SD rescale" in HPLC/KIN manual (S.D. Util section)
Add a subsection to the S.D. Util documentation in somo_saxs_hplc.html
describing the new "SD rescale" button: purpose (assess/rescale existing
I(q) errors, vs the baseline-fluctuation SD estimation of eval/apply), the
BayesApp-based method and significance gate, the three modes (constant /
non-constant / intensity-dependent), verdict/factor reporting in Messages,
and undo. Updates the button count (two -> three) and cross-links the
SAS IFT / BayesApp module.
Implements ehb54/ultrascan-tickets#966
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
(cherry picked from commit bd64fd69edefe841b82676a7f5e8fa1faa437d88)
Commit: 74ad6e7883e00a73bdbf492eeee6c9bc1dddb861
https://github.com/ehb54/ultrascan3/commit/74ad6e7883e00a73bdbf492eeee6c9bc1dddb861
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/somo/doc/manual/somo/somo_saxs_hplc.html
Log Message:
-----------
Update last-edited dates on HPLC manual page
Bump "Last updated" (header) and "Last modified" (footer) to July 2026 / July
13, 2026 to reflect the SD rescale documentation addition.
Implements ehb54/ultrascan-tickets#966
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
(cherry picked from commit a92ff44060c764135af406f73ec97b7635aaec33)
Commit: c13477427138bde8333cba604db74d266afd1248
https://github.com/ehb54/ultrascan3/commit/c13477427138bde8333cba604db74d266afd1248
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/etc/somo.residue.new
Log Message:
-----------
Fix deoxynucleotide C2' hybridization: C4H1 -> C4H2
Deoxyribose C2' is bonded to C1', C3' and two hydrogens, so it is a CH2
(C4H2, 14.03). It was typed C4H1 (13.02), the ribose value, where C2'
carries O2' and only one hydrogen.
The deoxy blocks were created by copying the corresponding ribo block and
deleting the O2' atom line, but C2' was never retyped. Every deoxy residue
therefore came out 1.01 Da light, and since residue mass is the sum of its
atom hybrid masses, the error propagated into MW, vbar-weighted quantities
and bead masses for every DNA run.
Corrected in all 22 affected blocks (DA/DC/DG/DT, both the primed and the
starred atom-naming variants, with and without phosphate). Each deoxy
residue is now exactly 16.00 Da below its ribo counterpart, i.e. the loss
of one oxygen and nothing else; previously the gap was 17.01 Da:
A ->DA 266.27 -> 250.27 (-16.00, was -17.01)
C ->DC 242.24 -> 226.24 (-16.00, was -17.01)
G ->DG 282.27 -> 266.27 (-16.00, was -17.01)
U ->DT 243.22 -> 241.25 (-1.97 = -O +CH2, was -2.98)
Ribose C2' (A/C/G/U, and sugars such as LMT) is untouched.
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
(cherry picked from commit 53f39f42b231277e413ace83e548826caa3ab7a4)
Commit: e72f1ea8918a6d6c85b50da8eebda6f2c01fa687
https://github.com/ehb54/ultrascan3/commit/e72f1ea8918a6d6c85b50da8eebda6f2c01fa687
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/etc/somo.atom.new
M us_somo/etc/somo.hybrid.new
M us_somo/etc/somo.residue.new
M us_somo/etc/somo.saxs_atoms.new
Log Message:
-----------
Add molybdenum cluster support to the SOMO parameter files
Adopts the additive part of Mattia's updated parameter files: support for
polyoxomolybdate clusters, which previously could not be typed at all.
somo.hybrid O2H02- (oxide O2-), MO+5, MO+6
somo.atom MO1-MO6 as MO+6, MO7/MO8 as MO+5; O2H02- oxide, O2H2
water and further O1H0 entries for the O1-O27 cluster
oxygens (38 rows)
somo.saxs_atoms Cromer-Mann form factors for MO+5 and MO+6, both the
9- and 11-parameter variants, matching the MO+3 rows
somo.residue two new residues, Molybdenum Cluster Subunit 1 (MO2)
and Subunit 2 (MO6)
Purely additive - no existing row is modified, so no current result can
change. Verified: every hybrid referenced by somo.residue resolves in
somo.hybrid; every (atom name, hybrid) pair used by the two new residues
exists in somo.atom; and the new electron counts are correct for Z minus
formal charge (O2- 10, MO+5 37, MO+6 36).
Mattia's copy of somo.residue predates 78465e20, so it is missing glucose;
GLC is deliberately retained here and only his new blocks were taken.
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
(cherry picked from commit 4ae31a8922b1bca3ae30d07dd6f66d2b5ac7c3bb)
Commit: a9aa09407e096821c9b10d7d9cebe126eeaefa35
https://github.com/ehb54/ultrascan3/commit/a9aa09407e096821c9b10d7d9cebe126eeaefa35
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/etc/somo.atom.new
Log Message:
-----------
Fix SAXS excluded volume for four hydroxyl entries in somo.atom
O10, O1A, O1B and O1N carried 9.13 A^3 as their O2H1 excluded volume, the
value belonging to a bare oxygen (O1H0/O2H0), rather than the 14.28 A^3 used
by every other hydroxyl. The four rows sit directly below O1H0/O2H0 rows for
the same atom names, so this reads as a copy-paste slip.
All 43 O2H1 rows in the file now use 14.28; before this change 39 did and
these 4 did not. Affects the excluded-volume term in SAXS curve computation
for structures containing those atom names.
>From Mattia's updated parameter files.
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
(cherry picked from commit b112dfd5c5fe820c5ddbac261d394c8ea900d844)
Commit: 28513ea99afa5c73f156a8b3d2272c2778436309
https://github.com/ehb54/ultrascan3/commit/28513ea99afa5c73f156a8b3d2272c2778436309
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/etc/somo.residue.new
Log Message:
-----------
Fix NDP ionized-state vbar: 0.599 -> 0.589
NADPH (NDP) declared vbar 0.589 for the neutral form but 0.599 for both
ionized states. 0.599 is NAD's vbar, and the NDP header otherwise matches
NAD's line, so the two ionized values were carried over when the entry was
copied from NAD.
Every other multi-state residue in the file repeats the same vbar across all
of its protonation states; NDP was the only one of the 20 that did not. It
now uses 0.589 throughout, so vbar no longer jumps by 1.7% as a function of
pH for NADPH-containing models.
>From Mattia's updated parameter files.
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
(cherry picked from commit 1f0b373b0887e359bf2dd08e7ef193f0800b2f56)
Commit: 9824edf652a077a177249c8fcd75334812927028
https://github.com/ehb54/ultrascan3/commit/9824edf652a077a177249c8fcd75334812927028
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/etc/somo.atom.new
M us_somo/etc/somo.hybrid.new
Log Message:
-----------
Set MO+3 radius to 0.69, completing the Mo series
Mattia changed the Mo(III) radius from 0.83 to 0.69 A in both somo.atom and
somo.hybrid when adding the MO+5 and MO+6 entries, and has confirmed 0.69 is
the value to use.
This makes the three Mo radii one consistently sourced set: 0.69 (+3), 0.61
(+5) and 0.73 (+6) are Shannon effective ionic radii, six-coordinate for
Mo(III) and Mo(V) and seven-coordinate for Mo(VI). The previous 0.83
corresponds to no standard Mo radius; it entered in 623ce9cc (2020) with the
multi-pKa support files, with no stated source.
Note for anyone reading the table later: the radius rises from +3 to +6
rather than falling, because the Mo(VI) value is seven-coordinate while the
other two are six-coordinate. That is intentional, not a transcription error.
Unlike the rest of this branch this change is not additive. It alters bead
radii, and hence hydrodynamic results, for existing structures containing
Mo(III).
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
(cherry picked from commit f00f0bfd2facda5de8de10142e040f2c8b2db1e9)
Commit: cb2ddab2bd73029d48eec94ae894f8b049fa6412
https://github.com/ehb54/ultrascan3/commit/cb2ddab2bd73029d48eec94ae894f8b049fa6412
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/etc/somo.atom.new
Log Message:
-----------
Complete the SAXS excluded volume fix: 31 further rows in somo.atom
Extends the O2H1 correction to every other row carrying the same mistake.
Throughout somo.atom a hybrid's excluded volume is the bare heavy-atom value
plus 5.15 A^3 per attached hydrogen, 5.15 being hydrogen's own excluded volume
in somo.saxs_atoms. These 31 rows carried the bare value despite the hybrid
having hydrogens, i.e. the hydrogen contribution was omitted:
C4H3 16.44 -> 31.89 x20 C13 C15 C1Q C1R C1T C1U C2 C20 C22 C25 C28
C2A C3 C35 C36 C38 C3P C4 C42 C5
C4H2 16.44 -> 26.74 x8 C14 C15 C16 C17 C18 C19 C1P C21
C3H2 16.44 -> 26.74 x2 CBB CBC
C4H1 16.44 -> 21.59 x1 C40
With the four O2H1 rows already corrected earlier on this branch, all 35 rows
of this error class are now consistent. The number of hybrids carrying more
than one excluded volume drops from 6 to 2.
Four rows deviate from the rule in some other way and are deliberately left
untouched, since they need a judgement call rather than arithmetic:
SG S2H1 25.1 rule gives 25.01 - looks like a dropped digit, but the
effect is negligible either way
NE2 N3H1+ 12.79 rule gives 7.64 - carries the two-hydrogen value while
its mass 15.02 says one hydrogen
B B4H0 2.14 rule gives 29.65 - 2.14 is boron's volume in
somo.saxs_atoms; B1/B2 use 29.65
OW O2H2 24 rule gives 19.43 - water oxygen; 24 may well be
deliberate for explicit water
Affects the excluded-volume term in SAXS curve computation for structures
containing these atom names.
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
(cherry picked from commit be9437cf7e072474c7e06337c0716df2ad1d3c34)
Commit: 423cb795720c1c37ee6a486b4875c87755d11650
https://github.com/ehb54/ultrascan3/commit/423cb795720c1c37ee6a486b4875c87755d11650
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_dad.h
M us_somo/develop/libus_somo.pro
M us_somo/develop/src/us_hydrodyn.cpp
M us_somo/develop/src/us_hydrodyn_dad.cpp
A us_somo/develop/src/us_hydrodyn_dad_script.cpp
M us_somo/develop/src/us_hydrodyn_dad_util.cpp
M us_somo/develop/src/us_hydrodyn_script.cpp
Log Message:
-----------
Add gui_script commands for the UV-Vis module
The UV-Vis module had no scripted path: gui_script knew nothing about it
and us_saxs_cmds_t does not reach it, so every change to the module could
only be exercised by hand in the GUI.
Add a "dad" command family to gui_script_run(): open, settimes,
lambdarange, lambdas, load, list, select, makealambda and save. Together
these load a wavelength list and an absorption matrix, build the A(t)
curves, make A(lambda) and write the results, with no interaction.
That needs the module to run without dialogs, so US_Hydrodyn_Dad gains a
script_mode plus the values dad_load() would otherwise prompt for. With
it set, the wavelength confirmation, the wavelength crop and the start
time and interval dialogs are all answered from the script. The
non-interactive entry points live in a new us_hydrodyn_dad_script.cpp.
Also add saxs_options iqscaleangstrom and iqscalenm, since whether q
values are converted from 1/nm on load was otherwise unreachable from a
script.
dad open reaches US_Hydrodyn_Saxs::dad() through the meta-object rather
than making the slot public, so no interface widens for scripting alone.
Fix an unrelated crash found by the first script run: US_Hydrodyn's
constructor initialises around thirty *_widget flags but misses
dad_widget, mals_widget and mals_saxs_widget, added later with those
windows, and nulls no window pointer. US_Hydrodyn_Saxs::dad(), mals()
and mals_saxs() test the flag and then dereference the matching window,
so an indeterminate read is a segmentation fault. Interactive runs
survive on zeroed heap; the headless run did not.
Refs ehb54/ultrascan-tickets#994
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
(cherry picked from commit 6c91cf6a276ec740abe198a0a3421a3eddd91daf)
Commit: b441643ba9b56c66d857d7461f9dc583071573da
https://github.com/ehb54/ultrascan3/commit/b441643ba9b56c66d857d7461f9dc583071573da
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn.h
M us_somo/develop/include/us_hydrodyn_pdb_parsing.h
M us_somo/develop/src/us_hydrodyn_load.cpp
M us_somo/develop/src/us_hydrodyn_other.cpp
M us_somo/develop/src/us_hydrodyn_pdb_parsing.cpp
M us_somo/develop/src/us_hydrodyn_pdb_tool.cpp
M us_somo/develop/src/us_hydrodyn_saxs_1d.cpp
M us_somo/develop/src/us_saxs_util_best.cpp
M us_somo/develop/src/us_saxs_util_dmd.cpp
M us_somo/develop/src/us_saxs_util_hydro.cpp
M us_somo/develop/src/us_saxs_util_loads.cpp
M us_somo/somo/doc/manual/somo/somo_pdb_parsing.html
M us_somo/somo/doc/manual/somo/somo_pdb_parsing_expert_mode.html
Log Message:
-----------
somo: ask about open RasMol windows on exit, and skip heavy water
Two housekeeping fixes for ehb54/ultrascan-tickets#1000.
RasMol viewers are started by model_viewer() with startDetached(), so nothing
held on to them. closeEvent() only ever looked at the legacy `rasmol` QProcess
member, which is allocated but never started - its one launch() call sits inside
#if defined( TODO_FIX_MOVIE_FRAME ) and uses a Qt3 API - so the check never
fired and every viewer SOMO opened was left behind. Track the detached pids and
ask on exit whether to close them or leave them open. Liveness and termination
go through small portable helpers rather than QProcess, since a detached child
has no QProcess to ask.
"Skip solvent water molecules" now means light and heavy water everywhere. The
main GUI reader already listed DOD, but the headless reader, the hydro reader,
1D SAXS, the PDB editor and the BEST/DMD exclusion lists each tested for HOH
alone, so the same structure parsed differently depending on the route - 5PTI,
63 D2O residues, keeps 728 atoms instead of 539 through those paths. All of
them now share one definition in us_hydrodyn_pdb_parsing.h. WAT stays out of
it: that is SOMO's own explicit hydration water, not solvent to discard.
(cherry picked from commit fbd25903bcbb082bfa6ecbdb0ab776e277329c8a)
Commit: fc4bcadd1e2381af336a5f7b57ca17099d5c139b
https://github.com/ehb54/ultrascan3/commit/fc4bcadd1e2381af336a5f7b57ca17099d5c139b
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_pdb_parsing.h
M us_somo/develop/src/us_hydrodyn_load.cpp
M us_somo/develop/src/us_hydrodyn_pdb_parsing.cpp
M us_somo/develop/src/us_hydrodyn_settings.cpp
M us_somo/develop/src/us_saxs_util_hydro.cpp
M us_somo/develop/src/us_saxs_util_loads.cpp
M us_somo/etc/somo.config.new
M us_somo/etc/somo.defaults.new
M us_somo/somo/doc/manual/somo/somo_pdb_parsing.html
M us_somo/somo/doc/manual/somo/somo_pdb_parsing_expert_mode.html
Log Message:
-----------
somo: add a "Skip deuterium atoms" PDB parsing option
Neutron structures carry deuterium where an X-ray structure carries hydrogen -
5PTI has 103 of them in the protein, on top of its D2O. The hydrogen test the
readers apply matches names beginning with H only, so those deuteriums survived
parsing and arrived as unknown atoms; somo.residue codes them no better than it
codes hydrogens.
New option below "Skip hydrogen atoms", default on, applied in the same four
readers. Unlike the hydrogen option it is live rather than greyed out, so the
old behaviour is still reachable, with the deuteriums then falling to the
missing atoms setting.
Deuterium is recognized from the wwPDB element field (columns 77-78) where the
file supplies it and from the atom name otherwise - a name test alone cannot
tell a deuterium from the second letter of a two-letter element, "CD " being
cadmium.
Persisted through the JSON config alongside the other parsing options, and added
to the somo.config/somo.defaults templates. Configs written before this option
existed simply take the default, since load_config_json() lays down the
hard-coded defaults before reading.
(cherry picked from commit 10d48cec080b53d282c4412ccfa6b46a44349c9f)
Commit: ab36a145d97c1bd480c4372d0610a2ac6406108b
https://github.com/ehb54/ultrascan3/commit/ab36a145d97c1bd480c4372d0610a2ac6406108b
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn.h
M us_somo/develop/src/us_hydrodyn.cpp
M us_somo/develop/src/us_hydrodyn_script.cpp
Log Message:
-----------
somo: close RasMol viewers a gui_script opened, rather than orphaning them
A gui_script never reaches closeEvent() - "exit" calls exit(0) directly, and
gui_script_error() calls exit(-1) - so the exit prompt was not a hang risk
(guiFlag is false for the duration of a script in any case). But it also meant
nothing cleaned up: auto_view_pdb is on by default, so any script that loads a
PDB without saying "norasmol" left a RasMol process behind on every run.
Route all three script exits through gui_script_exit(), which closes the
tracked viewers and says so on stdout. A script that wants them kept says
rasmol leaveopen
and "rasmol close" spells out the default. A script that runs off the end
without "exit" hands back to the GUI, where the interactive prompt still
applies - the viewers belong to whoever is now at the keyboard.
(cherry picked from commit f6627f7cd8c199bd5ffafc5c584bc570f9969003)
Commit: 3c28cfaa63a7704c9869fdf0b6200c2e1d3847c4
https://github.com/ehb54/ultrascan3/commit/3c28cfaa63a7704c9869fdf0b6200c2e1d3847c4
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
A us_somo/develop/include/us_hydrodyn_perceive.h
A us_somo/develop/include/us_hydrodyn_perceive_elements.h
A us_somo/develop/include/us_hydrodyn_perceive_hybrid.h
A us_somo/develop/include/us_hydrodyn_perceive_saxs.h
A us_somo/develop/include/us_hydrodyn_perceive_somo.h
M us_somo/develop/libus_somo.pro
A us_somo/develop/perceiver/.gitignore
A us_somo/develop/perceiver/DECISIONS.md
A us_somo/develop/perceiver/README.md
A us_somo/develop/perceiver/data/ref/f0_WaasKirf.dat
A us_somo/develop/perceiver/data/ref/it1992.cpp
A us_somo/develop/perceiver/data/ref/somo.saxs_atoms.generated
A us_somo/develop/perceiver/pdb_lite.h
A us_somo/develop/perceiver/residue_oracle.h
A us_somo/develop/perceiver/tests/coverage.cpp
A us_somo/develop/perceiver/tests/emit_residue.cpp
A us_somo/develop/perceiver/tests/regression.cpp
A us_somo/develop/perceiver/tests/tests_unit.cpp
A us_somo/develop/perceiver/tinytest.h
A us_somo/develop/perceiver/tools/gen_saxs_entries.py
A us_somo/develop/src/us_hydrodyn_perceive.cpp
A us_somo/develop/src/us_hydrodyn_perceive_somo.cpp
M us_somo/develop/src/us_hydrodyn_script.cpp
Log Message:
-----------
Perceive hybridization/vdW radius/electron count for non-coded residues
Phases A and B of ehb54/ultrascan-tickets#978.
SOMO needs an atom's hybridization, vdW radius and electron count to build a
bead model, and today they come only from the hand-curated somo.residue. For a
residue that table does not code, SOMO synthesises a "<RESNAME>_NC<n>"
placeholder and models it as a generic ABB average bead. This adds a chemical
perceiver that derives the real per-atom chemistry from element + coordinates,
so such a residue can be given a proper entry instead of an averaged one.
somo.residue remains the master: perception runs only for residues SOMO itself
recorded in unknown_residues.
Phase A - core compiled into libus_somo:
include/us_hydrodyn_perceive{,_elements,_hybrid,_saxs}.h
src/us_hydrodyn_perceive.cpp
Pipeline: spatial-grid bond perception (honouring CONECT where present, and
H-/ion-agnostic so implicit-H inference is identical with or without explicit
hydrogens) -> ring detection + planarity aromaticity -> Kekule bond orders ->
per-element classification -> emit a somo.residue block plus any somo.hybrid
rows for novel types.
The core is deliberately Qt-free, so the standalone harness in
us_somo/develop/perceiver builds the very same sources without Qt: 23 unit
tests plus a regression that takes residues somo.residue DOES code, pretends
they are unknown, and checks they are reproduced - 41,219 atoms over 8 demo
structures, 99.83% geometric perception, 0.17% genuine error. The residual is
protonation/tautomer state, which heavy-atom geometry cannot resolve in
principle. The harness reads us_somo/etc directly so it cannot drift from the
real tables.
us_hydrodyn_perceive_somo.{h,cpp} is the only Qt-aware layer: it converts
PDB_model/PDB_chain/PDB_atom, reads CONECT and HETNAM from the source file,
and returns tentative entries. It converts the whole model rather than one
residue because bond perception needs surrounding context (peptide links,
disulfides, metal coordination) to get coordination numbers, and hence
implicit-H counts, right. Instances are de-duplicated back to the base residue
name so one confirmation covers all instances of the same chemistry.
Phase B - headless "perceive <pdbfile>" gui_script command, so the whole path
is exercisable against real structures with no GUI:
us3_somo _pad -I -g <script>
Entries carry a REVIEW block naming every atom whose perception was uncertain
(ambiguous protonation, assumed oxidation state, estimated vbar), which is what
the confirmation UI in ehb54/ultrascan-tickets#979 will present to the user.
No existing behaviour changes: nothing calls the perceiver outside the new
command.
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit 74123ff052110d14c1b81d7e4b8e1b30cdf87a20)
Commit: a8d3ff41490671e82da2a30ae4ebe279c137c725
https://github.com/ehb54/ultrascan3/commit/a8d3ff41490671e82da2a30ae4ebe279c137c725
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_perceive_somo.h
M us_somo/develop/perceiver/README.md
A us_somo/develop/perceiver/examples/perceive.somo
M us_somo/develop/src/us_hydrodyn_perceive_somo.cpp
M us_somo/develop/src/us_hydrodyn_script.cpp
Log Message:
-----------
Add "perceive compare" hand-testing sub-command
Part of ehb54/ultrascan-tickets#978.
"perceive compare <pdb>" runs perception over the residues somo.residue DOES
code and diffs the result against the curated types, reporting exact-match and
physics-match rates, a curated->perceived difference histogram, and the first
differing atoms. It is the interactive equivalent of the standalone regression
harness, but run inside SOMO against the user's own installed ~/ultrascan/etc
tables - so it also reveals when an installed table is out of date.
Cross-validation on 1HEL: the in-SOMO path and the standalone harness agree
exactly (1000 atoms scored, 984 exact 98.40%, 995 physics 99.50%), despite
using different PDB parsers and different copies of the tables. The five
physics differences are all known, explainable categories: the chain
N-terminus (a real -NH3+, where the perceiver is chemically right and the
residue template cannot know), the His tautomer and its charge, and the
Asp carboxylate protonation convention.
Also adds examples/perceive.somo documenting the invocation, including the
gotchas that cost time otherwise: the throwaway "_pad" argument is required on
macOS and must be omitted on Linux, "-I" avoids blocking config dialogs, and
the first run after rebuilding libus_somo only re-installs configs and exits,
so it must be run twice.
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit 894686fd90e20d5b1ba8cb1bc37a048d6a32e299)
Commit: 990df0ddeb7da273e5b4da8b6edefd8bb7ebaed8
https://github.com/ehb54/ultrascan3/commit/990df0ddeb7da273e5b4da8b6edefd8bb7ebaed8
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/perceiver/README.md
Log Message:
-----------
Correct perceiver README: tables are read from us_somo/etc, not copied
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit 3969e7dbd75c4a6428f04e9b5e819dbe7ab7dea2)
Commit: 2af5dc769da3ece9ec6dc2012ac464307a4c08f9
https://github.com/ehb54/ultrascan3/commit/2af5dc769da3ece9ec6dc2012ac464307a4c08f9
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
A us_somo/develop/perceiver/tools/psv_model.py
Log Message:
-----------
Add psv group-contribution probe (analysis for ticket #980)
Tests Mattia's suggestion that a rough psv can be suggested for a non-coded
residue from similarity to the hybridizations already in somo.residue, by
fitting a Cohn-Edsall / Durchschlag-Zipper style group-contribution model over
the ~100 genuine polyatomic residues somo.residue codes and scoring it
leave-one-out.
Result (MAE in vbar, cm^3/g; typical vbar ~0.73):
global mean 0.110
sum-of-vdW-spheres (emitted now) 0.193 <- worst option available
residue-type group average 0.070
hybrid group-contribution 0.054 (organic only: 0.036, metals: 0.222)
So the estimate the perceiver currently emits is worse than guessing the mean,
the group-contribution model is good for organic residues, and it should not
be trusted for metal-containing ones. Findings recorded on
ehb54/ultrascan-tickets#980.
NOT pushed: this belongs with the #980 work rather than the #978 PR.
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit 64bc533aaafe3c536d6ea31313aa4a9638f172ad)
Commit: 27652fdb900e20c4d5ea34b5f7f9ce5611bc01d2
https://github.com/ehb54/ultrascan3/commit/27652fdb900e20c4d5ea34b5f7f9ce5611bc01d2
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/perceiver/DECISIONS.md
M us_somo/develop/src/us_hydrodyn_perceive.cpp
Log Message:
-----------
Remove the psv/molvol estimate from generated entries
The tentative entry emitted a vbar (and molvol) from a sum of vdW spheres.
Fitting a group-contribution model over the ~100 polyatomic residues
somo.residue codes, scored leave-one-out (perceiver/tools/psv_model.py),
shows that estimate is the WORST option available: mean absolute error 0.193
in vbar, against 0.110 for simply assuming the global mean. Summing spheres
ignores bond overlap and runs systematically high.
vbar enters hydrodynamics through the buoyancy term (1 - vbar*rho), so
emitting a number worse than a guess is actively misleading. Both fields are
now left at 0 = unset, and the entry says why and points at
ehb54/ultrascan-tickets#980, where the tiered replacement is tracked
(group-contribution for organic residues, MAE 0.036; residue-type group
average for out-of-domain cases such as metal-containing residues, where the
fit degrades to 0.222 - worse than that average; always user-overridable).
0 rather than omission because the header must keep its 7 fields to parse,
0 reads unambiguously as unset (the convention somo.saxs_atoms already uses
for F and SE), and it fails loudly: a 0 vbar is obviously wrong if used,
whereas a plausible-looking 0.80 is not.
The entry now reports the residue mass instead, since what decides whether an
imprecise psv matters is its mass fraction of the model - molecular vbar is
mass-weighted, so a 616 Da heme in a 50 kDa protein shifts it ~0.5% even with
a 0.34 vbar error.
Also tightens the REVIEW block to genuinely uncertain atoms: a confident
classification carrying an informational note was being listed as uncertain,
disagreeing with the flagged count callers report.
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit 8491edd5fef0b4cf3f5c6ed8b9fb9267073055fe)
Commit: 9c5b6831ab862461ff1e3b0a94028aa441b8762f
https://github.com/ehb54/ultrascan3/commit/9c5b6831ab862461ff1e3b0a94028aa441b8762f
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_perceive.h
M us_somo/develop/src/us_hydrodyn_perceive.cpp
Log Message:
-----------
Fix bead colour field in generated residue entries
emit_residue() wrote the residue's atom count into the bead line's COLOUR
field. The bead line is hydration, colour, placing_method, chain, volume
(US_Hydrodyn::read_residue_file, us_hydrodyn_load.cpp:509), so a generated
entry's colour was whatever the atom count happened to be:
- 6 atoms -> colour 6, RESERVED brown, which marks a bead as buried and
EXCLUDES it from the hydrodynamic computation
- 7 atoms -> colour 7, reserved for fused beads
- 8 atoms -> colour 8, reserved for beads found exposed on re-check
- >15 -> out of range entirely
Six- to eight-atom ligands are common (glycerol has 6, phosphate 5), so this
silently dropped beads from models built with a generated entry.
Emit DEFAULT_BEAD_COLOR instead, defined once in us_hydrodyn_perceive.h with
the documented colour list from the SOMO manual (somo_residue.html, Panel 3)
and helpers bead_color_is_reserved() / bead_color_is_selectable() for the
residue-definition UI. Default is 10 (light green), which the manual records
as the Automatic Bead Builder's colour for non-coded residues; it is a single
named constant so the policy can be changed in one place.
Also spell out the remaining bead-line fields rather than emitting bare zeros.
Refs ehb54/ultrascan-tickets#978
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit cc7774a574a51cd1104b396d05ff4f8b4004483b)
Commit: dc57245d0a1c641408e2c347cc4413aee5dce68a
https://github.com/ehb54/ultrascan3/commit/dc57245d0a1c641408e2c347cc4413aee5dce68a
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
A us_somo/develop/include/us_hydrodyn_grid_volume.h
M us_somo/develop/perceiver/DECISIONS.md
A us_somo/develop/perceiver/Makefile
M us_somo/develop/perceiver/README.md
A us_somo/develop/perceiver/tests/grid_volume.cpp
A us_somo/develop/perceiver/tools/calibrate_3v_context.py
A us_somo/develop/perceiver/tools/hydration_table.py
A us_somo/develop/perceiver/tools/psv_durchschlag.py
A us_somo/develop/perceiver/tools/recalc_ligand_volumes.py
A us_somo/develop/src/us_hydrodyn_grid_volume.cpp
Log Message:
-----------
Native grid volume + analysis tools for vbar/molvol/hydration
Groundwork for filling the three fields a generated residue entry currently
leaves at zero: psv (vbar), anhydrous molar volume, and hydration.
Native grid volume (us_hydrodyn_grid_volume.h/.cpp, Qt-free)
accessible A = { v : |v - c_i| > r_i + probe for every atom i }
excluded E = { v : v not in A, and dist(v, A) > probe }
volume = |E| * grid^3
probe 0 gives the bare van der Waals union, probe 1.4 the solvent-excluded
volume. Interior cavities are deliberately not counted, which is what lets
V(complex) - V(complex minus ligand) measure a bound ligand in context. Only
the accessible/blocked boundary is dilated -- the nearest accessible voxel to
any blocked voxel is always a boundary one -- so the cost is a surface rather
than a volume, and a 0.25 A grid runs in about a second for a 1300-atom
protein.
This removes what would otherwise be a new external dependency on 3V
(vossvolvox). 3V is retained only as the validation oracle: tests/grid_volume.cpp
reproduces Volume.exe to within 0.8% on an isolated residue, a whole protein,
and a bound-ligand difference, and adds analytic checks (single sphere,
coincident spheres, and a sealed hollow shell whose cavity must not be counted).
10 checks, 0 failures.
Analysis tools (prototypes, not built into libus_somo)
psv_durchschlag.py Durchschlag & Zipper atomic volume increments, no
fitting. Self-tests against the papers' own worked
values before reporting anything.
hydration_table.py derives a hybrid-type -> waters lookup from
somo.residue; 36 of 48 types unanimous, 7 weak and
flagged for review rather than silently defaulted.
calibrate_3v_context.py calibrates the in-context difference method against
residues whose volume we already know.
recalc_ligand_volumes.py recomputes prosthetic-group volumes, guarded on
elemental formula and on reproducing the stored value.
DECISIONS.md records the findings behind these, including why the anhydrous
volume field wants a 1.4 A probe rather than 0, and the measured-versus-
calculated trap in the Durchschlag 1986 tables.
The perceiver's hand-written test Makefile is force-added: the repository root
ignores "Makefile" for the qmake-generated ones, which left the documented
"make unit" impossible from a fresh clone.
Refs ehb54/ultrascan-tickets#980
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit 901c01d2b81385f3c9f57e349b6a2acf4dc996c3)
Commit: 90b66109a993d724c19c7f27ccd06367e8531b66
https://github.com/ehb54/ultrascan3/commit/90b66109a993d724c19c7f27ccd06367e8531b66
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/perceiver/.gitignore
M us_somo/develop/perceiver/DECISIONS.md
M us_somo/develop/perceiver/tools/calibrate_3v_context.py
M us_somo/develop/perceiver/tools/psv_durchschlag.py
M us_somo/develop/perceiver/tools/recalc_ligand_volumes.py
Log Message:
-----------
Remove local filesystem paths from perceiver files
The repository is public, so absolute paths from a personal workspace should
not appear in it. Five places carried them, all written by me:
.gitignore a home-directory path naming where the demo PDBs
were copied from
DECISIONS.md the local clone location
psv_durchschlag.py where the source PDFs happened to sit
calibrate_3v_context.py a hardcoded default path to Volume.exe
recalc_ligand_volumes.py the same
The two tools now resolve Volume.exe from $VOLUME_EXE, else PATH, which is
also what makes them runnable by anyone rather than only where that binary
was built. Behaviour is otherwise unchanged; self-tests still pass.
Refs ehb54/ultrascan-tickets#980
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit 6fc6d85ed01956401dc09c0a967453ea48a37ccb)
Commit: 9af5da1ecb9fca159164755b7adc548c56d8be1e
https://github.com/ehb54/ultrascan3/commit/9af5da1ecb9fca159164755b7adc548c56d8be1e
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_perceive.h
M us_somo/develop/perceiver/DECISIONS.md
M us_somo/develop/perceiver/Makefile
A us_somo/develop/perceiver/tests/sssr.cpp
A us_somo/develop/perceiver/tests/sssr_real.cpp
M us_somo/develop/src/us_hydrodyn_perceive.cpp
Log Message:
-----------
Add SSSR ring perception and expose the perceived bond graph
Prerequisite for the Durchschlag & Zipper volume increments, which charge a
ring-formation decrement once per ring (3-ring 2.1 through >=9-ring 14.1).
The perceiver exposed only an "aromatic" flag and never returned Bonds at all,
so ring sizes and the topology needed to classify a nitrogen or oxygen
environment were unavailable to any caller.
Bonds gains "rings", the smallest set of smallest rings. find_sssr() is
declared in the header so it can be unit-tested on hand-built adjacency with
no geometry involved. A new perceive(atoms, bonds_out, explicit_bonds)
overload hands the graph back; the existing signature delegates to it, so
current callers are unaffected.
SSSR is kept separate from find_rings(), which enumerates every simple 5- or
6-cycle and feeds aromaticity. That is the right input for "is this atom in a
flat conjugated ring" but the wrong one for anything charged per ring: a fused
bicyclic has three simple cycles and circuit rank two. Keeping them apart also
leaves the validated perception untouched, confirmed by the regression figure
holding at 99.833%.
Method is the standard one for molecule-sized graphs: smallest cycle through
each bond, then greedy smallest-first acceptance while a candidate covers a
bond no accepted ring covers, until the circuit rank is reached. Rings beyond
max_ring (12) are not sought, since the consumer charges a single large-ring
term for everything from nine up.
Tests
sssr.cpp 35 checks on hand-built graphs: acyclic shapes, every ring size
3 to 9, ring with substituent, fused bicyclics (naphthalene,
indole, purine) giving two rings rather than three cycles,
spiro, bridged, three-fused, disconnected components,
macrocycle beyond max_ring, idempotency, and that every
reported ring is a genuine cycle. Also checks the arithmetic
the counts drive: one 6-ring decrement reproduces the published
phenylalanine volume, one 5-ring the proline one.
sssr_real.cpp 18 checks on real coordinates through the whole perception
path, over all eight demo structures. Phe {6}, Tyr {6},
Trp {5,6}, His {5}, Pro {5}, DA/DG {5,5,6}, DC/DT {5,6}, and
Ala/Gly/Leu/Ser/Arg ring-free, with every instance of a type
giving an identical signature.
Some demo structures carry physically impossible geometry, which produces
spurious small rings: 1AO6 models LYS536/NZ 0.73 A from LEU583/CG, shorter
than any covalent bond, and 6LYZ has two oxygens 1.22 A apart. This yields 13
cross-residue and 12 three-membered rings across the demo set, none of them
inside a residue, so no residue's own ring count is affected. The tests assert
this as such: a cross-residue ring must be closed by an inter-residue bond that
is neither a backbone link nor a disulfide, and no three-membered ring may lie
within a single residue.
Refs ehb54/ultrascan-tickets#980
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit 0d1e1d24187f9a7e110f0e465f8acef746ffd5f9)
Commit: e3a33a0717a72f0e90b4f6b2b8e8550605329377
https://github.com/ehb54/ultrascan3/commit/e3a33a0717a72f0e90b4f6b2b8e8550605329377
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
A us_somo/develop/include/us_hydrodyn_psv.h
M us_somo/develop/perceiver/DECISIONS.md
M us_somo/develop/perceiver/Makefile
A us_somo/develop/perceiver/tests/psv.cpp
A us_somo/develop/src/us_hydrodyn_psv.cpp
Log Message:
-----------
Add the Durchschlag & Zipper psv engine
Computes partial specific volume from published atomic volume increments,
consuming the perceived atoms and the bond/ring graph added in the previous
commit. Returns molar volume, vbar and a labelled decomposition -- atomic sum,
covolume, ring decrement, electrostriction, ring and charge counts -- so a
value can be audited rather than taken on trust. Atoms whose environment
cannot be classified are reported for review rather than guessed.
The covolume defaults off, since a residue is a monomeric unit and SOMO
already adds one structure-level covolume in calc_vbar_updated; a flag turns
it on for a standalone molecule. Only rings lying entirely inside the residue
are charged, which is both correct chemistry and immunity to the spurious
cross-residue rings that clashing coordinates produce.
Two rules a naive implementation gets wrong, both verified against the
published tables:
The hydroxyl increment is topological, not a running count. A second
NEIGHBOURING hydroxyl takes 0.4 but an isolated one is a fresh 2.3, so
hydroxyls are clustered by whether their carrier atoms are bonded.
1,2-ethanediol comes out at 53.5 and 1,8-octanediol at 152.0, exactly the
published calculated volumes; a running count reproduces neither.
Guanidinium charges only the terminal nitrogens. Table 1's footnote limits
the 8.0 increment "in Arg only to the two terminal N", so arginine's NE
takes the amine value.
Tests reproduce urea 44.2, glycerol 70.0 and all seven published group
increments exactly, and give mean absolute error of 1.64% against the stored
somo.residue vbar over the fifteen charge-neutral amino acids, none worse
than 6%.
Arginine and histidine sit outside that: the perceiver assigns them no formal
charge while somo.residue stores them protonated, so they lose an
electrostriction term. Arginine is essentially always protonated at
physiological pH, so that is a perception gap for the deferred pH layer rather
than ambiguous chemistry.
Refs ehb54/ultrascan-tickets#980
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit edb0798874626def9c02b95641b4332e1548bac9)
Commit: ed82128ad27431a229a087382731cbebd27c63ed
https://github.com/ehb54/ultrascan3/commit/ed82128ad27431a229a087382731cbebd27c63ed
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
A us_somo/develop/include/us_hydrodyn_hydration.h
M us_somo/develop/include/us_hydrodyn_perceive.h
A us_somo/develop/include/us_hydrodyn_residue_builder.h
M us_somo/develop/perceiver/DECISIONS.md
M us_somo/develop/perceiver/Makefile
A us_somo/develop/perceiver/tests/builder.cpp
M us_somo/develop/perceiver/tests/emit_residue.cpp
A us_somo/develop/perceiver/tests/hydration.cpp
A us_somo/develop/src/us_hydrodyn_hydration.cpp
M us_somo/develop/src/us_hydrodyn_perceive.cpp
A us_somo/develop/src/us_hydrodyn_residue_builder.cpp
Log Message:
-----------
Fill in psv, anhydrous volume and hydration for generated entries
A generated somo.residue entry left vbar, molvol and hydration at zero. This
computes all three and emits a complete entry, with anything still unset
stated as "NOT SET" in the header so a partly filled entry always looks
partly filled.
Hydration lookup (us_hydrodyn_hydration.h/.cpp)
Derived at run time from whatever somo.residue is loaded rather than
embedded, so it cannot drift from the user's own tables. 1581 observations
give 48 hybrid types, 41 of them confident and 7 flagged; flagged types are
surfaced for review rather than silently defaulted, and ties break toward
the lower water count, since under-hydrating a proposal the user will edit
is safer than over-hydrating one they may accept unchanged.
The per-atom values in somo.residue are a hand distribution of a
per-residue Kuntz total rather than a per-atom rule, so this is a starting
point for editing and says so. The residue total is the quantity with
literature backing; tests confirm the totals reproduce Kuntz for 14 of 14
applicable residues, with Asp and Glu deliberately low because SOMO stores
them protonated.
One test records a gap Mattia suspected: every nucleotide entry carries
zero hydration. It is asserted as the current state, so it turns red the day
someone fills those in, which is when models built on the old values need
revisiting.
Orchestration (us_hydrodyn_residue_builder.h/.cpp)
perceive, then psv, volume and hydration, then emit. emit_residue takes an
optional Properties argument rather than including the new headers, which
include it in turn.
A generated tryptophan entry now gives vbar 0.753 against a stored 0.738,
molvol 224.29 against 228.2, and hydration 2.0 against 2.0. Over twelve
residues treated as unknown, computed molvol is within 2.32% of the stored
values on average and never worse than 4.6%.
The volume convention factor is specific to the radius set. The 1.204/1.131
measured previously came from 3V's default radii; this pipeline uses SOMO's
own, which are smaller, so the right factors are 1.248 and 1.179. The factor
tracks polarity as much as size, hydrophobics sitting near 1.26 to 1.29 and
polar residues near 1.16 to 1.21, so the band split is placed below the
hydrophobic cluster rather than at the midpoint, where it separated leucine
from isoleucine and cost both 8%.
Also corrects a comment that described the residue header's ASA field as a
molecular weight column.
Refs ehb54/ultrascan-tickets#980
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit b5710a31a1277ea592fa2c59e5538bb4596967c8)
Commit: 0f80d31def8c0c0f5b7a9cc86ab0e58e7e8f23e1
https://github.com/ehb54/ultrascan3/commit/0f80d31def8c0c0f5b7a9cc86ab0e58e7e8f23e1
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_perceive_somo.h
M us_somo/develop/libus_somo.pro
M us_somo/develop/perceiver/DECISIONS.md
M us_somo/develop/src/us_hydrodyn_perceive_somo.cpp
M us_somo/develop/src/us_hydrodyn_script.cpp
Log Message:
-----------
Wire the computed properties into SOMO and add a headless perceive
libus_somo.pro did not list the four sources added since the perceiver work
resumed, so the grid volume, psv engine, hydration lookup and residue builder
were never compiled into the library at all. Registered, and the symbols are
confirmed present in the built dylib.
The Qt adapter now takes the bond graph from the new perceive overload and
goes through somo_residue_builder, so a proposal made inside SOMO carries
vbar, molvol and hydration rather than zeros. Tentative gained those three
fields for callers that want the numbers instead of the text block. The
hydration lookup is built from SOMO's own loaded residue_list, so a proposal
is always consistent with the user's tables rather than a snapshot compiled
into the binary.
"perceive auto <pdb>" is the headless sub-command: every default accepted,
nothing prompted, nothing written back to somo.residue. It also prints how
many atoms were flagged, since in a pipeline nobody is watching the REVIEW
block go past.
Defaults are pinnable through gparams in the same way as covolume:
perceive_psv, perceive_volume, perceive_hydration, perceive_volume_probe,
perceive_volume_grid and perceive_bead_color. A reserved bead colour is a
hard error rather than a silent substitution, because two of the reserved
values exclude a bead from the hydrodynamic computation and accepting one
would quietly produce a model missing beads.
Verified end to end through us3_somo -g on 2CMD, whose citrate is genuinely
not coded: vbar 0.542, molvol 186.56, and seven review flags. On the residue
basis SOMO stores, that vbar corresponds to 0.607 for the free molecule
against a literature value near 0.59 to 0.62. The proposed hydration of zero
for a triacid is plainly too low, and all four hydroxyl oxygens come back
flagged at 49% agreement, which is the intended behaviour: propose, then say
what cannot be supported.
Refs ehb54/ultrascan-tickets#980
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit 670110805dc743ff825a2cc7e71c70592d373829)
Commit: f2c6ac8bbd1abf6e1bcdc68e3f5ee7af36f2c172
https://github.com/ehb54/ultrascan3/commit/f2c6ac8bbd1abf6e1bcdc68e3f5ee7af36f2c172
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_perceive_somo.h
M us_somo/develop/perceiver/DECISIONS.md
M us_somo/develop/src/us_hydrodyn_perceive_somo.cpp
M us_somo/develop/src/us_hydrodyn_script.cpp
Log Message:
-----------
Add perceive validate: predict the coded residues as if unknown
Rebuilds every residue somo.residue does code, pretending it is unknown, and
reports computed vbar, molvol and hydration against the stored values with a
summary. The same idea as perceive compare, which does this for atom typing,
but for the computed properties, and it exercises the whole pipeline
including perception. That makes it the only end-to-end measure of accuracy.
Chain termini and residues with unmodelled atoms are counted and skipped
rather than quietly averaged in.
Over seven structures and 1157 rebuilt residue instances, ordinary amino
acids give mean absolute errors of about 2.7% on vbar and 2.1% on molvol,
matching what the standalone harness claimed.
The ligand rows are the interesting ones. Heme's computed volume is 32.6%
above the stored value and NAD's is 28.1% above. Earlier work in this branch
reached the same conclusion by a completely different route, using 3V both on
the isolated molecule and by difference in context, and arrived at comparable
numbers. Two independent methods agree the stored ligand volumes are around
30% low. NAD's computed vbar of 0.619 is also closer to the measured 0.620
than the stored 0.599 is.
Heme's vbar comes out 24% low, which is the expected failure: it is a
metalloporphyrin, Durchschlag and Zipper publish no increment for iron, and
the engine reports the atom for review rather than inventing a value.
Hydration is much the weakest of the three, around half the residues within
half a water and systematically low, the misses being the polar and charged
side chains. A per-type majority cannot express residue-specific hydration.
This also confirms the pH coupling from the runtime side: residue_list
carries pH-adjusted hydration, so aspartate reads 6.0 and glutamate 7.0,
exactly the charged-carboxylate values, where the raw file fields give 1.0.
The lookup counts one vote per residue name, since residue_list holds several
entries for residues with ionization variants and counting each weights them
more heavily purely for being pH-aware, which was enough to flip a borderline
type and cost serine and threonine a water each.
Refs ehb54/ultrascan-tickets#980
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit 00118929e83385759ef54c44a775754120cc5bbc)
Commit: c9dfd6ff18aafb0756b97fd4ebc642c9cddb75d2
https://github.com/ehb54/ultrascan3/commit/c9dfd6ff18aafb0756b97fd4ebc642c9cddb75d2
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn.h
A us_somo/develop/include/us_hydrodyn_perceive_dialog.h
M us_somo/develop/libus_somo.pro
M us_somo/develop/perceiver/DECISIONS.md
A us_somo/develop/perceiver/run_dialog_test.sh
A us_somo/develop/perceiver/tests/dialog_qt.cpp
M us_somo/develop/src/us_hydrodyn.cpp
A us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
Log Message:
-----------
Add a GUI review dialog for non-coded residues
Everything built so far was reachable only from gui_script. A user working in
SOMO saw none of it, and a non-coded residue still fell silently to the
Automatic Bead Builder's averaged generic bead. This makes it visible and
correctable.
US_Hydrodyn_Perceive_Dialog presents one modal review per non-coded residue,
in the order Mattia laid out: view the residue in RasMol, confirm the
perceived atom table, edit the proposed per-atom hydration, check the
anhydrous volume, see the bead count and position, choose a bead colour, and
check the psv, with the somo.residue entry rebuilt live below so what is on
screen is exactly what Accept returns.
Only hydration is editable in the atom table. Name, hybrid, mass and radius
are perceived, and editing them would desynchronise the entry from the
geometry it came from. Hydration is editable because it is the weakest of the
three computed numbers; the residue total is shown beneath it and updates
live, with a note that the total is the quantity with literature backing while
the per-atom split is convention.
The colour combo is built from the manual's table and shows index, name and
meaning. The four reserved colours are never offered, since two of them mark a
bead for exclusion from the hydrodynamic computation and the other two are
assigned automatically during model generation.
Appending to somo.residue is opt-in and off by default, so accepting an entry
is per-session unless the user asks otherwise. After a save the user is told
to reload the structure, since hot-reloading the residue table would
invalidate indices the loaded model already holds.
The trigger is a Lookup Tables menu item rather than a hook inside model
building: check_for_missing_atoms runs per model and inside batch paths, so
opening a modal dialog from there would be invasive and wrong for scripted
runs. Skip leaves the residue to the Automatic Bead Builder exactly as before.
Testing a widget needs a widget test: run_dialog_test.sh builds the dialog
against the real library and exercises it under an offscreen Qt platform, so
it needs no display. Eighteen checks cover the proposal round-tripping through
parse and rebuild, a hydration edit propagating to both the atom line and the
bead total, a nonsense edit being rejected and the previous value restored,
read-only columns actually being read-only, the colour combo offering twelve
of the sixteen colours and defaulting to the configured one, and nothing being
marked accepted or saved until the user acts.
Refs ehb54/ultrascan-tickets#980
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit 39fd984788128ab669b66be14b38729293be1a92)
Commit: e85d9069ee6c2edbdab816a0d037b981b7c93cbe
https://github.com/ehb54/ultrascan3/commit/e85d9069ee6c2edbdab816a0d037b981b7c93cbe
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_hydration.h
M us_somo/develop/perceiver/DECISIONS.md
M us_somo/develop/perceiver/tests/builder.cpp
M us_somo/develop/src/us_hydrodyn_hydration.cpp
M us_somo/develop/src/us_hydrodyn_perceive_somo.cpp
M us_somo/develop/src/us_hydrodyn_residue_builder.cpp
Log Message:
-----------
Propose hydration from pH 7 chemistry rules rather than type averages
Mattia supplied the chemistry: at pH 7 an acidic side chain is a carboxylate,
with one oxygen double-bonded and neutral and the other deprotonated and
charged; an aliphatic amine is protonated; and the water a carboxylate carries
depends on the length of the aliphatic chain linking it to the backbone, which
is what separates aspartate from glutamate. No general pH machinery, just the
pH 7 assumption.
The residue table confirms this exactly. The ionised hydration is field 15 of
an atom line, not 13 as the layout first suggests, and reading it gives
aspartate 5 waters on its carboxylate against glutamate's 6, lysine 3 on its
ammonium, arginine 1 on each terminal guanidinium nitrogen. So aspartate's
runtime total of 6 and glutamate's 7 are carboxylate plus backbone amide, and
the difference between them really is the extra methylene.
The rules replace the previous per-hybrid-type majority vote, which could not
express residue-specific hydration and systematically under-predicted the
polar and charged side chains. Anything the rules do not recognise still falls
back to the observed averages and is flagged, so a novel group never receives
a confident-looking number by accident.
Hydration within half a water improves from roughly 69 of 145 residue types to
136 of 145 across seven structures, 48% to 94%, with lysozyme and both
ribonucleases now exact on every type. All fifteen applicable coded residues
reproduce exactly in the unit tests, including the aspartate/glutamate
methylene difference. Partial specific volume and anhydrous volume are
unchanged, and perception still scores 99.833%.
Validation also has to skip chain termini at both ends, not just the carboxy
end. An amino-terminal residue has a free protonated backbone nitrogen rather
than an amide, so an amino-terminal lysine genuinely carries two ammonium
groups and six waters where the tabulated internal residue has four. The rules
were right and the comparison was wrong.
Two rule edges the coded residues exposed: a disulfide sulfur has two heavy
neighbours just as a thioether does, so both partners must be carbon before it
counts as hydrated; and proline's tertiary ring amide nitrogen carries no
hydrogen, so amide nitrogens are identified by their carbonyl neighbour rather
than by hydrogen count.
Refs ehb54/ultrascan-tickets#980
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit fbf7da800e6866e0b3c203cfbe900c5af41f4050)
Commit: e57988fd0d8b7c019f905b9b80631001bf0cbf61
https://github.com/ehb54/ultrascan3/commit/e57988fd0d8b7c019f905b9b80631001bf0cbf61
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_psv.h
M us_somo/develop/perceiver/DECISIONS.md
M us_somo/develop/perceiver/tests/psv.cpp
M us_somo/develop/src/us_hydrodyn_psv.cpp
Log Message:
-----------
Measure pH 7 ionisation for psv, and leave it off
The pH 7 assumption transformed hydration, so the same reasoning was applied
to partial specific volume: charge the carboxyl as a carboxylate, protonate
the guanidinium, and take an electrostriction term for each. Implemented as an
option and measured against the stored values.
The measurement says not to use it. Aspartate moves from 1.3% low to 11.0%
low, glutamate from 1.2% to 9.0%, while arginine improves from 15.9% high to
9.7%. Mean absolute error goes from 6.23% to 9.05%: a clear net loss.
The reason the symmetry with hydration breaks is visible in the residue table.
It lists the same vbar for the protonated and deprotonated state of every
ionisable residue, so ionisation there changes mass, radius, protons and
hydration but never volume. Those values descend from densitometry on real
amino acids at neutral pH and already contain whatever ionisation was present,
whereas the Durchschlag and Zipper electrostriction is an explicit correction
to a neutral-basis increment sum. Applying both counts it twice.
Hydration was different precisely because the table does carry two hydration
numbers per ionisable atom, with the pH 7 value in its own field. There the
assumption had a ground truth to match, and matching it took hydration from
48% to 94% of residue types within half a water.
The option stays, off by default, with the measured numbers in the header
comment and a test that asserts the default is whichever setting actually
measures better. If the reference values are ever placed on a single stated
ionisation basis, flipping it will be a one-line change and the test will
report whether it helped.
This does not explain arginine, which is still 15.9% high untouched and 9.7%
high with electrostriction. It is the known outlier of the scheme: the six
published residue-volume sets in Perkins 1986 disagree with each other about
arginine by 17%.
Refs ehb54/ultrascan-tickets#980
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit 3e1508f51183466c7aa40e80697f4fd817310078)
Commit: aaed7ac36e466f01301a60b7642568f3f817c854
https://github.com/ehb54/ultrascan3/commit/aaed7ac36e466f01301a60b7642568f3f817c854
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/perceiver/DECISIONS.md
Log Message:
-----------
Correct the record on the vbar ionisation design
An earlier note inferred that the identical vbar for the protonated and
deprotonated states meant the stored values already absorbed whatever
ionisation the underlying measurements carried. Mattia has corrected this: the
amino acid vbar values were recalculated by him at pH 7, and setting the
ionised value equal to the base is a deliberate statement that at pH 7 the
volume does not change.
There is also no stored "pH 7 value" anywhere. SOMO derives the species
fractions at run time from the stored pKa by Henderson-Hasselbalch, in
basic_fractions(), and mixes the base and ionised values by those fractions.
For aspartate at pH 7 that is 99.95% deprotonated, which is why the runtime
hydration is effectively the fully ionised value. The field described earlier
as "the pH 7 one" is the fully ionised one; pH 7 merely sits almost entirely
at that end.
This also reframes arginine. Its 0.698 is Mattia's recalculated pH 7 value,
which he states is better than the published sets, so the calculation being
16% high means it is reproducing a published-style number while the reference
is deliberately better than those, rather than the reference being uncertain.
The decision to leave the electrostriction option off is unchanged, and so is
the measurement behind it. Only the explanation changes: the correction
overshoots relative to a recalculated pH 7 reference.
What this confirms is that the implemented design is the intended one. Work at
pH 7 for a non-coded residue, since its pKa cannot be known, and assume the
hydrations determined for the amino acids, every carboxyl deprotonated and
every amine protonated. That is what the hydration rules already do.
Refs ehb54/ultrascan-tickets#980
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit 8a415144544fffc27d929ee9cdb7cc46e9620c0a)
Commit: 593ad18770203fdded42e0a77da0a4538ede13c5
https://github.com/ehb54/ultrascan3/commit/593ad18770203fdded42e0a77da0a4538ede13c5
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_psv.h
M us_somo/develop/perceiver/DECISIONS.md
M us_somo/develop/perceiver/tests/psv.cpp
M us_somo/develop/src/us_hydrodyn_psv.cpp
Log Message:
-----------
Implement the published metal and ion volumes
The engine reported "no volume increment for this element" for every metal.
That was wrong: Durchschlag and Zipper tabulate them, and the values had
already been extracted into the Python prototype and then never carried across
to the C++ implementation.
Table 2 supplies atomic volumes for a metal bonded into a complex, such as a
haem iron or B12's cobalt. Table 3 supplies aqueous volumes for free monatomic
ions, including iron at -32.3 and -55.1 for the divalent and trivalent forms.
Those ion values already contain the ionisation contribution, so
electrostriction is not charged a second time on top of them, and a test
asserts an isolated magnesium comes out at exactly its tabulated value with no
electrostriction term.
The trivalent iron value of -55.1 is -0.99 mL/g, the same sign and order as the
figure quoted from another compilation. Negative because electrostriction
draws water inward around the ion more than the bare ion displaces.
The effect on haem is real but small: its partial specific volume moves from
24.3% low to 23.0% low. Iron is about a percent of a 616 dalton molecule, so it
was never going to close that gap. The bulk of the error is most likely the
porphyrin itself, four fused pyrrole rings and a heavily conjugated macrocycle,
which is not what Traube-style additivity was built for.
Refs ehb54/ultrascan-tickets#980
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit f355b4f83f28e5c3f287ee030841d44f257043b1)
Commit: b994a6df61b027c399a2120683dc53f2f888f5e1
https://github.com/ehb54/ultrascan3/commit/b994a6df61b027c399a2120683dc53f2f888f5e1
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_perceive_dialog.h
M us_somo/develop/perceiver/DECISIONS.md
M us_somo/develop/src/us_hydrodyn.cpp
M us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
M us_somo/develop/src/us_hydrodyn_script.cpp
Log Message:
-----------
Fix cross-structure state leak and add Skip all remaining
Two defects found while preparing structures for GUI testing, both visible
only when perceive is run over more than the demo set.
Running perceive twice in one session reported the previous structure's
non-coded residues against the new one. Ubiquitin alone has none, but after
malate dehydrogenase it reported two, which were citrate's. SOMO fills
unknown_residues during model building and never clears it, so the set
accumulates across loads. The emitted entries were still right, since a stale
name absent from the new model produces nothing, but the reported counts
described a structure that was no longer open. Both the script command and the
GUI slot now intersect that set with the residue names actually present in the
loaded model.
The second is a usability failure with real consequences. 5PTI is a neutron
structure carrying heavy water and explicit deuteriums, so its residues have
more atoms than the table's entries and SOMO matches none of them: fifty-five
non-coded instances across eighteen types, which meant eighteen modal dialogs
in succession with no way out but to dismiss each one. The dialog now offers
Skip all remaining, which abandons the review and leaves everything to the
Automatic Bead Builder, with a tooltip naming the likely cause so a user
seeing an implausible count suspects the file rather than the tool. The caller
honours it and reports how many residues went unreviewed.
Worth noting that the perceiver itself handles these structures correctly, as
it excludes hydrogens from bond perception by design. It is SOMO's residue
matching that fails on the atom count. Making that match hydrogen-agnostic
would be the real fix.
Refs ehb54/ultrascan-tickets#980
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
(cherry picked from commit 18f170ffb8e37948c975e05f7f8b56c4698bb646)
Commit: cb0b567de8a88851843964a6086b0c350818fc00
https://github.com/ehb54/ultrascan3/commit/cb0b567de8a88851843964a6086b0c350818fc00
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/perceiver/.gitignore
M us_somo/develop/perceiver/README.md
A us_somo/develop/perceiver/data/non-coded/1MBO.pdb
A us_somo/develop/perceiver/data/non-coded/2CMD.pdb
A us_somo/develop/perceiver/data/non-coded/3PTB.pdb
A us_somo/develop/perceiver/data/non-coded/5PTI.pdb
A us_somo/develop/perceiver/data/non-coded/README.md
M us_somo/develop/perceiver/examples/perceive.somo
Log Message:
-----------
perceiver: add tracked test structures containing non-coded residues
The demo structures under perceiver/data/ are all fully coded, so nothing in
the tree exercised the path the perceiver exists for. Add four structures that
do, tracked in git since they are copies of nothing else here (the parent
data/*.pdb ignore rule is deliberately non-recursive).
1MBO SO4 only -- heme and O2 are coded, so it also shows selectivity
2CMD citrate, 13 atoms, 3 flagged for review -- the clean first test
3PTB benzamidine -- the only case reaching SSSR/ring-decrement and
electrostriction; its Ca2+ is coded and correctly left alone
5PTI neutron/deuterated -- 50 instances across 18 types, the stress case
for "Skip all remaining" (residue matching fails on atom count, not
chemistry: the perceiver excludes hydrogens by design)
data/non-coded/README.md records the expected scan output for each so a
regression is visible without rerunning everything.
Also correct the example gui_script: paths must be absolute, since SOMO
changes directory during startup and a shell-relative path fails to resolve.
(cherry picked from commit b14eb3c1403d622b64d9c2bcaf59cb85955629ed)
Commit: 9dce2a8639dd81e9538c83b42bf592f1b4d76bfa
https://github.com/ehb54/ultrascan3/commit/9dce2a8639dd81e9538c83b42bf592f1b4d76bfa
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/perceiver/tests/dialog_qt.cpp
M us_somo/develop/src/us_hydrodyn.cpp
M us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
Log Message:
-----------
perceiver: fix the review dialog never appearing from the GUI menu
Lookup Tables -> Perceive Non-Coded Residues... appeared to do nothing:
the dialog was constructed as a CHILD WIDGET of the main window, not as a
window. A QFrame given a parent and no window flag is an ordinary child, so
setWindowTitle and setWindowModality were silently ignored and the
setGeometry( x, y, 0, 0 ) idiom the other 116 SOMO dialogs use -- which a
window manager expands to the layout minimum -- left it 0 x 0, positioned by
a screen-coordinate global inside (and clipped by) the parent. The caller
then waited on isVisible(), which for a child never goes false, so SOMO sat
in the wait loop with nothing on screen.
Measured, with the dialog built the way the slot builds it:
before isWindow 0, 0 x 0
after isWindow 1, 1154 x 718
Every other SOMO dialog avoids this by passing no parent at all. Keeping the
parent and adding Qt::Window is better on macOS: the dialog then also stays
stacked above its owner. Adds fixWinButtons/raise/activateWindow to match
what the other dialogs do on show.
Also make the slot incapable of failing silently again: every exit path now
writes to the text window, including both "nothing to do" cases, and the
message boxes get a parent so they cannot open behind the main window.
dialog_qt.cpp gained the check that catches this -- it constructed the dialog
with no parent, i.e. exactly the case that works. Building it with a parent
and asserting isWindow() plus a non-degenerate size after show() reproduces
the failure offscreen (3 failures on the old code, 21/21 on the new).
(cherry picked from commit fb9664846f9c72140d61c2fcc88b3aa887c033a8)
Commit: e8bb66fdff163f9a9dbe39fead661e6e7bea3d38
https://github.com/ehb54/ultrascan3/commit/e8bb66fdff163f9a9dbe39fead661e6e7bea3d38
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn.h
M us_somo/develop/include/us_hydrodyn_perceive.h
M us_somo/develop/perceiver/README.md
M us_somo/develop/perceiver/examples/perceive.somo
M us_somo/develop/perceiver/tests/builder.cpp
M us_somo/develop/src/us_hydrodyn.cpp
M us_somo/develop/src/us_hydrodyn_perceive.cpp
M us_somo/develop/src/us_hydrodyn_script.cpp
Log Message:
-----------
perceiver: make an accepted entry actually take effect
Accepting an entry in the review dialog only printed it. The bead builder
still saw a non-coded residue and fell back to a generic averaged bead --
the outcome this feature exists to prevent. Three separate defects, each of
which alone was enough to break it:
1. ASA was emitted as 0. Every SOMO residue loader -- read_residue_file
(us_hydrodyn_load.cpp:534), US_AddResidue (:1288), US_Saxs_Util (:693) --
skips a record whose ASA is zero, and skips it SILENTLY. The entry parsed,
never entered residue_list or multi_residue_map, and the residue went on
being reported non-coded with nothing to indicate why. All 127 coded
residues have ASA > 0. Emit 18 A^2/atom, the coded-residue mean, labelled
a placeholder in the REVIEW block: nothing computes with the tabulated
residue ASA (it appears only in info dumps), but it may not be zero.
Properties::asa lets a caller supply a measured value later.
2. The block was not a valid record. The table is strictly positional -- one
free-text comment line, then header, atoms, beads -- and has no comment
syntax. The emitted block's ~20 '#' lines were consumed two at a time as
comment/header pairs, silently creating zero-atom residues named "#".
Ticking "add to somo.residue" would have written that into the user's own
table. perceived_table_record() collapses the block to one comment line.
3. Nothing applied the entry. apply_perceived_entries() puts accepted entries
into a session overlay (<table>.perceived), re-runs read_residue_file on
it and re-reads the structure, so the atoms rebind. The user's table is
written only when they tick the box. Novel hybrid rows, previously dropped
on the floor, are injected into hybrid_to_protons/electrons first, since
read_residue_file rejects atoms whose hybrid it cannot resolve.
Adds "perceive apply <pdb>" -- the headless equivalent of accepting every
entry -- reporting the non-coded count after the fact. That assertion is what
found (1) and (2); the GUI path had no way to tell "file written" from
"entry in effect". builder.cpp now checks the emitted ASA is positive.
Verified: 1MBO SO4 and 2CMD CIT both apply, 0 types still non-coded, and a
fresh perceive of 1MBO reports every residue already coded. Suites green
(54/35/18/60/5/37/55/21), regression 99.833%.
(cherry picked from commit dfa109153157c58937f05c55b23b8eec154dc55b)
Commit: f9f9f9a85f6e2d90f2a2016eef695e12bdec0e04
https://github.com/ehb54/ultrascan3/commit/f9f9f9a85f6e2d90f2a2016eef695e12bdec0e04
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_perceive_dialog.h
M us_somo/develop/perceiver/tests/dialog_qt.cpp
M us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
Log Message:
-----------
perceiver: stop the review dialog overriding the emitted ASA
The dialog does not write the perceiver's block -- refresh_entry() rebuilds
the whole entry from its widgets, and its header format string hardcoded the
ASA slot to 0:
s += QString( "%1\t0\t%2\t0\t%3\t1\t%4\n" )
so fixing the emitter changed nothing for anyone using the GUI. A run shows
both the new REVIEW line about the ASA placeholder AND a header reading
"SO4 0 61.75 0 5 1 0.390" -- one binary, two emitters, and the loaders drop a
zero-ASA record silently, so the residue stayed non-coded after acceptance.
"perceive apply" could not catch this: it uses the Tentative block directly
and never constructs a dialog, so it exercised the half that was already
right. The dialog now parses type and ASA out of the proposed header and
writes them back untouched, editing only what it owns -- molvol, vbar,
hydration and colour. Anything it hardcodes silently overrides perception,
so it should hold nothing it does not edit.
The dialog test could not catch it either: its fixture block carried ASA 0,
so any assertion would have passed vacuously. The fixture now carries 54.00
and the test parses the rebuilt header and asserts the ASA field is positive
and still 54.0, alongside molvol -- the two fields the loaders gate on.
25 checks, 0 failures; Qt-free suites unchanged (54/35/18/60/37/55).
(cherry picked from commit 2f95e97d15f10253a1b9946b9a863eb233b6e6f2)
Commit: 13351141f45ff96ec4477d6e46925670532c8014
https://github.com/ehb54/ultrascan3/commit/13351141f45ff96ec4477d6e46925670532c8014
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn.h
M us_somo/develop/src/us_hydrodyn_beads.cpp
M us_somo/develop/src/us_hydrodyn_core.cpp
M us_somo/develop/src/us_hydrodyn_fractal_dimension.cpp
M us_somo/develop/src/us_hydrodyn_load.cpp
M us_somo/develop/src/us_hydrodyn_saxs_1d.cpp
M us_somo/develop/src/us_hydrodyn_saxs_2d.cpp
M us_somo/develop/src/us_hydrodyn_saxs_iqq.cpp
Log Message:
-----------
somo: derive an atom-table entry instead of dropping the atom
somo.atom is keyed by ATOM NAME, so an atom whose name that table has never
seen resolves to nothing and is dropped from both the ASA and the excluded
volume -- reported once, then ignored. That is routine for a non-coded
ligand: 1MBO's sulfate sulfur is named "S", and the table carries only the
Fe-S cluster names S1..S4B.
Chain A Molecule 2 Atom S Residue SO4 154 Hybrid S name missing from
Atom file. Atom skipped for SAS.
ensure_atom_entry() derives one instead. It prefers another atom with the
SAME HYBRID -- which fixes element, mass and radius exactly, leaving only the
excluded volume a convention -- and falls back to the same ELEMENT. The
derived entry goes into the map, so it is also the memo: the next lookup is
an ordinary hit.
Excluded volume takes the value that key uses MOST OFTEN in the table rather
than whichever row is found first, because it is not a function of the
hybrid: C4H3 appears with both 31.89 and 16.44 A^3 depending on atom name.
For sulfur the question does not arise -- every S row is 19.86.
It reports what it did, once per atom name. A silent substitution here would
be the same class of defect as the silent skip it replaces:
Note: S (S) is not in the atom table; using the hybrid match:
mw 32.065, radius 0.43, excluded volume 19.86 A^3
Applied at all six lookup sites, not only the two a bead build reaches: bead
building, SAS, fractal dimension, and the SAXS 1D/2D/I(q) paths.
Verified on 1MBO: the fallback fires once for S, nothing is skipped, and the
perceived SO4 entry still applies cleanly (0 types still non-coded).
(cherry picked from commit 57804dfa39b133200c82b059fbd356cb6ee7663f)
Commit: f1e0db9fb28d1c7eb374c0a0546192e77e890c7c
https://github.com/ehb54/ultrascan3/commit/f1e0db9fb28d1c7eb374c0a0546192e77e890c7c
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/perceiver/README.md
M us_somo/develop/perceiver/examples/perceive.somo
M us_somo/develop/src/us_hydrodyn_load.cpp
M us_somo/develop/src/us_hydrodyn_script.cpp
Log Message:
-----------
perceiver: add "perceive build" so bead-build defects are testable headlessly
"perceive apply" cannot cover the model builder. A clean load takes calc_mw(),
not the excluded-volume path, so the somo.atom lookup -- and anything else
that only bites at bead-build time -- was exercised solely by clicking
through the GUI. That is how the atom-table skip reached the user in the
first place.
perceive build [somo|somo_o|vdw|grid|a2b] <pdb>
is apply plus what the user does next: select the model, call the same
function the button does (calc_somo / calc_somo_o / calc_vdw_beads /
calc_grid_pdb), report the bead count, and FAIL the script if the build
fails or yields no beads. vdw is the sharpest of the four for a perceived
residue: it relies on atomic hydration, which the perceiver only proposes.
Two things this immediately caught in the harness itself:
- Counting bead_models[current_model] reported 0 beads for a build that had
plainly succeeded (rc 0, three overlap-reduction stages, a written bead
model). The build walks current_model as its loop variable and leaves it
ONE PAST the last model, so that index is out of range right afterwards.
Count bead_model, the model just built.
- ensure_atom_entry's report went out through editor_msg(), which only ever
writes to the GUI text widget -- so in a gui_script run the substitution
was completely silent, and its absence from a log proved nothing. It now
also goes to stdout. A silent substitution is the same defect class as the
silent skip it replaces.
Verified on 1MBO/2CMD against the reference tables: the fallback fires once
during the first build ("atom table: S (S) is not in the atom table; using
the hybrid match ... 19.86 A^3") and all four methods build --
somo 305, somo_o 305, vdw 1267, grid 331 beads. The 305 matches the count
from the user's GUI session.
Docs record that a script using "perceive build" must set "somo overwrite"
first -- without it the bead-model write calls setSomoGridFile(), which
raises a modal dialog and hangs a headless run (batch suppresses those
prompts, a gui_script does not) -- and that there is no equivalent flag for
the hydrodynamic calculations.
(cherry picked from commit ba5015a5511fb573d07cf81b27f13e979bb95cd0)
Commit: bd6412bb43db3c7a5cc683fb20637b36b95349ec
https://github.com/ehb54/ultrascan3/commit/bd6412bb43db3c7a5cc683fb20637b36b95349ec
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
A us_somo/develop/perceiver/GUI_TESTING.md
M us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
M us_somo/somo/doc/manual/somo/somo.html
A us_somo/somo/doc/manual/somo/somo_perceive.html
Log Message:
-----------
perceiver: dedicated help page for the non-coded residue dialog
The review dialog's Help button pointed at somo_residue.html, which documents
the residue table editor and says nothing about perception. Point it at a new
somo_perceive.html and link that from the Lookup Tables list in somo.html,
beside Add/Edit Residue.
The page follows the manual's conventions and uses the dialog's actual
labels -- Skip this residue, Also append this entry to somo.residue, Flagged
for review -- rather than paraphrases. It reserves an <img> slot for
somo-perceive.png next to the HTML.
Its substance is what a GUI tester cannot get from the interface itself:
- perceive BEFORE building, or the Automatic Bead Builder's _NC placeholders
are already in the model
- what Accept actually does. An accepted entry goes to somo.residue.perceived
and becomes the active table IMMEDIATELY, but only for this session:
residue_filename is reset to somo.residue at every start and is not stored
in the config, and the next session's first Accept REBUILDS that file from
somo.residue, discarding what an earlier session accepted. Tick the
checkbox, or re-select the file by hand before accepting anything new
- what each computed number is worth, and that hydration is the weakest --
which is why vdW models are where a weak proposal becomes a real problem
- that ASA is a placeholder which nonetheless may not be zero
Also adds perceiver/GUI_TESTING.md, the same ground as a cheat sheet for
someone testing only through the GUI, with the four test structures and what
to be sceptical of in a proposed entry.
Note US_Help::show_help() falls back to underconstruction.html when the file
is missing, so "under construction" means help_dir points at an installed
release rather than at this tree.
(cherry picked from commit 26495b76b360b4c7ad8b70a164531dc54439f8ab)
Commit: a7ac63c79bdacda4184688db31492c81a80cbefb
https://github.com/ehb54/ultrascan3/commit/a7ac63c79bdacda4184688db31492c81a80cbefb
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
A us_somo/develop/perceiver/data/non-coded/8RATNC.pdb
A us_somo/develop/perceiver/data/non-coded/8RAT_gap3.pdb
A us_somo/develop/perceiver/data/non-coded/8RAT_run3.pdb
A us_somo/develop/perceiver/tools/make_noncoded_variant.py
Log Message:
-----------
perceiver: chain-embedded test residues with a known answer
Every non-coded structure in the test set so far is a free ligand -- citrate,
benzamidine, sulfate -- so nothing exercises a non-coded residue INSIDE a
chain, and nothing has a ground truth to check the computed numbers against.
us_somo/somo/demo/8RATNC.pdb is 8RAT with LYS 31 renamed to LYD, done by hand
upstream. That trick is the useful one: the atoms are untouched, so whatever
the perceiver derives can be compared directly against the coded entry for
the residue it really is. Add it here and generalise it.
tools/make_noncoded_variant.py IN.pdb OUT.pdb A:31=LYZ ...
renames residues by chain and resSeq, refusing to write if a spec matched
nothing -- a silently unmodified file would quietly pass any test built on
it. Two shapes beyond the single-residue case, both aimed at the chain
handling rather than the chemistry:
8RAT_run3.pdb LYS31/SER32/ARG33 -> LYZ/SEZ/ARZ, an unbroken run
8RAT_gap3.pdb LYS31/ARG33/LEU35 -> LYZ/ARZ/LEZ, alternating with coded
Coded values to check against (somo.residue.new):
LYS vbar 0.818 molvol 167.30 hydration 4.0
SER vbar 0.628 molvol 95.40 hydration 2.0
ARG vbar 0.698 molvol 194.00 hydration 3.0
LEU vbar 0.898 molvol 164.00 hydration 1.0
Expect a systematic offset rather than a match: the perceiver treats a
residue as an isolated unit, while the coded amino-acid entries describe it
in a chain.
(cherry picked from commit a2e127b4d827e58300de76c52522b858b3657e9a)
Commit: 386ffa92bb78ee712e9ef6911b8edcbcfef66409
https://github.com/ehb54/ultrascan3/commit/386ffa92bb78ee712e9ef6911b8edcbcfef66409
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/perceiver/GUI_TESTING.md
M us_somo/somo/doc/manual/somo/somo_perceive.html
Log Message:
-----------
perceiver: record the measured accuracy in the help page
The help page said what each computed number is worth in general terms.
Now there are numbers, from residues where the answer is known: rename a
residue the table already codes, leave its atoms untouched, and the coded
entry becomes the answer key.
really psv perceived/coded volume perceived/coded hydration
SER 0.632 / 0.628 +0.6% 97.95 / 95.40 +2.7% 2.0 / 2.0
LEU 0.892 / 0.898 -0.7% 158.61 / 164.00 -3.3% 1.0 / 1.0
LYS 0.871 / 0.818 +6.5% 172.85 / 167.30 +3.3% 4.0 / 4.0
ARG 0.809 / 0.698 +15.9% 196.19 / 194.00 +1.1% 3.0 / 3.0
Hydration was exact on all four -- the quantity with the least theoretical
backing, and the one a tester is most able to sanity-check. Volume within
+-3.3%. psv splits by charge: neutral side chains +-0.7%, charged ones high.
The arginine +15.9% is reproduced independently by the isolated-residue
validation and matches the reading that the tabulated Arg psv was measured
unprotonated while the increments assume protonation -- so the help page
tells the user to treat a perceived psv for a charged group as provisional.
Chain embedding caused no difficulty: one non-coded residue, three in a row
and three alternating with coded ones gave identical values and built
cleanly (244/242/242 beads). The residuals track charge, not chain context
-- the opposite of what was expected, since the perceiver sees the real
bonded neighbours and so perceives backbone N and C as amide and carbonyl.
Same table added to the GUI cheat sheet, with the three new test files.
(cherry picked from commit cdd288a85403d8acde8bccbb73c6c2c01266521c)
Commit: 6857cecb525088dc9c21a108542a13270192fcdc
https://github.com/ehb54/ultrascan3/commit/6857cecb525088dc9c21a108542a13270192fcdc
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
A us_somo/somo/doc/manual/somo/somo-perceive.png
M us_somo/somo/doc/manual/somo/somo_perceive.html
Log Message:
-----------
perceiver: add the review dialog screenshot to the help page
The page referenced somo-perceive.png without the file existing, so it
rendered a broken image. Adds it, with a caption.
The screenshot is citrate rather than benzamidine deliberately: benzamidine
has 0 atoms flagged and an empty-looking review box, while citrate shows the
Flagged for review box populated with the carboxyl/carboxylate protonation
and pH 7 hydration notes -- the part of the dialog the page spends most of
its words on, and the part a tester most needs to recognise.
Verified: every SRC and href on the page resolves, all three tables close.
(cherry picked from commit d78eaba38000ea86a71fde17cb204f085409417f)
Commit: 4d3df1019a3ab1ec766cde2a7cb484248d686dc8
https://github.com/ehb54/ultrascan3/commit/4d3df1019a3ab1ec766cde2a7cb484248d686dc8
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn.h
M us_somo/develop/src/us_hydrodyn.cpp
M us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
M us_somo/develop/src/us_hydrodyn_script.cpp
Log Message:
-----------
wip: mattia review items 1-3
(cherry picked from commit 64b54a4df90fa2200154bbb7fecc3176213d95ef)
Commit: c15e0db3ffd6f88fbc7dc037b3308d94e7d2e1ba
https://github.com/ehb54/ultrascan3/commit/c15e0db3ffd6f88fbc7dc037b3308d94e7d2e1ba
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn.cpp
Log Message:
-----------
wip: fix coded-test, map operator[] inserts on read
(cherry picked from commit 80e08e9dc5f268df0224b53014c5fe76bd609b11)
Commit: 7ae8eae45adbf0218c510c0177e3893f231e30fa
https://github.com/ehb54/ultrascan3/commit/7ae8eae45adbf0218c510c0177e3893f231e30fa
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn.h
M us_somo/develop/include/us_hydrodyn_perceive_dialog.h
M us_somo/develop/src/us_hydrodyn.cpp
M us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
Log Message:
-----------
wip: revisit accepted entries + reset-all
(cherry picked from commit c3dfad80e43d0d95d71045119cfe2b9b50243ed1)
Commit: 35b3f5560da01e850284074087dea20d9ae739da
https://github.com/ehb54/ultrascan3/commit/35b3f5560da01e850284074087dea20d9ae739da
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn.h
Log Message:
-----------
fix: perceived_entries member must not live in a slots block (moc)
(cherry picked from commit 93a8250cbe4f4c68d26de4826e678b9a54643e3c)
Commit: bc5fe0a85cc53a252bdda9450116f3d886bf15e8
https://github.com/ehb54/ultrascan3/commit/bc5fe0a85cc53a252bdda9450116f3d886bf15e8
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn.cpp
Log Message:
-----------
fix: raw newline inside a string literal from a scripted edit
(cherry picked from commit cdd317c12649f7998590441633172f998bd7ef39)
Commit: 5bf0bc01ca589ccbed29876f64911df8c28075ee
https://github.com/ehb54/ultrascan3/commit/5bf0bc01ca589ccbed29876f64911df8c28075ee
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_perceive_elements.h
M us_somo/develop/perceiver/tests/tests_unit.cpp
M us_somo/develop/src/us_hydrodyn_perceive_somo.cpp
M us_somo/develop/src/us_hydrodyn_psv.cpp
Log Message:
-----------
perceiver: never compute a psv from unidentified elements
A PDB with an empty element column (77-78) produced psv values of 0.001,
-0.068, -0.087 -- meaningless numbers that still look like numbers.
1AO6-compl_monA.pdb in the demo set is such a file, which is how it surfaced.
Two independent defects, either alone enough:
1. The atom-name fallback used norm_element(), which only strips
non-alphabetics. So the alpha carbon "CA" became CALCIUM, "NE2" became
NEON, and "CB", "CG", "OD1" matched no element at all. Every atomic volume
increment then evaluated to zero and the sum collapsed to roughly the
electrostriction terms. element_from_atom_name() takes the leading letter,
accepting a two-letter element only when the atom name equals the residue
name -- HETATM "CA" in residue "CA" is calcium, "CA" in "ALA" is carbon.
2. somo_psv::compute() reported ok on a residue containing atoms it had no
increment for. It now counts them, records why in the review block, and
returns ok == false, so the caller emits no psv rather than a plausible
figure. An unidentified element is not a small error; it is not a volume.
The grid volume was unaffected and still looked sensible (Ala 77.45 A^3),
which is precisely why this was not obvious from the output.
tests_unit.cpp gains the case that catches it: CA/CB/CG1/OD1/NE2/NZ/SD/OXT
must resolve by leading letter, while CA-in-CA, FE-in-FE, ZN-in-ZN, MG-in-MG
resolve as the two-letter element. 69 checks, 0 failures.
(cherry picked from commit f7a45de8f2384fb01f344630a2c4d70e974b3150)
Commit: bcf439527abd06606dd9d1a75160adec9b52e785
https://github.com/ehb54/ultrascan3/commit/bcf439527abd06606dd9d1a75160adec9b52e785
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_perceive_elements.h
M us_somo/develop/perceiver/tests/tests_unit.cpp
Log Message:
-----------
perceiver: element inference must key on the residue, not the atom name
The previous rule took the leading letter unless the atom name equalled the
residue name. That is right for proteins and wrong for ligands -- exactly the
population this code exists for. Six of fifteen test cases failed:
FE in HEM -> F (fluorine) CU in CUA -> C
CL in CIT -> C SE in MSE -> S
NA in XYZ -> N BR in LIG -> B
so a heme iron contributed a fluorine volume, silently.
The discriminator is the RESIDUE. In a standard residue the naming convention
is fixed and the element is always the leading letter: CA is the alpha carbon,
NE2 a nitrogen, SD a sulfur. In a ligand it is not, and a two-letter atom name
that matches a known element is that element.
Residual ambiguity, stated in the header: a ligand carbon named bare "CA"
reads as calcium. Ligand carbons are normally C1/CAA/CB1, and the psv now
refuses to compute rather than guessing when an element cannot be resolved,
so the failure is visible either way.
Answers the question directly: with this, a PDB with no element column is
handled correctly for proteins AND for ligands with two-letter elements.
Without it, only proteins were safe.
79 checks, 0 failures.
(cherry picked from commit cf4246cc29f0abb38781388293af0d633ac2df95)
Commit: ce30c44be40989a1cb6814c52703c8650ae4db9e
https://github.com/ehb54/ultrascan3/commit/ce30c44be40989a1cb6814c52703c8650ae4db9e
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_residue_builder.h
M us_somo/develop/perceiver/tests/builder.cpp
M us_somo/develop/src/us_hydrodyn_residue_builder.cpp
Log Message:
-----------
perceiver: emit psv at the table temperature, not the increments'
The Durchschlag & Zipper increments describe 25 C. somo.residue is a 20 C
table -- SOMO itself converts with tc_vbar() using 4.25e-4 cm^3 g^-1 K^-1.
The perceiver applied no conversion at all, so every generated entry was
5 K x 4.25e-4 = 0.0021 cm^3/g high: about +0.3%, small enough to read as
method noise and not noise at all.
Found by comparing against Mattia Rocco's independent recalculation. Matching
the temperature reference collapses the disagreement:
residue vs his 25 C vs his 20 C
GLY ALA VAL -0.07 .. +0.02% +0.20 .. +0.33%
LEU ILE THR
CYS MET PHE
TRP ASN GLN
SER +0.07% +0.41%
ASP +0.16% +0.52%
14 of 20 residues agree to within +-0.07% once the reference matches.
His conversion itself is exact, which was the other possibility Mattia raised:
the dv/dT implied by his 25 C and 20 C columns is 4.2500e-04 for all 20
residues with ZERO spread, and equals SOMO's tc_vbar coefficient. No rounding
error there -- the discrepancy was entirely on this side.
The temperatures and the coefficient are Options fields rather than literals,
so a table at another reference temperature is a parameter change.
builder.cpp gains the check: ALA psv 0.7413 at 25 C -> 0.7392 at 20 C, which
is Rocco's tabulated 20 C value exactly. 57 checks, 0 failures.
(cherry picked from commit cd05f6908b8f9fe815785b83e87ae31d869ac939)
Commit: bcfe8be56ce83329c0476b2b2e295101925c9002
https://github.com/ehb54/ultrascan3/commit/bcfe8be56ce83329c0476b2b2e295101925c9002
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_perceive_elements.h
M us_somo/develop/perceiver/tests/tests_unit.cpp
Log Message:
-----------
perceiver: protein atom names win over two-letter elements
Keying element inference on the residue name alone broke modified residues --
the very population this feature exists for. MSE, PTR, CGU and any renamed
residue carry protein atom names (CA, CB, CD, NE) under a NON-standard
residue name, so they took the ligand branch and every backbone CA became
CALCIUM. That changed the hybrid, the radius, the grid volume and the
hydration as well as the psv: alanine came back as vbar 0.171, molvol 83.9,
hydration 4.0 instead of 0.739 / 87.4 / 1.0.
Caught by re-running the 20-residue comparison rather than trusting the unit
tests, which used real residue names and so never entered that branch.
Resolution order is now explicit:
1. lone ion atom name == residue name ("CA" in residue "CA")
2. standard residue leading letter
3. protein atom name leading letter, whatever the residue is called
4. two-letter element FE, CL, SE, BR, CU, ZN, MG
5. leading letter
Step 3 is the one that makes modified and renamed residues work, and it is
why "SE in MSE" still resolves to selenium while "CA in MSE" resolves to
carbon: the collision set is atom NAMES, not residues.
86 checks, 0 failures, with MSE/PTR/CGU/renamed cases in the suite.
(cherry picked from commit e95f8708da6bdf9072a82b2a4b5334f77670f1f0)
Commit: fadfdc6efab90b10347861fd5f530fdd5c7ca596
https://github.com/ehb54/ultrascan3/commit/fadfdc6efab90b10347861fd5f530fdd5c7ca596
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/perceiver/Makefile
A us_somo/develop/perceiver/data/psv/1BEB.pdb
A us_somo/develop/perceiver/data/psv/2CGA.pdb
A us_somo/develop/perceiver/data/psv/README.md
A us_somo/develop/perceiver/data/psv_measured.txt
A us_somo/develop/perceiver/tests/protein_psv.cpp
Log Message:
-----------
perceiver: whole-protein psv, incumbent table vs D&Z increments vs D&Z+pH7
Mattia's question was whether to substitute somo.residue's amino-acid psv set with
one derived from the atomic volume increments. The residue-level four-way table
localised the differences but could not say which is right; this compares all three
against measured protein psv, using SOMO's own aggregation (calc_vbar_updated).
Measured values mined from Durchschlag Table 5 + the albumin table, taking only the
CORRECTED columns (phi, phi(0), v(0)) -- the apparent columns vary 5.7% at constant
pH purely from cosolvent, so they cannot be compared against a computed value.
Two guards the first run needed:
- explicit H/D are stripped. D&Z is a united-atom scheme and so is somo.residue
(ALA: N 15.02, CA 13.02, CB 15.04), so explicit hydrogens double count. The psv
guard already refused them; the tool must not hand them over in the first place.
- a structure whose usable residues fall below 95% is EXCLUDED, not reported. Before
this, 2AAS averaged a handful of surviving residues into a confident-looking
+13.7%. With H stripped it agrees with 8RAT to four decimals.
All three columns are gated on table membership so they cover identical residues;
otherwise a ligand the table cannot represent (1BEB's SO4) would count for D&Z only.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
(cherry picked from commit ad6a2302da74ee7c1ecab449fdb7f593cbf19f60)
Commit: 54a518afca8ab6995588716107a73f6722a463ef
https://github.com/ehb54/ultrascan3/commit/54a518afca8ab6995588716107a73f6722a463ef
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/perceiver/pdb_lite.h
M us_somo/develop/perceiver/tests/protein_psv.cpp
Log Message:
-----------
perceiver: strip hydrogens and index MODELs in pdb_lite, as SOMO does
Mattia: 'US-SOMO should strip them away! Why isn't it doing it in its tests?
Also the multiple models in NMR-style files. It should correctly recognize them
and perform the calculations anyway.'
He is right, and SOMO itself was never the problem:
- US_Hydrodyn::read_pdb strips H by name (us_hydrodyn_load.cpp:1489-1492,
including the ^\dH form that catches 1HB / HD21)
- it keeps every MODEL in model_vector, with a workaround for files whose
MODEL tag is missing
perceiver/pdb_lite.h did neither properly: it passed hydrogens straight through
and silently kept only model 1. That is not confined to the psv test -- 2AAS is
the one demo file with hydrogens (7840, 245 in model 1) and it drives regress,
coverage and sssrreal, so every one of those has been perceiving a structure
SOMO would never have handed it.
Fixed at the reader so every test inherits it, rather than patching one test:
- is_hydrogen_atom() reproduces SOMO's name rule, with one deliberate
divergence -- an explicit element column wins, so a mercury named HG survives
where SOMO's name rule would drop it. The perceiver exists for such ligands.
- MODELs are indexed on the atom; model_count()/model_of() split them. protein_psv
now computes every model and reports the ensemble spread instead of assuming
model 1, since which model to use is a later choice (his point exactly).
Effect: 2AAS goes from unusable to agreeing with 8RAT -- the same protein solved
by a different method -- to four decimals, and across its 32 NMR models the psv
spread is 0.0005 cm3/g (0.07%), which is the precision check that ensemble buys.
Regression unchanged and healthy: 97.894% exact, 99.833% geometric perception.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
(cherry picked from commit 17dd65468fbc3f2c188106285b6d777acf5c8fb6)
Commit: 2dcf9d9dcc7c7cd3077cdb68543285cc62c3a11b
https://github.com/ehb54/ultrascan3/commit/2dcf9d9dcc7c7cd3077cdb68543285cc62c3a11b
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/perceiver/pdb_lite.h
Log Message:
-----------
perceiver: recognize deuterium too, matching somo-dev's new skip option
somo-dev 10d48cec added a 'Skip deuterium atoms' parsing option (default on) with
pdb_parse_is_deuterium() in us_hydrodyn_pdb_parsing.h. pdb_lite's hydrogen test
already stripped D via the element column but not via the atom name, so a neutron
structure without col 77-78 would have leaked deuteriums into the perceiver.
Aligned with their helper, including its rationale: the element column wins over
the name because a name test alone cannot tell a deuterium from the second letter
of a two-letter element -- their example is 'CD' (cadmium), mine was 'HG'
(mercury). Same conclusion reached independently, now spelled the same way.
5PTI (data/non-coded) is the case: 229 deuteriums, all carrying an element column,
so behaviour there is unchanged -- this closes the no-element-column path.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
(cherry picked from commit c18f890853e48ded035a956bbff0cb7f78cf35d1)
Commit: befb24f1511b6f1ac909a97ec6524292bbcd7f0d
https://github.com/ehb54/ultrascan3/commit/befb24f1511b6f1ac909a97ec6524292bbcd7f0d
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/perceiver/tests/protein_psv.cpp
Log Message:
-----------
perceiver: allow a tabulated vbar to be overridden, to test candidate values
Mattia asked which of the three competing arginine values fares better. An argv
token RES=vbar now replaces that residue's vbar in the [table] column only; the
D&Z columns are computed from coordinates and stay untouched, so the run asks
exactly one question -- which tabulated value best predicts measured protein psv.
Result over 7 proteins, mean |error| of [table]:
ARG 0.698 (somo.residue) 0.84%
ARG 0.7686 (Rocco recalc) 1.37%
ARG 0.809 (D&Z increments) 1.67%
Monotonic: every step up is worse. The incumbent value wins and should stay.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
(cherry picked from commit 0c1fcd9179ba31a2df164eb1bb7c14af3c7b1f19)
Commit: d1d1422f9d04e9d391b0c454d2c5b22b735da650
https://github.com/ehb54/ultrascan3/commit/d1d1422f9d04e9d391b0c454d2c5b22b735da650
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/perceiver/tests/protein_psv.cpp
Log Message:
-----------
perceiver: show per-residue D&Z spread and a sequence-only cross-check
Mattia's point: psv is a composition property, so an experimental structure may
be unnecessary -- a sequence-correct model (AF2) would do, and then verifying the
protein's SOURCE and processed form matters more than the coordinates.
Measured rather than assumed. Per-residue D&Z psv across 7 proteins:
ALA SER TRP MET HIS ARG SD exactly 0.000 -- fully context-independent
most others SD 0.1-1.0%
CYS 2.21%, TYR 1.23%, LYS 1.00% -- real chemistry, not noise: free thiol vs
disulfide for CYS, termini for LYS. Sequence-only averages over these.
Recomputing every protein from composition alone, using corpus-mean per-residue
values, against the full structure-based calculation:
mean |diff| 0.076%, worst +0.116%
An order of magnitude below the effect being measured (table 0.84% vs D&Z 3.07%).
So structures are not the bottleneck after all: a correct sequence suffices, and
the binding constraint moves to source/isoform/processing verification.
Caveat: the per-residue means come from these same proteins, so the check is
mildly circular; the six zero-SD residues are exempt by construction.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
(cherry picked from commit 80159a145019f75db9608c30f77b1b4a74fa9606)
Commit: e9748b6a027f1fa45f80d82db269184fd068bf90
https://github.com/ehb54/ultrascan3/commit/e9748b6a027f1fa45f80d82db269184fd068bf90
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
A us_somo/develop/perceiver/data/psv/candidates.fasta
M us_somo/develop/perceiver/tests/protein_psv.cpp
Log Message:
-----------
perceiver: score proteins from UniProt mature sequences, no structures needed
Follows the sequence-only validation: composition reproduces the structural answer
to 0.076%, so any protein with a known MATURE sequence can join the validation set.
PROTEIN_PSV_FASTA=<file> reads records of '>label measured_psv' + one-letter sequence.
The processed form comes from UniProt MOLECULE_PROCESSING rather than guesswork,
which matters because the tables measure different forms of the same gene product:
pepsinogen = PROPEP + CHAIN (activation peptide RETAINED), P00791 16..385
papain = CHAIN only, propeptide removed, P00784 134..345
carboxypep A = CHAIN only, 94-residue activation peptide off, P00730 111..419
chymotrypsinogen A = full zymogen 1..245
a-chymotrypsin = chains A+B+C, dipeptides 14-15/147-148 excised, 241 residues
Eight new proteins, table column vs measured:
catalase -0.04, pepsinogen -0.06, a-chymotrypsin +0.05, chymotrypsinogen +0.18,
calmodulin +0.93, papain +1.05, carboxypeptidase A -1.51, a-lactalbumin +4.02
Excluding a-lactalbumin: bias +0.09%, mean |err| 0.55% -- better than the
structure-based set. Combined 14 proteins: bias +0.46%, mean |err| 0.69%.
Two things worth noting. The chymotrypsinogen/a-chymotrypsin pair differ by four
excised residues out of 245; measured +0.30%, calculated +0.18% -- the method
resolves it, and in the right direction. And a-lactalbumin, the one bad case, is
the entry Table 6 annotates '~12% carbohydrate content'; a carbohydrate correction
explains roughly half the 4% and it should stay excluded.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
(cherry picked from commit c2290b2405b9902ebfc422c684ce3db21e4bab41)
Commit: bd07e054b10b4775c0ebe0b7a1d4549424679d55
https://github.com/ehb54/ultrascan3/commit/bd07e054b10b4775c0ebe0b7a1d4549424679d55
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_perceive.cpp
M us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
Log Message:
-----------
perceiver: white dialog background, and one review line per atom
Two of three items from Mattia's Linux GUI testing (2026-08-10).
Background: the dialog is mostly close reading -- a generated table entry and a
list of flags -- and SOMO's global frame grey is hard going, more so on Linux
where it renders darker. Only this frame's background changes; every label here
calls AUTFBACK and paints its own, and the global palette is untouched.
Review list: two independent streams feed it, perception ambiguity notes and the
psv/volume/hydration reviews, both keyed "NAME (HYB)". Emitted raw, an atom with
one of each appeared twice, so citrate showed six entries for three atoms and read
as flagging far more waters than it does. Now grouped by atom, first-appearance
order, notes joined:
before after
O2 (O2H1): carboxyl -OH O2 (O2H1): carboxyl -OH; carboxylate at pH 7, 5 waters
O4 (O2H1): carboxylate O (symmetric...) O4 (O2H1): carboxylate O (symmetric...); carboxylate at pH 7, 5 waters
O6 (O2H1): carboxylate O (symmetric...) O6 (O2H1): carboxylate O (symmetric...); carboxylate at pH 7, 5 waters
O2 (O2H1): carboxylate at pH 7, 5 waters
O4 (O2H1): carboxylate at pH 7, 5 waters
O6 (O2H1): carboxylate at pH 7, 5 waters
The third item -- hydration on the wrong oxygen -- is a real inconsistency but
needs a convention decision, so it is not touched here.
Tests unchanged: unit 86/0, psv 60/0, hydration 37/0, regression 97.894% exact.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
(cherry picked from commit 45c7a165c46eac6c86500795ccaf86169ebdfbd8)
Commit: 069cc9bd31b3393077ced9e21c6fd81b5c11a612
https://github.com/ehb54/ultrascan3/commit/069cc9bd31b3393077ced9e21c6fd81b5c11a612
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
Log Message:
-----------
perceiver: pin the dialog foreground too, not just the background
Mattia: the font colour came out different on Linux and macOS.
Cause: PALET_LABEL and PALET_FRAME construct a whole QPalette from a single
configured colour, and Qt derives the remaining roles itself. That derivation is
not identical across Qt versions and platforms, so the text colour drifted.
perceive_palette() now names every role this dialog relies on -- Window, Base,
AlternateBase, WindowText, Text, ButtonText -- and is applied to the frame, all
labels, the info line, the checkbox and both read-only text views. Nothing is
derived, so both platforms render the same.
Push buttons deliberately keep PALET_PUSHB: they are controls users recognise by
their SOMO styling, and they are not the surface being read.
libus_somo builds clean.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
(cherry picked from commit cd3273186cd71d1e13df7e48c645aa592a704e9b)
Commit: 0c1521843ba1f0df3d40e3f8dfed9b2bc89f0b91
https://github.com/ehb54/ultrascan3/commit/0c1521843ba1f0df3d40e3f8dfed9b2bc89f0b91
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
Log Message:
-----------
perceiver: make the review list's length visible, and fix the flagged count
Mattia, testing on Linux: "I didn't get from the actual perceiver that there were
more lines to be scrolled, likely the grey bkg fooled me. It should be evident".
Three things were hiding it:
- the box had no frame, so on the old grey it blended into the dialog. White needs
the border more than grey did: both text views are now StyledPanel|Sunken.
- no scrollbar until you tried to scroll. Both views now keep a vertical scrollbar
permanently, so a list longer than its box says so without being discovered.
- the summary quoted tent_.flagged, which counts only atoms the PERCEPTION step
found ambiguous, while the box also carries psv, volume and hydration notes. The
two disagreed -- a "0 atom(s) flagged" line could sit above a box with entries in
it. The REVIEW lines are now extracted once, before the summary, and the same
count feeds both; the label reads "Flagged for review - N item(s), scroll for all".
Wording moves from "atom(s)" to "item(s)", which is what they are.
Also AUTFBACK on the two text views and the checkbox. Per ehb54, SOMO needs it
per-field for backgrounds to render consistently, and those three were given a
palette without it.
libus_somo builds clean.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
(cherry picked from commit cf0adf435b6dbfef0b6f699a42947e0162aa5270)
Commit: d0f26f6e0505280cf77c8afa6a844bfda0d1ad84
https://github.com/ehb54/ultrascan3/commit/d0f26f6e0505280cf77c8afa6a844bfda0d1ad84
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_hydration.h
M us_somo/develop/include/us_hydrodyn_perceive.h
M us_somo/develop/include/us_hydrodyn_perceive_dialog.h
M us_somo/develop/src/us_hydrodyn_hydration.cpp
M us_somo/develop/src/us_hydrodyn_perceive.cpp
M us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
M us_somo/develop/src/us_hydrodyn_residue_builder.cpp
Log Message:
-----------
perceiver: emit both protonation states for ionizable atoms
Option (b), per ehb54. An ionizable atom now gets the 16-field atom line the coded
residues use -- protonated species in fields 1-8, deprotonated in 10-16 -- plus
vbar_ionized and pKa in the residue header.
The convention was read off somo.residue rather than assumed, and it is the same
for acids and bases: primary = protonated, alternate = deprotonated.
ASP OD2 O2H1 ...0 | O1H0- ...5 COOH -> COO-
LYS NZ N4H3+ ...3 | N3H2 ...1 NH3+ -> NH2
ARG NH2 N3H2+ ...1 | N3H1 ...0 guanidinium+ -> neutral
This also fixes what Mattia found on citrate. The old code put the pH-7 water count
on an O2H1 primary -- a row that exists nowhere in somo.residue, since an O2H1 is a
hydroxyl and carries 1 -- and summed those into a bead total of 16. Now the neutral
-COOH carries 0, the alternate carries 5, and the bead total reads 1 for the
neutral state. The 16 was never wrong arithmetic; it was the ionized total written
into a neutral record.
pKa is a CONVENTION value from whichever coded residue shares the group (carboxyl
3.67/4.25 by chain length, the same discriminator the 5-vs-6-water rule already
uses). It is not a prediction: citrate's three carboxyls all come out short-chain
and are proposed at 3.67 where the real values are ~3.13/4.76/6.40 -- which is why
it is presented for the user to accept or change, and labelled as convention in the
REVIEW block.
Alternate mass and radius are resolved from somo.hybrid, not hard-coded; an
alternate type missing from the table is reported and the alternate is not written.
Dialog: three columns on the same row -- Ionized, Ionized hydration (edit), pKa
(edit) -- blank and uneditable for non-ionizable atoms. pKa is per residue, as
somo.residue stores it in the header, so editing it on any row updates them all.
Bad input reverts rather than clamps.
Citrate now emits a 9-field header and 16 fields on exactly the three carboxyl
oxygens. Tests unchanged: unit 86/0, hydration 37/0, psv 60/0, regression 97.894%
exact. libus_somo builds clean.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
(cherry picked from commit 9290eb14043008f1964676f85f19d12d16a8ef85)
Commit: 3a7d71bdb0724129cbecb1b6ed7c502f1cc118fe
https://github.com/ehb54/ultrascan3/commit/3a7d71bdb0724129cbecb1b6ed7c502f1cc118fe
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
Log Message:
-----------
perceiver: RasMol shows the structure again, without solvent
Mattia, 2026-08-10: "The 'view Residue in RasMol' was better before, where it was
showed together with the structure (solvent molecules should be, however,
discarded... usually unchecking the H atoms remove waters from visualization)".
Reverts the residue-only view to whole-structure-with-context, but fixes the two
things that made the first version of it unusable:
- solvent and hydrogens are dropped. Waters buried the residue in a haze of
oxygens; his own workaround was that unchecking H removes them, so both go.
Solvent is matched by residue name, hydrogen by the same rule the readers use --
element column when present, atom name otherwise, including the 1HB form.
- the view centres ON the residue, not on the model, and zooms in. Centring on the
model is why 1MBO's sulfate was lost inside the surrounding wireframe and why
this was reduced to residue-only in the first place.
Protein is thin grey wireframe (15), the residue spacefilled in cpk at wireframe 40,
so it reads as the subject with the fold as context.
The residue-present check still runs against the filtered file, so a structure whose
residue was entirely solvent-named would still report rather than open an empty view.
libus_somo builds clean.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
(cherry picked from commit 8956bda1bed8ba8995b859bd1bff18ae7902ee40)
Commit: 590f686412b06ac7ed5fb16dc75ff1c1ab3af960
https://github.com/ehb54/ultrascan3/commit/590f686412b06ac7ed5fb16dc75ff1c1ab3af960
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/somo/doc/manual/somo/somo_perceive.html
Log Message:
-----------
perceiver: bring the help page up to date
Seven commits of user-visible change had landed since the page was last touched.
Documents what a reviewer now actually sees:
- the ionizable columns (Ionized / Ionized hydration / pKa), why they exist -- the
coded ionizable residues are already stored this way, so an entry written the same
way lets US-SOMO pick the state by pH -- and which of them are editable.
- that the proposed pKa is a CONVENTION value from whichever coded residue shares
the group, not a prediction, with citrate as the cautionary case: all three
carboxyls proposed at 3.67 where the real values are ~3.13/4.76/6.40.
- that the pKa is one value per residue, so editing it anywhere changes the entry.
- RasMol now shows the residue inside the structure with solvent and hydrogens
removed, centred on the residue.
- the review box gives its item count and scrolls, one line per atom.
- Reset this residue, and revisiting an accepted entry.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
(cherry picked from commit 8b715d0c3744e8b6afbd371165322e84614a3a1b)
Commit: d8dae41bfdd6dabee48ae07db498d964dfce0df3
https://github.com/ehb54/ultrascan3/commit/d8dae41bfdd6dabee48ae07db498d964dfce0df3
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_hydration.cpp
M us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
Log Message:
-----------
perceiver: readable table headers, and stop flagging plain carbonyl oxygens
Two things from Mattia's screenshot of 8RAT_gap3 / LYZ.
Headers unreadable: QHeaderView paints its sections with Button/ButtonText, not
Window/WindowText. perceive_palette() set only the text, so the section background
stayed inherited and the headers came out dark on dark. Button is now an explicit
light grey, and the palette is applied to the table and its header widget -- neither
inherits the frame's -- with the header in bold so it reads as one.
Spurious review flag: an oxygen with no hydrogen that is not part of a carboxyl --
a backbone carbonyl, an ester, an ether, a phosphate O -- matched no rule and fell
through to "no pH 7 rule for this group", so nearly every entry was flagged for its
own backbone. Every O1H0 in somo.residue carries 0 waters (36 backbone O, plus
O2/O4/O6/OP1/OP2 and the rest), so that is a confident zero and is now stated as one.
LYZ in 8RAT_gap3 goes from 3 flagged items to 1, the remaining one being the real
ASA placeholder note.
Tests unchanged: unit 86/0, hydration 37/0, psv 60/0. libus_somo builds clean.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
(cherry picked from commit bb17af1bcaf6164b068ae745e30cca99b1222cb1)
Commit: 503d9d6e075af6f6c468c53d3929af030ff3919d
https://github.com/ehb54/ultrascan3/commit/503d9d6e075af6f6c468c53d3929af030ff3919d
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_core.cpp
M us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
Log Message:
-----------
perceiver: show both hydration totals, and point at the module from the load
Two from Mattia's testing.
Hydration total read 1 for 2CMD. That is the PROTONATED total and it is correct as
far as it goes -- since ionizable atoms started carrying their waters in the
deprotonated alternate, citrate's three carboxyls contribute 0 each and only the
central hydroxyl's 1 remains. But at pH 7 citrate is deprotonated, so the number
that matters is 16, and showing only the neutral one is misleading. The label now
gives both, and only when the entry actually has an ionizable atom:
Residue hydration total: 1.00 waters neutral, 16.00 ionized
Missing perceiver warning: no such message has ever existed in this branch -- I
searched the history for one and there is none -- so this is a gap rather than a
regression, but the gap is real. The load reports non-coded residues, the bead
builder then represents each by a single crude bead, and nothing told the user an
entry could be derived from the coordinates first. check_for_missing_atoms now says
so once unknown_residues is final, naming the residues it means.
libus_somo builds clean.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
(cherry picked from commit 71f1ee61a3daf2baf4560952ef17abf67f8c6c8e)
Commit: 9c78c064d798a860b57d4941a83bc343994fcace
https://github.com/ehb54/ultrascan3/commit/9c78c064d798a860b57d4941a83bc343994fcace
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_perceive.cpp
M us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
Log Message:
-----------
perceiver: fix the ionization index, respect the 2-pKa limit, reword the total
Accepting a citrate entry failed with "Duplicate ionization index". Three separate
constraints in the residue-file format, none of which the emitter was honouring:
1. the ionization index must be UNIQUE within a residue. Every ionizable atom was
written with index 1, so citrate's second carboxyl collided. Now counts from 1.
2. the header is a vbar followed by one (vbar, pKa) PAIR per ionization, and each
atom's index must match a declared pKa, which it then consumes. Only one pair was
being written no matter how many atoms were ionizable.
3. at most TWO are supported -- the loader rejects a third outright. Citrate has
three carboxyls and simply cannot be written in two states.
For (3) the entry now collapses to the single state that is true at pH 7, the
deprotonated one, applied to the primary fields so the TYPES and the WATERS agree --
unlike the original bug, where the types were neutral and the waters ionized. The
REVIEW block says the entry is not pH-switchable and why. Silently emitting a record
the loader refuses is the one option not on the table.
Verified both paths: a single-carboxyl residue emits ASP's exact shape (header
"0.593 0.593 3.67", one 16-field line at index 1); citrate emits 8-field lines with
O1H0- and 5 waters, and the collapse note.
Hydration total reworded as Mattia reads it -- "16 waters proposed, 1 for non-ionized
and 15 for ionized atoms" -- split by atom category rather than by state, and
coloured, since it is the number most worth checking.
Tests unchanged: unit 86/0, hydration 37/0, psv 60/0, regression 97.894% exact.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
(cherry picked from commit c4bced72a8e5f15e3372a0ae7faaf2ef444fb0f9)
Commit: f108df8633d7c4085a0b413abb9ed3268c8d540f
https://github.com/ehb54/ultrascan3/commit/f108df8633d7c4085a0b413abb9ed3268c8d540f
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_perceive_dialog.h
M us_somo/develop/src/us_hydrodyn_perceive.cpp
M us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
Log Message:
-----------
perceiver: keep the ionizable columns populated when an entry is collapsed
Mattia: "now the ionizable fields are empty, I suppose because the three pKs are not
anymore supported even at this stage. I would left this in at this stage".
He is right that they should not go blank. The file cannot hold three ionizations,
but the dialog is the review surface, not the storage, and blanking the columns
throws away what the perceiver actually found.
The perceiver now records each ionization it had to drop as a machine-readable
comment -- "# ION <atom> <hybrid> <waters> <pKa>" -- which the loader ignores and the
dialog keeps, so this needs no new plumbing. The dialog fills the columns from it and
marks them display-only: shown so the reviewer can see what was perceived, greyed
from editing because they are not part of what gets written, and skipped when the
entry is rebuilt. The emitted record stays 8-field and loadable.
Also colours the water counts in the editable cells themselves, not only the summary
("I meant in the editable fields").
While there: refresh_entry() was writing a hardcoded ionization index of 1 and a
single header pKa pair, the same two bugs just fixed in the emitter. It now numbers
indices from 1 and writes one pair per emitted ionization, so an entry edited in the
dialog round-trips as loadably as one written headless.
Tests unchanged: unit 86/0, hydration 37/0, psv 60/0. libus_somo builds clean.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
(cherry picked from commit 5bacee9b80ee3cab0f37294dcc06962d3dca17b5)
Commit: 154cb217a37fe5be0a7f1d93aa9c00046180f73f
https://github.com/ehb54/ultrascan3/commit/154cb217a37fe5be0a7f1d93aa9c00046180f73f
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
Log Message:
-----------
perceiver: split the hydration total onto two lines
As one line the caveat was the widest widget in the dialog, so the window
grew to fit it (Mattia, 2026-08-12). Break before the parenthetical: the
number and its ionized/non-ionized split stay together on line 1, the
caveat moves to line 2. Both the ionizable and non-ionizable variants.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
(cherry picked from commit 202cb61cc4073b43f24166a205c8d0e2a159d04c)
Commit: 6f0798d1da70561c81cb76edccbf9ed98a40b058
https://github.com/ehb54/ultrascan3/commit/6f0798d1da70561c81cb76edccbf9ed98a40b058
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_perceive_dialog.h
M us_somo/develop/perceiver/tests/tests_unit.cpp
M us_somo/develop/src/us_hydrodyn_perceive.cpp
M us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
M us_somo/somo/doc/manual/somo/somo_perceive.html
Log Message:
-----------
perceiver: phosphate convention for residues with >2 ionizable groups
somo.residue holds at most two ionizations per residue, so citrate's three
carboxyls used to collapse the whole entry to its pH 7 state -- correct at
pH 7 and frozen everywhere else.
Adopt the convention the coded table already uses for phosphate (ehb54 and
Mattia, 2026-08-12: "assume the first oxygen to be always deprotonated").
The lowest-pKa groups are written permanently deprotonated in the primary
fields; the two highest keep real switchable slots. Lowest-first is what
makes it defensible: that group is already fully ionized wherever the entry
is usable. Phosphate (2.15/7.20/12.35) reproduces the hand-written entry
exactly; citrate keeps its 2-/3- transition instead of being frozen.
The pKa becomes per-group rather than per-residue -- two switchable groups
can differ (citrate 4.76 and 6.40) and the header stores one pair per
ionization, selected by the atom's ionization index. One predicate now
drives both the atom line and the header pair so an index can never
reference a pair that was not declared.
Also fixes the bead hydration, which summed the protonated column while the
coded residues count ionizable atoms ionized (Asp's OD2 is 0/5 and Asp's
second bead is written 5). 2CMD's citrate emitted a bead of 1 against the 16
its own review dialog computed for the same entry; both now say 16.
6 new unit tests; regression unchanged at 99.833% geometric perception.
Help page updated: per-group pKa, and the convention documented.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
(cherry picked from commit fa2ad021f3ad467403b337a3166ef384eb0242c0)
Commit: 7219ae0dee09d8a702752d60b7d6093119ef7965
https://github.com/ehb54/ultrascan3/commit/7219ae0dee09d8a702752d60b7d6093119ef7965
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/version.sh
Log Message:
-----------
somo: fix version.sh to read the current US_Version definition
version.sh extracted the version with
sed -n '/0x0500/,/define/p' $us3/utils/us_defines.h | grep US_Vers
which depended on a 0x0500-delimited block that utils/us_defines.h no longer
has -- the version is now a plain '#define US_Version QString("4.2.0-dev")'.
The sed range matched nothing, so US_Version_string was generated empty and
every SOMO build carried a blank version.
Read the define directly instead, anchored so it cannot also match
US_Version_string. Also strip the padding that BSD/macOS 'wc -l' puts in
front of the revision count (SOMO_Revision was 'SOMOgit- 185'), and silence
the grep errors on the first run, when include/us_version.h does not exist yet.
Before: US_Version_string "" SOMO_Revision "SOMOgit- 185"
After: US_Version_string "4.2.0-dev" SOMO_Revision "SOMOgit-185"
(cherry picked from commit 6357594151cf1e07f30e20a832b5aaf623a789c1)
(cherry picked from commit 23a60b9ad635e383d834167a461cd0fddf3185c3)
Commit: e660154cc960ba0d9a7bc71ca63ad2b4483881ef
https://github.com/ehb54/ultrascan3/commit/e660154cc960ba0d9a7bc71ca63ad2b4483881ef
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M .gitignore
Log Message:
-----------
somo: ignore the generated us_somo us_revision.h
main untracked us_somo/develop/include/us_revision.h (f57e5fb62) because it is
a build artifact -- libus_somo.pro regenerates it every build via the revision
extra-target -- but no ignore rule was added, so it shows up untracked after
every build. That is how it gets committed by accident; somo-dev tracks the
generated header for exactly this reason.
The sibling artifact us_version.h and programs/us/us_revision.h are already
ignored here; add the missing us_somo one alongside them.
(cherry picked from commit c96829fb61a6bfae932c70c15ba0f5d5f8e82b2b)
(cherry picked from commit 169ba28af6e86d80a588fd5949dc79ef12e93f96)
Commit: 4fabf4c087fe5a19e30d8614dcba4b2992e37841
https://github.com/ehb54/ultrascan3/commit/4fabf4c087fe5a19e30d8614dcba4b2992e37841
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_saxs_iqq_load_csv.cpp
Log Message:
-----------
somo: hold back the extrapolate-to-zero-concentration control
The extrapolation code is merged and maintained, but the feature is not being
released yet. Hide and disable its only user-facing control -- the
"Extrap. to zero conc" checkbox in the I(q) CSV load dialog -- so the code
travels with main without being offered.
Also clear the caller's *extrapolate_c0 flag here. set_extrapolate_c0() is the
only thing that maintains it and it can no longer run, so a value left over from
an earlier session would otherwise stand with no way to clear it.
There is no manual page for this feature and no gui_script command for it on
this branch, so the checkbox is the whole surface. To expose it later, restore
setEnabled(true)/setChecked(*extrapolate_c0) and drop the setVisible(false).
(cherry picked from commit 48a8da73386fe26bd0dc83714be122730146f0f9)
Commit: 18ddf6844deea6f8c9ef06afaeedc1610210a88c
https://github.com/ehb54/ultrascan3/commit/18ddf6844deea6f8c9ef06afaeedc1610210a88c
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
Log Message:
-----------
somo/perceive: hold back writing perceived entries into somo.residue
Perception itself is released: an uncoded residue is perceived and used for the
run through the session overlay, as before. What is held back is the permanent
write into the user's own residue table.
- Disable the " Also append this entry to somo.residue " checkbox, and say why
in the tooltip. Left visible rather than hidden, so it is evident that the
table is deliberately not being touched.
- Force save_requested_ false in accept_entry(), so the append cannot fire
whatever state the disabled box is in. That guards the single writer, at
us_hydrodyn.cpp:2406.
The entry stays in the dialog's read-only box and in the log, so it can still be
copied out by hand. To release: restore cb_save->isChecked() and its
setEnabled, and revert the tooltip.
(cherry picked from commit 0465d69edc58be59f68e1875b0461aa8b63f5ef9)
Commit: 3a08b43d7d63f1ed405372947e037d921306271b
https://github.com/ehb54/ultrascan3/commit/3a08b43d7d63f1ed405372947e037d921306271b
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
A us_somo/develop/perceiver/data/ref/cctbx_LICENSE.txt
M us_somo/develop/perceiver/data/ref/it1992.cpp
Log Message:
-----------
perceiver: retain the cctbx copyright notice on the vendored it1992.cpp
data/ref/it1992.cpp is a verbatim copy of cctbx's transcription of International
Tables Vol. C Table 6.1.1.4, carrying none of its copyright or license. The
cctbx license is BSD-style and its condition (1) requires source redistributions
to retain the copyright notice, the conditions and the disclaimer.
Add the notice and vendor the full license text alongside as cctbx_LICENSE.txt.
The file is not compiled -- gen_saxs_entries.py parses it -- but it is
redistributed in source form, which is exactly what condition (1) covers.
Reported-by: aaron-auc
Commit: 3cace687794aa91751658f87a10fb8457b857c6b
https://github.com/ehb54/ultrascan3/commit/3cace687794aa91751658f87a10fb8457b857c6b
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/perceiver/tests/regression.cpp
Log Message:
-----------
perceiver: fail the regression test when it scores nothing
The regression target scores against demo PDB structures that are NOT committed
to the repository. read_pdb() returns an empty list for a missing file, so it
scored 0 atoms, every percentage divided by zero and printed 0.000%, and it
exited 0 -- reporting 'genuine perception errors remaining: 0 (0.000%)' having
looked at nothing. Confirmed by running it from a clean checkout: it passed,
with 0 atoms scored, on all eight demo structures.
A test that reports success because it examined nothing is worse than no test.
Name any input that yielded no atoms, and exit 2 when nothing was scored at all,
saying that the demo structures are absent.
Committing the structures is a separate call: that is a data decision about size
and provenance, not a code fix.
Reported-by: aaron-auc
Commit: ca3fc42d25957af2c3ac1fef4d9c3f9b4cebb4ce
https://github.com/ehb54/ultrascan3/commit/ca3fc42d25957af2c3ac1fef4d9c3f9b4cebb4ce
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
A .github/workflows/somo-module-tests.yml
Log Message:
-----------
somo: run the perceiver suite in CI, and assert the vacuous-pass guard
The perceiver tests were only ever run by hand, so a change could pass CI while
breaking the behaviour they cover.
The workflow runs the perceiver unit tests -- Qt-free, standalone -- and asserts
the guard added alongside it: with no input, bin/regression must FAIL rather than
report 0.000% and exit 0.
The regression target proper stays out of CI until it has structures to score.
(An equivalent job for the in-process grpy module is deliberately absent: that
module is not part of this merge, see the licence note on the ticket.)
Commit: 2a584cacd1e8a82e9c492a57d4fb5f5655e84795
https://github.com/ehb54/ultrascan3/commit/2a584cacd1e8a82e9c492a57d4fb5f5655e84795
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_load.cpp
Log Message:
-----------
somo: silence the per-atom debug dump at the end of calc_mw()
It printed "end of calc_mw()" and then one CSV row per atom on every PDB load
-- thousands of lines for a large structure -- which slows a debug cycle when
stdout is a terminal or an editor shell.
Commented rather than deleted: it is diagnostic, not dead, and is the thing to
re-enable when ionization or net-charge numbers look wrong. Left with a note
of the caveat that made it misleading anyway -- its pH is hardwired to 7 rather
than read from the form, so it does not describe the pH actually in use; the
already-commented call immediately above is the variant that does.
Matches the several other commented-out info_* diagnostics around it.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
(cherry picked from commit faf147fa301e7485b3f1f68bb4c54fceee7f4c70)
Commit: aabbfce4341e05ae22094eca86391082b6a3fba3
https://github.com/ehb54/ultrascan3/commit/aabbfce4341e05ae22094eca86391082b6a3fba3
Author: emre brookes <ehb54 at users.noreply.github.com>
Date: 2026-08-17 (Mon, 17 Aug 2026)
Changed paths:
A .github/workflows/somo-module-tests.yml
M .gitignore
M us_somo/develop/include/us_hydrodyn.h
M us_somo/develop/include/us_hydrodyn_dad.h
M us_somo/develop/include/us_hydrodyn_dad_fit.h
M us_somo/develop/include/us_hydrodyn_dad_options.h
A us_somo/develop/include/us_hydrodyn_grid_volume.h
A us_somo/develop/include/us_hydrodyn_hydration.h
M us_somo/develop/include/us_hydrodyn_mals_fit.h
M us_somo/develop/include/us_hydrodyn_mals_options.h
M us_somo/develop/include/us_hydrodyn_mals_saxs_fit.h
M us_somo/develop/include/us_hydrodyn_mals_saxs_options.h
M us_somo/develop/include/us_hydrodyn_pdb_parsing.h
A us_somo/develop/include/us_hydrodyn_perceive.h
A us_somo/develop/include/us_hydrodyn_perceive_dialog.h
A us_somo/develop/include/us_hydrodyn_perceive_elements.h
A us_somo/develop/include/us_hydrodyn_perceive_hybrid.h
A us_somo/develop/include/us_hydrodyn_perceive_saxs.h
A us_somo/develop/include/us_hydrodyn_perceive_somo.h
A us_somo/develop/include/us_hydrodyn_psv.h
A us_somo/develop/include/us_hydrodyn_residue_builder.h
M us_somo/develop/include/us_hydrodyn_saxs.h
M us_somo/develop/include/us_hydrodyn_saxs_hplc.h
A us_somo/develop/include/us_hydrodyn_saxs_iqq_extrap_c0_conc.h
M us_somo/develop/include/us_hydrodyn_saxs_iqq_load_csv.h
M us_somo/develop/include/us_saxs_util.h
M us_somo/develop/include/us_vector.h
M us_somo/develop/libus_somo.pro
A us_somo/develop/perceiver/.gitignore
A us_somo/develop/perceiver/DECISIONS.md
A us_somo/develop/perceiver/GUI_TESTING.md
A us_somo/develop/perceiver/Makefile
A us_somo/develop/perceiver/README.md
A us_somo/develop/perceiver/data/non-coded/1MBO.pdb
A us_somo/develop/perceiver/data/non-coded/2CMD.pdb
A us_somo/develop/perceiver/data/non-coded/3PTB.pdb
A us_somo/develop/perceiver/data/non-coded/5PTI.pdb
A us_somo/develop/perceiver/data/non-coded/8RATNC.pdb
A us_somo/develop/perceiver/data/non-coded/8RAT_gap3.pdb
A us_somo/develop/perceiver/data/non-coded/8RAT_run3.pdb
A us_somo/develop/perceiver/data/non-coded/README.md
A us_somo/develop/perceiver/data/psv/1BEB.pdb
A us_somo/develop/perceiver/data/psv/2CGA.pdb
A us_somo/develop/perceiver/data/psv/README.md
A us_somo/develop/perceiver/data/psv/candidates.fasta
A us_somo/develop/perceiver/data/psv_measured.txt
A us_somo/develop/perceiver/data/ref/cctbx_LICENSE.txt
A us_somo/develop/perceiver/data/ref/f0_WaasKirf.dat
A us_somo/develop/perceiver/data/ref/it1992.cpp
A us_somo/develop/perceiver/data/ref/somo.saxs_atoms.generated
A us_somo/develop/perceiver/examples/perceive.somo
A us_somo/develop/perceiver/pdb_lite.h
A us_somo/develop/perceiver/residue_oracle.h
A us_somo/develop/perceiver/run_dialog_test.sh
A us_somo/develop/perceiver/tests/builder.cpp
A us_somo/develop/perceiver/tests/coverage.cpp
A us_somo/develop/perceiver/tests/dialog_qt.cpp
A us_somo/develop/perceiver/tests/emit_residue.cpp
A us_somo/develop/perceiver/tests/grid_volume.cpp
A us_somo/develop/perceiver/tests/hydration.cpp
A us_somo/develop/perceiver/tests/protein_psv.cpp
A us_somo/develop/perceiver/tests/psv.cpp
A us_somo/develop/perceiver/tests/regression.cpp
A us_somo/develop/perceiver/tests/sssr.cpp
A us_somo/develop/perceiver/tests/sssr_real.cpp
A us_somo/develop/perceiver/tests/tests_unit.cpp
A us_somo/develop/perceiver/tinytest.h
A us_somo/develop/perceiver/tools/calibrate_3v_context.py
A us_somo/develop/perceiver/tools/gen_saxs_entries.py
A us_somo/develop/perceiver/tools/hydration_table.py
A us_somo/develop/perceiver/tools/make_noncoded_variant.py
A us_somo/develop/perceiver/tools/psv_durchschlag.py
A us_somo/develop/perceiver/tools/psv_model.py
A us_somo/develop/perceiver/tools/recalc_ligand_volumes.py
M us_somo/develop/src/us_hydrodyn.cpp
M us_somo/develop/src/us_hydrodyn_beads.cpp
M us_somo/develop/src/us_hydrodyn_core.cpp
M us_somo/develop/src/us_hydrodyn_dad.cpp
M us_somo/develop/src/us_hydrodyn_dad_conc.cpp
M us_somo/develop/src/us_hydrodyn_dad_conc_load.cpp
M us_somo/develop/src/us_hydrodyn_dad_fit.cpp
M us_somo/develop/src/us_hydrodyn_dad_makeiq.cpp
M us_somo/develop/src/us_hydrodyn_dad_modes.cpp
M us_somo/develop/src/us_hydrodyn_dad_options.cpp
A us_somo/develop/src/us_hydrodyn_dad_script.cpp
M us_somo/develop/src/us_hydrodyn_dad_util.cpp
M us_somo/develop/src/us_hydrodyn_fractal_dimension.cpp
A us_somo/develop/src/us_hydrodyn_grid_volume.cpp
A us_somo/develop/src/us_hydrodyn_hydration.cpp
M us_somo/develop/src/us_hydrodyn_load.cpp
M us_somo/develop/src/us_hydrodyn_mals.cpp
M us_somo/develop/src/us_hydrodyn_mals_conc.cpp
M us_somo/develop/src/us_hydrodyn_mals_conc_load.cpp
M us_somo/develop/src/us_hydrodyn_mals_fit.cpp
M us_somo/develop/src/us_hydrodyn_mals_makeiq.cpp
M us_somo/develop/src/us_hydrodyn_mals_modes.cpp
M us_somo/develop/src/us_hydrodyn_mals_options.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_conc.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_conc_load.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_fit.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_makeiq.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_modes.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_options.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_util.cpp
M us_somo/develop/src/us_hydrodyn_mals_util.cpp
M us_somo/develop/src/us_hydrodyn_other.cpp
M us_somo/develop/src/us_hydrodyn_pdb_parsing.cpp
M us_somo/develop/src/us_hydrodyn_pdb_tool.cpp
A us_somo/develop/src/us_hydrodyn_perceive.cpp
A us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
A us_somo/develop/src/us_hydrodyn_perceive_somo.cpp
A us_somo/develop/src/us_hydrodyn_psv.cpp
A us_somo/develop/src/us_hydrodyn_residue_builder.cpp
M us_somo/develop/src/us_hydrodyn_saxs.cpp
M us_somo/develop/src/us_hydrodyn_saxs_1d.cpp
M us_somo/develop/src/us_hydrodyn_saxs_2d.cpp
M us_somo/develop/src/us_hydrodyn_saxs_buffer.cpp
M us_somo/develop/src/us_hydrodyn_saxs_buffer_conc.cpp
M us_somo/develop/src/us_hydrodyn_saxs_buffer_conc_load.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_bl.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_ciq.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_conc.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_conc_load.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_gui.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_makeiq.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_modes.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_options.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_util.cpp
M us_somo/develop/src/us_hydrodyn_saxs_iqq.cpp
A us_somo/develop/src/us_hydrodyn_saxs_iqq_extrap_c0.cpp
A us_somo/develop/src/us_hydrodyn_saxs_iqq_extrap_c0_conc.cpp
M us_somo/develop/src/us_hydrodyn_saxs_iqq_load_csv.cpp
M us_somo/develop/src/us_hydrodyn_saxs_loads.cpp
M us_somo/develop/src/us_hydrodyn_script.cpp
M us_somo/develop/src/us_hydrodyn_settings.cpp
M us_somo/develop/src/us_saxs_util_best.cpp
M us_somo/develop/src/us_saxs_util_dmd.cpp
M us_somo/develop/src/us_saxs_util_hydro.cpp
M us_somo/develop/src/us_saxs_util_loads.cpp
M us_somo/develop/src/us_saxs_util_static.cpp
M us_somo/develop/src/us_vector.cpp
M us_somo/develop/version.sh
M us_somo/etc/somo.atom.new
M us_somo/etc/somo.config.new
M us_somo/etc/somo.defaults.new
M us_somo/etc/somo.hybrid.new
M us_somo/etc/somo.residue.new
M us_somo/etc/somo.saxs_atoms.new
A us_somo/somo/doc/manual/somo/DAWN_head.png
A us_somo/somo/doc/manual/somo/MALS_angles.png
A us_somo/somo/doc/manual/somo/WyattRayleigh ratios csv.png
M us_somo/somo/doc/manual/somo/mals_parameters.html
M us_somo/somo/doc/manual/somo/mals_saxs_options.html
M us_somo/somo/doc/manual/somo/saxs_hplc_ciq.html
M us_somo/somo/doc/manual/somo/saxs_hplc_options.html
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_EMG_option.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_GaussFit1.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_GaussFit2.png
A us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_options_Min_Gauss.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_options_new.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_options_new_Gaussians.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_options_new_baseline.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian1.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian11.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian11a.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian11b.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian11c.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian12.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian2.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian3.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian4.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian5.png
A us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian6a.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian8.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian9a.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian_adv_sel.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_smoothing.png
A us_somo/somo/doc/manual/somo/somo-MALS_Concs.png
A us_somo/somo/doc/manual/somo/somo-MALS_Concs2.png
A us_somo/somo/doc/manual/somo/somo-MALS_Concs3.png
A us_somo/somo/doc/manual/somo/somo-MALS_Concs4.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss1anew.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss1bnew.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss1cnew.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss1dnew.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss1enew.png
A us_somo/somo/doc/manual/somo/somo-MALS_GaussFit.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss_all_Idash_t_selected.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gaussian_final.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gaussian_init.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gaussian_options.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gaussian_start.png
A us_somo/somo/doc/manual/somo/somo-MALS_GlobalFit_done.png
A us_somo/somo/doc/manual/somo/somo-MALS_GlobalGauss_done.png
A us_somo/somo/doc/manual/somo/somo-MALS_GlobalGauss_start_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_GlobalGaussianSDreminder.png
A us_somo/somo/doc/manual/somo/somo-MALS_GlobalGaussian_init.png
A us_somo/somo/doc/manual/somo/somo-MALS_I_hash_q_example.png
A us_somo/somo/doc/manual/somo/somo-MALS_I_starq_NoGauss_movieframe155.png
A us_somo/somo/doc/manual/somo/somo-MALS_I_starq_NoGauss_movieframe316.png
A us_somo/somo/doc/manual/somo/somo-MALS_I_starq_NoGauss_movieframe99.png
A us_somo/somo/doc/manual/somo/somo-MALS_Istarq_file_view_selected.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIdash_final.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIdash_final_kin.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIdash_final_kin_cropped.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIdash_final_kin_zoom.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIstar_final_kin.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIstar_sel_kin_dots_err.png
A us_somo/somo/doc/manual/somo/somo-MALS_Messages.png
A us_somo/somo/doc/manual/somo/somo-MALS_Movie_selected.png
A us_somo/somo/doc/manual/somo/somo-MALS_Plot_Options_demo.png
A us_somo/somo/doc/manual/somo/somo-MALS_Produced_data.png
A us_somo/somo/doc/manual/somo/somo-MALS_R_theta_csv_loaded.png
A us_somo/somo/doc/manual/somo/somo-MALS_R_theta_kin_shown.png
A us_somo/somo/doc/manual/somo/somo-MALS_R_theta_shown.png
A us_somo/somo/doc/manual/somo/somo-MALS_Residuals_twocurvesSD.png
A us_somo/somo/doc/manual/somo/somo-MALS_Residuals_twocurves_percent.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_MALS_data_loglog.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Make_scaled_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Messages.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Plot_Options_demo.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Plot_Options_demo2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Produced_data.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Produced_data_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_SAXS_common_times.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_SAXS_common_times_scroll1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_SAXS_common_times_scroll2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_SAXS_data_loading.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_bottom line.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_commons times_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_commontimes_all_dots.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_cropping_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_cropvis_results.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_cropvis_results1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_cropvis_select.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_exclude_q_vis_demo1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_exclude_q_vis_demo2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_fitting_methods.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_generating_joined_excl_q_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_initial.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_joined.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_joined_scroll.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_loadMALS.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_make_scaled.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_make_scaled_popup1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_make_scaled_popup2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_make_scaled_view_MALS_file.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_minimize_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_options.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_options1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_other_MALS_data_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_plot_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_polynomials.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_q_exclude_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_remove_panel.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale3.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale4.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale5.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale6.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale7.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale8.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scaled_MALS_generated_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scaled_SAXS_generated_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scroll_warning.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_second_set_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_second_set_buttons1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_selections_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_top_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_viewselected.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_weighting_methods.png
A us_somo/somo/doc/manual/somo/somo-MALS_SD_eval_applied.png
A us_somo/somo/doc/manual/somo/somo-MALS_SD_eval_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SD_eval_comparisonD2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SD_eval_define_1region.png
A us_somo/somo/doc/manual/somo/somo-MALS_SD_eval_define_2regions.png
A us_somo/somo/doc/manual/somo/somo-MALS_Select_Istarq_for_norm.png
A us_somo/somo/doc/manual/somo/somo-MALS_Selected_Istarq_normalized.png
A us_somo/somo/doc/manual/somo/somo-MALS_Selected_Istarq_normalized_ave.png
A us_somo/somo/doc/manual/somo/somo-MALS_Selected_normalized_ave.png
A us_somo/somo/doc/manual/somo/somo-MALS_Selected_orig_and_norm_files.png
A us_somo/somo/doc/manual/somo/somo-MALS_UV_data_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_adjust_times_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_adjust_times_pop_up2.png
A us_somo/somo/doc/manual/somo/somo-MALS_angles_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_commands1.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_chrom_Gauss_fit.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_chrom_fit_module.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_chrom_init_Gauss.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_used_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_add_MALS_data.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_loaded_data.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_pop_up2.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_pop_up3.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_repeak.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_timeshift.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_timeshift_set.png
A us_somo/somo/doc/manual/somo/somo-MALS_crop_I_dash_chromatograms.png
A us_somo/somo/doc/manual/somo/somo-MALS_cropping_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_inconsistent times_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_incorrect processing_param_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_info_panel.png
A us_somo/somo/doc/manual/somo/somo-MALS_initial.png
A us_somo/somo/doc/manual/somo/somo-MALS_main1.png
A us_somo/somo/doc/manual/somo/somo-MALS_make_Istar_q_enterparam_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_make_Istar_q_enterparam_popup1.png
A us_somo/somo/doc/manual/somo/somo-MALS_make_Istar_q_noGauss_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_no_Gaussians_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_no_conc_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_no_conc_pop_up2.png
A us_somo/somo/doc/manual/somo/somo-MALS_options.png
A us_somo/somo/doc/manual/somo/somo-MALS_options_conc_detector.png
A us_somo/somo/doc/manual/somo/somo-MALS_options_new_Gaussians.png
A us_somo/somo/doc/manual/somo/somo-MALS_options_new_misc.png
A us_somo/somo/doc/manual/somo/somo-MALS_param.png
A us_somo/somo/doc/manual/somo/somo-MALS_plot_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_processing_param_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_processing_param_pop_up2.png
A us_somo/somo/doc/manual/somo/somo-MALS_remove_panel.png
A us_somo/somo/doc/manual/somo/somo-MALS_resulting_I_starq_NoGauss.png
A us_somo/somo/doc/manual/somo/somo-MALS_scattering_angles.png
A us_somo/somo/doc/manual/somo/somo-MALS_second_set_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_selected_Ihash_EMG_GMG.png
A us_somo/somo/doc/manual/somo/somo-MALS_selections_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_set_conc_detector.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians1.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians2.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_GlobFit_Final.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_GlobFit_Init.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_GlobFit_by_q.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_GlobFit_saving_warning.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_GlobGauss.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_scroll1.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_scroll2.png
A us_somo/somo/doc/manual/somo/somo-MALS_six_Gaussians1.png
A us_somo/somo/doc/manual/somo/somo-MALS_six_Gaussians2.png
A us_somo/somo/doc/manual/somo/somo-MALS_timeshift_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_timeshift_pop_up2.png
A us_somo/somo/doc/manual/somo/somo-MALS_top_buttons.png
A us_somo/somo/doc/manual/somo/somo-mals_Residuals_twocurves.png
A us_somo/somo/doc/manual/somo/somo-perceive.png
M us_somo/somo/doc/manual/somo/somo.html
M us_somo/somo/doc/manual/somo/somo_mals.html
A us_somo/somo/doc/manual/somo/somo_mals_dctr.html
A us_somo/somo/doc/manual/somo/somo_mals_options.html
M us_somo/somo/doc/manual/somo/somo_mals_saxs.html
M us_somo/somo/doc/manual/somo/somo_pdb_parsing.html
M us_somo/somo/doc/manual/somo/somo_pdb_parsing_expert_mode.html
A us_somo/somo/doc/manual/somo/somo_perceive.html
M us_somo/somo/doc/manual/somo/somo_saxs_hplc.html
M us_somo/somo/doc/manual/somo/somo_saxs_hplc_skewedGauss.html
M us_somo/somo/doc/manual/somo/somo_uv_vis.html
A us_somo/somo/doc/manual/somo_mals.html
Log Message:
-----------
Merge pull request #517 from ehb54/ehb54-issue-1009-somo-merge
SOMO: merge the somo-dev backlog and the perceiver into main (GRPY excluded)
Commit: 957cb96251a46900e8dab0c6d58516bbc9b86b39
https://github.com/ehb54/ultrascan3/commit/957cb96251a46900e8dab0c6d58516bbc9b86b39
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
A us_somo/develop/grpy/README.md
A us_somo/develop/grpy/tests/data/1znf.bead_model
A us_somo/develop/grpy/tests/data/1znf_golden.txt
A us_somo/develop/grpy/tests/data/dumbbell_golden.txt
A us_somo/develop/grpy/tests/run.sh
M us_somo/develop/libus_somo.pro
Log Message:
-----------
somo/grpy: add self-contained in-process GRPY module (Eigen)
Adds us_somo/develop/grpy/: a C++ port of GRPY (generalized Rotne-Prager-Yamakawa
hydrodynamics) callable in-process, to replace the external Fortran binary run via
QProcess with stdout scraping.
The module is self-contained and isolated from the SOMO god classes:
- header-only, own namespace (grpy), dependency-injected threading (la::Parallel;
QtParallel over QThreadPool for SOMO, std::thread for the CLI/tests);
- memory-lean tiled Cholesky (solve M X = T instead of forming the full inverse;
upper-triangle, factored in place) with single-precision and out-of-core (mmap)
options for large systems, and fine-grained in-inversion progress via callback;
- grpy::Solver::run(beads, params, progressCb) returns structured scalars AND the
full report text, so the on-disk results file is preserved as before.
- tests/ validate against the captured GRPY golden (report + scalars) and prove the
Qt in-process path; run standalone via tests/run.sh.
Wires the qmake build (QT += concurrent, INCLUDEPATH += include grpy, HEADERS).
No US_Hydrodyn changes yet; the QProcess call-site swap is a follow-up commit.
Refs ehb54/ultrascan-tickets#972
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
Commit: 50f27cadff1633fd80b25b4760f680883159395d
https://github.com/ehb54/ultrascan3/commit/50f27cadff1633fd80b25b4760f680883159395d
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
A us_somo/develop/grpy/tests/data/dumbbell.grpy
M us_somo/develop/src/us_hydrodyn_grpy.cpp
Log Message:
-----------
somo/grpy: run GRPY in-process, drop external binary + Docker path
Wire the self-contained grpy module into US_Hydrodyn::calc_grpy_hydro /
grpy_process_next: read the .grpy file SOMO already writes via
grpy::read_native_file(), run grpy::Solver over a QtParallel backend on
SOMO's thread pool, and fill grpy_stdout from Results::report so the
existing grpy_finished() parsing and .grpy_res preservation are unchanged.
Removes the QProcess launch, the US_Container_Grpy selection, and the
Docker/parallel-image plumbing -- in-process is now the sole path. Progress
is driven by the Solver callback (processEvents keeps the GUI painting).
Adds grpy::read_native_file() + a native-reader test case (dumbbell.grpy)
that reproduces the dumbbell golden.
Refs ehb54/ultrascan-tickets#972
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
Commit: d25790b2348fd52a6058e56480e68992e0ad2831
https://github.com/ehb54/ultrascan3/commit/d25790b2348fd52a6058e56480e68992e0ad2831
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
R us_somo/develop/include/us_container_grpy.h
M us_somo/develop/include/us_hydrodyn.h
M us_somo/develop/include/us_hydrodyn_misc.h
M us_somo/develop/libus_somo.pro
R us_somo/develop/src/us_container_grpy.cpp
M us_somo/develop/src/us_hydrodyn.cpp
M us_somo/develop/src/us_hydrodyn_grpy.cpp
M us_somo/develop/src/us_hydrodyn_misc.cpp
M us_somo/develop/src/us_hydrodyn_settings.cpp
Log Message:
-----------
somo/grpy: remove dead external/Docker GRPY plumbing
Now that GRPY runs in-process (the external binary + Docker path is gone),
delete the symbols that only served the old QProcess path:
- US_Container_Grpy class (src/us_container_grpy.cpp, include/us_container_grpy.h)
and its libus_somo.pro SOURCES/HEADERS entries; the us_container_grpy member,
its includes/init, and grpy_parallel_pulled.
- cb_parallel_grpy checkbox + set_parallel_grpy() slot and the misc.parallel_grpy
field, incl. its settings save/load/default (old saved values are simply ignored).
- the grpy QProcess* member, grpy_prog, and the grpy_readFromStdout/Stderr/started
slots. stop_calc()'s process-terminate block is replaced by a note: cancellation
now flows through stopFlag, honored by the Solver progress callback and
grpy_finished().
Objects rebuild cleanly (us_hydrodyn, us_hydrodyn_grpy, us_hydrodyn_misc,
us_hydrodyn_settings).
Refs ehb54/ultrascan-tickets#972
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
Commit: 74c0abb3406272fcc7d3b1c5d35dbe90889439f0
https://github.com/ehb54/ultrascan3/commit/74c0abb3406272fcc7d3b1c5d35dbe90889439f0
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_grpy.cpp
Log Message:
-----------
somo/grpy: fix in-process finish hand-off + resolve input path
Two fixes found while validating the in-process path end-to-end via the
batch gui_script on a real bead model:
1. grpy_finished() was never invoked. It was posted with
QMetaObject::invokeMethod(..., Qt::QueuedConnection, Q_ARG(QProcess::
ExitStatus, ...)), but QProcess::ExitStatus is not a registered
queued-connection metatype, so the invoke silently failed
("Unable to handle unregistered datatype 'QProcess::ExitStatus'").
grpy_running then never cleared and the batch's
while(grpy_running) processEvents() loop hung forever. Replaced both
call sites with QTimer::singleShot(0, this, lambda) which defers to the
event loop (still no deep recursion through the model batch) but calls
grpy_finished() directly, needing no metatype registration.
2. read_native_file() read grpy_last_processed (a bare filename) relative
to the process CWD. The old QProcess set its working directory to
get_somo_dir(); resolve the path against get_somo_dir() to match, and
guard a missing file with a clear error instead of a silent empty solve.
Validated: gui_script batch run on a 165-bead model produces a .grpy_res
whose every physical observable (rotational diffusion, sedimentation,
intrinsic viscosities, all 8 relaxation times, diagonal diffusion tensor)
matches the Fortran GRPY_osx10.11 binary on the same .grpy input exactly;
only the documented eigenvector sign-gauge and ~1e-9 coupling noise differ.
Refs ehb54/ultrascan-tickets#972
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
Commit: 8620f4721c98ca61f60f9e02fe1abd8f97c5a90f
https://github.com/ehb54/ultrascan3/commit/8620f4721c98ca61f60f9e02fe1abd8f97c5a90f
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_grpy.cpp
Log Message:
-----------
somo/grpy: expose single-precision + out-of-core options
Wire grpy::Options.single and .ooc_dir at the in-process call site. These
matter only for very large bead models (memory-bound; run via batch/cluster),
so they are surfaced through the lightweight, no-UI mechanisms rather than
new god-class dialog controls:
- gui_script `global grpy_single 1` / `global grpy_ooc_dir <dir>`
- GRPY_SINGLE / GRPY_OOC_DIR environment-variable fallback (matches the
standalone CLI's env knobs)
Default off = in-core double precision, byte-identical to prior behavior. A
"GRPY options: ..." editor message is emitted when either is active.
Validated: gui_script run with `global grpy_single 1` on the 165-bead model
completes and reproduces every labeled observable of the double-precision /
Fortran-golden result (single matches to 4 sig figs by design). The module's
single-precision and out-of-core paths themselves are covered by the grpy
unit tests (test_linalg float, test_ooc).
Refs ehb54/ultrascan-tickets#972
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
Commit: afdee374e5d99499a8e0f35f4af1a0466d650e84
https://github.com/ehb54/ultrascan3/commit/afdee374e5d99499a8e0f35f4af1a0466d650e84
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_hydro.h
M us_somo/develop/src/us_hydrodyn_grpy.cpp
M us_somo/develop/src/us_hydrodyn_hydro.cpp
M us_somo/develop/src/us_hydrodyn_settings.cpp
Log Message:
-----------
somo/grpy: add GRPY precision (double/float) control to Hydro Options
Per review, surface the single-precision option as a proper control in the
SOMO Hydrodynamic Calculation Options window rather than script/env only.
Adds a "GRPY Numerical Precision:" group with "Double (default)" / "Float
(for large systems)" radios to US_Hydrodyn_Hydro, right below the existing
"Inclusion of Buried Beads (for GRPY)" group and mirroring its idiom. Backed
by hydro.grpy_single (default false = double), persisted in the SOMO settings
(save/load/default) and reported in display_default_differences() like the
sibling GRPY setting.
The in-process call site now reads hydro.grpy_single as the primary source;
the gui_script `global grpy_single` param and GRPY_SINGLE env var still
override for headless/batch automation. Out-of-core stays script/env only
(a cluster-scale knob, no GUI control).
Validated: full libus_somo rebuild clean (0 errors); default-double gui_script
run reproduces the Fortran-golden scalars (no regression).
Refs ehb54/ultrascan-tickets#972
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
Commit: dfa7079363d71ce319492932925fa40b58f9afc6
https://github.com/ehb54/ultrascan3/commit/dfa7079363d71ce319492932925fa40b58f9afc6
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/README.md
A us_somo/develop/grpy/grpy_exposure.hpp
A us_somo/develop/grpy/grpy_shell.hpp
M us_somo/develop/grpy/tests/run.sh
A us_somo/develop/grpy/tests/test_shell.cpp
M us_somo/develop/libus_somo.pro
Log Message:
-----------
somo/grpy: self-validating shell reduction with reported error bars
GRPY costs O((11N)^3), so the bead count dominates. A dense bead packing is
hydrodynamically screened -- interior beads sit in near-stagnant fluid and carry
almost no force -- so the exact calculation can run on a surface-enriched subset.
This generalizes the existing binary ASA buried-bead exclusion into a convergence
test that reports the error it introduced.
Method: Shrake-Rupley exposure per bead (1.4 A probe), keep the most-exposed
ceil(f*N), solve on a doubling ladder of bead fractions, stop when the reported
bar drops below tolerance. Three rungs give the convergence order from the ratio
of successive gaps, so the remaining error is Richardson-extrapolated per
observable. The ladder is geometric against O(N^3) and costs ~1.14x its final
rung, so the check is nearly free; its final rung is the unreduced model, so an
unreducible structure degrades to exactly today's behaviour.
The bar bounds the true error: verified 92/92 (translational, 23 models,
N=204-4068) and 252/252 (7 observables x 12 models x 3 tolerances) against
unreduced exact GRPY. The observed convergence order (median 1.83) matches a
value predicted independently by a raw reduction sweep, so the error model is
derived rather than fitted.
Selection is by target bead FRACTION, not a fixed exposure threshold: the buried
fraction ranges ~1%-50% across model types, so one threshold gives wildly
different cost per model while a fraction controls O(N^3) directly.
Observables do not share a reduction frontier. Median error relative to D_t at
equal reduction is 1.77x for D_r but 3.34x for intrinsic viscosity, which drove
the stopping decision in 36/36 test cases. ShellOptions::require therefore lets
the caller choose what must converge, and ShellReport::viscosity_unreliable tells
the caller to withhold viscosity and the viscosity-derived Einstein radius when
it was not converged; the values stay in the report for the record, with a
warning appended.
Known failure mode, guarded: on a degenerate exposure distribution (a perfect
cubic lattice realizes ~9 distinct values over 216 beads) rungs swallow whole
symmetry shells instead of refining, the estimated order comes out spuriously
high, and the bar understated by ~1.4x. A floor caps extrapolation tightening at
2x the raw gap. That restores honesty on the lattice and is slack on every real
model tested -- identical honesty, no speedup cost. The lattice is kept as a
regression in tests/test_shell.cpp.
MW and Rg are pinned to full-model values. Re-derived from a reduced bead list,
MW would fall with the dropped beads (corrupting sedimentation and both
viscosities, which are mass-normalized) and Rg would rise (a hollow shell has a
larger radius of gyration than the solid body). Both are regression-tested.
Disabled by default: with enabled=false the result is byte-identical to
Solver::run, so results never move silently.
On speed, honestly: against an unreduced model the gain reaches ~120x, but SOMO
defaults to ASA buried-bead exclusion, which already removes most dead beads.
Measured on that production baseline the incremental gain is ~2-3x, rising with
model size. The durable contribution is the error bar -- the existing exclusion
reports no uncertainty at all.
Module only; the SOMO call site and GUI control follow separately.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 9728a90a216f39e8b37d00848bf8f58ce2a90646
https://github.com/ehb54/ultrascan3/commit/9728a90a216f39e8b37d00848bf8f58ce2a90646
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/grpy_shell.hpp
M us_somo/develop/grpy/tests/test_shell.cpp
M us_somo/develop/include/us_hydrodyn.h
M us_somo/develop/include/us_hydrodyn_hydro.h
M us_somo/develop/src/us_hydrodyn_grpy.cpp
M us_somo/develop/src/us_hydrodyn_hydro.cpp
M us_somo/develop/src/us_hydrodyn_settings.cpp
Log Message:
-----------
somo/grpy: wire shell reduction into SOMO with a Hydrodynamics Options control
Adds the GUI control, settings persistence, and the call-site integration for the
shell-reduction layer, plus two fixes that only an end-to-end run exposed.
GUI: a "GRPY Shell Reduction" groupbox in the SOMO Hydrodynamic Calculation
Options window, below GRPY Numerical Precision and alongside the buried-bead
exclusion it generalizes. Off / On, a target-accuracy field, and a "require
intrinsic viscosity" checkbox. Backed by hydro.grpy_shell{,_tol,_require_eta},
persisted in settings save/load/default and display_default_differences,
mirroring grpy_single. gui_script `global grpy_shell` / `grpy_shell_tol` /
`grpy_shell_require_eta` and GRPY_SHELL still override, for headless work.
Intrinsic viscosity: when it was not required to converge (or was and did not),
it is WITHHELD from the reported results rather than propagated with a caveat --
a value carrying a warning is still a value that gets used downstream. Withheld
together with it is the GRPY Einstein radius: both are parsed from the same
report line ("Zero frequency intrinsic viscosity eta 0", fields 1 and 2) and the
radius is viscosity-derived, so it inherits the identical unreliability. Guarded
at all three sites -- the per-model assignments and the cross-model accumulator.
The values remain in the results file, annotated, for the record.
Note the cross-model mean divides by the TOTAL model count, not a per-observable
count, so a run mixing contributing and non-contributing models would silently
corrupt it. That is safe only because this is a run-level setting: every model in
a run either requires viscosity convergence or none does. Commented at the site.
Two fixes found by running it, not by the unit tests:
1. When the ladder cannot meet the tolerance it runs out onto its final rung,
which is the unreduced model -- so the result is exact. It was still reporting
the last inter-rung gap as the error bar (1.68% on a 246-bead test), which
describes the coarser rung just discarded, not the answer returned. Honest,
since it bounds a true error of zero, but plainly misleading. A ShellReport
::unreduced flag now zeroes the bars and the annotation states that the result
is exact.
2. The same path wrongly marked viscosity unreliable. An unreduced solve has
nothing to converge, so viscosity is exact regardless of what was requested;
withholding it would have discarded a perfectly good value. viscosity_ok()
now short-circuits on unreduced.
Six assertions cover both in tests/test_shell.cpp.
Verified end to end on a bead model via gui_script: the annotation reports
"98 of 98" beads (SOMO's ASA buried-bead exclusion having already reduced 246 ->
98, which is exactly why a model this size has nothing left to give), zero
estimated error, no viscosity warning, and every observable bit-identical to the
unreduced baseline. Clean libus_somo + app builds, no new warnings.
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: ce01d78729819c430ef871988325cd5147a7d2fd
https://github.com/ehb54/ultrascan3/commit/ce01d78729819c430ef871988325cd5147a7d2fd
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/somo/doc/manual/somo/somo_hydro.html
Log Message:
-----------
somo/doc: document GRPY shell reduction in the Hydrodynamics Options manual
Adds a section to somo_hydro.html covering the new "GRPY Shell Reduction"
box, placed after the GRPY buried-bead exclusion it generalizes, and bumps
the page's Last updated stamp.
Covers what the procedure does (repeated exact GRPY on progressively larger
subsets of the most solvent-exposed beads, stopping when successive results
agree, with the remaining error estimated by Richardson extrapolation), the
three controls and their defaults, and why the check is nearly free.
Gives particular attention to the "Require intrinsic viscosity" checkbox,
since the hydrodynamic quantities do not tolerate reduction equally: at equal
reduction the rotational diffusion error is ~1.8x the translational, and the
intrinsic viscosity ~3.3x and systematically one-sided. It is the viscosity
that determines when the procedure can stop, so requiring it costs much of
the speed gain; when not required, the viscosity and the Einstein radius
derived from it are withheld from the results rather than reported with a
caveat, while being retained and annotated in the results file.
Also answers, quantitatively, the question the preceding buried-bead
paragraph explicitly left open ("would need an in depth investigation",
supported only by preliminary 2021 tests on lysozyme): retaining >50% of
beads changes the translational diffusion coefficient by ~0.02%, 30-50% by
~0.12%, 20-30% by ~0.5%, degrading rapidly below ~10%. Buried-bead exclusion
typically retains ~40%, so that paragraph's regime is now measured. Notes
the reported error bounded the true deviation in all 344 validation tests.
Ends with the honest practical caveat: the gain grows with model size,
is negligible for small models, and on top of the default buried-bead
exclusion is typically 2-3x rather than the larger factors available from a
completely unreduced model -- the lasting benefit being the error estimate,
not the speed.
All markup uses named entities, so the page remains pure ASCII under its
declared ISO-8859-1 charset.
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: fe3b56c73eb62bf1f055eff78d1c1bbcdae3a0e0
https://github.com/ehb54/ultrascan3/commit/fe3b56c73eb62bf1f055eff78d1c1bbcdae3a0e0
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/somo/doc/manual/somo/somo_hydro.html
Log Message:
-----------
somo/doc: document the GRPY Numerical Precision control
The Double/Float control shipped with the in-process GRPY work but was never
documented -- a grep across the whole manual returned nothing for it, despite
the box sitting directly above the shell-reduction one just added. Same file,
same window, so it is described here in window order: buried-bead exclusion,
precision, shell reduction.
Explains what the setting actually governs (the precision in which the large
internal matrix is stored and factored), why it matters (that matrix holds
eleven quantities per bead and grows as the square of the bead count, so it
is what limits the treatable model size), and that the tensor arithmetic and
all subsequent processing stay in double precision regardless.
States the accuracy cost from validation rather than in the abstract: every
labelled observable is identical to the four significant figures displayed,
with only the near-zero reoriented coupling terms differing. Recommends
Double as the default nonetheless, since the benefit appears only when memory
is the binding constraint.
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 08ceeff3fcac01232b1dbb852b2262f5f348ac95
https://github.com/ehb54/ultrascan3/commit/08ceeff3fcac01232b1dbb852b2262f5f348ac95
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_grpy.cpp
Log Message:
-----------
somo/grpy: pre-flight memory guard for oversized models
The in-process GRPY solver holds the tiled upper triangle of the 11N x 11N
mobility matrix in RAM (peak ~ (11N)^2/2 * scalar bytes), so a model larger
than physical RAM cannot fit in-core -- e.g. 20k beads needs ~180 GB double /
~90 GB single. Because the solve runs synchronously on the GUI thread, such a
model previously sent the machine into heavy swapping with a frozen interface.
Add a pre-flight guard in calc_grpy_hydro() before the batch starts: estimate
peak memory for the largest selected model from its used-bead count and the
chosen precision, read physical RAM (macOS hw.memsize / Linux sysconf; unknown
-> no guard), and if the estimate exceeds ~70% of RAM:
- interactive: a Cancel / Run-anyway dialog naming the estimate, the machine
RAM, and the remedies (single precision, or a smaller model);
- script mode (gui_script): never block on a dialog -- report the error to the
editor and stderr and fail with a non-zero exit.
Verified: a headless run of a 20,000-bead model on a 32 GB machine reports
"~198.3 GB needed, 32.0 GB available" and exits non-zero pre-flight, instead of
thrashing.
Fixes ehb54/ultrascan-tickets#987
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
Commit: 4dc23b667d2edc83e5a7ff3dc5ce1e0f0b21afe0
https://github.com/ehb54/ultrascan3/commit/4dc23b667d2edc83e5a7ff3dc5ce1e0f0b21afe0
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_grpy.cpp
Log Message:
-----------
somo/grpy: memory guard - add Windows physical-RAM detection
Windows is a shipped SOMO target (GRPY_win64) but was falling through to the
"unknown -> no guard" path. Add GlobalMemoryStatusEx (ullTotalPhys) so the
pre-flight memory guard applies there too. Mac/Linux paths unchanged; the
Windows branch is #if'd out off-Windows and needs verifying on the win build.
Refs ehb54/ultrascan-tickets#987
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
Commit: 4630de678797468292907e9972c76944982befba
https://github.com/ehb54/ultrascan3/commit/4630de678797468292907e9972c76944982befba
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_grpy.cpp
Log Message:
-----------
somo/grpy: memory guard - point oversized models to ZENO
Single precision only ~halves the footprint, so a genuinely huge structure
(e.g. 20k beads ~90 GB single) still will not fit on a modest machine. Add
ZENO to the guard's remedy message as the size-independent alternative, noting
its limitation (it does not compute rotational diffusion).
Refs ehb54/ultrascan-tickets#987
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
Commit: d59737c6fd0287ee8d194724f64388b91cebd6e1
https://github.com/ehb54/ultrascan3/commit/d59737c6fd0287ee8d194724f64388b91cebd6e1
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_grpy.cpp
Log Message:
-----------
somo/grpy: clear grpy_used_beads at run start (fix stale count)
grpy_used_beads was populated with push_back each run but, unlike its sibling
lists (grpy_to_process, grpy_model_numbers), was never cleared at the top of
calc_grpy_hydro -- it only drained via pop_front as models processed. So any
run that aborts before processing (now including the pre-flight memory guard,
but also the stop-flag and filename-length aborts) left a stale count behind,
and the next run's max()/processing saw it. Observed as: a vdW model triggers
the memory guard, then a subsequent smaller SoMo model in the same session is
wrongly reported with the vdW bead count. Clear grpy_used_beads at run start,
consistent with the other lists.
Refs ehb54/ultrascan-tickets#987
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
Commit: 0d5f7bb309d44c7b785d8a3c41493d3f04d06725
https://github.com/ehb54/ultrascan3/commit/0d5f7bb309d44c7b785d8a3c41493d3f04d06725
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/somo/doc/manual/somo/somo_hydro.html
M us_somo/somo/doc/manual/somo/somo_misc.html
Log Message:
-----------
somo/doc: update manual for in-process GRPY, precision, memory guard
The GRPY overhaul (#972) and the memory guard (#987) left the SOMO manual
stale/incomplete:
- somo_misc.html documented the removed "Enable Parallel GRPY" checkbox and the
Docker-based parallel path. Rewritten: GRPY now runs in-process, multi-threaded
by default (no checkbox); notes the memory-lean/single-precision solver and the
pre-flight memory guard, and points oversized models to single precision, a
smaller model, or ZENO (size-independent, no rotational diffusion). Also softened
the "GRPY can crash" note to the guarded behavior.
- somo_hydro.html: document the new "GRPY Numerical Precision" (Double/Float)
control; drop the stale "parallel GRPY ... July 2024 release" clause from the
buried-beads paragraph.
Release date in somo_misc.html marked with an HTML comment to confirm at release.
Refs ehb54/ultrascan-tickets#987
Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
Commit: 08c896853cda4ec84d74fb18e7205c9c573eb12a
https://github.com/ehb54/ultrascan3/commit/08c896853cda4ec84d74fb18e7205c9c573eb12a
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/somo/doc/manual/somo/somo_hydro.html
M us_somo/somo/doc/manual/somo/somo_misc.html
Log Message:
-----------
somo/doc: bump manual last-updated/last-modified dates
Update both date fields (top "Last updated" and bottom "Last modified on")
on somo_misc.html and somo_hydro.html to reflect the GRPY doc edits.
Refs ehb54/ultrascan-tickets#987
Commit: a2f85d5c14bb339b7c0afb67f05e055879dd5258
https://github.com/ehb54/ultrascan3/commit/a2f85d5c14bb339b7c0afb67f05e055879dd5258
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/somo/doc/manual/somo/somo_hydro.html
Log Message:
-----------
somo/doc: drop duplicate precision paragraph, fix shell-reduction cross-ref
Merging somo-dev brought in its own "GRPY Numerical Precision" paragraph
(e34ae210, PR #497), written independently of the one added on this branch.
Git merged both cleanly since they landed in adjacent places, leaving the box
documented twice. Upstream's is the project's own wording and landed first,
so this drops ours and keeps it.
Also fixes a cross-reference this exposed. The shell-reduction paragraph was
written directly after the GRPY buried-bead paragraph and referred to "the
question raised in the paragraph above". Our precision paragraph was later
inserted between the two, silently breaking that reference; upstream's now
sits in the same position. Rather than depend on ordering again, the
reference now names the buried-bead option explicitly.
Box order in the page matches the window: buried beads, precision, shell
reduction. Page remains pure ASCII under its declared ISO-8859-1 charset.
Commit: 44b631e157d3ca8f17964a89a701f2f56ad93df2
https://github.com/ehb54/ultrascan3/commit/44b631e157d3ca8f17964a89a701f2f56ad93df2
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/grpy_shell.hpp
M us_somo/develop/grpy/tests/test_shell.cpp
M us_somo/develop/src/us_hydrodyn_grpy.cpp
M us_somo/somo/doc/manual/somo/somo_hydro.html
Log Message:
-----------
somo/grpy: cap the shell-reduction ladder by available memory
Merging somo-dev brought in the issue-987 pre-flight memory guard, which
refuses a GRPY run whose mobility matrix would exceed RAM. It sizes that
matrix from the FULL bead count, in calc_grpy_hydro(), before shell reduction
is applied in grpy_process_next() -- so it would turn away precisely the large
models shell reduction exists to make feasible. The ladder normally stops well
short of the full model, and memory goes as the square of the bead count, so a
run that stops at ~25% of the beads needs ~6% of the refused matrix.
Rather than weaken the guard, the budget is now passed into the ladder:
- ShellOptions::max_beads caps the largest rung. Checked after building the
subset (cheap) but before the solve (expensive), so a rejected rung costs
nothing; the ladder ascends, so the first rung over budget ends it.
- A capped ladder reports mem_capped and does NOT claim convergence. The
result stands on its error bar, which is stated as usual and will generally
exceed the requested target. It is never passed off as converged.
- The guard defers to shell reduction only when the budget admits at least the
smallest rung; below that there is nothing to compute and it still refuses.
When shell reduction is off, its message now offers the option, noting that
unlike ZENO it still yields rotational diffusion.
So an oversized model now gives the best result that fits, with a quantified
error, instead of nothing.
Two supporting cleanups, both forced by the above: truthy() is promoted from a
lambda local to grpy_process_next() to a file-static, so the guard and the
solver setup resolve the same scripting overrides (the guard previously read
hydro.grpy_single directly and would have ignored a grpy_single override); and
the matrix-size estimate is factored into grpy_matrix_bytes() with
grpy_max_beads_for_ram() as its inverse, so the guard and the cap cannot drift
apart about what fits.
Tests cover a slack cap (must not perturb the unreduced, exact path), a
binding cap (capped, non-converged, bar finite, budget respected, explained in
the report), and a cap below the smallest rung. The last of these found a
latent crash: with no rung run, err_est was empty while require was not, and
the report loop indexed past the end. Guarded, and that case now states
plainly that nothing was computed.
Manual documents the lifted refusal in the shell-reduction section.
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 7fe7c35e50f8c11541d0a52834793159ad012b36
https://github.com/ehb54/ultrascan3/commit/7fe7c35e50f8c11541d0a52834793159ad012b36
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/grpy_shell.hpp
M us_somo/develop/grpy/tests/test_shell.cpp
M us_somo/develop/src/us_hydrodyn_grpy.cpp
Log Message:
-----------
somo/grpy: report ladder progress, and fix stray double percent in messages
Two reported problems with what the shell-reduction ladder shows while running.
PROGRESS. Every rung is a separate solve sweeping 0..100%, and each was
forwarded to the caller raw, so the bar restarted once per rung and the stage
text was only ever "Model 1 : inverting matrices" -- several solves looked
like one stalled repeating one. The ladder now maps each rung onto its share
of the whole run, weighted by predicted cost (~N^3), and prefixes the stage
with "rung i/n, N beads". The bar advances monotonically instead of
restarting. The denominator assumes the ladder runs to its last planned rung,
so converging early makes the bar jump to done, which is correct.
This is done by wrapping the callback inside the module, so the SOMO callback
signature is untouched and the non-shell path still passes progress through
verbatim (asserted by a test).
Also added ShellOptions::on_rung, called as each rung lands, wired to log the
bead count and the error estimate against the target. The ladder was otherwise
silent for its whole duration; now its convergence is visible as it happens.
PERCENT. Reported from a real run: "estimated error 0.489%%". QString::arg(),
unlike printf, has no "%%" escape -- it substitutes %1..%99 and passes every
other "%" through untouched -- so the literal "%%" written in five messages
reached the user verbatim. The tolerance line had it too ("tolerance 0.5%%").
Rather than rely on "%1%%2" parsing correctly (it does, but it is ambiguous to
read), the percent sign is now attached by grpy_pct(), which formats the whole
token. Verified against real Qt: the old form reproduces the reported string
exactly, the new one renders "0.489%".
The module's own report text was checked and is unaffected -- it formats via
snprintf, where "%%" is the correct escape.
Tests assert progress never goes backwards across a multi-rung ladder, stays
in 0..100, names its rung and bead count, and is left unmodified when shell
reduction is off.
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 036b9bcfd343c7e8ccd76f99e2ee5c30ba1bb8e6
https://github.com/ehb54/ultrascan3/commit/036b9bcfd343c7e8ccd76f99e2ee5c30ba1bb8e6
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/README.md
M us_somo/somo/doc/manual/somo/somo_hydro.html
Log Message:
-----------
somo/grpy: document the memory cap and progress reporting
Docs lagged the last two commits.
Module README gains two sections. The memory cap covers why a caller's
pre-flight refusal has to size the matrix from the full bead count and so
turns away the very models the ladder can handle, what max_beads does about
it, and the two contract points a caller must honour: a capped run reports
mem_capped and is never marked converged, and levels == 0 means there is no
result and the default-constructed Results must not be read.
The progress section records that ShellSolver wraps the ProgressFn it is
given rather than forwarding it per rung -- the reason the caller's bar no
longer restarts several times per model -- that the callback signature is
unchanged and passes through verbatim when disabled, and what on_rung
reports.
The manual gains one sentence in the shell-reduction description: each
calculation in the series is reported as it completes with its bead count and
error estimate, and the progress bar refers to the series as a whole. That is
what a user actually sees, and previously the page implied a single opaque
calculation.
INTEGRATION.md was checked and needs nothing -- it covers the drop-in core
solver and does not mention shell reduction at all.
Page remains pure ASCII under its declared ISO-8859-1 charset.
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 6e1320de39609487c6985fe2feed32032da1401b
https://github.com/ehb54/ultrascan3/commit/6e1320de39609487c6985fe2feed32032da1401b
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/README.md
Log Message:
-----------
somo/grpy: document how to read ShellReport
The README covered the fields that decide what happened (converged,
unreduced, mem_capped, viscosity_unreliable) but not the ones a caller
actually reads out. Adds a field table.
The points that are not guessable from the names: err_est, extrapolated and
k_obs are parallel to require, not to anything else; k_obs == 0 means
extrapolation was declined, so err_est is the raw inter-rung gap and
extrapolated holds the final rung's value rather than an extrapolated one;
and run() returns the final rung's Results verbatim, so the extrapolated
values live only in the report -- deliberately, since overwriting the scalars
would contradict the report text embedded in them.
Also states that only `unreduced` licenses treating a result as exact.
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: d350b7a2e0ff48c622830828f3336f3a70bc515b
https://github.com/ehb54/ultrascan3/commit/d350b7a2e0ff48c622830828f3336f3a70bc515b
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/tests/test_shell.cpp
Log Message:
-----------
somo/grpy: keep the UI alive during assembly, factor and solve
The GUI froze for seconds at a time during "INVERTING MATRICES", and was dead
outright either side of it. Two causes.
The calling thread is a compute worker: QtConcurrent::blockingMap both blocks
the caller and uses it to run tasks, so the event loop cannot turn for the
whole duration of any for_range. Progress -- and therefore the processEvents()
that keeps the GUI breathing -- only ran between for_range calls.
And progress was emitted from exactly one place in the numeric core: once per
tile column of the Cholesky. Assembly (one for_range over ~4M pair blocks on a
2832-bead model) and solve reported nothing whatsoever. Within the factor, the
trailing update costs O((nt-k)^2), so the earliest columns are by far the
longest -- measured ~5 s each at dim 31152, decaying to milliseconds.
Assembly and the factor's trailing update are now chunked, with the chunk
self-tuning toward ~80 ms per slice (double under 40 ms, halve over 160 ms) so
the granularity holds across machines and model sizes rather than being a
constant tuned here. The factor retunes within a column, not just between
columns, because the first columns are exactly where the freeze was worst.
Solve reports per tile. The bar now spans 0-30 assemble, 30-90 factor,
90-100 solve.
The factor bar is also cost-weighted by trailing-update work completed instead
of being linear in the column index; since cost per column is quadratic, the
old bar crawled at the start and raced at the end.
With no callback -- the CLI and every test -- the work runs as a single chunk,
exactly as before.
Tests assert the chunked path is numerically INERT: same Dt, same eta, and a
byte-identical report versus the unchunked path. That check is the real guard,
since the goldens only ever exercise the no-callback path. It earned its place
immediately: the first version advanced the loop by `chunk`, which is retuned
inside the loop, so a doubling silently skipped beads and corrupted the matrix.
Both loops now advance by what was actually processed. Also asserts progress is
monotone, stays in 0..100, and that no phase is silent.
Tick count is deliberately not asserted tightly -- the chunker targets a wall
time, so a small model that finishes fast correctly uses few large chunks.
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 34155ff3c29814619e2be299670ecadf3033ff3e
https://github.com/ehb54/ultrascan3/commit/34155ff3c29814619e2be299670ecadf3033ff3e
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_grpy.cpp
M us_somo/somo/doc/manual/somo/somo_hydro.html
Log Message:
-----------
somo/grpy: GRPY_SHELL_MAX_BEADS override, and report the cap every run
The shell-reduction bead cap was derived solely from physical RAM, with no way
to move it. That made the memory-capped path effectively untestable: the ladder
can only reach the cap by FAILING on the rung below it, so on a model large
enough to have a cap at all, exercising it means paying for that rung first --
5h44m on a real 11328-bead model, which then converged one rung short of the
cap anyway and never exercised it.
GRPY_SHELL_MAX_BEADS in the environment, or grpy_shell_max_beads as a script
parameter, now overrides it. With a small value the same model reaches the cap
in seconds. Env/script only with no GUI control, matching grpy_ooc_dir: a
diagnostic and shared-machine knob rather than a user setting. It is also the
only way to hold GRPY under a chosen footprint on a machine shared with other
work, which the 70%-of-RAM rule cannot express.
Honoured in both directions. A value above what memory supports is flagged
rather than silently clamped -- overriding is deliberate, and clamping would
make the reported cap a lie.
Reported every run, which is the point: an override changes which results are
obtainable, and a stale environment variable would otherwise silently bound
every calculation with nothing on screen to say so. With no override and shell
reduction on, the memory-derived cap and the RAM it came from are printed
instead, so the limit is never a mystery. Both go to the progress window, once
per run.
The guard and the ladder resolve the cap through one shared function. If they
resolved it separately the guard could admit a run the ladder then refuses to
compute, or refuse one it could have done.
Manual documents the variable in the shell-reduction section; the parameter is
also added to the gui_script reference ticket (ultrascan-tickets#990).
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: ea71b59b9fdd3d25d522a5f4e7cb90c2e1b10a86
https://github.com/ehb54/ultrascan3/commit/ea71b59b9fdd3d25d522a5f4e7cb90c2e1b10a86
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/somo/doc/manual/somo/somo_hydro.html
Log Message:
-----------
somo/doc: bump somo_hydro last-modified to the actual last edit date
Content was current; only the stamp lagged.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: b3067a1690a014e926d0cc7f9d2fbd4fe857fa05
https://github.com/ehb54/ultrascan3/commit/b3067a1690a014e926d0cc7f9d2fbd4fe857fa05
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_grpy.cpp
Log Message:
-----------
somo/grpy: name the worst observable, and stop announcing an inert cap
Both found by a real capped run (3GUT vdW, GRPY_SHELL_MAX_BEADS=2000).
The result line quoted err_max alone: "estimated error 3.85%". That is the
MAX over the requested observables, and intrinsic viscosity runs ~3.3x the
error of D_t at equal reduction, so on an unconverged run the single number
quoted is essentially always the viscosity's. Reading it as the accuracy of
the whole calculation makes D_t look several times worse than it is -- in that
run, 1416 of 11328 beads kept implies a D_t bar near 1.15%, not 3.85%.
ShellReport::worst was already computed for exactly this and had never been
shown; it is now named, with a following line pointing at the per-observable
estimates in the results file. Suppressed on an exact (unreduced) result,
where every bar is zero and "worst" means nothing.
The cap override also announced itself when shell reduction was OFF, where it
bounds nothing: the same run printed "bead cap OVERRIDDEN to 2000" and then
refused the model on memory, implying the 2000 had caused the refusal when it
was irrelevant. It now says so when inert, rather than going silent -- a stale
environment variable should still be visible.
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 438a3c0f57e89a1e0ae420ff4fc0ca930e2864eb
https://github.com/ehb54/ultrascan3/commit/438a3c0f57e89a1e0ae420ff4fc0ca930e2864eb
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/somo/doc/manual/somo/somo_hydro.html
Log Message:
-----------
somo/doc: say that the quoted shell-reduction error is the largest over quantities
The page said the achieved error is written to the results file, but not that
the single figure shown in the progress window is the MAXIMUM over the
requested quantities. Since intrinsic viscosity converges far more slowly than
the rest, that figure is usually its, and reading it as the accuracy of the
translational diffusion coefficient understates the latter severalfold -- a
misreading a real run produced.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 14d0e0a86d907e7ccf08d0a0f4714d7c4d330be2
https://github.com/ehb54/ultrascan3/commit/14d0e0a86d907e7ccf08d0a0f4714d7c4d330be2
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_grpy.cpp
Log Message:
-----------
somo/grpy: exclude the overwrite prompt from the GRPY timer
"Time to process" spans the whole run, and the results-writing path prompts
for a filename whenever an output file exists and overwrite_hydro is false.
That prompt is modal, so the operator's response time was counted as compute.
Measured directly: the same binary, model and settings gave 5m 00s answering
slowly and 3m 49s answering quickly -- 71 s of pure click latency, varying per
run, which makes interactive GRPY timings incomparable with each other.
It also cost real analysis time here: a 21% gap between two runs was
attributed to machine contention on the strength of a microbenchmark that
bounded the alternative explanation at ~3%. The bound was right; the
conclusion was wrong. The missing time was the operator.
US_Timer already supports this exactly: stop_timer banks the interval so far
WITHOUT counting a completion, and start_timer restarts from zero, so
stop/start is pause/resume and the paused span is never accumulated. No change
to US_Timer. An RAII guard applies it at the four prompt sites that fall inside
the timed region; the fifth call runs before the timer starts and is untouched.
The prompt itself is deliberately unchanged -- this only stops it being counted
as compute.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 64de263a8d3652904146a29834262555665eb4de
https://github.com/ehb54/ultrascan3/commit/64de263a8d3652904146a29834262555665eb4de
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/grpy_exposure.hpp
M us_somo/develop/grpy/grpy_shell.hpp
M us_somo/develop/grpy/tests/test_shell.cpp
M us_somo/develop/include/us_hydrodyn.h
M us_somo/develop/include/us_hydrodyn_hydro.h
M us_somo/develop/src/us_hydrodyn_grpy.cpp
M us_somo/develop/src/us_hydrodyn_hydro.cpp
M us_somo/develop/src/us_hydrodyn_settings.cpp
M us_somo/develop/src/us_hydrodyn_write.cpp
M us_somo/somo/doc/manual/somo/somo_hydro.html
Log Message:
-----------
somo/grpy: optionally write and display a bead model of each shell rung
A "Save shell bead models" checkbox in the GRPY Shell Reduction box. When set,
the reduced model used at each ladder rung is written and opened in the viewer,
so the shell can be seen thickening as the ladder converges and the retained
beads inspected directly. For validating the reduction by eye; off by default.
Files go to <somo>/tmp as <model>-shell-rung-<n>, overwritten without prompting
-- they are regenerated every run, and prompting per rung would add a modal
dialog per rung to a diagnostic.
The mapping from the shell report back to beads was the part worth care.
ShellReport now records the indices its ranking selected (ShellOptions::
record_subsets, off by default, so nothing is paid when unused), and those
index the bead list handed to GRPY -- i.e. the .grpy file, which holds the
beads that are active and, unless buried beads are included, not buried, in
`use_model` order. That order is NOT bead_model order: bead_output.sequence == 1
reorders into exposed-sidechain / exposed-main-chain / buried. Taking
bead_model order would therefore have written models of the wrong beads,
silently and plausibly.
To make that impossible rather than merely correct today, the ordering is
extracted from write_bead_model() into US_Hydrodyn::bead_model_output_order()
and both callers use it. The writer also refuses and says so if an index falls
outside the rebuilt list, rather than emitting a wrong picture.
Selection now returns indices (reduce_top_frac_idx), which also removes the old
coordinate-matching rebuild -- O(keep*N), some 32M comparisons on an
11328-bead model -- with reduce_top_frac kept as a wrapper so existing callers
and tests are unaffected.
Tests: recorded subsets are sized to their rung, in range, unique, nested
(each rung contains the previous), complete on the full rung, absent unless
requested, and identical to the ranking's own selection.
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 2c3340cfae89a4327875bf557a92be2496e695e4
https://github.com/ehb54/ultrascan3/commit/2c3340cfae89a4327875bf557a92be2496e695e4
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/somo/doc/manual/somo/somo_hydro.html
A us_somo/somo/doc/manual/somo/somo_hydro_shell_reduction.html
Log Message:
-----------
somo/doc: theory page for GRPY shell reduction, with the mathematics and references
The user-facing documentation named Richardson extrapolation in a single
sentence and stopped there. The mathematics existed only in the module README
and the header comments, neither of which a SOMO user reads.
New page somo_hydro_shell_reduction.html, following the existing theory-page
pattern (cormap.html, IntegralBaselineTheory.html), linked from the sentence
that previously stood alone. It covers why bead count dominates the cost, how
the subsets are chosen and why by fraction rather than by exposure threshold,
the extrapolation itself, the safeguards, per-quantity convergence, the extent
of the testing, and what the option is and is not for.
Every formula and constant on the page was checked against the implementation
rather than written from memory: the order equation, the remaining-error and
extrapolated-value expressions, the clamp range, the 1.5 safety factor, the
half-the-raw-gap floor, the default ladder, and the 8/7 geometric cost.
Two things it makes explicit that the documentation did not say anywhere:
- The extrapolation needs THREE subsets. A run that stops after two -- because
it converged at once, or because memory allowed no more -- reports the raw
inter-rung difference instead. Still conservative, but cruder, and decided by
how the ladder happens to stop rather than by anything the user set.
- "Shell reduction" is NOT the classical shell model. That method replaces the
particle with surface beads and extrapolates to zero bead radius; this one
retains existing beads and extrapolates to the complete model. Same physical
motivation, both extrapolations to a limit, different procedures -- and an
easy confusion for exactly this audience.
References: Richardson 1911 and Richardson & Gaunt 1927 for the method; Roache
1994/1998 for the three-level observed-order practice this follows (the Grid
Convergence Index, with bead count in place of grid spacing); Shrake & Rupley
1973 for the exposure calculation; Garcia de la Torre & Bloomfield 1981 and
Carrasco & Garcia de la Torre 1999 for the shell-model context distinguished
above; Zuk et al 2018 and Brookes & Rocco 2018 for GRPY and SOMO.
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 6890857538a071c14ac2259e2729f02f25e1845f
https://github.com/ehb54/ultrascan3/commit/6890857538a071c14ac2259e2729f02f25e1845f
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/somo/doc/manual/somo/somo_hydro.html
Log Message:
-----------
somo/doc: link the shell-reduction theory page from the section head and the accuracy text
The theory page had a single inbound link, buried in the second of eight
paragraphs. A reader arriving at the box heading, or skimming to the accuracy
figures, would not have seen it.
Now linked from three places, each where a reader would want it: the opening
paragraph, which poses the question the page answers; the Richardson sentence,
which names the method; and the accuracy paragraph, from which the natural next
question is how far the estimate has been tested.
Dates: both stamps on both pages already read the current date, so nothing to
bump. somo_misc.html carries an earlier date but is upstream's edit, correctly
stamped for itself.
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 76bb13833ea7c6aa7a21baf1f95f5fb5c6660544
https://github.com/ehb54/ultrascan3/commit/76bb13833ea7c6aa7a21baf1f95f5fb5c6660544
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/grpy_shell.hpp
M us_somo/develop/grpy/tests/test_shell.cpp
M us_somo/develop/include/us_hydrodyn.h
M us_somo/develop/src/us_hydrodyn_grpy.cpp
M us_somo/develop/src/us_hydrodyn_hydro.cpp
M us_somo/somo/doc/manual/somo/somo_hydro.html
Log Message:
-----------
somo/grpy: show each shell model as it is made, and let Stop end the ladder
Two changes that only make sense together.
The shell models were written in a batch after the whole ladder finished, which
is the least useful moment: by then there is nothing left to decide. They are
now written and displayed as each rung completes, so a shell that is obviously
wrong can be seen while the calculation is still running.
That is worth nothing unless the run can then be stopped, and it could not.
stopFlag was consulted only inside the progress callback, where it skipped a UI
update and nothing else -- pressing Stop did not end a running GRPY calculation
at all. ShellOptions::should_stop is now checked between rungs and wired to
stopFlag, so Stop ends the ladder at the end of the rung in progress. Since each
rung costs roughly eight times the one before, stopping before the next begins
saves nearly all of what remained.
A stopped run keeps what it computed, reports its error bar, and is marked NOT
converged -- the same treatment as a memory-capped one, and never passed off as
if it had converged. Stopping before any rung ran leaves levels == 0 and no
result, which the caller must detect, again as with the memory cap.
Between rungs only: a rung already running goes to completion, since the solve
has no interior abort. Adding one would mean threading cancellation through the
factorization, which is a larger change for much less benefit.
The per-rung write reads srep.kept.back() from the live report, which is sound
because the module records each rung's selection before calling on_rung.
Also widens the options window to 740 and lays the shell-reduction box out in
two rows. That box carries six controls, about a hundred characters of label
text -- half again the widest of the other boxes -- and was clipped on the
right. Two rows drops what it demands to roughly a single row's width, so it
survives larger fonts rather than merely clearing today's threshold; the width
increase is headroom, not the fix.
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 551a81a6b14082989eb4d86d0e2b0fb673f45a1c
https://github.com/ehb54/ultrascan3/commit/551a81a6b14082989eb4d86d0e2b0fb673f45a1c
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_grpy.cpp
Log Message:
-----------
somo/grpy: fix build -- srep was captured by a lambda declared before it
The on_rung lambda added in the previous commit captures srep by reference to
write each rung's shell model as it lands, but srep was declared 26 lines
further down. Moved ahead of the lambda.
This should not have been pushed. It was not caught because the build that
"passed" never compiled this file: both build stages write the same Makefile,
so after an earlier `qmake us_somo.pro` every plain `make` rebuilt only the
apps and linked them against a stale library. The object file was three hours
older than the source.
Verified this time by compiling the translation unit directly, and the full
two-stage sequence (qmake libus_somo.pro && make && qmake us_somo.pro && make)
is what the build notes now require, with an object-newer-than-source check
before any claim that a build passed.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 615f53bf508720ba14420bac19c2e257e2de4485
https://github.com/ehb54/ultrascan3/commit/615f53bf508720ba14420bac19c2e257e2de4485
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_grpy.cpp
M us_somo/somo/doc/manual/somo/somo_hydro.html
Log Message:
-----------
somo/grpy: name shell models for the settings that produced them
The shell bead models were named only for the model, so runs differing in
target accuracy, in whether intrinsic viscosity had to converge, or in
precision produced identically-named files that overwrote each other. Each of
those settings changes which beads are retained, so those are exactly the
files one would want to compare -- and could not.
Encoded in SOMO's existing style (short mnemonic + value, '.' -> '_', present
only when the option is set, as with PR1_4, TH10, pH7, A20, hy, G4):
..._R1PR1-SR0_5eta-shell-rung-3 0.5% target, viscosity required
..._R1PR1-SR1noeta-shell-rung-3 1% target, viscosity not required
..._R1PR1-sp-SR0_5eta-shell-rung-3 as the first, in single precision
Only non-defaults appear, so `sp` is absent from a double-precision run just
as `hy` is absent when hydration is off.
NOT applied to the .grpy_res or .grpy.csv result files, which have the same
collision -- a shell-reduced result and an unreduced one share a name. That is
a wider change (four sites in grpy_finished, a member to carry the suffix,
and names that batch runs may depend on) and is left as a decision rather than
taken unasked.
Built with the full two-stage sequence and the object verified newer than the
source, per the previous commit.
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: f42ba901aa57c168171940cf412e6ef3198cd20f
https://github.com/ehb54/ultrascan3/commit/f42ba901aa57c168171940cf412e6ef3198cd20f
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn.h
M us_somo/develop/include/us_hydrodyn_save.h
M us_somo/develop/src/us_hydrodyn_grpy.cpp
M us_somo/develop/src/us_hydrodyn_save.cpp
M us_somo/somo/doc/manual/somo/somo_hydro.html
M us_somo/somo/doc/manual/somo/somo_save.html
Log Message:
-----------
somo/grpy: settings suffix on result files, GRPY options in the saved CSV
Extends the shell-model naming of the previous commit to the .grpy_res and
.grpy.csv result files, which had the same collision: a reduced and an
unreduced calculation of one model, or two at different target accuracies,
produced different numbers under the same name. Only non-defaults appear, so
a run with shell reduction off in double precision writes exactly the names it
always has.
Also records the settings IN the saved file, which distinct names alone do not
give you -- a new "GRPY options:" screen in the parameter selector with six
entries: single precision, shell reduction, target accuracy, viscosity
required, the estimated error achieved, and the quantity that error belongs
to. Tabs are built from the section list, so the screen appears without a count
to update anywhere.
The estimated error is the one that matters. The CSV is what gets compared
across runs, and until now it recorded the numbers with no uncertainty attached
to them.
These record the EFFECTIVE settings, not the dialog's: this_data.hydro now
comes from a copy carrying any scripting or environment overrides, so a headless
run reports what it actually used. Saving the dialog values would have been
wrong precisely in the batch case where nobody would notice.
FIX, found while checking this: used_beads was the count from setup, taken
before any reduction, so a run using 2832 of 11328 beads reported 11328 in the
CSV, the results table and the .grpy_res report line alike. Narrowed to what
the ladder actually used, never widened, so shell-off runs are unaffected.
Batch mode needs nothing: it enters through the same calc_grpy_hydro(), so the
guard, the reduction, the cancellation and these names all apply, and the
suffix is cleared at run start so a batch cannot inherit stale settings.
Docs: somo_save.html goes from eight screens to nine, describes the six
parameters, notes that the achieved error may exceed the target when stopped
early or memory-limited, and records the used_beads correction.
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: c8693bcb2c4f5eb5b18325d8870677817a951277
https://github.com/ehb54/ultrascan3/commit/c8693bcb2c4f5eb5b18325d8870677817a951277
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_save.cpp
M us_somo/somo/doc/manual/somo/somo_save.html
Log Message:
-----------
somo: shorten the save-parameters tab titles and widen the window
Nine tabs of titles no longer fitted; adding the GRPY options screen is what
tipped it over. Measured: the titles wanted 1818 px of tab bar in a 640 px
window.
Multi-line titles were tried first and do not work. Qt keeps a tab's height
fixed regardless of newlines -- verified at one, two and three lines, all 36 px
-- so the extra lines are simply clipped. Newlines do narrow the bar (1818 ->
1255 px) because the width is measured from the longest line, but 1255 still
does not fit, and making the height follow would need a custom QTabBar
overriding tabSizeHint().
Shortening instead: "Additional" and the trailing colons carry no information
in a window already titled Select Parameters to be Saved. That gives 846 px,
which fits an 880 px window (640 -> 880) with room to spare. Robust across
styles and font sizes in a way that a width bump alone would not have been.
Main hydro | SMI | ZENO | GRPY | GRPY options | vdW | Solvent | ASA |
Fractal dim.
Manual updated so the documented names match the screen, including two things
the rename exposed: a paragraph still calling one screen by its old name, and
a doubled period where a name ending in "." met the end of a sentence.
Measurements were taken under Qt's offscreen platform, which may not use the
same style as a live macOS build, so the pixel figures are indicative; there is
~34 px of headroom at 880.
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: e23ab8ab3cb6bd509ef2f14142aea561d08625ba
https://github.com/ehb54/ultrascan3/commit/e23ab8ab3cb6bd509ef2f14142aea561d08625ba
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_hydro.cpp
M us_somo/somo/doc/manual/somo/somo_hydro.html
M us_somo/somo/doc/manual/somo/somo_hydro_shell_reduction.html
Log Message:
-----------
somo/grpy: name the shell viscosity checkbox for what it gates
" Require intrinsic viscosity " read as an on/off switch for the quantity
itself. Because a disabled checkbox keeps its setting, unchecking it with shell
reduction on and then switching the reduction off left an unchecked, greyed-out
box that looked as though viscosity had been turned off for ordinary GRPY runs
too -- and could not be turned back on without re-enabling the reduction.
It never was off, and no behaviour changes here. With shell reduction off,
ShellSolver::run() returns on the unreduced path having set
viscosity_unreliable false; that flag is additionally cleared at the start of
every run, there is exactly one solver construction site so nothing bypasses
it, and it is the only thing that withholds [eta] or the viscosity-derived
Einstein radius from the reported results. The setting reaches nothing else:
the result-file name suffix and the non-default-settings report are both gated
on grpy_shell.
So this is a naming fix. "to converge" says that the box governs when the series
of calculations may stop, not whether the quantity is computed -- intrinsic
viscosity comes from the same matrix as every other quantity, at no additional
cost, and is therefore always computed. A tooltip states the same in the window
itself, the first in this one, following the newer MALS/DAD screens.
The manual had it right but under the old name. Both pages are renamed to match,
and somo_hydro.html now says explicitly that the checkbox bears only on the
stopping decision, that the quantity is always computed, and that the retained
setting has no effect at all while the option is off.
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 392aa0b584154cd8c1a983f156b2b34b6d6cffd2
https://github.com/ehb54/ultrascan3/commit/392aa0b584154cd8c1a983f156b2b34b6d6cffd2
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_hydro.cpp
Log Message:
-----------
somo/grpy: break the shell viscosity tooltip onto sense-lines
The tags make Qt treat the tip as rich text, so the lines fall where the sense
does rather than at whatever width a single long line happens to take. The point
that answers the question which prompted the rename -- that intrinsic viscosity
is always computed, and always reported when shell reduction is off -- now
stands on its own line instead of trailing a paragraph.
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 8f3797b286908f4a1a61fd69fd95ab7178b322ed
https://github.com/ehb54/ultrascan3/commit/8f3797b286908f4a1a61fd69fd95ab7178b322ed
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/grpy_shell.hpp
M us_somo/develop/grpy/tests/test_shell.cpp
M us_somo/somo/doc/manual/somo/somo_hydro.html
Log Message:
-----------
somo/grpy: report the computed and extrapolated values side by side
The shell report gave the estimated error but only one value, and an audit of the
development benchmarks turned up why that matters: the research harness that produced
them accepted the Richardson-extrapolated value as the answer and scored the error
estimate against ITS deviation, while the shipped solver returns the finest rung's own
value and delivers the extrapolated one separately. Those are two different claims. On
the same archived runs the estimate covers the extrapolated value's deviation in 92 of
92 cases but the finest rung's in 82 of 92, so which value is reported decides what the
error estimate means. The module's own tests happened to score the finest rung, which is
why the divergence went unnoticed.
Reporting both settles it. The scalars keep the computed value -- a reported result
should be one the program computed, not one inferred from a trend -- and the report now
prints the extrapolated value beside it, with the estimate stated as the distance
between the two and a sentence saying which column the results elsewhere in the file
are. A reader shown one column alone cannot tell what the estimate applies to, which is
the entire content of the estimate.
ShellReport gains `reported`, the finest rung's value per requested observable, parallel
to the existing `extrapolated`. It is what Results carries, and a test asserts that
equality exactly -- if they ever diverge, the report and the returned scalars would be
describing different answers. A further test asserts the two columns are genuinely
distinct, so the block cannot pass by printing one number twice.
Manual updated to describe both columns and to say plainly that they are two answers
rather than a value and a correction to it.
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 89a6773a3ecda473f45eb69c164f3475a9e64b62
https://github.com/ehb54/ultrascan3/commit/89a6773a3ecda473f45eb69c164f3475a9e64b62
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/grpy_shell.hpp
M us_somo/develop/grpy/tests/test_shell.cpp
M us_somo/develop/src/us_hydrodyn_grpy.cpp
M us_somo/somo/doc/manual/somo/somo_hydro.html
Log Message:
-----------
somo/grpy: record what the ladder did, so a validation run can be audited
Three additions, all in service of re-validating shell reduction against a frozen
implementation rather than against benchmarks whose provenance cannot be reconstructed.
ShellReport::values -- every rung's value for every requested observable. The ladder
already computes this; it was a local. Exposed, any variant of the estimator can be
recomputed from the stored sequence instead of re-solving, which is the difference
between seconds and hours per corpus when comparing estimators.
ShellReport::prov -- which mechanism produced each observable's estimate: whether
Richardson succeeded or the raw gap was used and why it declined, whether the observed
order was pinned at either clamp, and whether the 2x tightening floor set the number
rather than the extrapolation. This matters more than it sounds: on the archived
development runs the extrapolation tightened the estimate in only ~11% of cases, so most
of the reported margin came from the gap and the safety factor -- a fact that had to be
inferred from a separate harness's columns because the solver recorded none of it.
grpy_bead_inclusion scripting override -- the run already honours grpy_single,
grpy_shell, grpy_shell_tol, grpy_shell_require_eta, grpy_shell_max_beads and
grpy_ooc_dir, but not this one, so the screened and unscreened cases could not be swept
headlessly. Unlike the others it sets hydro rather than a call-site local, because bead
selection happens in several places across a run including after calc_grpy_hydro
returns; applied for the run and announced, since a silent change to which beads are
used would invalidate every number the run produces.
Tests: values has one row per rung and one column per observable, its last row IS the
reported value, and it changes between rungs (so it cannot pass by copying one rung);
prov is self-consistent (extrapolated xor declined, k_obs set iff extrapolated, no
safeguard flags when extrapolation did not run, never both clamps); and a deliberately
two-rung ladder declines to extrapolate and says why. Full module suite passes, clean
libus_somo and app builds.
Fixes ehb54/ultrascan-tickets#984
Commit: 002ca07ff9e8dfcd85a1bdcacadde64a59f3b85f
https://github.com/ehb54/ultrascan3/commit/002ca07ff9e8dfcd85a1bdcacadde64a59f3b85f
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/grpy_shell.hpp
M us_somo/develop/grpy/tests/test_shell.cpp
Log Message:
-----------
somo/grpy: an exact result must not carry a stale error estimate
When the rung just solved is the full model the answer is exact and every bar should be
zero, but the loop tested the tolerance first and the full-model case second. If the full
rung also happened to satisfy the tolerance, the run exited as merely "converged", kept
the inter-rung gap as its estimate, and left `unreduced` false. Measured on a 216-bead
model at tol=0.5%: the ladder reached all 216 beads, the value was bit-identical to the
unreduced solve, and the report claimed 0.159% on a true error of zero.
The value was never wrong and the estimate was conservative rather than misleading, but
"converged, 0.16% estimated error" is a false statement about an exact calculation, and
`unreduced` is the flag the report and the results file use to say the answer is exact.
Test the full-model condition first, and widen it to cover n_used >= n_full so it does not
depend on the nominal fraction matching the realised bead count.
The existing exhaustion test missed this because it used tol=1e-12: unsatisfiable by
construction, so the tolerance branch could never win the race. The new test uses a
satisfiable tolerance on a ladder ending at 1.0 and asserts the full rung is flagged
unreduced, that err_max and every per-observable estimate are zero, that the result equals
the plain unreduced solve, and that viscosity is not flagged unreliable.
Found by a smoke run of the re-validation driver, which prints the retained fraction beside
the estimate: a row reading keep_frac=1.0, true error 0.000000, estimate 0.159% cannot all
be true at once. Worth landing before those runs, since full-rung rows would otherwise be
scored as an 0.16% estimate against a true error of zero -- inflating the reported
conservatism and hiding that the answers are exact.
Fixes ehb54/ultrascan-tickets#984
Commit: 90f69de2788122de5fa3973237a69a16795640cb
https://github.com/ehb54/ultrascan3/commit/90f69de2788122de5fa3973237a69a16795640cb
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/grpy_exposure.hpp
M us_somo/develop/grpy/tests/test_shell.cpp
Log Message:
-----------
somo/grpy: break exposure ties on geometry, not on input order
Exposure is quantised to the K surface sample points, so ties are large -- at ~2500 beads
the mean tie class holds ~90 of them, and the boundary between ladder rungs generally falls
inside one. Whatever breaks those ties therefore decides a large part of which beads are
kept, and it was breaking them by bead index: the order the beads happened to appear in the
input file.
Measured before this change, by permuting the input order of real models with geometry and
radii held fixed: a 3712-bead model gave a different retained subset in 20 of 20
permutations, and two more models in 20 and 17 of 20. Little downstream moved -- the
stopping rung was invariant, reported values shifted by at most 0.0098%, and all 240 runs
met their tolerance -- so this was never a correctness bug. But a selection that changes
when a file is rewritten cannot be reproduced from the model alone, which is worth more
than the noise it caused.
Ties now break by radius, then by distance from the model centroid, then by coordinate, and
only then by index. Farthest-first among equally exposed beads follows the same argument
that motivates ranking by exposure at all: the outermost contribute most to the drag. The
index fallback survives only for beads identical in exposure, radius and position, which are
interchangeable anyway.
A test permutes a model eight times and asserts the retained set, compared by coordinates
rather than indices, is unchanged. It fails on the previous tie-break.
This changes which beads are selected, so every frozen validation figure must be regenerated
against it; the tag will move.
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 6cc1fe8f0753441ee2c3b081f1d19529f41174e7
https://github.com/ehb54/ultrascan3/commit/6cc1fe8f0753441ee2c3b081f1d19529f41174e7
Author: Emre Brookes <emre.brookes at umontana.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/grpy_shell.hpp
Log Message:
-----------
somo/grpy: raise the shell-reduction error floor to 0.75 of the raw gap
The estimate is max(safety * Richardson remainder, floor * raw inter-rung gap).
Validating the full 23-model grid with all five observables -- the previous
multi-observable grid ran only 12 of the 23 models, so eleven never had intrinsic
viscosity or rotational diffusion checked -- exposed two evaluations that passed
the estimator's stop test yet missed the requested tolerance (2GD1 intrinsic
viscosity at 1%: estimate 0.859%, true error 1.066%), plus eleven more that were
compliant but undercovered.
Tolerance compliance is a subset of estimator coverage: the ladder stops when the
estimate falls below the tolerance, so an estimate that covers the true error
makes stopping imply compliance. Verified on the grid -- no row missed its
tolerance while covered, and all 235 reduced rows converged.
Raising the floor rather than `safety` is deliberate. The two terms are combined
with max(), so while the floor binds the safety factor does nothing: with a
doubling ladder and the order at k_max = 3 the remainder is gap/7, and
safety * gap/7 stays under 0.5 * gap for any safety <= 3.5. Measured on the same
grid, safety = 2.0 fixed neither failure and drove the median case to retain every
bead, because it inflates the estimate for the well-behaved majority where the
floor is slack. The floor acts only on the high-observed-order rows that fail.
At 0.75 the grid is clean: 200/200 reduced evaluations inside their tolerance and
all 200 covered, worst case spending 55.3% of the allowed budget (was 106.6%), for
4.6 percentage points more beads retained on average.
floor_frac is exposed on ShellOptions rather than left hardcoded, alongside k_min,
k_max and safety. Measuring it required patching a private copy of this header,
and a second copy of an estimator is what makes validation results unattributable.
The file's own MEASURED note claimed 92/92 and 252/252; both were wrong (seven
observables counted, three research-only; and the narrow model grid). Corrected to
what this code actually returns -- the finest rung, not the extrapolation.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: eda0c70b198e9b39d6d589158206563e8833c0e1
https://github.com/ehb54/ultrascan3/commit/eda0c70b198e9b39d6d589158206563e8833c0e1
Author: Emre Brookes <emre.brookes at umontana.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/grpy_exposure.hpp
M us_somo/develop/grpy/grpy_shell.hpp
Log Message:
-----------
somo/grpy: raise the exposure quadrature to 512 points per bead
The exposure point pattern is generated once in the coordinate frame and applied to
every bead by translation and scaling, so it does not rotate with the structure. A
rigid rotation therefore changes 34-77% of bead exposures by a few of the K sample
points and changes the ranking. A translation-only control is completely inert and
the unreduced result is invariant to zero parts per million, so this is the
quadrature, not arithmetic.
The effect reaches the answer almost entirely through the stopping decision, not
through which beads are kept: where the ladder stops at the same rung in every frame
the reported value moves by at most 0.075%, and where the orientation flips the rung
by one it moves by up to 1.043% -- a ratio of roughly fourteen, replicated on two
independent grids.
Measured over twelve rigid motions of six models, matched but for K: at 64, one case
of eighteen changed its stopping rung and the frame-to-frame spread reached 0.23%; at
512, no case changes rung and the spread falls to 0.016%. Retained beads are unchanged
(mean 31.5% vs 31.3%), and compliance and coverage are perfect at both values, so the
finer quadrature costs only exposure time -- about 3% of the ladder, exposure being
milliseconds against a solve of seconds.
This does not make selection frame-independent; subsets still differ in nearly every
frame. It makes the delivered result about 14x less sensitive to orientation, which is
what matters to a user who reorients their coordinates and reruns.
The low-level exposure() default stays 64 and is now annotated as such: every
production caller passes K explicitly, and the shipped value is ShellOptions::K.
This changes which beads are selected, so all frozen validation figures must be
regenerated and the freeze tag moved.
Fixes ehb54/ultrascan-tickets#984
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 6632667cb3c6f7876a02621f181588e7439b4233
https://github.com/ehb54/ultrascan3/commit/6632667cb3c6f7876a02621f181588e7439b4233
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_grpy.cpp
Log Message:
-----------
somo/grpy: add a failure boundary, and let Stop reach the solve
Two defects that both come from the move to an in-process solver.
A failure boundary. As a subprocess a GRPY failure was isolated -- the process
died, SOMO read a non-zero exit and carried on. In-process there is nothing
between a throw and the application: a failed allocation, an unreadable input
or a bad out-of-core path would terminate SOMO and lose the session. The parse
and the whole compute now run inside a try; the catch reports the error and
restores the interface exactly as the pre-flight memory guard does when it
refuses a model, and in gui_script mode fails properly to stderr with a
non-zero exit rather than reporting success. The body is left at its existing
indentation so the diff shows the boundary and nothing else.
Stop. sopt.should_stop was installed inside 'if ( sopt.enabled )', so it existed
only for a shell-reduced run. With shell reduction off -- the default, and now
the only configuration -- nothing was installed and Stop could not reach the
solve at all: the progress callback's 'if ( stopFlag ) return;' suppresses
repaints but does not end the computation, so a long model ran to completion
looking hung. Install it for every run.
This does not make Stop instant. A solve already running still finishes, since
the factor has no interior abort; with a ladder, Stop takes effect between rungs
and saves nearly all of what remained. Said plainly in the comment rather than
implied.
Reported-by: aaron-auc
(cherry picked from commit 876a76a1fd47c75e70def12fab87b0fff40f1dce)
Commit: bcdc2e7e9b47ad20c2562edebe7aad636793453c
https://github.com/ehb54/ultrascan3/commit/bcdc2e7e9b47ad20c2562edebe7aad636793453c
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_other.cpp
Log Message:
-----------
somo: don't let Close act during a running GRPY solve
The GRPY solve runs synchronously on the GUI thread and calls processEvents()
to keep the interface responsive, which also leaves Close live. Taking it would
hide the window, clear the temporary directories and ask the application to quit
while the solve was still running over those files -- SOMO appearing closed
while it went on computing.
closeEvent() now treats Close as a Stop request while grpy_running: it sets
stopFlag, says that the current model must finish first because the solve cannot
be interrupted part-way, and ignores the event. Closing again once it has
stopped behaves normally.
Reported-by: aaron-auc
(cherry picked from commit 5bf6554af39173167c0b78fb1307373d4329f15e)
Commit: 61ae0b5ba7cde24192764f0426a77f8041bb50ac
https://github.com/ehb54/ultrascan3/commit/61ae0b5ba7cde24192764f0426a77f8041bb50ac
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/grpy_exposure.hpp
M us_somo/develop/grpy/grpy_shell.hpp
A us_somo/develop/grpy/grpy_types.hpp
M us_somo/develop/grpy/tests/test_shell.cpp
M us_somo/develop/libus_somo.pro
M us_somo/develop/src/us_hydrodyn_grpy.cpp
Log Message:
-----------
somo/grpy: reach the solver through an injected function
The shell reduction and the exposure ranking are original work; the solver they drive is
a translation of GPLv3 GRPY.f. This separates the two so the latter can move to its own
program (ehb54/grpy-cpp) and be called rather than linked.
grpy_shell.hpp and grpy_exposure.hpp no longer name a solver, include grpy_core.hpp or
use Eigen. They take grpy::SolveFn -- one bead list in, Results out -- which SOMO will
implement by running the external GRPY program, once per rung. At most five rungs per
model, against O((11N)^3) where the last rung alone is ~7/8 of the work, so the extra
invocations cost nothing measurable.
New grpy_types.hpp holds the value types both sides exchange (Bead, PhysParams, Options,
Results, ProgressFn, Obs) plus the SolveFn injection point. It is plain data with nothing
translated from GRPY.f, so it stays with UltraScan; grpy_api.hpp now includes it instead
of defining the same types.
full_rg2() is computed here from the definition -- the volume-weighted second moment of a
union of uniform spheres, with each sphere's own (3/5)a^2 term -- rather than calling into
the core. Rg is pinned to the full model across rungs, so the ladder needs it even though
no rung computes the whole structure.
The call site is transitional: it still solves in process, through a lambda that wraps
grpy::Solver, so this commit changes no results. Replacing that lambda with a run of the
external program is the next step, after which grpy_api.hpp and grpy_core.hpp leave the
tree and nothing shipped links GPLv3 code.
Verified: the whole grpy module test suite passes, including test_shell driving the ladder
through the injection point; a translation unit including only grpy_shell.hpp compiles and
runs the ladder with neither the core nor Eigen present; and us_hydrodyn_grpy.cpp compiles
against the real Qt flags.
Refs ehb54/ultrascan-tickets#1012
Commit: 18f84edf14db5819e01eead1b366d2a1b4586102
https://github.com/ehb54/ultrascan3/commit/18f84edf14db5819e01eead1b366d2a1b4586102
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
A us_somo/develop/grpy/grpy_process.hpp
M us_somo/develop/grpy/tests/run.sh
A us_somo/develop/grpy/tests/test_process.cpp
M us_somo/develop/libus_somo.pro
M us_somo/develop/src/us_hydrodyn_grpy.cpp
Log Message:
-----------
somo/grpy: run GRPY as a program again, not as linked code
Implements the injection point from the previous commit: grpy::ProcessSolver runs the GRPY
program on a bead list and returns its results, and the shell reduction calls it once per
rung. Nothing GPLv3-derived is invoked here through anything but a process boundary.
The contract is the one SOMO used before the in-process port -- run it with '-e <file>',
read the report from stdout, scrape the carriage-return-separated 'NN% TASK:' banner for
progress -- so the program's command line is still the one the Fortran GRPY published. The
controls added since (precision, out-of-core, thread count) are passed as environment
variables rather than as new flags, which is what keeps that true.
A rung that uses every bead runs on the .grpy file SOMO already wrote, so the ordinary
unreduced calculation reads exactly the file the user sees, as it always has. Only a
reduced rung gets a temporary file, and it is removed however the run ends.
The binary lookup is the one the external path used before, minus the Docker/container
branch, which is not coming back: bin/GRPY_{osx10.11,linux64,win64.exe}, which add_to_bin
still ships and linux.pl still installs.
read_grpy_input() reads the .grpy file written by us_hydrodyn_write.cpp. It is written
against our own writer rather than translated from the Fortran reader, so the last thing
the call site needed from grpy_api.hpp is gone.
Out of process restores two things the in-process port had given up: a failure kills a
child rather than the session, and Stop ends a solve that is ALREADY RUNNING -- the
in-process factorization had no interior abort, so Stop only took effect between models.
That arrives as grpy::Stopped and is handled as a stop, not as a failure.
New test_process.cpp drives all of it with a fake GRPY program that replays a real golden
report and the real banner: parsing, progress, a non-zero exit, a missing program, and the
mid-solve kill. 19 checks, all passing, and the whole module suite still passes.
Caught by that test: the sedimentation label contains '(1. - (vbar*rho))', so taking the
first number after the label parsed 1.0 as the sedimentation coefficient. The value is
identified by its exponent, not by its position.
Refs ehb54/ultrascan-tickets#1012
Commit: 212f2cfbb6105b64394f31838d6992180baf96ce
https://github.com/ehb54/ultrascan3/commit/212f2cfbb6105b64394f31838d6992180baf96ce
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/README.md
M us_somo/develop/grpy/tests/run.sh
M us_somo/develop/grpy/tests/test_shell.cpp
M us_somo/develop/libus_somo.pro
M us_somo/develop/src/us_hydrodyn_grpy.cpp
Log Message:
-----------
somo/grpy: remove the GRPY-derived solver from the tree
This is the commit that resolves the licence conflict: the GPLv3-derived translation is no
longer present in an LGPLv3 repository, and no shipped binary can link it.
Deleted: grpy_core.hpp and grpy_report.hpp (translations of GRPY.f), grpy_api.hpp (its
readers and display formulas), and linalg.hpp / parallel_std.hpp / parallel_qt.hpp, which
existed to serve them. All of it now lives in ehb54/grpy-cpp, where it is GPLv3 and is
validated against the original Fortran by its own golden tests.
What remains in grpy/ is original work: the exposure ranking, the self-validating shell
reduction, the value types, and the process boundary. It is Eigen-free and QtConcurrent-
free as a result, so libus_somo.pro drops 'QT += concurrent'.
test_shell now drives the ladder with an ANALYTIC model instead of the real solver, which
is a stronger test rather than a weaker one: each observable approaches the full-model
value at a known rate, so the true error of every rung is known exactly and the reported
bar can be checked for actually bounding it. The model derives mass and Rg from the beads
it is given, exactly as the solver did, so the ladder's pinning of both to full-model
values is still what those tests exercise -- a model that echoed them back could not tell
a pinned value from an unpinned one.
Deleted with their subject: test_api, test_linalg, test_assemble, test_threaded, test_ooc
and qt_proof, which tested the solver, its linear algebra and its threading. Their
successors live in grpy-cpp.
Also updated the module README, removed INTEGRATION.md (it documented an integration that
no longer exists), and corrected the comments and messages that still described GRPY as
running in process.
Fixes ehb54/ultrascan-tickets#1012
Commit: 760b2eac03b89bb7daa69754b4590b6df33c4e3b
https://github.com/ehb54/ultrascan3/commit/760b2eac03b89bb7daa69754b4590b6df33c4e3b
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/add_to_bin/GRPY_linux64
M us_somo/add_to_bin/GRPY_osx10.11
M us_somo/add_to_bin/GRPY_win64.exe
Log Message:
-----------
somo/grpy: ship the C++ GRPY binaries in add_to_bin
Replaces the Fortran GRPY binaries with builds of ehb54/grpy-cpp, under the same names, so
the lookup, add_to_bin and linux.pl all keep working untouched. Without this the branch
calls the program it always called and none of the port's work reaches a user.
GRPY_osx10.11 universal x86_64 + arm64, ad-hoc signed. The Fortran binary was x86_64
only, so every Apple Silicon Mac was running GRPY under Rosetta.
GRPY_linux64 fully static, as its predecessor was: no glibc floor. Threading checked
under -static (67.1 s on 1 thread vs 2.81 s on 32 at 1200 beads).
GRPY_win64.exe cross-compiled with mingw-w64, imports only KERNEL32 and the UCRT stubs.
The macOS and Linux binaries pass the full golden suite against the original Fortran output
at worst relative error 0.00e+00. THE WINDOWS BINARY HAS NOT BEEN RUN -- no Windows machine
or wine was reachable from any build host -- so it needs a smoke test on Windows before
this branch ships. Everything else about it is verified statically only.
What a user gets that the Fortran binaries could not give: threading, single precision,
out-of-core, and native arm64.
Refs ehb54/ultrascan-tickets#1012
Commit: 8033018f4af8d6620225dcb0137a5e8fb80e0a85
https://github.com/ehb54/ultrascan3/commit/8033018f4af8d6620225dcb0137a5e8fb80e0a85
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/grpy_process.hpp
M us_somo/develop/grpy/grpy_shell.hpp
M us_somo/develop/grpy/grpy_types.hpp
M us_somo/develop/grpy/tests/test_shell.cpp
M us_somo/somo/doc/manual/somo/somo_hydro.html
M us_somo/somo/doc/manual/somo/somo_misc.html
Log Message:
-----------
somo/grpy: keep the finished rungs when Stop lands mid-calculation, and correct the manual
Updating the manual turned up a regression rather than just stale prose. somo_hydro.html
promises that a stopped shell reduction 'keeps the result and error estimate obtained so
far'. That held while GRPY ran in process, because it could only be stopped between rungs.
A separate program can be killed the instant Stop is pressed -- which is the improvement --
but the exception was propagating straight past the ladder, discarding every rung that had
already completed. The promise in the manual was no longer true of the code.
ShellSolver now treats a stop during a rung exactly as it treats one between rungs: the
ladder ends where it stands, reports itself as not converged, and keeps its result and its
error bar. Only a stop before the first rung has finished leaves nothing to report, and
that one still propagates. grpy::Stopped moved from grpy_process.hpp to grpy_types.hpp so
the ladder can catch it without acquiring a Qt dependency.
Two tests pin it: a solver that stops during the third rung must leave two usable rungs
with a bar, and one that stops immediately must propagate.
Manual:
* somo_misc.html said GRPY is 'built directly into US-SOMO and runs multi-core
in-process'. It is again a separate multi-core program, which US-SOMO installs and
runs; no Docker image and no checkbox, as before. The historical sentence about the
original external and Docker versions is left as it stands, being history.
* somo_hydro.html said Stop ends the series 'at the end of the calculation currently in
progress'. It now ends immediately, per the change above.
Refs ehb54/ultrascan-tickets#1012
Commit: 6d1e39e44ea3cedaa2ba8ef0afbfdb7927e7b664
https://github.com/ehb54/ultrascan3/commit/6d1e39e44ea3cedaa2ba8ef0afbfdb7927e7b664
Author: Emre Brookes <emre.brookes at umontana.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/grpy_process.hpp
M us_somo/develop/grpy/tests/test_process.cpp
Log Message:
-----------
somo/grpy: ask the solver for its high-precision report
The GRPY program's default report is the Fortran's own ES11.3 -- four significant
figures. That is right for a drop-in replacement a human reads, and wrong for a
caller that DIFFERENCES successive results, which is exactly what the shell
reduction does: the error estimate is built from the gap between consecutive rungs
and from the ratio of two such gaps, so a relative quantisation of ~1e-4 in the
parsed values lands directly on the reported bar.
Measured over 266 reduced evaluations, by rounding recorded full-precision rung
values through %11.3E and re-running the estimator on both:
reported estimate median 2.5% different, up to 17.6%
observed order k shifts by up to 0.26
floor activation changes which term governs in 14 cases
stopping decision flips in 2 cases
Coverage happened to survive on that corpus -- the minimum margin fell only from
1.131x to 1.119x, and no evaluation lost coverage -- so this is not a correctness
fix. But none of that movement should exist. It is an output format leaking into a
numerical result, and into the delivered value too, which was being truncated to
four significant figures.
The program already supports this: GRPY_HP switches the report to %24.15E. Nothing
changes for anyone running the program directly, since the default is untouched and
the drop-in behaviour is preserved.
The parser finds values by their exponent rather than by column, so it is indifferent
to the field width. Tests assert that rather than leaving it to inspection: a
%24.15E report round-trips a double to better than 1e-12, and the legacy ES11.3
report still parses, since an older binary on PATH would still emit it.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 8abf8f48b6a5e3b834fe28b1dc7ceed6cc594fb7
https://github.com/ehb54/ultrascan3/commit/8abf8f48b6a5e3b834fe28b1dc7ceed6cc594fb7
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/etc/somo.residue.new
Log Message:
-----------
somo.residue - add glucose
(cherry picked from commit 78465e20f3484e65b83e09bfccd8cd624204beaa)
Commit: 17bdf1eca3c3acbc5eced6629badec343a7390bb
https://github.com/ehb54/ultrascan3/commit/17bdf1eca3c3acbc5eced6629badec343a7390bb
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/perceiver/.gitignore
A us_somo/develop/perceiver/data/1ADO_noSO4.pdb
A us_somo/develop/perceiver/data/1AO6-compl_monA.pdb
A us_somo/develop/perceiver/data/1HEL.pdb
A us_somo/develop/perceiver/data/2AAS.pdb
A us_somo/develop/perceiver/data/3CRO.pdb
A us_somo/develop/perceiver/data/3GUT.pdb
A us_somo/develop/perceiver/data/6LDH1.pdb
A us_somo/develop/perceiver/data/6LYZ.pdb
A us_somo/develop/perceiver/data/8RAT.pdb
Log Message:
-----------
perceiver: commit the regression fixtures instead of ignoring them
data/*.pdb was ignored on the grounds that those structures are copies of
us_somo/somo/demo/*.pdb, so make regress could not score anything from a clean
checkout -- it read no atoms, divided by zero into 0.000%, and (before the guard
added in the previous merge) exited 0.
Track them instead. The two sets serve different purposes and are free to
diverge: the demo structures exist for the demos and may be edited for demo
reasons, while these are the perceiver's regression fixtures and the calibrated
score must not move underneath them. They are byte-identical today; that is a
coincidence of history, not a guarantee, and coupling a regression baseline to
someone else's demo data is the kind of thing that fails silently.
Nine files, 7.7 MB: the eight DEMOS consumed by regress/coverage/sssrreal, plus
1ADO_noSO4.pdb for protein_psv.
Scoring 41219 atoms, the harness now reports 99.833% geometric perception with
69 genuine errors remaining.
Commit: 1e5b57fae902fe18c175ce1e2a2c7f508c06b6bb
https://github.com/ehb54/ultrascan3/commit/1e5b57fae902fe18c175ce1e2a2c7f508c06b6bb
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/perceiver/data/2AAS.pdb
Log Message:
-----------
perceiver: trim the 2AAS fixture to its first model
2AAS is a 32-model NMR ensemble and was 3.0 MB -- 40% of the fixture set -- while
contributing the fewest scored atoms of any structure in it (950). pdb_lite's
read_pdb() defaults to keep_first_model = true and stops at the first ENDMDL, so
the regression only ever read model 1; the other 31 were carried for nothing.
Keep the header, MODEL 1 and its ENDMDL, and the trailing CONECT records -- those
are the four disulfides, and the harness uses CONECT connectivity where a file
provides it, which is what tells a cystine from a free cysteine. Drop MASTER: its
counts describe the 32-model file and would be numerically false here.
3060 KB -> 120 KB. Verified inert: the full regression output is byte-identical
before and after (sha 41f02d6f7b8a70e7 both ways), 41219 atoms scored, 99.833%
geometric perception, and 2AAS itself still scores 950 atoms at 98.63% exact.
The only multi-model consumer, protein_psv, does not use 2AAS.
Commit: c18a832b7bf0f34ee9f041d8220f02c582e7e3ea
https://github.com/ehb54/ultrascan3/commit/c18a832b7bf0f34ee9f041d8220f02c582e7e3ea
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/perceiver/Makefile
R us_somo/develop/perceiver/data/2AAS.pdb
A us_somo/develop/perceiver/data/2AAS_mod1.pdb
M us_somo/develop/perceiver/data/psv_measured.txt
M us_somo/develop/perceiver/pdb_lite.h
Log Message:
-----------
perceiver: name the trimmed fixture 2AAS_mod1, not 2AAS
A file trimmed to one model is no longer the published entry, so it should not
carry the bare PDB ID -- anyone comparing it against 2AAS from the PDB, or against
us_somo/somo/demo/2AAS.pdb, would find 31 models missing with nothing in the name
to say why.
Rename to 2AAS_mod1.pdb and follow it everywhere it is referenced:
- Makefile: the DEMOS entry the regression consumes.
- pdb_lite.h: the explicit-H note cited '7840 H, 245 in model 1'. 7840 is the
count for the whole ensemble and is no longer true of this file; it now reads
245 explicit H, with the ensemble figure kept as context.
- data/psv_measured.txt: rows are keyed by pdb-basename, so the 2AAS key would
have stopped matching. Re-keyed to 2AAS_mod1, label '(2AAS, model 1)'. The
file is not in PSV_PROTEINS today, so nothing was broken -- but a silent lookup
miss later would have been hard to spot.
DECISIONS.md keeps saying 2AAS: those entries are a historical design log about
the structure, not references to a path.
Verified: regression totals identical to the untrimmed baseline (41219 atoms,
99.833%), 2AAS_mod1 itself still 950 atoms at 98.63%, unit tests 147/0, and the
no-input guard still exits 2.
Commit: eff11e9bd8f834df7ee539c847dab0753cd26242
https://github.com/ehb54/ultrascan3/commit/eff11e9bd8f834df7ee539c847dab0753cd26242
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/somo/doc/manual/somo/somo_misc.html
Log Message:
-----------
somo/doc: drop the resolved release-date query from somo_misc
The GRPY paragraph carried an author note asking for the release date to be
confirmed:
<!-- confirm actual release date; merged to somo-dev 2026-08-06 -->
August 2026 is correct, so the note has served its purpose and should not ship.
The six user-facing 'August 2026' claims across the four changed manual pages
stand unchanged; only the comment is removed.
Commit: 2eb987336bc767e1b22c3edf4802a733a971755e
https://github.com/ehb54/ultrascan3/commit/2eb987336bc767e1b22c3edf4802a733a971755e
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M .gitignore
Log Message:
-----------
gitignore: ignore generated moc output, not just the moc/ directory
Two qmake-generated moc artifacts had been committed under
us_saxs_cmds_t/ and rode in with the GRPY history. They break the Qt6
CI build outright: moc output carries
#error "This file was generated using the moc from 5.15.14. It
cannot be used with the include files from this version of Qt."
so any Qt6 compile of a Qt5-generated moc_*.cpp fails, and moc_predefs.h
is a dump of one compiler's predefined macros, wrong on any other
platform. Both are regenerated by qmake on every build.
The existing rule was moc/, which only covers the output directory used
by some .pro files; files generated beside the source were not matched.
Add moc_*.cpp and moc_predefs.h. No tracked file matches either rule.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 505b560e0e802db5fe8bb52f906b70d1f7f2264d
https://github.com/ehb54/ultrascan3/commit/505b560e0e802db5fe8bb52f906b70d1f7f2264d
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M .github/workflows/somo-module-tests.yml
M us_somo/develop/perceiver/Makefile
M us_somo/develop/perceiver/residue_oracle.h
M us_somo/develop/perceiver/tests/regression.cpp
Log Message:
-----------
perceiver: run the regression in CI, under floors that can actually fail
Set 2 committed the fixtures, but CI still only asserted the vacuous-pass
guard -- it built bin/regression, ran it with NO arguments to prove it fails
on nothing, and never scored a structure. The regression itself had not run
in CI at all.
Running it is not enough on its own: the harness only failed when it scored
ZERO atoms, so perception could fall from 99.8% to 90% and still exit 0. Two
optional floors are added, and `make regress-ci` pins them to the committed
fixture set:
--min-atoms 41219 a fixture going missing or truncated would quietly
shrink what every percentage is measured over while
still reporting a healthy-looking number
--min-geometric 99.8 perception getting worse fails the build
They are floors, not expected values: an improvement must not fail. Both are
reported together rather than short-circuiting, so one run tells you
everything out of tolerance. Unknown options are now rejected rather than
being read as input filenames.
The vacuous-pass step is kept alongside the real run, because the real run
would still go green if the fixtures vanished AND the guard broke.
residue_oracle.h is brought to the coding standards. It had
while (ss>>t) v.push_back(t); return v;
which is what -Wmisleading-indentation was reporting on every build: the
return reads as guarded by the while and is not. Braces settle it. Scoring is
unchanged -- 41219 atoms, 99.833% geometric perception, 69 genuine errors,
before and after.
Also drops the stale "the demo structures are not committed to the
repository" text from the failure message, which set 2 made untrue.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 59325d3cbbd758a15ae9fe6f17c5f53fda5aa85d
https://github.com/ehb54/ultrascan3/commit/59325d3cbbd758a15ae9fe6f17c5f53fda5aa85d
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/grpy_exposure.hpp
M us_somo/develop/grpy/grpy_shell.hpp
M us_somo/develop/grpy/tests/test_shell.cpp
M us_somo/develop/src/us_hydrodyn_grpy.cpp
M us_somo/develop/src/us_hydrodyn_other.cpp
M us_somo/develop/src/us_hydrodyn_settings.cpp
Log Message:
-----------
somo: braces on the code this set adds, per the coding standards
The UltraScan III standards require braces on a simple if/for/while body.
The rule earns its keep: an unbraced body is what produced the
-Wmisleading-indentation warning on the perceiver build, and it is the shape
that lets a second statement be added later outside the guard it appears to
be under.
Scope is deliberately narrow, so this stays reviewable:
- the four grpy files this set ADDS are formatted in full with the project
tool (ehb54/grpy-cpp tools/us3_style.pl). The whole file is new code, so
there is no existing formatting for a reviewer to diff against.
- the files this set MODIFIES get braces ONLY, only on lines this set
added: 15 sites across us_hydrodyn_grpy.cpp, _other.cpp and _settings.cpp.
No spacing, indentation or reflow -- those files carry ~1400 pre-existing
unbraced bodies between them, and touching any of them would bury this
set's actual changes in the diff. That remains for the planned full pass.
Verified: brace counts balance in every edited file (delta 0 opening vs
closing), grpy test_shell and test_process both ALL PASS, perceiver unit
tests 147 checks 0 failures, regression unchanged at 99.833% over 41219
atoms.
Note for anyone repeating this with the tool: `--check` reports a body whose
brace sits on its own line as unbraced, though the formatter correctly leaves
it alone. Acting on that list mechanically produces `) {` above `{`. Twelve
of the sites here were that false positive and were skipped. Fixed upstream
in ehb54/grpy-cpp#1.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 22f5fbbfeccad48466fb20aa2b3af2b5b9cb9a1b
https://github.com/ehb54/ultrascan3/commit/22f5fbbfeccad48466fb20aa2b3af2b5b9cb9a1b
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/grpy_shell.hpp
M us_somo/develop/grpy/tests/run.sh
Log Message:
-----------
somo/grpy: build the module under C++11, and test it at that standard
SOMO supports Qt5 as well as Qt6, so it has to build under the older
compilers Qt5 is used with, and nothing in its build raises the language
standard. The grpy module did not honour that:
grpy/grpy_shell.hpp: error: no viable overloaded '='
note: cannot convert initializer list argument to
'grpy::ShellReport::Provenance'
ShellReport::Provenance carries default member initializers, which makes it a
non-aggregate before C++14, so the braced assignment
rep.prov[ m ] = { ri.ok, ri.clamped_low, ... };
is not valid C++11. It is now assigned field by field. The initializers stay:
prov is filled by assign() and they are what make an untouched entry read
false/nullptr rather than indeterminate.
That was the only C++11 violation in the module -- grpy_shell, grpy_exposure,
grpy_types and grpy_process all compile clean at -std=gnu++11, as do both
test programs.
The reason it survived is the second half of this commit. grpy/tests/run.sh
compiled the module at -std=c++17, a HIGHER standard than the product it
ships in, so every test passed on code the Qt5 build would not accept.
Testing above the product's standard hides breakage instead of finding it.
run.sh now uses -std=gnu++11, to be raised when SOMO's own standard moves --
which is a question for the Qt6 migration, not for this module.
Compilers new enough to default to gnu++17 (the CI containers) built it
either way, which is why CI stayed green; the Qt5 macOS build did not.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: d37eeb1678b8a4eba616a47c465ea4ce743ddc08
https://github.com/ehb54/ultrascan3/commit/d37eeb1678b8a4eba616a47c465ea4ce743ddc08
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_residue_builder.cpp
Log Message:
-----------
somo/perceive: C++11 aggregate init in the residue builder
Same defect as the grpy one, in code that arrived with the perceiver:
src/us_hydrodyn_residue_builder.cpp:47: error: no matching member
function for call to 'push_back'
note: cannot convert initializer list argument to
'somo_volume::Sphere'
somo_volume::Sphere declares `double x = 0, y = 0, z = 0, r = 0;`, so it is
not an aggregate before C++14 and cannot be built from a braced list under
the C++11 that the Qt5 builds use. Filled field by field instead; the
initializers stay, since they are what make a default Sphere read zero.
This one is NOT new to this merge set -- it came in with the perceiver and is
already on main. It stayed hidden because the grpy error above aborted the
compile first, and because every CI container defaults to gnu++17.
With this, the whole library compiles at -std=gnu++11: 0 errors over the full
source tree, checked with make -k so nothing was masked by an early abort.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: e2a880b8512de6620852466ae6a617ba629f8102
https://github.com/ehb54/ultrascan3/commit/e2a880b8512de6620852466ae6a617ba629f8102
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M .github/workflows/somo-module-tests.yml
M us_somo/develop/perceiver/Makefile
M us_somo/develop/perceiver/tests/regression.cpp
Log Message:
-----------
perceiver: make the CI regression gate slack, not pinned
The gate added earlier in this branch would have broken CI for the perceiver
work happening in parallel. It required --min-atoms 41219, which is EXACTLY
the current count -- one atom's difference fails -- and --min-geometric 99.8
against an actual 99.833, leaving 0.033 of room. Any legitimate change to the
module trips both.
The atom floor was there to catch a fixture going missing. That is worth
keeping, but it is the wrong instrument: the atom count moves with parsing
and with which atoms are scorable, i.e. with exactly the work in flight.
Replaced with --require-all-inputs, which asserts that every fixture handed
in produced something to score. It catches the failure that matters -- a
fixture missing, unreadable or truncated, which would otherwise leave the
percentages looking healthy while measuring less -- and it is orthogonal to
perception quality, so tuning the perceiver cannot trip it. The failing
inputs are named.
--min-geometric drops to 95, a collapse detector rather than a pin, leaving
about five points of room below the current 99.833%.
What this keeps is the thing that was actually missing: the regression RUNS
in CI and its numbers are in the log on every build. What it gives up is
catching a small drift, which is not something to enforce on a module still
being developed. Tighten once it settles.
Verified: passes with the fixture set; fails, naming the file, when an input
is missing and when one is empty; the vacuous-pass guard still fails on no
input at all.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: f1f016b8bd741b66eb80d86f0908e47f3ecfac17
https://github.com/ehb54/ultrascan3/commit/f1f016b8bd741b66eb80d86f0908e47f3ecfac17
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M .github/workflows/somo-module-tests.yml
M us_somo/develop/grpy/grpy_process.hpp
M us_somo/develop/grpy/grpy_shell.hpp
M us_somo/develop/grpy/tests/test_process.cpp
M us_somo/develop/include/us_hydrodyn.h
M us_somo/develop/src/us_hydrodyn.cpp
M us_somo/develop/src/us_hydrodyn_grpy.cpp
M us_somo/develop/src/us_hydrodyn_other.cpp
Log Message:
-----------
somo/grpy: review fixes -- wrong model, stderr deadlock, split banners
>From the review on ehb54/ultrascan3#524.
Shell models were written from the WRONG MODEL. grpy_write_shell_model()
rebuilt the bead order from `bead_model`, which calc_grpy_hydro()'s setup
loop leaves holding the LAST selected model. With several models selected and
"save shell models" on, every model but the last had its shells built from
another structure's beads. The index-bounds check below it only caught that
when the bead counts happened to differ. It now uses
bead_models[ grpy_last_model_number ], which grpy_process_next() sets per
model, with a bounds guard.
A child writing to stderr could DEADLOCK the run. run_program() drained
stdout in its poll loop but read stderr only after waitForFinished( -1 ). The
channels are separate and each pipe buffer is finite, so a child that writes
more than that buffer to stderr blocks in write(), stops producing stdout,
the loop stops advancing, and the wait -- which has no timeout -- never
returns. stderr is now drained every pass.
Progress text could reach the report. consume_progress() treated each read as
whole records, but reads off a pipe break wherever the buffer fills: a banner
split across two reads matched nothing and had both halves appended to the
report, which is what lands in .grpy_res and what parse_report() reads. It
now holds a trailing partial record back until its terminator arrives, which
also repairs a "\r\n" straddling the boundary. Covered by a new test that
fails against the old behaviour.
A user's Stop was reported as a memory failure. ShellReport::annotation()
treated levels == 0 as "even the smallest rung exceeded the available
memory", but levels == 0 is also reached when should_stop fires before the
first rung finishes. It now distinguishes stopped from mem_capped.
std::snprintf in grpy_shell.hpp worked only through transitive includes;
<cstdio> is now included.
Stale comments, all saying a running solve cannot be interrupted. It can:
ProcessSolver polls every 100 ms and kills the child, which the test "a
running solve is killed on stop" already asserted. Corrected in
us_hydrodyn_grpy.cpp, us_hydrodyn.cpp (which still described GRPY as
in-process), the ShellOptions::should_stop doc in grpy_shell.hpp -- which
contradicted the correct comment 270 lines below it -- and the user-facing
message in us_hydrodyn_other.cpp, which told the user the model would finish
first.
The grpy::ShellReport forward declaration in us_hydrodyn.h is removed: it is
referenced nowhere in that header, and its stated reason (keeping Eigen out)
no longer holds since the module dropped Eigen.
GRPY had NO CI coverage -- neither grpy/** nor us_hydrodyn_grpy.cpp appeared
in the paths filters and no job ran the suite. Both paths added, plus a job
running grpy/tests/run.sh. test_shell is Qt-free and runs; test_process needs
QtCore and run.sh skips it when QTDIR is unset. Verified on Linux/g++ 13.3.1
at -std=gnu++11 before adding: ALL PASS, exit 0.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 45e44d2afe8e2e00ac5443f50cc1de61539b2487
https://github.com/ehb54/ultrascan3/commit/45e44d2afe8e2e00ac5443f50cc1de61539b2487
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M us_somo/develop/grpy/tests/test_shell.cpp
Log Message:
-----------
somo/grpy: brace three bodies the style tool did not catch
Answering "does this branch conform": it did not, in three places, all in
test_shell.cpp and all added by this set.
for ( size_t i : ref ) ref_xyz.push_back( {c[ i ].x, ... } );
for ( size_t i : got ) got_xyz.push_back( {pc[ i ].x, ... } );
if ( r ) for ( int k : rep.kept[ r - 1 ] )
us3_style.pl reported 0 violations on these files, which is why they
survived the earlier pass. Two blind spots in its --check:
- it treats ANY '{' on the line as "already opens a body", so an unbraced
body whose argument is a braced initializer list looks braced;
- its inline case requires the body to end in ';', so a body that is
itself a control statement (`if ( r ) for ( ... )`) matches nothing.
Found by cross-checking with a second checker rather than trusting one tool.
Both blind spots are being fixed upstream in ehb54/grpy-cpp#1.
Swept every line this branch adds with the stricter check afterwards: 0
unbraced bodies remain. grpy tests still ALL PASS.
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: 3b589698f1f40191278932113465a47202172eae
https://github.com/ehb54/ultrascan3/commit/3b589698f1f40191278932113465a47202172eae
Author: emre brookes <ehb54 at users.noreply.github.com>
Date: 2026-08-18 (Tue, 18 Aug 2026)
Changed paths:
M .github/workflows/somo-module-tests.yml
M .gitignore
M us_somo/add_to_bin/GRPY_linux64
M us_somo/add_to_bin/GRPY_osx10.11
M us_somo/add_to_bin/GRPY_win64.exe
A us_somo/develop/grpy/README.md
A us_somo/develop/grpy/grpy_exposure.hpp
A us_somo/develop/grpy/grpy_process.hpp
A us_somo/develop/grpy/grpy_shell.hpp
A us_somo/develop/grpy/grpy_types.hpp
A us_somo/develop/grpy/tests/data/1znf.bead_model
A us_somo/develop/grpy/tests/data/1znf_golden.txt
A us_somo/develop/grpy/tests/data/dumbbell.grpy
A us_somo/develop/grpy/tests/data/dumbbell_golden.txt
A us_somo/develop/grpy/tests/run.sh
A us_somo/develop/grpy/tests/test_process.cpp
A us_somo/develop/grpy/tests/test_shell.cpp
R us_somo/develop/include/us_container_grpy.h
M us_somo/develop/include/us_hydrodyn.h
M us_somo/develop/include/us_hydrodyn_hydro.h
M us_somo/develop/include/us_hydrodyn_misc.h
M us_somo/develop/include/us_hydrodyn_save.h
M us_somo/develop/libus_somo.pro
M us_somo/develop/perceiver/.gitignore
M us_somo/develop/perceiver/Makefile
A us_somo/develop/perceiver/data/1ADO_noSO4.pdb
A us_somo/develop/perceiver/data/1AO6-compl_monA.pdb
A us_somo/develop/perceiver/data/1HEL.pdb
A us_somo/develop/perceiver/data/2AAS_mod1.pdb
A us_somo/develop/perceiver/data/3CRO.pdb
A us_somo/develop/perceiver/data/3GUT.pdb
A us_somo/develop/perceiver/data/6LDH1.pdb
A us_somo/develop/perceiver/data/6LYZ.pdb
A us_somo/develop/perceiver/data/8RAT.pdb
M us_somo/develop/perceiver/data/psv_measured.txt
M us_somo/develop/perceiver/pdb_lite.h
M us_somo/develop/perceiver/residue_oracle.h
M us_somo/develop/perceiver/tests/regression.cpp
R us_somo/develop/src/us_container_grpy.cpp
M us_somo/develop/src/us_hydrodyn.cpp
M us_somo/develop/src/us_hydrodyn_grpy.cpp
M us_somo/develop/src/us_hydrodyn_hydro.cpp
M us_somo/develop/src/us_hydrodyn_misc.cpp
M us_somo/develop/src/us_hydrodyn_other.cpp
M us_somo/develop/src/us_hydrodyn_residue_builder.cpp
M us_somo/develop/src/us_hydrodyn_save.cpp
M us_somo/develop/src/us_hydrodyn_settings.cpp
M us_somo/develop/src/us_hydrodyn_write.cpp
M us_somo/etc/somo.residue.new
M us_somo/somo/doc/manual/somo/somo_hydro.html
A us_somo/somo/doc/manual/somo/somo_hydro_shell_reduction.html
M us_somo/somo/doc/manual/somo/somo_misc.html
M us_somo/somo/doc/manual/somo/somo_save.html
Log Message:
-----------
Merge pull request #524 from ehb54/ehb54-issue-1016-somo-merge-2
SOMO: second somo-dev merge set — externalised GRPY, shell reduction, perceiver fixtures
Commit: 9aa0949130b92f547f2c57fa30ad88440de41896
https://github.com/ehb54/ultrascan3/commit/9aa0949130b92f547f2c57fa30ad88440de41896
Author: emre brookes <ehb54 at users.noreply.github.com>
Date: 2026-08-19 (Wed, 19 Aug 2026)
Changed paths:
A .github/workflows/somo-module-tests.yml
M .gitignore
M us_somo/add_to_bin/GRPY_linux64
M us_somo/add_to_bin/GRPY_osx10.11
M us_somo/add_to_bin/GRPY_win64.exe
A us_somo/develop/grpy/README.md
A us_somo/develop/grpy/grpy_exposure.hpp
A us_somo/develop/grpy/grpy_process.hpp
A us_somo/develop/grpy/grpy_shell.hpp
A us_somo/develop/grpy/grpy_types.hpp
A us_somo/develop/grpy/tests/data/1znf.bead_model
A us_somo/develop/grpy/tests/data/1znf_golden.txt
A us_somo/develop/grpy/tests/data/dumbbell.grpy
A us_somo/develop/grpy/tests/data/dumbbell_golden.txt
A us_somo/develop/grpy/tests/run.sh
A us_somo/develop/grpy/tests/test_process.cpp
A us_somo/develop/grpy/tests/test_shell.cpp
R us_somo/develop/include/us_container_grpy.h
M us_somo/develop/include/us_hydrodyn.h
M us_somo/develop/include/us_hydrodyn_dad.h
M us_somo/develop/include/us_hydrodyn_dad_fit.h
M us_somo/develop/include/us_hydrodyn_dad_options.h
A us_somo/develop/include/us_hydrodyn_grid_volume.h
A us_somo/develop/include/us_hydrodyn_hydration.h
M us_somo/develop/include/us_hydrodyn_hydro.h
M us_somo/develop/include/us_hydrodyn_mals_fit.h
M us_somo/develop/include/us_hydrodyn_mals_options.h
M us_somo/develop/include/us_hydrodyn_mals_saxs_fit.h
M us_somo/develop/include/us_hydrodyn_mals_saxs_options.h
M us_somo/develop/include/us_hydrodyn_misc.h
M us_somo/develop/include/us_hydrodyn_pdb_parsing.h
A us_somo/develop/include/us_hydrodyn_perceive.h
A us_somo/develop/include/us_hydrodyn_perceive_dialog.h
A us_somo/develop/include/us_hydrodyn_perceive_elements.h
A us_somo/develop/include/us_hydrodyn_perceive_hybrid.h
A us_somo/develop/include/us_hydrodyn_perceive_saxs.h
A us_somo/develop/include/us_hydrodyn_perceive_somo.h
A us_somo/develop/include/us_hydrodyn_psv.h
A us_somo/develop/include/us_hydrodyn_residue_builder.h
M us_somo/develop/include/us_hydrodyn_save.h
M us_somo/develop/include/us_hydrodyn_saxs.h
M us_somo/develop/include/us_hydrodyn_saxs_hplc.h
A us_somo/develop/include/us_hydrodyn_saxs_iqq_extrap_c0_conc.h
M us_somo/develop/include/us_hydrodyn_saxs_iqq_load_csv.h
M us_somo/develop/include/us_saxs_util.h
M us_somo/develop/include/us_vector.h
M us_somo/develop/libus_somo.pro
A us_somo/develop/perceiver/.gitignore
A us_somo/develop/perceiver/DECISIONS.md
A us_somo/develop/perceiver/GUI_TESTING.md
A us_somo/develop/perceiver/Makefile
A us_somo/develop/perceiver/README.md
A us_somo/develop/perceiver/data/1ADO_noSO4.pdb
A us_somo/develop/perceiver/data/1AO6-compl_monA.pdb
A us_somo/develop/perceiver/data/1HEL.pdb
A us_somo/develop/perceiver/data/2AAS_mod1.pdb
A us_somo/develop/perceiver/data/3CRO.pdb
A us_somo/develop/perceiver/data/3GUT.pdb
A us_somo/develop/perceiver/data/6LDH1.pdb
A us_somo/develop/perceiver/data/6LYZ.pdb
A us_somo/develop/perceiver/data/8RAT.pdb
A us_somo/develop/perceiver/data/non-coded/1MBO.pdb
A us_somo/develop/perceiver/data/non-coded/2CMD.pdb
A us_somo/develop/perceiver/data/non-coded/3PTB.pdb
A us_somo/develop/perceiver/data/non-coded/5PTI.pdb
A us_somo/develop/perceiver/data/non-coded/8RATNC.pdb
A us_somo/develop/perceiver/data/non-coded/8RAT_gap3.pdb
A us_somo/develop/perceiver/data/non-coded/8RAT_run3.pdb
A us_somo/develop/perceiver/data/non-coded/README.md
A us_somo/develop/perceiver/data/psv/1BEB.pdb
A us_somo/develop/perceiver/data/psv/2CGA.pdb
A us_somo/develop/perceiver/data/psv/README.md
A us_somo/develop/perceiver/data/psv/candidates.fasta
A us_somo/develop/perceiver/data/psv_measured.txt
A us_somo/develop/perceiver/data/ref/cctbx_LICENSE.txt
A us_somo/develop/perceiver/data/ref/f0_WaasKirf.dat
A us_somo/develop/perceiver/data/ref/it1992.cpp
A us_somo/develop/perceiver/data/ref/somo.saxs_atoms.generated
A us_somo/develop/perceiver/examples/perceive.somo
A us_somo/develop/perceiver/pdb_lite.h
A us_somo/develop/perceiver/residue_oracle.h
A us_somo/develop/perceiver/run_dialog_test.sh
A us_somo/develop/perceiver/tests/builder.cpp
A us_somo/develop/perceiver/tests/coverage.cpp
A us_somo/develop/perceiver/tests/dialog_qt.cpp
A us_somo/develop/perceiver/tests/emit_residue.cpp
A us_somo/develop/perceiver/tests/grid_volume.cpp
A us_somo/develop/perceiver/tests/hydration.cpp
A us_somo/develop/perceiver/tests/protein_psv.cpp
A us_somo/develop/perceiver/tests/psv.cpp
A us_somo/develop/perceiver/tests/regression.cpp
A us_somo/develop/perceiver/tests/sssr.cpp
A us_somo/develop/perceiver/tests/sssr_real.cpp
A us_somo/develop/perceiver/tests/tests_unit.cpp
A us_somo/develop/perceiver/tinytest.h
A us_somo/develop/perceiver/tools/calibrate_3v_context.py
A us_somo/develop/perceiver/tools/gen_saxs_entries.py
A us_somo/develop/perceiver/tools/hydration_table.py
A us_somo/develop/perceiver/tools/make_noncoded_variant.py
A us_somo/develop/perceiver/tools/psv_durchschlag.py
A us_somo/develop/perceiver/tools/psv_model.py
A us_somo/develop/perceiver/tools/recalc_ligand_volumes.py
R us_somo/develop/src/us_container_grpy.cpp
M us_somo/develop/src/us_hydrodyn.cpp
M us_somo/develop/src/us_hydrodyn_beads.cpp
M us_somo/develop/src/us_hydrodyn_core.cpp
M us_somo/develop/src/us_hydrodyn_dad.cpp
M us_somo/develop/src/us_hydrodyn_dad_conc.cpp
M us_somo/develop/src/us_hydrodyn_dad_conc_load.cpp
M us_somo/develop/src/us_hydrodyn_dad_fit.cpp
M us_somo/develop/src/us_hydrodyn_dad_makeiq.cpp
M us_somo/develop/src/us_hydrodyn_dad_modes.cpp
M us_somo/develop/src/us_hydrodyn_dad_options.cpp
A us_somo/develop/src/us_hydrodyn_dad_script.cpp
M us_somo/develop/src/us_hydrodyn_dad_util.cpp
M us_somo/develop/src/us_hydrodyn_fractal_dimension.cpp
A us_somo/develop/src/us_hydrodyn_grid_volume.cpp
M us_somo/develop/src/us_hydrodyn_grpy.cpp
A us_somo/develop/src/us_hydrodyn_hydration.cpp
M us_somo/develop/src/us_hydrodyn_hydro.cpp
M us_somo/develop/src/us_hydrodyn_load.cpp
M us_somo/develop/src/us_hydrodyn_mals.cpp
M us_somo/develop/src/us_hydrodyn_mals_conc.cpp
M us_somo/develop/src/us_hydrodyn_mals_conc_load.cpp
M us_somo/develop/src/us_hydrodyn_mals_fit.cpp
M us_somo/develop/src/us_hydrodyn_mals_makeiq.cpp
M us_somo/develop/src/us_hydrodyn_mals_modes.cpp
M us_somo/develop/src/us_hydrodyn_mals_options.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_conc.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_conc_load.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_fit.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_makeiq.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_modes.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_options.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_util.cpp
M us_somo/develop/src/us_hydrodyn_mals_util.cpp
M us_somo/develop/src/us_hydrodyn_misc.cpp
M us_somo/develop/src/us_hydrodyn_other.cpp
M us_somo/develop/src/us_hydrodyn_pdb_parsing.cpp
M us_somo/develop/src/us_hydrodyn_pdb_tool.cpp
A us_somo/develop/src/us_hydrodyn_perceive.cpp
A us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
A us_somo/develop/src/us_hydrodyn_perceive_somo.cpp
A us_somo/develop/src/us_hydrodyn_psv.cpp
A us_somo/develop/src/us_hydrodyn_residue_builder.cpp
M us_somo/develop/src/us_hydrodyn_save.cpp
M us_somo/develop/src/us_hydrodyn_saxs.cpp
M us_somo/develop/src/us_hydrodyn_saxs_1d.cpp
M us_somo/develop/src/us_hydrodyn_saxs_2d.cpp
M us_somo/develop/src/us_hydrodyn_saxs_buffer.cpp
M us_somo/develop/src/us_hydrodyn_saxs_buffer_conc.cpp
M us_somo/develop/src/us_hydrodyn_saxs_buffer_conc_load.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_bl.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_ciq.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_conc.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_conc_load.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_gui.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_makeiq.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_modes.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_options.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_util.cpp
M us_somo/develop/src/us_hydrodyn_saxs_iqq.cpp
A us_somo/develop/src/us_hydrodyn_saxs_iqq_extrap_c0.cpp
A us_somo/develop/src/us_hydrodyn_saxs_iqq_extrap_c0_conc.cpp
M us_somo/develop/src/us_hydrodyn_saxs_iqq_load_csv.cpp
M us_somo/develop/src/us_hydrodyn_saxs_loads.cpp
M us_somo/develop/src/us_hydrodyn_script.cpp
M us_somo/develop/src/us_hydrodyn_settings.cpp
M us_somo/develop/src/us_hydrodyn_write.cpp
M us_somo/develop/src/us_saxs_util_best.cpp
M us_somo/develop/src/us_saxs_util_dmd.cpp
M us_somo/develop/src/us_saxs_util_hydro.cpp
M us_somo/develop/src/us_saxs_util_loads.cpp
M us_somo/develop/src/us_saxs_util_static.cpp
M us_somo/develop/src/us_vector.cpp
M us_somo/develop/version.sh
M us_somo/etc/somo.atom.new
M us_somo/etc/somo.config.new
M us_somo/etc/somo.defaults.new
M us_somo/etc/somo.hybrid.new
M us_somo/etc/somo.residue.new
M us_somo/etc/somo.saxs_atoms.new
A us_somo/somo/doc/manual/somo/DAWN_head.png
A us_somo/somo/doc/manual/somo/MALS_angles.png
A us_somo/somo/doc/manual/somo/WyattRayleigh ratios csv.png
M us_somo/somo/doc/manual/somo/mals_parameters.html
M us_somo/somo/doc/manual/somo/mals_saxs_options.html
M us_somo/somo/doc/manual/somo/saxs_hplc_ciq.html
M us_somo/somo/doc/manual/somo/saxs_hplc_options.html
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_EMG_option.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_GaussFit1.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_GaussFit2.png
A us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_options_Min_Gauss.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_options_new.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_options_new_Gaussians.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_options_new_baseline.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian1.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian11.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian11a.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian11b.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian11c.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian12.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian2.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian3.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian4.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian5.png
A us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian6a.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian8.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian9a.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian_adv_sel.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_smoothing.png
A us_somo/somo/doc/manual/somo/somo-MALS_Concs.png
A us_somo/somo/doc/manual/somo/somo-MALS_Concs2.png
A us_somo/somo/doc/manual/somo/somo-MALS_Concs3.png
A us_somo/somo/doc/manual/somo/somo-MALS_Concs4.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss1anew.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss1bnew.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss1cnew.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss1dnew.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss1enew.png
A us_somo/somo/doc/manual/somo/somo-MALS_GaussFit.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss_all_Idash_t_selected.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gaussian_final.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gaussian_init.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gaussian_options.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gaussian_start.png
A us_somo/somo/doc/manual/somo/somo-MALS_GlobalFit_done.png
A us_somo/somo/doc/manual/somo/somo-MALS_GlobalGauss_done.png
A us_somo/somo/doc/manual/somo/somo-MALS_GlobalGauss_start_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_GlobalGaussianSDreminder.png
A us_somo/somo/doc/manual/somo/somo-MALS_GlobalGaussian_init.png
A us_somo/somo/doc/manual/somo/somo-MALS_I_hash_q_example.png
A us_somo/somo/doc/manual/somo/somo-MALS_I_starq_NoGauss_movieframe155.png
A us_somo/somo/doc/manual/somo/somo-MALS_I_starq_NoGauss_movieframe316.png
A us_somo/somo/doc/manual/somo/somo-MALS_I_starq_NoGauss_movieframe99.png
A us_somo/somo/doc/manual/somo/somo-MALS_Istarq_file_view_selected.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIdash_final.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIdash_final_kin.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIdash_final_kin_cropped.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIdash_final_kin_zoom.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIstar_final_kin.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIstar_sel_kin_dots_err.png
A us_somo/somo/doc/manual/somo/somo-MALS_Messages.png
A us_somo/somo/doc/manual/somo/somo-MALS_Movie_selected.png
A us_somo/somo/doc/manual/somo/somo-MALS_Plot_Options_demo.png
A us_somo/somo/doc/manual/somo/somo-MALS_Produced_data.png
A us_somo/somo/doc/manual/somo/somo-MALS_R_theta_csv_loaded.png
A us_somo/somo/doc/manual/somo/somo-MALS_R_theta_kin_shown.png
A us_somo/somo/doc/manual/somo/somo-MALS_R_theta_shown.png
A us_somo/somo/doc/manual/somo/somo-MALS_Residuals_twocurvesSD.png
A us_somo/somo/doc/manual/somo/somo-MALS_Residuals_twocurves_percent.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_MALS_data_loglog.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Make_scaled_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Messages.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Plot_Options_demo.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Plot_Options_demo2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Produced_data.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Produced_data_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_SAXS_common_times.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_SAXS_common_times_scroll1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_SAXS_common_times_scroll2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_SAXS_data_loading.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_bottom line.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_commons times_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_commontimes_all_dots.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_cropping_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_cropvis_results.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_cropvis_results1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_cropvis_select.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_exclude_q_vis_demo1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_exclude_q_vis_demo2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_fitting_methods.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_generating_joined_excl_q_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_initial.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_joined.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_joined_scroll.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_loadMALS.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_make_scaled.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_make_scaled_popup1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_make_scaled_popup2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_make_scaled_view_MALS_file.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_minimize_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_options.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_options1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_other_MALS_data_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_plot_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_polynomials.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_q_exclude_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_remove_panel.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale3.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale4.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale5.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale6.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale7.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale8.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scaled_MALS_generated_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scaled_SAXS_generated_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scroll_warning.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_second_set_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_second_set_buttons1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_selections_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_top_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_viewselected.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_weighting_methods.png
A us_somo/somo/doc/manual/somo/somo-MALS_SD_eval_applied.png
A us_somo/somo/doc/manual/somo/somo-MALS_SD_eval_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SD_eval_comparisonD2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SD_eval_define_1region.png
A us_somo/somo/doc/manual/somo/somo-MALS_SD_eval_define_2regions.png
A us_somo/somo/doc/manual/somo/somo-MALS_Select_Istarq_for_norm.png
A us_somo/somo/doc/manual/somo/somo-MALS_Selected_Istarq_normalized.png
A us_somo/somo/doc/manual/somo/somo-MALS_Selected_Istarq_normalized_ave.png
A us_somo/somo/doc/manual/somo/somo-MALS_Selected_normalized_ave.png
A us_somo/somo/doc/manual/somo/somo-MALS_Selected_orig_and_norm_files.png
A us_somo/somo/doc/manual/somo/somo-MALS_UV_data_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_adjust_times_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_adjust_times_pop_up2.png
A us_somo/somo/doc/manual/somo/somo-MALS_angles_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_commands1.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_chrom_Gauss_fit.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_chrom_fit_module.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_chrom_init_Gauss.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_used_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_add_MALS_data.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_loaded_data.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_pop_up2.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_pop_up3.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_repeak.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_timeshift.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_timeshift_set.png
A us_somo/somo/doc/manual/somo/somo-MALS_crop_I_dash_chromatograms.png
A us_somo/somo/doc/manual/somo/somo-MALS_cropping_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_inconsistent times_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_incorrect processing_param_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_info_panel.png
A us_somo/somo/doc/manual/somo/somo-MALS_initial.png
A us_somo/somo/doc/manual/somo/somo-MALS_main1.png
A us_somo/somo/doc/manual/somo/somo-MALS_make_Istar_q_enterparam_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_make_Istar_q_enterparam_popup1.png
A us_somo/somo/doc/manual/somo/somo-MALS_make_Istar_q_noGauss_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_no_Gaussians_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_no_conc_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_no_conc_pop_up2.png
A us_somo/somo/doc/manual/somo/somo-MALS_options.png
A us_somo/somo/doc/manual/somo/somo-MALS_options_conc_detector.png
A us_somo/somo/doc/manual/somo/somo-MALS_options_new_Gaussians.png
A us_somo/somo/doc/manual/somo/somo-MALS_options_new_misc.png
A us_somo/somo/doc/manual/somo/somo-MALS_param.png
A us_somo/somo/doc/manual/somo/somo-MALS_plot_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_processing_param_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_processing_param_pop_up2.png
A us_somo/somo/doc/manual/somo/somo-MALS_remove_panel.png
A us_somo/somo/doc/manual/somo/somo-MALS_resulting_I_starq_NoGauss.png
A us_somo/somo/doc/manual/somo/somo-MALS_scattering_angles.png
A us_somo/somo/doc/manual/somo/somo-MALS_second_set_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_selected_Ihash_EMG_GMG.png
A us_somo/somo/doc/manual/somo/somo-MALS_selections_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_set_conc_detector.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians1.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians2.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_GlobFit_Final.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_GlobFit_Init.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_GlobFit_by_q.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_GlobFit_saving_warning.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_GlobGauss.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_scroll1.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_scroll2.png
A us_somo/somo/doc/manual/somo/somo-MALS_six_Gaussians1.png
A us_somo/somo/doc/manual/somo/somo-MALS_six_Gaussians2.png
A us_somo/somo/doc/manual/somo/somo-MALS_timeshift_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_timeshift_pop_up2.png
A us_somo/somo/doc/manual/somo/somo-MALS_top_buttons.png
A us_somo/somo/doc/manual/somo/somo-mals_Residuals_twocurves.png
A us_somo/somo/doc/manual/somo/somo-perceive.png
M us_somo/somo/doc/manual/somo/somo.html
M us_somo/somo/doc/manual/somo/somo_hydro.html
A us_somo/somo/doc/manual/somo/somo_hydro_shell_reduction.html
M us_somo/somo/doc/manual/somo/somo_mals.html
A us_somo/somo/doc/manual/somo/somo_mals_dctr.html
A us_somo/somo/doc/manual/somo/somo_mals_options.html
M us_somo/somo/doc/manual/somo/somo_mals_saxs.html
M us_somo/somo/doc/manual/somo/somo_misc.html
M us_somo/somo/doc/manual/somo/somo_pdb_parsing.html
M us_somo/somo/doc/manual/somo/somo_pdb_parsing_expert_mode.html
A us_somo/somo/doc/manual/somo/somo_perceive.html
M us_somo/somo/doc/manual/somo/somo_save.html
M us_somo/somo/doc/manual/somo/somo_saxs_hplc.html
M us_somo/somo/doc/manual/somo/somo_saxs_hplc_skewedGauss.html
M us_somo/somo/doc/manual/somo/somo_uv_vis.html
A us_somo/somo/doc/manual/somo_mals.html
Log Message:
-----------
Merge branch 'main' into 875-request-cmake-remove-gmp-module-from-installer-for-osx
Commit: c32962f2eaf66f7230830f436e0fdb491e8ad9a8
https://github.com/ehb54/ultrascan3/commit/c32962f2eaf66f7230830f436e0fdb491e8ad9a8
Author: Lukas Dobler <69309597+doluk at users.noreply.github.com>
Date: 2026-08-19 (Wed, 19 Aug 2026)
Changed paths:
M gui/us_plot.cpp
M gui/us_plot.h
M gui/us_solution_gui.cpp
M gui/us_theme.cpp
M gui/us_theme.h
M gui/us_widgets.cpp
M gui/us_widgets_dialog.cpp
M programs/us_config/us_color.cpp
Log Message:
-----------
Fix theme edge cases
Commit: b79db6ebbbcc6df95babf034d1f7372ec746c623
https://github.com/ehb54/ultrascan3/commit/b79db6ebbbcc6df95babf034d1f7372ec746c623
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-19 (Wed, 19 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_perceive_dialog.h
Log Message:
-----------
Fix Windows/MinGW build: std::byte vs rpcndr.h byte ambiguity
moc_us_hydrodyn_perceive_dialog.cpp failed to compile under MSYS2/MinGW64
with ~40 "reference to byte is ambiguous" errors from the Win32 SDK headers.
us_hydrodyn_perceive_somo.h reaches us_hydrodyn_pdbdefs.h, whose
"using namespace std;" makes std::byte visible unqualified. us_util.h then
pulls in windows.h via us.h -> QtWidgets -> qopengl.h -> qt_windows.h, and
rpcndr.h typedefs a global "byte", so every subsequent use is ambiguous.
Including us_util.h first parses windows.h before the using-directive is in
scope, which is the order every other SOMO header already follows (see
us_hydrodyn.h, us.h at line 29 ahead of us_hydrodyn_pdbdefs.h at line 35).
The .cpp was unaffected because it includes us3_defines.h first; only the moc
translation unit, which includes the header bare, hit the error.
Ref ehb54/ultrascan-tickets#1022
Co-Authored-By: Claude Opus 5 <noreply at anthropic.com>
Commit: e235c2d5b3f5800f7831622b920971a1e5dfcc0a
https://github.com/ehb54/ultrascan3/commit/e235c2d5b3f5800f7831622b920971a1e5dfcc0a
Author: emre brookes <ehb54 at users.noreply.github.com>
Date: 2026-08-19 (Wed, 19 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_perceive_dialog.h
Log Message:
-----------
Merge pull request #529 from ehb54/ehb54-issue-1022
Fix Windows/MinGW build: std::byte vs rpcndr.h byte ambiguity in perceive dialog header
Commit: 541ee619eefc3ce6c914f427300b34e325e1b9bb
https://github.com/ehb54/ultrascan3/commit/541ee619eefc3ce6c914f427300b34e325e1b9bb
Author: Lukas Dobler <69309597+doluk at users.noreply.github.com>
Date: 2026-08-19 (Wed, 19 Aug 2026)
Changed paths:
M us_somo/develop/include/us_hydrodyn_perceive_dialog.h
Log Message:
-----------
Merge branch 'main' into lukas/theme-fixes
Commit: c6a60ed2b23dfa8ae71808dca2f60bf724bba514
https://github.com/ehb54/ultrascan3/commit/c6a60ed2b23dfa8ae71808dca2f60bf724bba514
Author: alexsav815 <alexsav.science at gmail.com>
Date: 2026-08-19 (Wed, 19 Aug 2026)
Changed paths:
M programs/us_experiment/us_experiment_gui_optima.cpp
Log Message:
-----------
GMP | R&D: 1. EXP.: Speeds -- align time widgets...
Commit: ebd251ac84ba1fdb734b8d72ac3bac37e6d6c433
https://github.com/ehb54/ultrascan3/commit/ebd251ac84ba1fdb734b8d72ac3bac37e6d6c433
Author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Date: 2026-08-19 (Wed, 19 Aug 2026)
Changed paths:
M VERSION
M utils/us_defines.h
Log Message:
-----------
Bump version to 4.2.0
Commit: c3af75e5474aa48d83525e0131866f61357ca870
https://github.com/ehb54/ultrascan3/commit/c3af75e5474aa48d83525e0131866f61357ca870
Author: aaron-auc <95181880+aaron-auc at users.noreply.github.com>
Date: 2026-08-19 (Wed, 19 Aug 2026)
Changed paths:
M doc/manual/source/conf.py
Log Message:
-----------
Update docs version to v4.2.0 in conf.py
Commit: b6fe806f04bd4ffa22a2ea0d3a338b5a2ca208e0
https://github.com/ehb54/ultrascan3/commit/b6fe806f04bd4ffa22a2ea0d3a338b5a2ca208e0
Author: Lukas Dobler <69309597+doluk at users.noreply.github.com>
Date: 2026-08-19 (Wed, 19 Aug 2026)
Changed paths:
M gui/us_plot.cpp
M gui/us_plot.h
M gui/us_solution_gui.cpp
M gui/us_theme.cpp
M gui/us_theme.h
M gui/us_widgets.cpp
M gui/us_widgets_dialog.cpp
M programs/us_config/us_color.cpp
Log Message:
-----------
Merge pull request #528 from ehb54/lukas/theme-fixes
Fix theme edge cases
Commit: 03df6a27c1dcfd2740fa58f3bc38da61ec94f407
https://github.com/ehb54/ultrascan3/commit/03df6a27c1dcfd2740fa58f3bc38da61ec94f407
Author: aaron-auc <95181880+aaron-auc at users.noreply.github.com>
Date: 2026-08-19 (Wed, 19 Aug 2026)
Changed paths:
M gui/us_plot.cpp
M gui/us_plot.h
M gui/us_solution_gui.cpp
M gui/us_theme.cpp
M gui/us_theme.h
M gui/us_widgets.cpp
M gui/us_widgets_dialog.cpp
M programs/us_config/us_color.cpp
Log Message:
-----------
Merge branch 'main' into bump-to-v4.2.0
Commit: 6d9a1a1e6df5f257919824974de23c3f26ab0a6f
https://github.com/ehb54/ultrascan3/commit/6d9a1a1e6df5f257919824974de23c3f26ab0a6f
Author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Date: 2026-08-19 (Wed, 19 Aug 2026)
Changed paths:
M VERSION
M utils/us_defines.h
Log Message:
-----------
Bump version to 4.3.0-dev
Commit: 9887a93993076263fc434ca7610e1fe94096aec5
https://github.com/ehb54/ultrascan3/commit/9887a93993076263fc434ca7610e1fe94096aec5
Author: emre brookes <ehb54 at users.noreply.github.com>
Date: 2026-08-19 (Wed, 19 Aug 2026)
Changed paths:
M VERSION
M doc/manual/source/conf.py
M utils/us_defines.h
Log Message:
-----------
Merge pull request #531 from ehb54/bump-to-v4.2.0
Bump to v4.2.0
Commit: d6c7fbd12aab697c443183f00b8f48d4af54aae8
https://github.com/ehb54/ultrascan3/commit/d6c7fbd12aab697c443183f00b8f48d4af54aae8
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-08-20 (Thu, 20 Aug 2026)
Changed paths:
M gui.pri
Log Message:
-----------
Define US_MAKE_DLL and QWT_DLL for Windows application builds
Applications include gui.pri, which never defined US_MAKE_DLL, so
us_extern.h fell through its Windows branch and expanded US_GUI_EXTERN
and US_UTIL_EXTERN to a GCC visibility attribute instead of
__declspec(dllimport). qwt_global.h leaves QWT_EXPORT empty on the same
terms, and only libus_gui.pro defined QWT_DLL.
Without the import attribute MinGW resolves the library classes through
import thunks linked into the executable, so taking the address of a
signal in an application translation unit yields the thunk rather than
the function the library holds. The pointer-to-member form of connect()
matches signals by that address, so every such connection silently
failed to bind on Windows while the string based SIGNAL/SLOT form, which
matches by name, was unaffected.
This surfaced as the meniscus control-click and the scan exclusion click
doing nothing in us_edit on the Windows package. The CMake build
already defines both for every application target, which is why builds
made through the presets were never affected.
Commit: 9e358c8bba18a8ccba5b44c40ed4d869c8e69c27
https://github.com/ehb54/ultrascan3/commit/9e358c8bba18a8ccba5b44c40ed4d869c8e69c27
Author: emre brookes <ehb54 at users.noreply.github.com>
Date: 2026-08-20 (Thu, 20 Aug 2026)
Changed paths:
M gui.pri
Log Message:
-----------
Merge pull request #533 from ehb54/ehb54-qmake-win-dllimport
Fix Windows application builds losing dllimport for us_gui, us_utils and qwt
Commit: f73ffab665d1015d137908badc7e64212136eebd
https://github.com/ehb54/ultrascan3/commit/f73ffab665d1015d137908badc7e64212136eebd
Author: alexsav815 <alexsav.science at gmail.com>
Date: 2026-08-20 (Thu, 20 Aug 2026)
Changed paths:
M VERSION
M doc/manual/source/conf.py
M gui.pri
M gui/us_plot.cpp
M gui/us_plot.h
M gui/us_solution_gui.cpp
M gui/us_theme.cpp
M gui/us_theme.h
M gui/us_widgets.cpp
M gui/us_widgets_dialog.cpp
M programs/us_config/us_color.cpp
M utils/us_defines.h
Log Message:
-----------
Merge branch 'main' into alexey-dev-issue1020
Commit: b9bb346987fe0adee3ebccbc8a10a60e2928becd
https://github.com/ehb54/ultrascan3/commit/b9bb346987fe0adee3ebccbc8a10a60e2928becd
Author: alexsav815 <alexsav.science at gmail.com>
Date: 2026-08-20 (Thu, 20 Aug 2026)
Changed paths:
M programs/us_experiment/us_experiment_gui_optima.cpp
Log Message:
-----------
Merge pull request #530 from ehb54/alexey-dev-issue1020
GMP | R&D: 1. EXP.: Speeds -- align time widgets...
Commit: 619ea38f136aec298a9ae6eb788febf322579889
https://github.com/ehb54/ultrascan3/commit/619ea38f136aec298a9ae6eb788febf322579889
Author: aaron-auc <95181880+aaron-auc at users.noreply.github.com>
Date: 2026-08-23 (Sun, 23 Aug 2026)
Changed paths:
M doc/manual/source/conf.py
M gui.pri
M programs/us_experiment/us_experiment_gui_optima.cpp
Log Message:
-----------
Merge branch 'main' into bump-to-v4.3.0-dev
Commit: 5d67a0aa5e8dc6ddefabb6c3ff80a3ad51aa9001
https://github.com/ehb54/ultrascan3/commit/5d67a0aa5e8dc6ddefabb6c3ff80a3ad51aa9001
Author: aaron-auc <95181880+aaron-auc at users.noreply.github.com>
Date: 2026-08-23 (Sun, 23 Aug 2026)
Changed paths:
M VERSION
M utils/us_defines.h
Log Message:
-----------
Merge pull request #532 from ehb54/bump-to-v4.3.0-dev
Bump to v4.3.0-dev
Commit: 0528228ee80ceba80429b97a74c2bcc2a42e8ce3
https://github.com/ehb54/ultrascan3/commit/0528228ee80ceba80429b97a74c2bcc2a42e8ce3
Author: aaron-auc <95181880+aaron-auc at users.noreply.github.com>
Date: 2026-09-02 (Wed, 02 Sep 2026)
Changed paths:
M VERSION
M doc/manual/source/conf.py
M gui.pri
M gui/us_plot.cpp
M gui/us_plot.h
M gui/us_solution_gui.cpp
M gui/us_theme.cpp
M gui/us_theme.h
M gui/us_widgets.cpp
M gui/us_widgets_dialog.cpp
M programs/us_config/us_color.cpp
M programs/us_experiment/us_experiment_gui_optima.cpp
M us_somo/develop/include/us_hydrodyn_perceive_dialog.h
M utils/us_defines.h
Log Message:
-----------
Merge branch 'main' into 875-request-cmake-remove-gmp-module-from-installer-for-osx
Commit: 6ccb5e00af0f0ae7f1ed8414c4e2f5719d5e7fad
https://github.com/ehb54/ultrascan3/commit/6ccb5e00af0f0ae7f1ed8414c4e2f5719d5e7fad
Author: aaron-auc <95181880+aaron-auc at users.noreply.github.com>
Date: 2026-09-02 (Wed, 02 Sep 2026)
Changed paths:
M admin/cmake/packaging/macos/MacDeploy.cmake
M admin/cmake/packaging/macos/MacHpcDeploy.cmake
M doc/manual/source/start_page-new.rst
M pkg/macos/README.md
M pkg/macos/preinstall
M programs/CMakeLists.txt
Log Message:
-----------
Merge pull request #473 from ehb54/875-request-cmake-remove-gmp-module-from-installer-for-osx
Exclude GMP tools from macOS installer build
Commit: 1b4c2e4650bbca66bd1f764df235dd5fde75b80f
https://github.com/ehb54/ultrascan3/commit/1b4c2e4650bbca66bd1f764df235dd5fde75b80f
Author: alexsav815 <alexsav.science at gmail.com>
Date: 2026-09-02 (Wed, 02 Sep 2026)
Changed paths:
A .github/workflows/somo-module-tests.yml
M .gitignore
M CMakePresets.json
M VERSION
M admin/cmake/packaging/macos/MacDeploy.cmake
M admin/cmake/packaging/macos/MacHpcDeploy.cmake
M doc/manual/source/conf.py
M doc/manual/source/config.rst
M doc/manual/source/start_page-new.rst
M gui.pri
M gui/libus_gui.pro
M gui/us_abstractrotor_gui.cpp
M gui/us_analysis_base2.h
M gui/us_analyte_gui.cpp
M gui/us_associations_gui.cpp
M gui/us_associations_gui.h
M gui/us_buffer_gui.cpp
M gui/us_choice.cpp
M gui/us_combined_plots_parms_gui.cpp
M gui/us_convert_gui.cpp
M gui/us_convert_gui.h
M gui/us_data_loader.cpp
M gui/us_edit_spectrum.cpp
M gui/us_editor.cpp
M gui/us_experiment_gui.cpp
M gui/us_extinctfitter_gui.cpp
M gui/us_extinction_gui.cpp
M gui/us_failed_gmp_run_gui.cpp
M gui/us_get_run.cpp
M gui/us_gui_settings.cpp
M gui/us_gui_settings.h
M gui/us_intensity.cpp
M gui/us_investigator.cpp
M gui/us_license.cpp
M gui/us_load_auc.cpp
M gui/us_minimize.cpp
M gui/us_model_gui.cpp
M gui/us_model_loader.cpp
M gui/us_new_spectrum.cpp
M gui/us_noise_loader.cpp
M gui/us_passwd.cpp
M gui/us_plot.cpp
M gui/us_plot.h
M gui/us_plot3d.cpp
M gui/us_predict1.cpp
M gui/us_predict1.h
M gui/us_project_gui.cpp
M gui/us_properties.cpp
M gui/us_properties.h
M gui/us_report_general_gui.cpp
M gui/us_report_gui.cpp
M gui/us_rotor_gui.cpp
M gui/us_run_details2.cpp
M gui/us_sassoc.cpp
M gui/us_sassoc.h
M gui/us_scan_excl_gui.cpp
M gui/us_select_edits.cpp
M gui/us_select_item.cpp
M gui/us_select_runs.cpp
M gui/us_select_triples.cpp
M gui/us_sim_params_gui.cpp
M gui/us_solution_gui.cpp
A gui/us_style.cpp
A gui/us_style.h
M gui/us_table.cpp
A gui/us_theme.cpp
A gui/us_theme.h
M gui/us_tmst_plot.cpp
M gui/us_widgets.cpp
M gui/us_widgets.h
M gui/us_widgets_dialog.cpp
M pkg/macos/README.md
M pkg/macos/preinstall
M programs/CMakeLists.txt
M programs/us/us.cpp
M programs/us_2dplot/us_2dplot.cpp
M programs/us_2dsa/us_2dsa.cpp
M programs/us_2dsa/us_2dsa_process.cpp
M programs/us_2dsa/us_adv_analysis_2d.cpp
M programs/us_2dsa/us_analysis_control_2d.cpp
M programs/us_2dsa/us_plot_control_2d.cpp
M programs/us_2dsa/us_resplot_2d.cpp
M programs/us_2dsa/us_show_norm.cpp
M programs/us_2dsa/us_show_norm.h
M programs/us_2dsa/us_worker_2d.cpp
M programs/us_abde/us_abde_main.cpp
M programs/us_abde/us_norm_profile.cpp
M programs/us_abde/us_norm_profile.h
M programs/us_analysis_profile/us_analysis_profile.cpp
M programs/us_astfem_sim/us_astfem_sim.cpp
M programs/us_astfem_sim/us_clipdata.cpp
M programs/us_audit_trail_gmp/us_audit_trail_gmp.cpp
M programs/us_autoflow_analysis/us_autoflow_analysis.cpp
M programs/us_autoflow_analysis/us_autoflow_analysis.h
M programs/us_buoyancy/us_buoyancy.cpp
M programs/us_colorgradient/us_colorgradient.cpp
M programs/us_com_project/us_com_project_gui.cpp
M programs/us_com_project/us_com_project_gui.h
M programs/us_combine_models/us_combine_models.cpp
M programs/us_config/us_admin.cpp
M programs/us_config/us_advanced.cpp
M programs/us_config/us_color.cpp
M programs/us_config/us_color.h
M programs/us_config/us_config.cpp
M programs/us_config/us_database.cpp
M programs/us_config/us_font.cpp
M programs/us_config/us_newxpnhost_db.cpp
M programs/us_config/us_xpnhost.cpp
M programs/us_config/us_xpnhost_db.cpp
M programs/us_ddist_combine/us_ddist_combine.cpp
M programs/us_ddist_combine/us_select_rundd.cpp
M programs/us_density_match/us_density_match.cpp
M programs/us_density_match/us_model_params.cpp
M programs/us_density_match/us_remove_models.cpp
M programs/us_dmga_init/us_constraints_edit.cpp
M programs/us_dmga_init/us_dmga_init.cpp
M programs/us_edit/us_edit.cpp
M programs/us_edit/us_edit.h
M programs/us_edit/us_edit_scan.cpp
M programs/us_edit/us_exclude_profile.cpp
M programs/us_edit/us_get_edit.cpp
M programs/us_edit/us_ri_noise.cpp
M programs/us_edit/us_select_lambdas.cpp
M programs/us_equiltime/us_equiltime.cpp
M programs/us_esigner_gmp/us_esigner_gmp.cpp
M programs/us_esigner_gmp/us_esigner_gmp.h
M programs/us_experiment/us_exp_utils.cpp
M programs/us_experiment/us_experiment_gui_optima.cpp
M programs/us_experiment/us_proto_ranges.cpp
M programs/us_export_legacy/us_export.cpp
M programs/us_fds_filemanager/us_fds_filemanager.cpp
M programs/us_fematch/us_adv_dmgamc.cpp
M programs/us_fematch/us_advanced_fem.cpp
M programs/us_fematch/us_fematch.cpp
M programs/us_fematch/us_plot_control_fem.cpp
M programs/us_fematch/us_resplot_fem.cpp
M programs/us_fematch/us_thread_worker.cpp
M programs/us_fit_meniscus/us_fit_meniscus.cpp
M programs/us_ga_init/us_ga_init.cpp
M programs/us_globalequil/us_eqfit_control.cpp
M programs/us_globalequil/us_eqmodel_control.cpp
M programs/us_globalequil/us_globalequil.cpp
M programs/us_globalequil/us_long_messagebox.cpp
M programs/us_globalequil/us_model_adpars.cpp
M programs/us_globalequil/us_model_select.cpp
M programs/us_grid_editor/us_grid_editor.cpp
M programs/us_helpdaemon/us_helpdaemon.cpp
M programs/us_integral/us_delete_models.cpp
M programs/us_integral/us_integral.cpp
M programs/us_manage_data/us_data_tree.cpp
M programs/us_manage_data/us_manage_data.cpp
M programs/us_modelmetrics/us_modelmetrics.cpp
M programs/us_mwl_species_fit/us_mwl_sf_plot3d.cpp
M programs/us_mwl_species_fit/us_mwl_species_fit.cpp
M programs/us_mwl_species_sim/us_mwl_species_sim.cpp
M programs/us_mwl_spectra/us_mwl_spectra.cpp
M programs/us_mwl_spectra/us_mwls_pltctl.cpp
M programs/us_mwlr_viewer/us_mwl_pltctrl.cpp
M programs/us_mwlr_viewer/us_mwl_run.cpp
M programs/us_mwlr_viewer/us_mwlr_viewer.cpp
M programs/us_pcsa/us_adv_analysis_pc.cpp
M programs/us_pcsa/us_adv_analysis_pc.h
M programs/us_pcsa/us_analysis_control_pc.cpp
M programs/us_pcsa/us_mlplot.cpp
M programs/us_pcsa/us_mrecs_loader.cpp
M programs/us_pcsa/us_pcsa_process.cpp
M programs/us_pcsa/us_plot_control_pc.cpp
M programs/us_pcsa/us_resplot_pc.cpp
M programs/us_pcsa/us_rpscan.cpp
M programs/us_predict2/us_predict2.cpp
M programs/us_protocol_dev/us_protocol_dev_gui.cpp
M programs/us_protocol_dev/us_protocol_dev_gui.h
M programs/us_pseudo3d_combine/us_remove_distros.cpp
M programs/us_pseudo_absorbance/us_add_refScan.cpp
M programs/us_pseudo_absorbance/us_convert_scan.cpp
M programs/us_pseudo_absorbance/us_pseudo_absorbance.cpp
M programs/us_pseudo_absorbance/us_remove_ri.cpp
M programs/us_query_rmsd/us_query_rmsd.cpp
M programs/us_ramp/us_experiment_gui_ra.cpp
M programs/us_ramp/us_get_dbrun_ra.cpp
M programs/us_ramp/us_intensity_ra.cpp
M programs/us_ramp/us_ramp_gui.cpp
M programs/us_ramp/us_select_triples_ra.cpp
M programs/us_reporter/us_reporter.cpp
M programs/us_reporter/us_sync_db.cpp
M programs/us_reporter_gmp/us_reporter_gmp.cpp
M programs/us_reporter_gmp/us_reporter_gmp.h
M programs/us_rotor_calibration/us_get_dbexp.cpp
M programs/us_rotor_calibration/us_rotor_calibration.cpp
M programs/us_second_moment/us_second_moment.cpp
M programs/us_spectrum/us_spectrum.cpp
M programs/us_tmst_viewer/us_tmst_viewer.cpp
M programs/us_vhw_combine/us_select_runid.cpp
M programs/us_vhw_combine/us_vhw_combine.cpp
M programs/us_vhw_combine/us_vhwc_pltctl.cpp
M programs/us_vhw_enhanced/us_distrib_plot.cpp
M programs/us_vhw_enhanced/us_vhw_enhanced.cpp
M programs/us_xpn_viewer/us_xpn_run_auc.cpp
M programs/us_xpn_viewer/us_xpn_run_raw.cpp
M programs/us_xpn_viewer/us_xpn_viewer_gui.cpp
M programs/us_xpn_viewer/us_xpn_viewer_gui.h
M scripts/build.ps1
M us_somo/add_to_bin/GRPY_linux64
M us_somo/add_to_bin/GRPY_osx10.11
M us_somo/add_to_bin/GRPY_win64.exe
A us_somo/develop/grpy/README.md
A us_somo/develop/grpy/grpy_exposure.hpp
A us_somo/develop/grpy/grpy_process.hpp
A us_somo/develop/grpy/grpy_shell.hpp
A us_somo/develop/grpy/grpy_types.hpp
A us_somo/develop/grpy/tests/data/1znf.bead_model
A us_somo/develop/grpy/tests/data/1znf_golden.txt
A us_somo/develop/grpy/tests/data/dumbbell.grpy
A us_somo/develop/grpy/tests/data/dumbbell_golden.txt
A us_somo/develop/grpy/tests/run.sh
A us_somo/develop/grpy/tests/test_process.cpp
A us_somo/develop/grpy/tests/test_shell.cpp
R us_somo/develop/include/us_container_grpy.h
M us_somo/develop/include/us_hydrodyn.h
M us_somo/develop/include/us_hydrodyn_dad.h
M us_somo/develop/include/us_hydrodyn_dad_fit.h
M us_somo/develop/include/us_hydrodyn_dad_options.h
A us_somo/develop/include/us_hydrodyn_grid_volume.h
A us_somo/develop/include/us_hydrodyn_hydration.h
M us_somo/develop/include/us_hydrodyn_hydro.h
M us_somo/develop/include/us_hydrodyn_mals_fit.h
M us_somo/develop/include/us_hydrodyn_mals_options.h
M us_somo/develop/include/us_hydrodyn_mals_saxs_fit.h
M us_somo/develop/include/us_hydrodyn_mals_saxs_options.h
M us_somo/develop/include/us_hydrodyn_misc.h
M us_somo/develop/include/us_hydrodyn_pdb_parsing.h
A us_somo/develop/include/us_hydrodyn_perceive.h
A us_somo/develop/include/us_hydrodyn_perceive_dialog.h
A us_somo/develop/include/us_hydrodyn_perceive_elements.h
A us_somo/develop/include/us_hydrodyn_perceive_hybrid.h
A us_somo/develop/include/us_hydrodyn_perceive_saxs.h
A us_somo/develop/include/us_hydrodyn_perceive_somo.h
A us_somo/develop/include/us_hydrodyn_psv.h
A us_somo/develop/include/us_hydrodyn_residue_builder.h
M us_somo/develop/include/us_hydrodyn_save.h
M us_somo/develop/include/us_hydrodyn_saxs.h
M us_somo/develop/include/us_hydrodyn_saxs_hplc.h
A us_somo/develop/include/us_hydrodyn_saxs_iqq_extrap_c0_conc.h
M us_somo/develop/include/us_hydrodyn_saxs_iqq_load_csv.h
M us_somo/develop/include/us_saxs_util.h
M us_somo/develop/include/us_vector.h
M us_somo/develop/libus_somo.pro
A us_somo/develop/perceiver/.gitignore
A us_somo/develop/perceiver/DECISIONS.md
A us_somo/develop/perceiver/GUI_TESTING.md
A us_somo/develop/perceiver/Makefile
A us_somo/develop/perceiver/README.md
A us_somo/develop/perceiver/data/1ADO_noSO4.pdb
A us_somo/develop/perceiver/data/1AO6-compl_monA.pdb
A us_somo/develop/perceiver/data/1HEL.pdb
A us_somo/develop/perceiver/data/2AAS_mod1.pdb
A us_somo/develop/perceiver/data/3CRO.pdb
A us_somo/develop/perceiver/data/3GUT.pdb
A us_somo/develop/perceiver/data/6LDH1.pdb
A us_somo/develop/perceiver/data/6LYZ.pdb
A us_somo/develop/perceiver/data/8RAT.pdb
A us_somo/develop/perceiver/data/non-coded/1MBO.pdb
A us_somo/develop/perceiver/data/non-coded/2CMD.pdb
A us_somo/develop/perceiver/data/non-coded/3PTB.pdb
A us_somo/develop/perceiver/data/non-coded/5PTI.pdb
A us_somo/develop/perceiver/data/non-coded/8RATNC.pdb
A us_somo/develop/perceiver/data/non-coded/8RAT_gap3.pdb
A us_somo/develop/perceiver/data/non-coded/8RAT_run3.pdb
A us_somo/develop/perceiver/data/non-coded/README.md
A us_somo/develop/perceiver/data/psv/1BEB.pdb
A us_somo/develop/perceiver/data/psv/2CGA.pdb
A us_somo/develop/perceiver/data/psv/README.md
A us_somo/develop/perceiver/data/psv/candidates.fasta
A us_somo/develop/perceiver/data/psv_measured.txt
A us_somo/develop/perceiver/data/ref/cctbx_LICENSE.txt
A us_somo/develop/perceiver/data/ref/f0_WaasKirf.dat
A us_somo/develop/perceiver/data/ref/it1992.cpp
A us_somo/develop/perceiver/data/ref/somo.saxs_atoms.generated
A us_somo/develop/perceiver/examples/perceive.somo
A us_somo/develop/perceiver/pdb_lite.h
A us_somo/develop/perceiver/residue_oracle.h
A us_somo/develop/perceiver/run_dialog_test.sh
A us_somo/develop/perceiver/tests/builder.cpp
A us_somo/develop/perceiver/tests/coverage.cpp
A us_somo/develop/perceiver/tests/dialog_qt.cpp
A us_somo/develop/perceiver/tests/emit_residue.cpp
A us_somo/develop/perceiver/tests/grid_volume.cpp
A us_somo/develop/perceiver/tests/hydration.cpp
A us_somo/develop/perceiver/tests/protein_psv.cpp
A us_somo/develop/perceiver/tests/psv.cpp
A us_somo/develop/perceiver/tests/regression.cpp
A us_somo/develop/perceiver/tests/sssr.cpp
A us_somo/develop/perceiver/tests/sssr_real.cpp
A us_somo/develop/perceiver/tests/tests_unit.cpp
A us_somo/develop/perceiver/tinytest.h
A us_somo/develop/perceiver/tools/calibrate_3v_context.py
A us_somo/develop/perceiver/tools/gen_saxs_entries.py
A us_somo/develop/perceiver/tools/hydration_table.py
A us_somo/develop/perceiver/tools/make_noncoded_variant.py
A us_somo/develop/perceiver/tools/psv_durchschlag.py
A us_somo/develop/perceiver/tools/psv_model.py
A us_somo/develop/perceiver/tools/recalc_ligand_volumes.py
R us_somo/develop/src/us_container_grpy.cpp
M us_somo/develop/src/us_hydrodyn.cpp
M us_somo/develop/src/us_hydrodyn_beads.cpp
M us_somo/develop/src/us_hydrodyn_core.cpp
M us_somo/develop/src/us_hydrodyn_dad.cpp
M us_somo/develop/src/us_hydrodyn_dad_conc.cpp
M us_somo/develop/src/us_hydrodyn_dad_conc_load.cpp
M us_somo/develop/src/us_hydrodyn_dad_fit.cpp
M us_somo/develop/src/us_hydrodyn_dad_makeiq.cpp
M us_somo/develop/src/us_hydrodyn_dad_modes.cpp
M us_somo/develop/src/us_hydrodyn_dad_options.cpp
A us_somo/develop/src/us_hydrodyn_dad_script.cpp
M us_somo/develop/src/us_hydrodyn_dad_util.cpp
M us_somo/develop/src/us_hydrodyn_fractal_dimension.cpp
A us_somo/develop/src/us_hydrodyn_grid_volume.cpp
M us_somo/develop/src/us_hydrodyn_grpy.cpp
A us_somo/develop/src/us_hydrodyn_hydration.cpp
M us_somo/develop/src/us_hydrodyn_hydro.cpp
M us_somo/develop/src/us_hydrodyn_load.cpp
M us_somo/develop/src/us_hydrodyn_mals.cpp
M us_somo/develop/src/us_hydrodyn_mals_conc.cpp
M us_somo/develop/src/us_hydrodyn_mals_conc_load.cpp
M us_somo/develop/src/us_hydrodyn_mals_fit.cpp
M us_somo/develop/src/us_hydrodyn_mals_makeiq.cpp
M us_somo/develop/src/us_hydrodyn_mals_modes.cpp
M us_somo/develop/src/us_hydrodyn_mals_options.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_conc.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_conc_load.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_fit.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_makeiq.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_modes.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_options.cpp
M us_somo/develop/src/us_hydrodyn_mals_saxs_util.cpp
M us_somo/develop/src/us_hydrodyn_mals_util.cpp
M us_somo/develop/src/us_hydrodyn_misc.cpp
M us_somo/develop/src/us_hydrodyn_other.cpp
M us_somo/develop/src/us_hydrodyn_pdb_parsing.cpp
M us_somo/develop/src/us_hydrodyn_pdb_tool.cpp
A us_somo/develop/src/us_hydrodyn_perceive.cpp
A us_somo/develop/src/us_hydrodyn_perceive_dialog.cpp
A us_somo/develop/src/us_hydrodyn_perceive_somo.cpp
A us_somo/develop/src/us_hydrodyn_psv.cpp
A us_somo/develop/src/us_hydrodyn_residue_builder.cpp
M us_somo/develop/src/us_hydrodyn_save.cpp
M us_somo/develop/src/us_hydrodyn_saxs.cpp
M us_somo/develop/src/us_hydrodyn_saxs_1d.cpp
M us_somo/develop/src/us_hydrodyn_saxs_2d.cpp
M us_somo/develop/src/us_hydrodyn_saxs_buffer.cpp
M us_somo/develop/src/us_hydrodyn_saxs_buffer_conc.cpp
M us_somo/develop/src/us_hydrodyn_saxs_buffer_conc_load.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_bl.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_ciq.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_conc.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_conc_load.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_gui.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_makeiq.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_modes.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_options.cpp
M us_somo/develop/src/us_hydrodyn_saxs_hplc_util.cpp
M us_somo/develop/src/us_hydrodyn_saxs_iqq.cpp
A us_somo/develop/src/us_hydrodyn_saxs_iqq_extrap_c0.cpp
A us_somo/develop/src/us_hydrodyn_saxs_iqq_extrap_c0_conc.cpp
M us_somo/develop/src/us_hydrodyn_saxs_iqq_load_csv.cpp
M us_somo/develop/src/us_hydrodyn_saxs_loads.cpp
M us_somo/develop/src/us_hydrodyn_script.cpp
M us_somo/develop/src/us_hydrodyn_settings.cpp
M us_somo/develop/src/us_hydrodyn_write.cpp
M us_somo/develop/src/us_saxs_util_best.cpp
M us_somo/develop/src/us_saxs_util_dmd.cpp
M us_somo/develop/src/us_saxs_util_hydro.cpp
M us_somo/develop/src/us_saxs_util_loads.cpp
M us_somo/develop/src/us_saxs_util_static.cpp
M us_somo/develop/src/us_vector.cpp
M us_somo/develop/version.sh
M us_somo/etc/somo.atom.new
M us_somo/etc/somo.config.new
M us_somo/etc/somo.defaults.new
M us_somo/etc/somo.hybrid.new
M us_somo/etc/somo.residue.new
M us_somo/etc/somo.saxs_atoms.new
A us_somo/somo/doc/manual/somo/DAWN_head.png
A us_somo/somo/doc/manual/somo/MALS_angles.png
A us_somo/somo/doc/manual/somo/WyattRayleigh ratios csv.png
M us_somo/somo/doc/manual/somo/mals_parameters.html
M us_somo/somo/doc/manual/somo/mals_saxs_options.html
M us_somo/somo/doc/manual/somo/saxs_hplc_ciq.html
M us_somo/somo/doc/manual/somo/saxs_hplc_options.html
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_EMG_option.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_GaussFit1.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_GaussFit2.png
A us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_options_Min_Gauss.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_options_new.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_options_new_Gaussians.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_options_new_baseline.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian1.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian11.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian11a.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian11b.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian11c.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian12.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian2.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian3.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian4.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian5.png
A us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian6a.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian8.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian9a.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_skewedGaussian_adv_sel.png
M us_somo/somo/doc/manual/somo/somo-HPLC-SAXS_smoothing.png
A us_somo/somo/doc/manual/somo/somo-MALS_Concs.png
A us_somo/somo/doc/manual/somo/somo-MALS_Concs2.png
A us_somo/somo/doc/manual/somo/somo-MALS_Concs3.png
A us_somo/somo/doc/manual/somo/somo-MALS_Concs4.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss1anew.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss1bnew.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss1cnew.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss1dnew.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss1enew.png
A us_somo/somo/doc/manual/somo/somo-MALS_GaussFit.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gauss_all_Idash_t_selected.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gaussian_final.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gaussian_init.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gaussian_options.png
A us_somo/somo/doc/manual/somo/somo-MALS_Gaussian_start.png
A us_somo/somo/doc/manual/somo/somo-MALS_GlobalFit_done.png
A us_somo/somo/doc/manual/somo/somo-MALS_GlobalGauss_done.png
A us_somo/somo/doc/manual/somo/somo-MALS_GlobalGauss_start_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_GlobalGaussianSDreminder.png
A us_somo/somo/doc/manual/somo/somo-MALS_GlobalGaussian_init.png
A us_somo/somo/doc/manual/somo/somo-MALS_I_hash_q_example.png
A us_somo/somo/doc/manual/somo/somo-MALS_I_starq_NoGauss_movieframe155.png
A us_somo/somo/doc/manual/somo/somo-MALS_I_starq_NoGauss_movieframe316.png
A us_somo/somo/doc/manual/somo/somo-MALS_I_starq_NoGauss_movieframe99.png
A us_somo/somo/doc/manual/somo/somo-MALS_Istarq_file_view_selected.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIdash_final.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIdash_final_kin.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIdash_final_kin_cropped.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIdash_final_kin_zoom.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIstar_final_kin.png
A us_somo/somo/doc/manual/somo/somo-MALS_MakeIstar_sel_kin_dots_err.png
A us_somo/somo/doc/manual/somo/somo-MALS_Messages.png
A us_somo/somo/doc/manual/somo/somo-MALS_Movie_selected.png
A us_somo/somo/doc/manual/somo/somo-MALS_Plot_Options_demo.png
A us_somo/somo/doc/manual/somo/somo-MALS_Produced_data.png
A us_somo/somo/doc/manual/somo/somo-MALS_R_theta_csv_loaded.png
A us_somo/somo/doc/manual/somo/somo-MALS_R_theta_kin_shown.png
A us_somo/somo/doc/manual/somo/somo-MALS_R_theta_shown.png
A us_somo/somo/doc/manual/somo/somo-MALS_Residuals_twocurvesSD.png
A us_somo/somo/doc/manual/somo/somo-MALS_Residuals_twocurves_percent.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_MALS_data_loglog.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Make_scaled_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Messages.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Plot_Options_demo.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Plot_Options_demo2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Produced_data.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_Produced_data_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_SAXS_common_times.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_SAXS_common_times_scroll1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_SAXS_common_times_scroll2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_SAXS_data_loading.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_bottom line.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_commons times_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_commontimes_all_dots.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_cropping_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_cropvis_results.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_cropvis_results1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_cropvis_select.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_exclude_q_vis_demo1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_exclude_q_vis_demo2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_fitting_methods.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_generating_joined_excl_q_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_initial.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_joined.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_joined_scroll.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_loadMALS.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_make_scaled.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_make_scaled_popup1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_make_scaled_popup2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_make_scaled_view_MALS_file.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_minimize_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_options.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_options1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_other_MALS_data_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_plot_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_polynomials.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_q_exclude_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_remove_panel.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale3.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale4.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale5.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale6.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale7.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scale8.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scaled_MALS_generated_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scaled_SAXS_generated_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_scroll_warning.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_second_set_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_second_set_buttons1.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_selections_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_top_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_viewselected.png
A us_somo/somo/doc/manual/somo/somo-MALS_SAXS_weighting_methods.png
A us_somo/somo/doc/manual/somo/somo-MALS_SD_eval_applied.png
A us_somo/somo/doc/manual/somo/somo-MALS_SD_eval_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_SD_eval_comparisonD2.png
A us_somo/somo/doc/manual/somo/somo-MALS_SD_eval_define_1region.png
A us_somo/somo/doc/manual/somo/somo-MALS_SD_eval_define_2regions.png
A us_somo/somo/doc/manual/somo/somo-MALS_Select_Istarq_for_norm.png
A us_somo/somo/doc/manual/somo/somo-MALS_Selected_Istarq_normalized.png
A us_somo/somo/doc/manual/somo/somo-MALS_Selected_Istarq_normalized_ave.png
A us_somo/somo/doc/manual/somo/somo-MALS_Selected_normalized_ave.png
A us_somo/somo/doc/manual/somo/somo-MALS_Selected_orig_and_norm_files.png
A us_somo/somo/doc/manual/somo/somo-MALS_UV_data_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_adjust_times_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_adjust_times_pop_up2.png
A us_somo/somo/doc/manual/somo/somo-MALS_angles_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_commands1.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_chrom_Gauss_fit.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_chrom_fit_module.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_chrom_init_Gauss.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_used_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_add_MALS_data.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_loaded_data.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_pop_up2.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_pop_up3.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_repeak.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_timeshift.png
A us_somo/somo/doc/manual/somo/somo-MALS_conc_util_timeshift_set.png
A us_somo/somo/doc/manual/somo/somo-MALS_crop_I_dash_chromatograms.png
A us_somo/somo/doc/manual/somo/somo-MALS_cropping_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_inconsistent times_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_incorrect processing_param_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_info_panel.png
A us_somo/somo/doc/manual/somo/somo-MALS_initial.png
A us_somo/somo/doc/manual/somo/somo-MALS_main1.png
A us_somo/somo/doc/manual/somo/somo-MALS_make_Istar_q_enterparam_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_make_Istar_q_enterparam_popup1.png
A us_somo/somo/doc/manual/somo/somo-MALS_make_Istar_q_noGauss_popup.png
A us_somo/somo/doc/manual/somo/somo-MALS_no_Gaussians_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_no_conc_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_no_conc_pop_up2.png
A us_somo/somo/doc/manual/somo/somo-MALS_options.png
A us_somo/somo/doc/manual/somo/somo-MALS_options_conc_detector.png
A us_somo/somo/doc/manual/somo/somo-MALS_options_new_Gaussians.png
A us_somo/somo/doc/manual/somo/somo-MALS_options_new_misc.png
A us_somo/somo/doc/manual/somo/somo-MALS_param.png
A us_somo/somo/doc/manual/somo/somo-MALS_plot_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_processing_param_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_processing_param_pop_up2.png
A us_somo/somo/doc/manual/somo/somo-MALS_remove_panel.png
A us_somo/somo/doc/manual/somo/somo-MALS_resulting_I_starq_NoGauss.png
A us_somo/somo/doc/manual/somo/somo-MALS_scattering_angles.png
A us_somo/somo/doc/manual/somo/somo-MALS_second_set_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_selected_Ihash_EMG_GMG.png
A us_somo/somo/doc/manual/somo/somo-MALS_selections_buttons.png
A us_somo/somo/doc/manual/somo/somo-MALS_set_conc_detector.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians1.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians2.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_GlobFit_Final.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_GlobFit_Init.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_GlobFit_by_q.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_GlobFit_saving_warning.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_GlobGauss.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_scroll1.png
A us_somo/somo/doc/manual/somo/somo-MALS_seven_Gaussians_scroll2.png
A us_somo/somo/doc/manual/somo/somo-MALS_six_Gaussians1.png
A us_somo/somo/doc/manual/somo/somo-MALS_six_Gaussians2.png
A us_somo/somo/doc/manual/somo/somo-MALS_timeshift_pop_up.png
A us_somo/somo/doc/manual/somo/somo-MALS_timeshift_pop_up2.png
A us_somo/somo/doc/manual/somo/somo-MALS_top_buttons.png
A us_somo/somo/doc/manual/somo/somo-mals_Residuals_twocurves.png
A us_somo/somo/doc/manual/somo/somo-perceive.png
M us_somo/somo/doc/manual/somo/somo.html
M us_somo/somo/doc/manual/somo/somo_hydro.html
A us_somo/somo/doc/manual/somo/somo_hydro_shell_reduction.html
M us_somo/somo/doc/manual/somo/somo_mals.html
A us_somo/somo/doc/manual/somo/somo_mals_dctr.html
A us_somo/somo/doc/manual/somo/somo_mals_options.html
M us_somo/somo/doc/manual/somo/somo_mals_saxs.html
M us_somo/somo/doc/manual/somo/somo_misc.html
M us_somo/somo/doc/manual/somo/somo_pdb_parsing.html
M us_somo/somo/doc/manual/somo/somo_pdb_parsing_expert_mode.html
A us_somo/somo/doc/manual/somo/somo_perceive.html
M us_somo/somo/doc/manual/somo/somo_save.html
M us_somo/somo/doc/manual/somo/somo_saxs_hplc.html
M us_somo/somo/doc/manual/somo/somo_saxs_hplc_skewedGauss.html
M us_somo/somo/doc/manual/somo/somo_uv_vis.html
A us_somo/somo/doc/manual/somo_mals.html
M utils/us_defines.h
M utils/us_extern.h
M utils/us_http_post.cpp
M utils/us_link_ssl.cpp
Log Message:
-----------
Merge remote-tracking branch 'origin/main' into alexey-dev-issue983
Compare: https://github.com/ehb54/ultrascan3/compare/4e05fdcf3daf...1b4c2e4650bb
To unsubscribe from these emails, change your notification settings at https://github.com/ehb54/ultrascan3/settings/notifications
More information about the us-commits
mailing list