pycat-napari 1.5.330__tar.gz → 1.5.332__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/CHANGELOG.md +80 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/PKG-INFO +1 -1
- pycat_napari-1.5.332/docs/audits/DEV_NOTES.md +157 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/development/roadmap.rst +63 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/pyproject.toml +1 -1
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/run_pycat.py +10 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/analysis_plots.py +13 -1
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/condensate_physics_tools.py +330 -4
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/vpt_tools.py +25 -27
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/vpt_ui.py +127 -11
- pycat_napari-1.5.332/src/pycat/ui/coordinate_readout.py +134 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/.gitignore +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/CONTRIBUTING.md +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/LICENSE +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/README.md +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/THIRD_PARTY_LICENSES.txt +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/config/pycat-devbio-napari-env-arm-mac.yaml +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/config/pycat-devbio-napari-env-x86-windows.yaml +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/config/pycat-napari-env-arm-mac.yaml +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/config/pycat-napari-env-x86-windows.yaml +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/config/requirements-arm-mac.txt +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/config/requirements-base.txt +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/config/requirements-devbio-napari-arm-mac.txt +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/config/requirements-devbio-napari.txt +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/Makefile +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/audits/PyCAT_method_audit_2026-07-09.md +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/audits/PyCAT_napari_integration_audit_2026-07-09.md +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/logos/pycat_logo-2.png +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/logos/pycat_logo.png +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/logos/pycat_logo_1024.png +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/logos/pycat_logo_256.png +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/logos/pycat_logo_512.png +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/make.bat +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/requirements.txt +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/_static/dark_mode.css +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/_static/examples/Image 1 dapi.tif +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/_static/examples/Image 1.tif +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/_static/pycat_logo_512.png +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/_static/screenshots/Viewer_and_menu_highlights.png +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/_static/screenshots/cell_analyzer.png +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/_static/screenshots/condensate_segmentation.png +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/_static/screenshots/measuring_lines.png +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/_static/screenshots/opened_image_in_viewer.png +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/_static/screenshots/preprocessed_images.png +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/_static/screenshots/save_and_clear_popup.png +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/_templates/autosummary/module.rst +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/api/index.rst +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/api/pycat.central_manager.rst +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/api/pycat.data.rst +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/api/pycat.file_io.rst +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/api/pycat.run_pycat.rst +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/api/pycat.toolbox.rst +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/api/pycat.ui.rst +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/api/pycat.utils.rst +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/conf.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/development/contributing.rst +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/development/index.rst +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/development/support.rst +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/features.rst +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/index.rst +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/installation.rst +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/usage/index.rst +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/source/usage/tutorials/nuclear_condensate_analysis_gui_tutorial.rst +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/docs/test.txt +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/notebooks/Synthtic Data Generation NB.ipynb +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/notebooks/int_truncated_dfs.ipynb +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/notebooks/pycat_plotting.ipynb +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/__init__.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/batch_processor.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/batch_step_registry.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/central_manager.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/data/__init__.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/data/data_modules.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/file_io/__init__.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/file_io/file_io.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/file_io/frap_io.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/file_io/metadata_extract.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/file_io/multidim_io.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/file_io/session_loader.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/fix_tifffile.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/icons/pycat_logo-2.png +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/icons/pycat_logo.png +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/icons/pycat_logo_1024.png +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/icons/pycat_logo_256.png +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/icons/pycat_logo_512.png +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/__init__.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/advanced_analysis_ui.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/batch_roi_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/benchmark_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/brightfield_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/brightfield_ui.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/clean_spot_detection_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/condensate_physics_ui.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/contrast_cascade_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/contrast_cascade_ui.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/correlation_func_analysis_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/data_qc_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/data_qc_ui.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/data_viz_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/dynamic_spatial_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/fd_curve_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/fd_curve_ui.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/feature_analysis_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/fft_bandpass_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/fibril_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/fibril_ui.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/frap_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/frap_ui.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/fusion_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/fusion_ui.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/gaussian_localization_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/gpu_utils.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/image_processing_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/intensity_profile_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/invitro_bf_ui.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/invitro_fluor_ui.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/invitro_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/label_and_mask_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/layer_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/molecular_counting_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/morphological_complexity_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/nb_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/nb_ui.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/numba_utils.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/obj_based_coloc_analysis_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/organizational_metrics_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/partition_enrichment_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/pipeline_diagnostic_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/pipeline_snr_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/pixel_wise_corr_analysis_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/segmentation_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/spatial_acf_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/spatial_metrology_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/spatial_metrology_ui.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/spatial_randomness_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/spida_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/spida_ui.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/temperature_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/temperature_ui.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/temporal_enhancement_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/timeseries_condensate_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/timeseries_invitro_fluor_ui.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/timeseries_invitro_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/topology_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/trackmate_bridge.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/ts_cache_manager.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/ts_cellpose_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/two_channel_coloc_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/video_export_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/zstack_segmentation_tools.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/toolbox/zstack_segmentation_ui.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/ui/__init__.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/ui/field_status.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/ui/ui_analysis_mixin.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/ui/ui_diagnostics_mixin.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/ui/ui_filtering_mixin.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/ui/ui_imageops_mixin.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/ui/ui_labels_mixin.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/ui/ui_modules.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/ui/ui_segmentation_mixin.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/ui/ui_utils.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/ui/workflow_checklist.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/utils/__init__.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/utils/channel_naming.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/utils/general_utils.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/utils/logging_utils.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/src/pycat/utils/math_utils.py +0 -0
- {pycat_napari-1.5.330 → pycat_napari-1.5.332}/tests/README.md +0 -0
|
@@ -4,6 +4,86 @@ All notable changes to PyCAT-Napari will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [1.5.332] - 2026-07-10
|
|
8
|
+
### Fixed — VPT classifier green↔yellow flicker on bright, well-matched beads
|
|
9
|
+
- **A bright, high-NCC bead no longer flips singlet↔out_of_plane frame-to-frame.**
|
|
10
|
+
The out_of_plane (yellow) class used a per-frame amplitude/SNR percentile, so
|
|
11
|
+
when the bead population is uniformly low-quality a genuinely good bead sitting
|
|
12
|
+
near the moving percentile line was demoted ~a quarter of the time — driven
|
|
13
|
+
mainly by a `low-SNR OR` clause that could yellow a bead whose amplitude was
|
|
14
|
+
fine. Fix: (1) require the AMPLITUDE to actually be low for the dim class (SNR
|
|
15
|
+
is now only a secondary confirmation, never demotes a bright bead on its own),
|
|
16
|
+
and (2) add a high-NCC singlet guard (NCC ≥ 0.80) so a well-matched bead is
|
|
17
|
+
immune to the dim percentile. Verified on real data: the previously-flickering
|
|
18
|
+
bead (amp~164, NCC~0.94) is now singlet in 1000/1000 frames (was ~76%), while a
|
|
19
|
+
genuinely dim bead (amp~75, NCC~0.76) correctly STAYS out_of_plane — the garbage
|
|
20
|
+
rejection (NCC floor) and aggregate class are untouched. This preserves the
|
|
21
|
+
hard-won hot-pixel/ring/noise rejection while stopping the erroneous demotion of
|
|
22
|
+
real beads.
|
|
23
|
+
|
|
24
|
+
### Added — MSD lag-window fit gate (hardware-defensible fit bounds)
|
|
25
|
+
- `fit_anomalous_diffusion` now computes a **defensible MSD lag window** bounded
|
|
26
|
+
by the frame rate (high-frequency cutoff = frame interval) and the acquisition
|
|
27
|
+
duration (low-frequency cutoff), and by default confines the D/α fit to it.
|
|
28
|
+
Fitting outside this band (only sub-second lags, dominated by the localization
|
|
29
|
+
floor, or out toward the full duration, where a handful of pairs dominate)
|
|
30
|
+
produces a wrong D/α. Exposed under the VPT "Show advanced fit / moduli options"
|
|
31
|
+
expander:
|
|
32
|
+
- **Upper-lag rule** (user-selectable, with tooltips): *Fraction of track length*
|
|
33
|
+
(default, 0.25), *Fixed frequency window* (set the upper lag in seconds), or
|
|
34
|
+
*Minimum independent pairs* (keep a lag only while ≥ N independent tracks span
|
|
35
|
+
it).
|
|
36
|
+
- **"Confine fit to scientifically defensible bounds"** toggle (default ON) —
|
|
37
|
+
clips the fit to the window; turn off to fit the full range at your own risk.
|
|
38
|
+
- The gate **warns, never blocks**: if the acquisition can't cover the requested
|
|
39
|
+
window (too-short clip), it emits a clear warning and falls back gracefully.
|
|
40
|
+
Validated on real data across all three rules + the confine toggle + the
|
|
41
|
+
too-short-data warning path.
|
|
42
|
+
|
|
43
|
+
## [1.5.331] - 2026-07-10
|
|
44
|
+
### Added — Evans (2009) viscoelastic moduli + bootstrap confidence bands
|
|
45
|
+
- **G′/G″ (storage/loss moduli) now use the Evans et al. (2009) direct
|
|
46
|
+
compliance→moduli conversion** (`compute_moduli_evans` in
|
|
47
|
+
condensate_physics_tools.py), replacing the Mason (2000) single-point algebraic
|
|
48
|
+
GSER in the VPT pipeline. Evans represents the creep compliance J(t) as a
|
|
49
|
+
piecewise-linear interpolant and analytically Fourier-transforms it, so
|
|
50
|
+
G*(ω)=1/(iω·J̃(ω)) with **no local-power-law assumption** — it handles
|
|
51
|
+
curvature, plateaus, and crossovers directly. Validated in-sandbox against
|
|
52
|
+
known analytic MSDs: exact on a pure viscous fluid (G′≈0, G″=ηω to machine
|
|
53
|
+
precision) and ~1–2% on a Maxwell fluid across the reliable band. The highest
|
|
54
|
+
one or two frequencies (shortest lags) are the least reliable and are dropped.
|
|
55
|
+
The Mason `compute_moduli_gser` is retained (additive/revertable).
|
|
56
|
+
- **Optional bootstrap confidence intervals on G′/G″**
|
|
57
|
+
(`compute_moduli_evans_bootstrap`), exposed under a new hidden "Show advanced
|
|
58
|
+
moduli (G′/G″) options" expander in the VPT Step-5 panel (default off). Resamples
|
|
59
|
+
whole tracks with replacement, recomputes moduli per resample, and shades
|
|
60
|
+
percentile bands on the plot (`plot_moduli` draws bands when present). Validated
|
|
61
|
+
in-sandbox: ~93–97% empirical coverage of a known analytic truth for a nominal
|
|
62
|
+
95% band. This is the honest response to noisy data — it shows which parts of
|
|
63
|
+
the spectrum to trust.
|
|
64
|
+
- NOTE: a compliance-interpolation upgrade (natural/Akima spline) was evaluated
|
|
65
|
+
and **rejected** — validated as a no-op on smooth MSDs and unhelpful (can worsen
|
|
66
|
+
jitter) on noisy ones; the real levers for noise are the CIs above plus upstream
|
|
67
|
+
trajectory cleanup. Documented as such in the code.
|
|
68
|
+
|
|
69
|
+
### Added — dual pixel/µm coordinate readout
|
|
70
|
+
- **The napari status bar now shows both the pixel index (r, c) and the world
|
|
71
|
+
(µm) position under the cursor**, plus the value under the cursor, e.g.
|
|
72
|
+
`px (r=362, c=483) | µm (y=242.5, x=323.6) | Bead Detections = 171`
|
|
73
|
+
(`pycat/ui/coordinate_readout.py`, installed at launch in run_pycat.py). PyCAT
|
|
74
|
+
scales image layers by pixel size (µm/px), so napari's default status showed
|
|
75
|
+
microns only; pixel indices are what the analysis actually runs in (blob sigma,
|
|
76
|
+
linking distances, template windows, FIJI cross-referencing), so both are now
|
|
77
|
+
surfaced. Best-effort and fail-safe — never blocks launch, and leaves napari's
|
|
78
|
+
default status untouched if the coordinate can't be resolved.
|
|
79
|
+
|
|
80
|
+
### Docs
|
|
81
|
+
- Added a "Near-term UX & interaction" section to the development roadmap
|
|
82
|
+
(frame-0-on-load, materialization progress, pixel-size acquisition profiles,
|
|
83
|
+
command palette, plot↔layer brushing, dual px/µm readout).
|
|
84
|
+
- Added `docs/audits/DEV_NOTES.md` (private, Sphinx-excluded): instrument-scoped
|
|
85
|
+
module roadmap and known-issues detail kept out of the published docs.
|
|
86
|
+
|
|
7
87
|
## [1.5.208] - 2026-07-05
|
|
8
88
|
### Fixed (overlay stripe — the ACTUAL root cause: a scale mismatch)
|
|
9
89
|
- **The Overlay Image now inherits the source image layer's scale.** Confirmed via git
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pycat-napari
|
|
3
|
-
Version: 1.5.
|
|
3
|
+
Version: 1.5.332
|
|
4
4
|
Summary: Python Condensate Analysis Toolbox - A napari-based tool for biomolecular condensate analysis
|
|
5
5
|
Project-URL: Homepage, https://github.com/BanerjeeLab-repertoire/pycat-napari
|
|
6
6
|
Project-URL: Repository, https://github.com/BanerjeeLab-repertoire/pycat-napari
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# PyCAT — Private Development Notes
|
|
2
|
+
|
|
3
|
+
> **PRIVATE / NOT PUBLISHED.** This file lives in `docs/audits/` which is *outside*
|
|
4
|
+
> the Sphinx source tree (`docs/source/`) and is not in any `toctree`, so it is never
|
|
5
|
+
> built into the public documentation. It intentionally contains lab-specific detail
|
|
6
|
+
> (instrument inventory, hardware-gated scoping, machine/collaborator-specific bug
|
|
7
|
+
> notes) that must **not** appear in anything scraped or shown externally. Keep
|
|
8
|
+
> equipment names and internal scoping here, not in `roadmap.rst`.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. Lab / instrument base (scoping reference — keep private)
|
|
13
|
+
|
|
14
|
+
Informs which advanced analysis modules are worth building; scope modules to real
|
|
15
|
+
hardware. **Do not list this equipment in published docs.**
|
|
16
|
+
|
|
17
|
+
- **LUMICKS C-TRAP** — optical-tweezers + confocal, 3 lasers. Source instrument for
|
|
18
|
+
the existing FRAP / droplet-fusion / force-distance modules; Lumicks `.h5` files.
|
|
19
|
+
- **ISS Q2** — laser-scanning confocal with APDs on 3 channels; does FLIM and
|
|
20
|
+
point-detector FCS/FCCS. Native instrument for single-point FCS/FCCS and FLIM.
|
|
21
|
+
- **Andor Dragonfly** — spinning-disk confocal with TIRF/HILO, Micropoint, Mosaic,
|
|
22
|
+
two pinhole discs (25 & 40 µm). Two cameras: Andor iXon 888 EMCCD (1024×1024,
|
|
23
|
+
back-illuminated) and Andor Zyla sCMOS; both fast (~1000 fps with cropping). For
|
|
24
|
+
camera-FCS the **Zyla (sCMOS)** is correct (no EM gain, well-characterized per-pixel
|
|
25
|
+
noise); the iXon EMCCD is weaker for FCS (EM gain adds multiplicative excess noise
|
|
26
|
+
~√2 on variance). Dragonfly TIRF/HILO gives a defined thin axial volume, so
|
|
27
|
+
**Dragonfly TIRF/HILO + Zyla is a viable present-day imaging/camera-FCS testbed**
|
|
28
|
+
(spinning-disk is a messier volume model). Unconfirmed: can Dragonfly TIRF route to
|
|
29
|
+
the Zyla port? sCMOS imaging-FCS also needs a per-pixel offset/gain/variance
|
|
30
|
+
calibration map (the N&B documented hook).
|
|
31
|
+
- **Leica Stellaris** (campus access) with LIGHTNING deconvolution + a STED path.
|
|
32
|
+
- **Zeiss Airyscan 2** — incoming access (super-resolution detector-array confocal).
|
|
33
|
+
- **Photometrics Kinetix sCMOS** — currently on a Zeiss Axio Observer with LED
|
|
34
|
+
widefield (epi, no defined axial slice → not ideal for FCS). Future: Kinetix moves
|
|
35
|
+
to a custom ring-TIRF/HILO scope, with planned PolScope (polarization/birefringence
|
|
36
|
+
orientation) and FLIM on the other illumination path.
|
|
37
|
+
- Confocal imaging source for the 2D/TS condensate pipelines: Zeiss/ZEN Plan-Apo
|
|
38
|
+
63×/1.40 Oil, 405 + Argon 488, 3 PMTs, 0.0264 µm/px, DAPI/EGFP/transmitted.
|
|
39
|
+
|
|
40
|
+
**Implications:** single-point FCS/FCCS and FLIM are native to the ISS Q2 (PyCAT does
|
|
41
|
+
phasor/lifetime *downstream* analysis + import, not raw TCSPC); PolScope/orientation
|
|
42
|
+
pairs with the future Kinetix polarization path.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 2. Advanced spectroscopy / imaging module roadmap (hardware-scoped)
|
|
47
|
+
|
|
48
|
+
All are **import-and-analyze** modules: PyCAT quantifies what the specialized
|
|
49
|
+
instrument produces; it does not reimplement acquisition. Ordered by data-availability.
|
|
50
|
+
|
|
51
|
+
**Buildable now (data exists today):**
|
|
52
|
+
|
|
53
|
+
- **FCS/FCCS analysis module** — native to the ISS Q2 (APDs, 3 channels). Import
|
|
54
|
+
point-detector correlation curves / photon streams; fit diffusion models
|
|
55
|
+
(single/multi-component, triplet, anomalous); FCCS cross-correlation amplitude ratio
|
|
56
|
+
→ bound fraction. Composes with the fluctuation-spectroscopy family (MSD/VPT
|
|
57
|
+
viscosity, N&B, SpIDA). *Prereq:* confirm what the Q2 exports (correlation curves vs
|
|
58
|
+
raw photon stream vs `.fcs`). Extend `correlation_func_analysis_tools.py` (already
|
|
59
|
+
has spatial ACF/CCF + Gaussian-peak fitting, ICS-style); N&B (`nb_tools.py`) already
|
|
60
|
+
flags per-pixel sCMOS variance/offset correction.
|
|
61
|
+
- **FLIM phasor + downstream module** — native to ISS Q2. Import-based (no raw TCSPC).
|
|
62
|
+
Import lifetime/decay → phasor-plot analysis (model-free lifetime separation) →
|
|
63
|
+
segmentation-linked biology (per-condensate mean lifetime, lifetime vs partition
|
|
64
|
+
coefficient, lifetime shift across a phase transition). The distinctive "PyCAT owns
|
|
65
|
+
the downstream biology" play.
|
|
66
|
+
- **RICS / STICS** (raster & spatiotemporal image correlation spectroscopy) —
|
|
67
|
+
highest-leverage near-term. Works on current laser-scanning confocals (ISS Q2,
|
|
68
|
+
C-Trap) with no new hardware; extracts diffusion maps AND flow/velocity fields.
|
|
69
|
+
Reuses the existing spatial-correlation backend. Smaller lift than camera
|
|
70
|
+
imaging-FCS. *Prereq:* confirm the Q2 / C-Trap scanned-image-series export format +
|
|
71
|
+
whether pixel dwell / line time is in metadata (RICS depends on scan timing).
|
|
72
|
+
|
|
73
|
+
**Future (hardware-gated):**
|
|
74
|
+
|
|
75
|
+
- **Imaging / multipoint camera-FCS** — flagship but future. Tie to the Kinetix's
|
|
76
|
+
future ring-TIRF/HILO scope, NOT the current Axio Observer + LED widefield (no
|
|
77
|
+
defined axial slice → per-pixel FCS volume not well-posed). Per-pixel temporal
|
|
78
|
+
autocorrelation of a fast sCMOS stream → diffusion/concentration maps. Hard parts:
|
|
79
|
+
per-pixel sCMOS noise/variance/offset correction, frame-timing calibration,
|
|
80
|
+
bleaching, TIRF/HILO axial volume model.
|
|
81
|
+
- **PolScope / orientation analysis** — future, pairs with the Kinetix polarization
|
|
82
|
+
path. Import orientation/birefringence/anisotropy maps → orientational order
|
|
83
|
+
parameters, anisotropy distributions, orientation-vs-condensate-structure.
|
|
84
|
+
- **SMLM / localization-table analysis** — three super-res-capable instruments
|
|
85
|
+
(Dragonfly TIRF single-molecule, campus STED, incoming Airyscan 2) but zero
|
|
86
|
+
localization-table analysis today. Import localization tables (PALM/STORM/PAINT);
|
|
87
|
+
the Ripley/PCF cluster-analysis machinery already exists and applies directly; add
|
|
88
|
+
localization precision + drift correction. LOCAN ecosystem interop lands here.
|
|
89
|
+
- **Fluorescence anisotropy / homo-FRET** (steady-state polarization) — precursor to
|
|
90
|
+
PolScope; buildable sooner if any current instrument has a parallel/perpendicular
|
|
91
|
+
channel pair. Two-channel ratiometric-style computation.
|
|
92
|
+
|
|
93
|
+
*Caveat for all:* some capabilities are inferred from instrument class — confirm the
|
|
94
|
+
specific unit configuration (does the Dragonfly config do true SMLM? does any current
|
|
95
|
+
instrument have polarization optics installed?) before committing.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 3. Known issues (may name specific machines/configs — keep private)
|
|
100
|
+
|
|
101
|
+
### GPU / OpenGL canvas corruption on some NVIDIA configs (ACTIVE, not resolved)
|
|
102
|
+
|
|
103
|
+
**Symptom:** after loading an image, clicking the canvas renders the view
|
|
104
|
+
tilted/sheared (diagonal split); scroll/zoom still work (input + data fine — a
|
|
105
|
+
display/framebuffer-presentation problem). Earlier empty-canvas clicks showed
|
|
106
|
+
triangular tearing / swirling moiré + UI vanishing. Constant flickering appears only
|
|
107
|
+
on dim/out-of-focus objects.
|
|
108
|
+
|
|
109
|
+
**Confirmed NOT a PyCAT bug** — reproduces in plain napari (no PyCAT).
|
|
110
|
+
|
|
111
|
+
**Environment where seen** (collaborator machine, NVIDIA T400 4GB): Win11, Python 3.12,
|
|
112
|
+
napari 0.7.1, vispy 0.16.2, Qt 5.15.2/PyQt5, **NVIDIA driver 595.97**, OpenGL 4.6,
|
|
113
|
+
1920×1080 @ 100% single monitor, 75Hz HDMI. Ruled out (via `gpu_diag.py`):
|
|
114
|
+
wrong-GPU-selection, integrated graphics, Qt high-DPI scaling, multi-monitor.
|
|
115
|
+
|
|
116
|
+
**Three OpenGL backends all fail differently:** native NVIDIA → tearing/tilt on click;
|
|
117
|
+
`QT_OPENGL=angle` → crashes at startup (GLError 1282 on `glGetParameter(GL_MAX_TEXTURE_SIZE)`,
|
|
118
|
+
GL context broken at creation); `LIBGL_ALWAYS_SOFTWARE=1` → opens clean but slow to
|
|
119
|
+
start, then tears after repeated clicks.
|
|
120
|
+
|
|
121
|
+
**Prime suspect:** NVIDIA driver 595.97 (newest; only recently-changed variable; a
|
|
122
|
+
tilt/shear = framebuffer stride/row-alignment presentation bug — a classic driver-build
|
|
123
|
+
regression that hits OpenGL apps while leaving the desktop compositor fine).
|
|
124
|
+
|
|
125
|
+
**Next steps (awaiting):** clear env vars (`set QT_OPENGL=` / `set LIBGL_ALWAYS_SOFTWARE=`),
|
|
126
|
+
roll back the NVIDIA driver to the prior Studio branch (clean-install checkbox), reboot,
|
|
127
|
+
retest plain napari + load image + click/scroll. Open question: is this the only machine
|
|
128
|
+
affected, or do others on the same napari/vispy fail? (only → isolate this box's
|
|
129
|
+
GPU/driver, rollback is the fix; several → consider pinning napari/vispy.)
|
|
130
|
+
|
|
131
|
+
**When the fix is confirmed:** write a *public-facing* known-issues note (symptom →
|
|
132
|
+
confirm via plain napari → `gpu_diag.py` → resolution = driver rollback; software
|
|
133
|
+
rendering as an imperfect last resort). A possible PyCAT `--safe-rendering` launch flag
|
|
134
|
+
(sets `LIBGL_ALWAYS_SOFTWARE` before napari init) is opt-in first, but software
|
|
135
|
+
rendering was not fully stable here (tore after repeated clicks) so it's an imperfect
|
|
136
|
+
stopgap, not a clean fix. `gpu_diag.py` delivered (one-shot GPU/OpenGL/Qt/scaling report
|
|
137
|
+
+ opens plain napari for the reproduce test).
|
|
138
|
+
|
|
139
|
+
### Multi-file OME-TIFF with a missing linked member (hardened 1.5.330)
|
|
140
|
+
|
|
141
|
+
A multi-file OME-TIFF that references a missing sibling (e.g. a `...MMStack_Pos0.ome.tif`
|
|
142
|
+
referencing an absent later-timepoint file) makes the loader zero/truncate the missing
|
|
143
|
+
data, and a degenerate 1-D frame could reach `score_beads_template`, crashing with
|
|
144
|
+
`ValueError: not enough values to unpack (expected 2, got 1)`. 1.5.330 guards this
|
|
145
|
+
(squeeze + skip frame with a warning). Root fix for a *complete* analysis: ensure all
|
|
146
|
+
linked `.ome.tif` files are present, or use a self-contained single-file export.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## 4. VPT calibrated-thermodynamics scoping notes (lab-specific framing)
|
|
151
|
+
|
|
152
|
+
The calibrated intensity → concentration → ΔG_transfer workflow (see public roadmap for
|
|
153
|
+
the capability description) is scoped against the lab's Csat / phase-diagram /
|
|
154
|
+
quantitative-measurement program. This is the flagship manuscript differentiator:
|
|
155
|
+
converts PyCAT from "image analysis" to "biophysical parameter extraction." PyCAT today
|
|
156
|
+
has intensity-based ratios (partition coefficient, client enrichment) but zero
|
|
157
|
+
`delta_g` / standard-curve-concentration code — that gap is the build.
|
|
@@ -396,6 +396,69 @@ supporting Category B, because PyCAT's point-based spatial statistics are alread
|
|
|
396
396
|
what localization-cluster analysis needs.
|
|
397
397
|
|
|
398
398
|
|
|
399
|
+
Near-term UX & interaction
|
|
400
|
+
--------------------------
|
|
401
|
+
|
|
402
|
+
Small, mostly self-contained quality-of-life items that improve responsiveness and
|
|
403
|
+
keep the scientist engaged with their data. None are architectural; each can ship
|
|
404
|
+
independently.
|
|
405
|
+
|
|
406
|
+
.. rubric:: Default to the first frame on load
|
|
407
|
+
|
|
408
|
+
Most image viewers open a stack on frame 0; PyCAT currently opens on the middle
|
|
409
|
+
frame. Change the default so a freshly loaded stack shows frame 0 (set the viewer's
|
|
410
|
+
current step on the T axis to 0 after load), matching viewer convention.
|
|
411
|
+
|
|
412
|
+
.. rubric:: Materialization progress on stack-consuming methods
|
|
413
|
+
|
|
414
|
+
Where a method must read/decode a whole stack before working (e.g. bead detection),
|
|
415
|
+
the progress indication should read as one continuous 0→100% pass rather than
|
|
416
|
+
reaching 100% twice (once for materialization, once for the work). The reusable
|
|
417
|
+
``PhasedProgress`` helper already exists; the remaining work is rolling it out to the
|
|
418
|
+
other stack-consuming workflows so a materialization wait is always labelled and never
|
|
419
|
+
double-counts. Useful app-wide, since materialization is a common shared wait.
|
|
420
|
+
|
|
421
|
+
.. rubric:: Pixel-size acquisition profiles
|
|
422
|
+
|
|
423
|
+
Users repeatedly image files from the same microscope with the same missing-metadata
|
|
424
|
+
flaw (no pixel size, often no magnification either), so re-entering the scale every
|
|
425
|
+
load is friction. The robust design is **named acquisition profiles**: the user
|
|
426
|
+
creates and names a profile (storing its pixel size), saved to a small JSON on disk,
|
|
427
|
+
and selects it (or it is remembered as default) at load time. This sidesteps the
|
|
428
|
+
metadata problem by having the human supply the key the file cannot. When camera +
|
|
429
|
+
magnification *are* present in metadata, auto-fill the pixel size as a bonus. Scoped
|
|
430
|
+
as an additive picker on the existing load-time pixel-size dialog, composing with the
|
|
431
|
+
existing "persist through session" option — not a rewrite. (Metadata-only
|
|
432
|
+
auto-recovery was considered and rejected as the primary mechanism, because the exact
|
|
433
|
+
scopes this targets omit the metadata needed to compute the scale.)
|
|
434
|
+
|
|
435
|
+
.. rubric:: Command palette / search bar
|
|
436
|
+
|
|
437
|
+
A search bar (command-palette pattern, à la VS Code Ctrl+Shift+P or Spotlight) to
|
|
438
|
+
find and jump to functionality by name, in three scopes of increasing difficulty:
|
|
439
|
+
(1) open a method/widget by name — easy, a fuzzy filter over the existing
|
|
440
|
+
analysis-method registry calling the same launch function the menu does; (2) find a
|
|
441
|
+
layer by name — trivial, a thin wrapper over the viewer's layer list; (3) find a
|
|
442
|
+
step/process within a widget by name — harder, requires steps to be enumerable and
|
|
443
|
+
addressable (name → widget + the control that runs it + a scroll-to/highlight). Ship
|
|
444
|
+
1 + 2 first as a simple palette; extend to steps once step-addressing infrastructure
|
|
445
|
+
firms up (the same "steps as first-class addressable things" requirement also serves
|
|
446
|
+
the pipeline-step-diagnostics dropdown and the linked-navigation object model).
|
|
447
|
+
|
|
448
|
+
.. rubric:: VPT/MSD plot ↔ layer brushing (first instance of linked navigation)
|
|
449
|
+
|
|
450
|
+
A concrete, near-term instance of the linked multiscale navigation idea (see the
|
|
451
|
+
biological object model section): click a trajectory in the MSD plot → highlight that
|
|
452
|
+
bead and its track in the canvas and surface its data row, so browsing the plot leads
|
|
453
|
+
back to the data in the image. This is a small build for VPT specifically because the
|
|
454
|
+
identity plumbing already exists end-to-end — every MSD line carries a track id, and
|
|
455
|
+
the tracks layer holds those trajectories keyed by the same id. The missing piece is
|
|
456
|
+
narrow: make the (currently static) MSD plot pickable, map the picked line → track id,
|
|
457
|
+
then select/centre that track in the viewer and surface its row. Once proven here it
|
|
458
|
+
generalizes to the other plots (partition-coefficient scatter → condensate;
|
|
459
|
+
enrichment plot → cell).
|
|
460
|
+
|
|
461
|
+
|
|
399
462
|
Calibrated Thermodynamic & Quantitative Condensate Reporting
|
|
400
463
|
------------------------------------------------------------
|
|
401
464
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pycat-napari"
|
|
7
|
-
version = "1.5.
|
|
7
|
+
version = "1.5.332"
|
|
8
8
|
description = "Python Condensate Analysis Toolbox - A napari-based tool for biomolecular condensate analysis"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12,<3.13"
|
|
@@ -322,6 +322,16 @@ def run_pycat_func():
|
|
|
322
322
|
# be skipped entirely by setting PYCAT_SKIP_WARMUP=1.
|
|
323
323
|
viewer = napari.Viewer(title="PyCAT-Napari")
|
|
324
324
|
|
|
325
|
+
# Dual pixel / micron coordinate readout in the status bar. PyCAT scales
|
|
326
|
+
# layers by pixel size (µm/px), so napari's default status shows microns
|
|
327
|
+
# only; this surfaces the raw pixel index alongside it (px is what the
|
|
328
|
+
# analysis runs in). Best-effort — never blocks launch.
|
|
329
|
+
try:
|
|
330
|
+
from pycat.ui.coordinate_readout import install_coordinate_readout
|
|
331
|
+
install_coordinate_readout(viewer)
|
|
332
|
+
except Exception as _e:
|
|
333
|
+
print(f"[PyCAT] Coordinate readout not installed: {_e}")
|
|
334
|
+
|
|
325
335
|
if os.environ.get('PYCAT_SKIP_WARMUP', '') not in ('1', 'true', 'True'):
|
|
326
336
|
import threading
|
|
327
337
|
def _warmup():
|
|
@@ -97,7 +97,7 @@ def plot_moduli(moduli_df, title="Viscoelastic moduli (microrheology)",
|
|
|
97
97
|
interactive=True):
|
|
98
98
|
"""
|
|
99
99
|
Log-log plot of storage G'(ω) and loss G''(ω) vs angular frequency, from
|
|
100
|
-
compute_moduli_gser(). The crossover (G'=G'') marks the viscoelastic
|
|
100
|
+
compute_moduli_evans() (or compute_moduli_gser()). The crossover (G'=G'') marks the viscoelastic
|
|
101
101
|
relaxation frequency.
|
|
102
102
|
"""
|
|
103
103
|
import matplotlib
|
|
@@ -114,6 +114,18 @@ def plot_moduli(moduli_df, title="Viscoelastic moduli (microrheology)",
|
|
|
114
114
|
w = d['omega_rad_s'].values
|
|
115
115
|
gp = d['g_prime_pa'].values
|
|
116
116
|
gpp = d['g_double_prime_pa'].values
|
|
117
|
+
|
|
118
|
+
# Optional bootstrap confidence bands (drawn only if the columns are present,
|
|
119
|
+
# produced by compute_moduli_evans_bootstrap). Shaded region behind the lines.
|
|
120
|
+
if {'g_prime_lo', 'g_prime_hi'}.issubset(d.columns):
|
|
121
|
+
ax.fill_between(w, np.clip(d['g_prime_lo'].values, 1e-12, None),
|
|
122
|
+
np.clip(d['g_prime_hi'].values, 1e-12, None),
|
|
123
|
+
color='#c44e52', alpha=0.18, linewidth=0)
|
|
124
|
+
if {'g_double_prime_lo', 'g_double_prime_hi'}.issubset(d.columns):
|
|
125
|
+
ax.fill_between(w, np.clip(d['g_double_prime_lo'].values, 1e-12, None),
|
|
126
|
+
np.clip(d['g_double_prime_hi'].values, 1e-12, None),
|
|
127
|
+
color='#4c72b0', alpha=0.18, linewidth=0)
|
|
128
|
+
|
|
117
129
|
# only positive values are meaningful on log axes
|
|
118
130
|
ax.plot(w, np.clip(gp, 1e-12, None), '-o', ms=4, color='#c44e52',
|
|
119
131
|
label="G′ (storage / elastic)")
|