TwoPy 0.3.5__tar.gz → 0.3.7__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.
- {twopy-0.3.5 → twopy-0.3.7}/PKG-INFO +1 -1
- {twopy-0.3.5 → twopy-0.3.7}/pyproject.toml +1 -1
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/empty_state.py +4 -4
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/docks/response_plot_widget.py +3 -2
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/protocols.py +18 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/version_check.py +17 -7
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/viewer.py +6 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy.egg-info/PKG-INFO +1 -1
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_load_workflow.py +9 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari.py +9 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari_plot_controls.py +6 -1
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_version_check.py +27 -0
- {twopy-0.3.5 → twopy-0.3.7}/README.md +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/setup.cfg +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/__init__.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/__init__.pyi +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/_segments.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/_version.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/__init__.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/background_subtraction.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/dff.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/dff_options.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/epoch_mapping.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/group_matching.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/kernels/__init__.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/kernels/_fitting.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/kernels/_stimulus.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/motion.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/persistence.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/response_context.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/response_maps.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/response_plotting.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/response_processing/__init__.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/response_processing/apply.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/response_processing/options.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/response_processing/persistence.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/response_processing/qc.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/response_processing/signals.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/response_window_options.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/responses.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/timing.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/trials.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis/workflow.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/analysis_cache.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/api.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/cache_inventory.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/calibrations/pixel_calibration_profiles.csv +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/calibrations/pixel_size.csv +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/config.example.yml +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/config.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/conversion/__init__.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/conversion/alignment_crop.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/conversion/api.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/conversion/hdf5_writing.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/conversion/matlab_values.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/conversion/orientation.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/conversion/source_loading.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/conversion/stimulus_code.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/conversion/types.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/converted.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/custom/__init__.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/custom/context.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/custom/discovery.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/custom/metadata.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/custom/native.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/custom/native_workflows/__init__.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/custom/native_workflows/direction_selectivity.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/custom/native_workflows/response_kernels.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/custom/parameters.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/custom/provenance.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/custom/registry.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/custom/results.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/custom/runner.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/custom/workflows.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/database/__init__.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/database/cache.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/database/catalog.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/database/connection.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/database/generic.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/database/modeled.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/database/search.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/database/sql.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/database/types.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/filenames.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/frame_ranges.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/hdf5_utils.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/inspection.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/matlab.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/__init__.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/__main__.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/assets/twopy-app-icon-128.png +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/assets/twopy-app-icon-16.png +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/assets/twopy-app-icon-256.png +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/assets/twopy-app-icon-32.png +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/assets/twopy-app-icon-512.png +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/assets/twopy-app-icon-64.png +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/assets/twopy-app-icon.icns +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/assets/twopy-app-icon.png +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/controls.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/custom_tab.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/database_favorite_editor.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/database_favorites.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/database_search.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/dims.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/display.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/display_paths.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/errors.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/group_matching/__init__.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/group_matching/cards.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/group_matching/fov_assignment.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/group_matching/fov_cards.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/group_matching/images.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/group_matching/protocols.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/group_matching/response_preview.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/group_matching/responses.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/group_matching/roi_assignment.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/group_matching/roi_cards.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/group_matching/style.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/group_matching/tables.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/group_matching/window.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/interactive.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/latest_worker.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/launcher.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/live_analysis.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/load_controller.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/load_progress.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/load_workflow.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/loaded_recordings_csv.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/loading.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/movie.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/output_routing.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/paths.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/__init__.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/data.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/dff_options.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/docks/__init__.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/docks/api.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/docks/dynamic_options.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/docks/options_panel.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/docks/paths.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/docks/plot_area.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/docks/response_map_area.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/docks/save_actions.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/docks/visibility_state.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/export.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/export_controls.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/form_controls.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/label_visibility.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/normalization_options.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/options.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/panels.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/preview_strip.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/processing_options.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/response_map_colors.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/response_map_display.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/response_map_options.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/response_window_options.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/roi_generation/__init__.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/roi_generation/actions.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/roi_generation/controls.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/roi_generation/options.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/plotting/widgets.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/responses.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/roi.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/roi_signatures.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/session.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/sidebar.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/state.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/text.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/trial_timeline.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/napari/types.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/parity/__init__.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/parity/dff.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/parity/psycho5.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/parity/roi.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/parity/roi_extraction.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/parity/saved_analysis.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/photodiode.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/photodiode_classification.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/pixel_calibration.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/pixel_calibration_profiles.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/response_roi_extraction.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/roi.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/roi_extraction.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/roi_mask_cleanup.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/session.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/spatial.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/spatial_orientation.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/stimulus.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/synchronization.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy/typing_guards.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy.egg-info/SOURCES.txt +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy.egg-info/dependency_links.txt +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy.egg-info/entry_points.txt +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy.egg-info/requires.txt +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/src/twopy.egg-info/top_level.txt +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_api.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_background_subtraction.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_cache_inventory.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_config.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_conversion.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_converted.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_custom_workflows.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_database.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_dff.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_epoch_mapping.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_filenames.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_frame_ranges.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_function_inventory.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_group_matching.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_hdf5_utils.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_import.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_inspection.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_kernels.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_matlab.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_motion.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari_database_search.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari_display.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari_export.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari_group_matching_responses.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari_group_matching_roi_cards.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari_live_controller.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari_load_controller.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari_load_progress.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari_load_tab.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari_loaded_recordings.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari_path_resolution.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari_plot_data.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari_plot_widgets.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari_processing_controls.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari_response_map_display.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari_response_workflow.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari_roi_generation.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari_roi_visibility.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari_text.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_napari_timeline.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_packaging.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_parity.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_parity_psycho5.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_parity_roi_extraction.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_persistence.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_photodiode_classification.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_pixel_calibration.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_pixel_calibration_profiles.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_real_fixture.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_recording_timing.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_response_map_area.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_response_maps.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_response_processing.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_response_roi_extraction.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_response_window_options.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_responses.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_roi.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_roi_extraction.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_roi_mask_cleanup.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_saved_analysis.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_session.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_stimulus.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_synchronization.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_trials.py +0 -0
- {twopy-0.3.5 → twopy-0.3.7}/tests/test_workflow.py +0 -0
|
@@ -85,10 +85,10 @@ def show_empty_viewer_message(
|
|
|
85
85
|
overlay.text = empty_viewer_message(update_command=update_command)
|
|
86
86
|
overlay.visible = True
|
|
87
87
|
overlay.position = "top_center"
|
|
88
|
-
overlay.font_size =
|
|
89
|
-
overlay.color = "
|
|
90
|
-
overlay.box =
|
|
91
|
-
overlay.box_color = (0.0, 0.0, 0.0, 0.
|
|
88
|
+
overlay.font_size = 18
|
|
89
|
+
overlay.color = "#c8cdd3"
|
|
90
|
+
overlay.box = False
|
|
91
|
+
overlay.box_color = (0.0, 0.0, 0.0, 0.0)
|
|
92
92
|
|
|
93
93
|
|
|
94
94
|
def hide_empty_viewer_message(viewer: object) -> None:
|
|
@@ -583,11 +583,12 @@ class _ResponsePlotWidget(QWidget):
|
|
|
583
583
|
"""Show the copyable update command when a newer release is known."""
|
|
584
584
|
if notice is None:
|
|
585
585
|
return
|
|
586
|
-
self._update_notice_label.setText(notice.
|
|
586
|
+
self._update_notice_label.setText(notice.text)
|
|
587
|
+
print(notice.text, flush=True)
|
|
587
588
|
if self._viewer is not None:
|
|
588
589
|
refresh_empty_viewer_message(
|
|
589
590
|
self._viewer,
|
|
590
|
-
update_command=notice.
|
|
591
|
+
update_command=notice.text,
|
|
591
592
|
)
|
|
592
593
|
|
|
593
594
|
def _ignore_update_notice_error(self, _error: Exception) -> None:
|
|
@@ -80,6 +80,24 @@ class NapariViewer(Protocol):
|
|
|
80
80
|
"""
|
|
81
81
|
...
|
|
82
82
|
|
|
83
|
+
def reset_view(
|
|
84
|
+
self,
|
|
85
|
+
*,
|
|
86
|
+
margin: float = 0.05,
|
|
87
|
+
reset_camera_angle: bool = True,
|
|
88
|
+
) -> None:
|
|
89
|
+
"""Fit visible layers into the current viewer canvas.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
margin: Fractional padding around visible layer extents.
|
|
93
|
+
reset_camera_angle: Whether to reset camera orientation as well as
|
|
94
|
+
zoom and pan.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
None.
|
|
98
|
+
"""
|
|
99
|
+
...
|
|
100
|
+
|
|
83
101
|
|
|
84
102
|
class NapariLayerWithData(Protocol):
|
|
85
103
|
"""Small protocol for napari layers that expose array-like data.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Check whether PyPI has a newer twopy release for the napari app.
|
|
2
2
|
|
|
3
3
|
Inputs: installed twopy version, PyPI JSON metadata, and local UI cache.
|
|
4
|
-
Outputs: an optional copyable update
|
|
4
|
+
Outputs: an optional copyable update notice for the Metadata tab.
|
|
5
5
|
|
|
6
6
|
The app only tells users how to update. It does not choose or run an
|
|
7
7
|
environment manager, because users may launch twopy from pip, conda, or another
|
|
@@ -97,14 +97,24 @@ class UpdateNotice:
|
|
|
97
97
|
latest_version: Newer version available from the package index.
|
|
98
98
|
command: Update command shown to the user.
|
|
99
99
|
|
|
100
|
-
The Metadata tab shows
|
|
101
|
-
user's Python environment is managed.
|
|
100
|
+
The Metadata tab shows text the user can copy. The command stays plain so
|
|
101
|
+
twopy does not assume how the user's Python environment is managed.
|
|
102
102
|
"""
|
|
103
103
|
|
|
104
104
|
current_version: str
|
|
105
105
|
latest_version: str
|
|
106
106
|
command: str = PIP_UPDATE_COMMAND
|
|
107
107
|
|
|
108
|
+
@property
|
|
109
|
+
def text(self) -> str:
|
|
110
|
+
"""Return the copyable user-facing update notice."""
|
|
111
|
+
return (
|
|
112
|
+
"Update available!\n"
|
|
113
|
+
f"Latest version is {self.latest_version}.\n"
|
|
114
|
+
"To update, run:\n"
|
|
115
|
+
f"{self.command}"
|
|
116
|
+
)
|
|
117
|
+
|
|
108
118
|
|
|
109
119
|
def check_for_update(
|
|
110
120
|
*,
|
|
@@ -131,9 +141,9 @@ def check_for_update(
|
|
|
131
141
|
Update notice, or ``None`` when twopy is current or the check cannot
|
|
132
142
|
prove that a newer final release exists.
|
|
133
143
|
|
|
134
|
-
A fresh cache avoids one network request per launch
|
|
135
|
-
|
|
136
|
-
show the update command.
|
|
144
|
+
A fresh cache avoids one network request per launch only after it has
|
|
145
|
+
already seen a newer version. If PyPI is unreachable and an older cache
|
|
146
|
+
proves a newer version exists, twopy can still show the update command.
|
|
137
147
|
"""
|
|
138
148
|
checked_now = _utc(now)
|
|
139
149
|
cache = read_version_check_cache(state_file=state_file)
|
|
@@ -261,7 +271,7 @@ def _cache_is_fresh(
|
|
|
261
271
|
latest = Version(cache.latest_version)
|
|
262
272
|
except InvalidVersion:
|
|
263
273
|
return False
|
|
264
|
-
if latest
|
|
274
|
+
if latest <= current:
|
|
265
275
|
return False
|
|
266
276
|
return now - checked_at <= max_age
|
|
267
277
|
|
|
@@ -17,6 +17,7 @@ from typing import TYPE_CHECKING, Protocol, cast
|
|
|
17
17
|
|
|
18
18
|
import numpy as np
|
|
19
19
|
import numpy.typing as npt
|
|
20
|
+
from qtpy.QtCore import QTimer
|
|
20
21
|
|
|
21
22
|
from twopy._version import __version__
|
|
22
23
|
from twopy.napari.empty_state import (
|
|
@@ -368,6 +369,11 @@ def add_prepared_recording_to_viewer(
|
|
|
368
369
|
)
|
|
369
370
|
set_labels_brush_size(roi_layer, brush_size=6)
|
|
370
371
|
|
|
372
|
+
QTimer.singleShot(
|
|
373
|
+
0,
|
|
374
|
+
lambda: viewer.reset_view(margin=0.05, reset_camera_angle=False),
|
|
375
|
+
)
|
|
376
|
+
|
|
371
377
|
from twopy.napari.types import NapariRecordingView
|
|
372
378
|
|
|
373
379
|
return NapariRecordingView(
|
|
@@ -115,6 +115,15 @@ class _Viewer:
|
|
|
115
115
|
self.labels.append(layer)
|
|
116
116
|
return layer
|
|
117
117
|
|
|
118
|
+
def reset_view(
|
|
119
|
+
self,
|
|
120
|
+
*,
|
|
121
|
+
margin: float = 0.05,
|
|
122
|
+
reset_camera_angle: bool = True,
|
|
123
|
+
) -> None:
|
|
124
|
+
"""Accept the recording-view camera fit request."""
|
|
125
|
+
del margin, reset_camera_angle
|
|
126
|
+
|
|
118
127
|
|
|
119
128
|
@dataclass
|
|
120
129
|
class _State:
|
|
@@ -31,6 +31,7 @@ from tests.napari_support import (
|
|
|
31
31
|
np,
|
|
32
32
|
open_recording_in_napari,
|
|
33
33
|
patch,
|
|
34
|
+
process_qt_events_until,
|
|
34
35
|
roi_label_image_from_layer,
|
|
35
36
|
save_napari_label_rois,
|
|
36
37
|
save_roi_set,
|
|
@@ -442,6 +443,9 @@ class CoreNapariAdapterTest(NapariAdapterTestCase):
|
|
|
442
443
|
self.assertTrue(viewer.text_overlay.text.startswith(f"{APPLICATION_TITLE}\n"))
|
|
443
444
|
self.assertTrue(viewer.text_overlay.visible)
|
|
444
445
|
self.assertEqual(viewer.text_overlay.position, "top_center")
|
|
446
|
+
self.assertEqual(viewer.text_overlay.font_size, 18)
|
|
447
|
+
self.assertEqual(viewer.text_overlay.color, "#c8cdd3")
|
|
448
|
+
self.assertFalse(viewer.text_overlay.box)
|
|
445
449
|
icon = viewer.window._qt_window.window_icon
|
|
446
450
|
self.assertIsNotNone(icon)
|
|
447
451
|
assert icon is not None
|
|
@@ -730,6 +734,7 @@ class CoreNapariAdapterTest(NapariAdapterTestCase):
|
|
|
730
734
|
viewer=viewer,
|
|
731
735
|
movie_frame_range=(0, 1),
|
|
732
736
|
)
|
|
737
|
+
process_qt_events_until(lambda: len(viewer.reset_view_calls) == 1)
|
|
733
738
|
|
|
734
739
|
self.assertIs(opened.viewer, viewer)
|
|
735
740
|
self.assertEqual(opened.recording.movie.shape, (3, 2, 2))
|
|
@@ -747,6 +752,10 @@ class CoreNapariAdapterTest(NapariAdapterTestCase):
|
|
|
747
752
|
self.assertEqual(viewer.images[1].contrast_limits_range, (0.0, 7.0))
|
|
748
753
|
self.assertEqual(np.asarray(viewer.images[1].data).shape, (2, 2, 2))
|
|
749
754
|
self.assertEqual(len(viewer.labels), 1)
|
|
755
|
+
self.assertEqual(
|
|
756
|
+
viewer.reset_view_calls,
|
|
757
|
+
[{"margin": 0.05, "reset_camera_angle": False}],
|
|
758
|
+
)
|
|
750
759
|
np.testing.assert_array_equal(
|
|
751
760
|
np.unique(np.asarray(viewer.labels[0].data)),
|
|
752
761
|
np.array([0, 3, 4]),
|
|
@@ -57,7 +57,12 @@ class NapariPlotControlsTest(NapariAdapterTestCase):
|
|
|
57
57
|
SidebarTextLabel(analysis_text),
|
|
58
58
|
SidebarTextLabel("ROI output: /very/long/path/to/rois.h5"),
|
|
59
59
|
SidebarTextLabel("Saved analysis."),
|
|
60
|
-
SidebarTextLabel(
|
|
60
|
+
SidebarTextLabel(
|
|
61
|
+
"Update available!\n"
|
|
62
|
+
"Latest version is 0.3.6.\n"
|
|
63
|
+
"To update, run:\n"
|
|
64
|
+
"python -m pip install -U twopy",
|
|
65
|
+
),
|
|
61
66
|
)
|
|
62
67
|
|
|
63
68
|
tab = response_metadata_tab(
|
|
@@ -32,6 +32,15 @@ class VersionCheckTest(unittest.TestCase):
|
|
|
32
32
|
self.assertIsNotNone(notice)
|
|
33
33
|
assert notice is not None
|
|
34
34
|
self.assertEqual(notice.command, PIP_UPDATE_COMMAND)
|
|
35
|
+
self.assertEqual(
|
|
36
|
+
notice.text,
|
|
37
|
+
(
|
|
38
|
+
"Update available!\n"
|
|
39
|
+
"Latest version is 0.3.3.\n"
|
|
40
|
+
"To update, run:\n"
|
|
41
|
+
"python -m pip install -U twopy"
|
|
42
|
+
),
|
|
43
|
+
)
|
|
35
44
|
|
|
36
45
|
def test_same_or_older_release_returns_no_notice(self) -> None:
|
|
37
46
|
"""Confirm current installs do not show an update command."""
|
|
@@ -84,6 +93,24 @@ class VersionCheckTest(unittest.TestCase):
|
|
|
84
93
|
assert notice is not None
|
|
85
94
|
self.assertEqual(notice.command, PIP_UPDATE_COMMAND)
|
|
86
95
|
|
|
96
|
+
def test_fresh_current_cache_still_checks_for_new_release(self) -> None:
|
|
97
|
+
"""Confirm a same-version cache does not hide a same-day release."""
|
|
98
|
+
with temporary_directory() as temp_dir:
|
|
99
|
+
state_file = Path(temp_dir) / "state.json"
|
|
100
|
+
now = datetime(2026, 6, 18, 12, tzinfo=UTC)
|
|
101
|
+
_write_cache(state_file, checked_at=now, latest_version="0.3.5")
|
|
102
|
+
|
|
103
|
+
notice = check_for_update(
|
|
104
|
+
current_version="0.3.5",
|
|
105
|
+
now=now + timedelta(hours=1),
|
|
106
|
+
state_file=state_file,
|
|
107
|
+
fetch_latest=lambda: PublishedVersion(version="0.3.6"),
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
self.assertIsNotNone(notice)
|
|
111
|
+
assert notice is not None
|
|
112
|
+
self.assertEqual(notice.latest_version, "0.3.6")
|
|
113
|
+
|
|
87
114
|
def test_stale_cache_is_used_when_network_fails(self) -> None:
|
|
88
115
|
"""Confirm old cache still helps when PyPI is unreachable."""
|
|
89
116
|
with temporary_directory() as temp_dir:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|