TwoPy 0.3.0__tar.gz → 0.3.1__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.0 → twopy-0.3.1}/PKG-INFO +1 -1
- {twopy-0.3.0 → twopy-0.3.1}/pyproject.toml +1 -1
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/__init__.py +0 -16
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/__init__.py +12 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/persistence.py +138 -67
- twopy-0.3.1/src/twopy/analysis/response_plotting.py +334 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/conversion/api.py +1 -11
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/custom/__init__.py +10 -11
- twopy-0.3.0/src/twopy/custom/types.py → twopy-0.3.1/src/twopy/custom/context.py +12 -484
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/custom/discovery.py +3 -6
- twopy-0.3.1/src/twopy/custom/metadata.py +228 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/custom/parameters.py +2 -2
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/custom/provenance.py +84 -7
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/custom/registry.py +2 -1
- twopy-0.3.1/src/twopy/custom/results.py +116 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/custom/runner.py +9 -6
- twopy-0.3.1/src/twopy/custom/workflows.py +98 -0
- twopy-0.3.1/src/twopy/napari/__init__.py +75 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/controls.py +10 -19
- twopy-0.3.1/src/twopy/napari/database_favorite_editor.py +106 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/database_favorites.py +56 -5
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/database_search.py +223 -2
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/dims.py +5 -9
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/group_matching/fov_assignment.py +1 -8
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/group_matching/images.py +4 -8
- twopy-0.3.1/src/twopy/napari/group_matching/protocols.py +27 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/group_matching/response_preview.py +1 -1
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/group_matching/responses.py +1 -1
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/group_matching/roi_assignment.py +2 -8
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/group_matching/roi_cards.py +4 -9
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/group_matching/window.py +9 -16
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/interactive.py +4 -16
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/live_analysis.py +1 -1
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/loaded_recordings_csv.py +32 -22
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/loading.py +14 -16
- twopy-0.3.1/src/twopy/napari/plotting/__init__.py +52 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/data.py +16 -289
- twopy-0.3.1/src/twopy/napari/plotting/docks/__init__.py +52 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/docks/api.py +20 -6
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/docks/dynamic_options.py +10 -1
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/docks/plot_area.py +1 -1
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/docks/response_plot_widget.py +51 -7
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/docks/visibility_state.py +1 -1
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/export.py +4 -9
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/export_controls.py +1 -1
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/options.py +49 -4
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/preview_strip.py +1 -1
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/widgets.py +1 -1
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/protocols.py +44 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/responses.py +4 -2
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/roi.py +54 -1
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/session.py +36 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/trial_timeline.py +11 -24
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/roi.py +28 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy.egg-info/PKG-INFO +1 -1
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy.egg-info/SOURCES.txt +8 -1
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_conversion.py +4 -4
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_custom_workflows.py +18 -1
- twopy-0.3.1/tests/test_import.py +121 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_napari_database_search.py +329 -3
- twopy-0.3.1/tests/test_napari_load_controller.py +257 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_napari_load_tab.py +126 -3
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_napari_loaded_recordings.py +31 -4
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_napari_path_resolution.py +65 -5
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_napari_plot_data.py +6 -4
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_napari_roi_generation.py +58 -1
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_napari_roi_visibility.py +23 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_persistence.py +90 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_roi.py +29 -0
- twopy-0.3.0/src/twopy/napari/__init__.py +0 -27
- twopy-0.3.0/src/twopy/napari/plotting/__init__.py +0 -21
- twopy-0.3.0/src/twopy/napari/plotting/docks/__init__.py +0 -23
- twopy-0.3.0/tests/test_import.py +0 -26
- {twopy-0.3.0 → twopy-0.3.1}/README.md +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/setup.cfg +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/_segments.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/_version.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/background_subtraction.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/dff.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/dff_options.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/epoch_mapping.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/group_matching.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/kernels/__init__.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/kernels/_fitting.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/kernels/_stimulus.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/motion.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/response_context.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/response_maps.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/response_processing/__init__.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/response_processing/apply.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/response_processing/options.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/response_processing/persistence.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/response_processing/qc.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/response_processing/signals.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/response_window_options.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/responses.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/timing.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/trials.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis/workflow.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/analysis_cache.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/api.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/calibrations/pixel_calibration_profiles.csv +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/calibrations/pixel_size.csv +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/config.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/conversion/__init__.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/conversion/alignment_crop.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/conversion/hdf5_writing.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/conversion/matlab_values.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/conversion/orientation.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/conversion/source_loading.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/conversion/stimulus_code.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/conversion/types.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/converted.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/custom/native.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/custom/native_workflows/__init__.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/custom/native_workflows/direction_selectivity.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/custom/native_workflows/response_kernels.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/database/__init__.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/database/cache.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/database/catalog.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/database/connection.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/database/generic.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/database/modeled.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/database/search.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/database/sql.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/database/types.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/filenames.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/frame_ranges.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/hdf5_utils.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/inspection.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/matlab.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/__main__.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/custom_tab.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/display.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/display_paths.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/errors.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/group_matching/__init__.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/group_matching/cards.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/group_matching/fov_cards.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/group_matching/style.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/group_matching/tables.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/latest_worker.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/launcher.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/load_controller.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/load_progress.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/load_workflow.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/movie.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/paths.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/dff_options.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/docks/options_panel.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/docks/paths.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/docks/response_map_area.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/docks/save_actions.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/form_controls.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/label_visibility.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/normalization_options.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/panels.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/processing_options.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/response_map_colors.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/response_map_display.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/response_map_options.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/response_window_options.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/roi_generation/__init__.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/roi_generation/actions.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/roi_generation/controls.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/plotting/roi_generation/options.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/roi_signatures.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/sidebar.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/state.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/text.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/types.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/napari/viewer.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/parity/__init__.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/parity/dff.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/parity/psycho5.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/parity/roi.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/parity/roi_extraction.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/parity/saved_analysis.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/photodiode.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/photodiode_classification.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/pixel_calibration.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/pixel_calibration_profiles.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/response_roi_extraction.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/roi_extraction.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/roi_mask_cleanup.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/session.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/spatial.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/spatial_orientation.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/stimulus.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/synchronization.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy/typing_guards.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy.egg-info/dependency_links.txt +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy.egg-info/entry_points.txt +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy.egg-info/requires.txt +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/src/twopy.egg-info/top_level.txt +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_api.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_background_subtraction.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_config.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_converted.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_database.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_dff.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_epoch_mapping.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_filenames.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_frame_ranges.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_function_inventory.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_group_matching.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_hdf5_utils.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_inspection.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_kernels.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_load_workflow.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_matlab.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_motion.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_napari.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_napari_display.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_napari_export.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_napari_group_matching_responses.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_napari_group_matching_roi_cards.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_napari_live_controller.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_napari_load_progress.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_napari_plot_controls.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_napari_plot_widgets.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_napari_processing_controls.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_napari_response_map_display.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_napari_response_workflow.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_napari_text.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_napari_timeline.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_packaging.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_parity.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_parity_psycho5.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_parity_roi_extraction.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_photodiode_classification.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_pixel_calibration.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_pixel_calibration_profiles.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_real_fixture.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_recording_timing.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_response_map_area.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_response_maps.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_response_processing.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_response_roi_extraction.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_response_window_options.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_responses.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_roi_extraction.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_roi_mask_cleanup.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_saved_analysis.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_session.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_stimulus.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_synchronization.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_trials.py +0 -0
- {twopy-0.3.0 → twopy-0.3.1}/tests/test_workflow.py +0 -0
|
@@ -94,15 +94,6 @@ from twopy.converted import (
|
|
|
94
94
|
recording_frame_rate_hz,
|
|
95
95
|
recording_hemisphere,
|
|
96
96
|
)
|
|
97
|
-
from twopy.napari import (
|
|
98
|
-
NapariRecordingView,
|
|
99
|
-
NapariSidebarWidgets,
|
|
100
|
-
add_twopy_magicgui_controls,
|
|
101
|
-
launch_napari,
|
|
102
|
-
open_recording_in_napari,
|
|
103
|
-
roi_label_image_from_layer,
|
|
104
|
-
save_napari_label_rois,
|
|
105
|
-
)
|
|
106
97
|
from twopy.photodiode_classification import (
|
|
107
98
|
ClassifiedPhotodiodeEvent,
|
|
108
99
|
ClassifiedStimulusTiming,
|
|
@@ -180,7 +171,6 @@ __all__ = [
|
|
|
180
171
|
"AnalysisResponseComputation",
|
|
181
172
|
"add_manual_roi_match_group",
|
|
182
173
|
"analyze_recording_responses",
|
|
183
|
-
"add_twopy_magicgui_controls",
|
|
184
174
|
"append_manual_roi_match_rows",
|
|
185
175
|
"apply_motion_artifact_mask_to_delta_f_over_f",
|
|
186
176
|
"BackgroundCorrectedRoiTraces",
|
|
@@ -227,7 +217,6 @@ __all__ = [
|
|
|
227
217
|
"is_baseline_epoch_name",
|
|
228
218
|
"KernelFitMethod",
|
|
229
219
|
"KernelStimulusModality",
|
|
230
|
-
"launch_napari",
|
|
231
220
|
"load_analysis_outputs",
|
|
232
221
|
"load_response_map_data",
|
|
233
222
|
"load_manual_fov_group_rows",
|
|
@@ -254,9 +243,6 @@ __all__ = [
|
|
|
254
243
|
"remove_manual_roi_match_group",
|
|
255
244
|
"replace_manual_roi_match_group",
|
|
256
245
|
"map_stimulus_specific_column",
|
|
257
|
-
"NapariRecordingView",
|
|
258
|
-
"NapariSidebarWidgets",
|
|
259
|
-
"open_recording_in_napari",
|
|
260
246
|
"pair_photodiode_events_to_imaging_frames",
|
|
261
247
|
"PhotodiodeAlignment",
|
|
262
248
|
"PhotodiodeDurationClass",
|
|
@@ -296,13 +282,11 @@ __all__ = [
|
|
|
296
282
|
"RoiResponseTrial",
|
|
297
283
|
"RoiSet",
|
|
298
284
|
"RoiTraces",
|
|
299
|
-
"roi_label_image_from_layer",
|
|
300
285
|
"roi_set_to_label_image",
|
|
301
286
|
"save_analysis_outputs",
|
|
302
287
|
"save_response_map_data",
|
|
303
288
|
"save_manual_fov_group_rows",
|
|
304
289
|
"save_manual_roi_match_rows",
|
|
305
|
-
"save_napari_label_rois",
|
|
306
290
|
"save_roi_set",
|
|
307
291
|
"select_baseline_frame_windows",
|
|
308
292
|
"select_pixel_calibration_group",
|
|
@@ -66,6 +66,13 @@ from twopy.analysis.response_maps import (
|
|
|
66
66
|
load_response_map_data,
|
|
67
67
|
save_response_map_data,
|
|
68
68
|
)
|
|
69
|
+
from twopy.analysis.response_plotting import (
|
|
70
|
+
EpochResponsePlotData,
|
|
71
|
+
ResponsePlotData,
|
|
72
|
+
filter_response_plot_data_rois,
|
|
73
|
+
response_plot_data_from_grouped,
|
|
74
|
+
response_plot_window_options_from_grouped,
|
|
75
|
+
)
|
|
69
76
|
from twopy.analysis.response_processing import (
|
|
70
77
|
CorrelationFilterOptions,
|
|
71
78
|
LowPassFilterOptions,
|
|
@@ -130,6 +137,7 @@ __all__ = [
|
|
|
130
137
|
"DeltaFOverFOptions",
|
|
131
138
|
"DeltaFOverFFitMode",
|
|
132
139
|
"EpochResponseMap",
|
|
140
|
+
"EpochResponsePlotData",
|
|
133
141
|
"EpochFrameWindow",
|
|
134
142
|
"extract_background_corrected_roi_traces",
|
|
135
143
|
"fit_recording_stimulus_kernels",
|
|
@@ -163,6 +171,7 @@ __all__ = [
|
|
|
163
171
|
"ResponseMapData",
|
|
164
172
|
"ResponseMapMode",
|
|
165
173
|
"ResponseMapOptions",
|
|
174
|
+
"ResponsePlotData",
|
|
166
175
|
"ResponseProcessingOptions",
|
|
167
176
|
"RoiCorrelationScores",
|
|
168
177
|
"RoiResponseSummary",
|
|
@@ -181,9 +190,12 @@ __all__ = [
|
|
|
181
190
|
"save_manual_roi_match_rows",
|
|
182
191
|
"select_baseline_frame_windows",
|
|
183
192
|
"finite_mean_and_sem",
|
|
193
|
+
"filter_response_plot_data_rois",
|
|
184
194
|
"split_traces_by_frame_windows",
|
|
185
195
|
"StimulusKernelOptions",
|
|
186
196
|
"SmoothingOptions",
|
|
197
|
+
"response_plot_data_from_grouped",
|
|
198
|
+
"response_plot_window_options_from_grouped",
|
|
187
199
|
"summarize_epoch_roi_responses",
|
|
188
200
|
"summarize_grouped_responses",
|
|
189
201
|
"TimingSource",
|
|
@@ -10,7 +10,9 @@ MATLAB/TIFF files or decide analysis parameters.
|
|
|
10
10
|
|
|
11
11
|
import csv
|
|
12
12
|
import json
|
|
13
|
-
|
|
13
|
+
import os
|
|
14
|
+
import tempfile
|
|
15
|
+
from collections.abc import Callable, Iterator, Mapping, Sequence
|
|
14
16
|
from dataclasses import dataclass
|
|
15
17
|
from pathlib import Path
|
|
16
18
|
|
|
@@ -157,8 +159,11 @@ def save_analysis_outputs(
|
|
|
157
159
|
None.
|
|
158
160
|
|
|
159
161
|
The HDF5 file stores arrays with gzip compression where arrays can be large.
|
|
160
|
-
The HDF5 file is the complete audit trail. CSV files
|
|
161
|
-
|
|
162
|
+
The HDF5 file is the complete audit trail. CSV files are derived exports for
|
|
163
|
+
quick spreadsheet plotting and checks, and are written after the HDF5 file.
|
|
164
|
+
Each output file is written through a temporary sibling path so a failed
|
|
165
|
+
write leaves the previous complete file in place; the HDF5 and CSV files are
|
|
166
|
+
not replaced as one multi-file transaction.
|
|
162
167
|
"""
|
|
163
168
|
summary_outputs = (
|
|
164
169
|
response_summary_trials_csv,
|
|
@@ -175,35 +180,40 @@ def save_analysis_outputs(
|
|
|
175
180
|
if grouped_responses is not None:
|
|
176
181
|
validate_grouped_roi_responses(grouped_responses)
|
|
177
182
|
|
|
178
|
-
output_path
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
183
|
+
def write_hdf5(output_path: Path) -> None:
|
|
184
|
+
"""Write the analysis HDF5 contents to one already-created path."""
|
|
185
|
+
with h5py.File(output_path, "w") as h5_file:
|
|
186
|
+
h5_file.attrs["twopy_format"] = ANALYSIS_OUTPUT_FILE_FORMAT
|
|
187
|
+
if roi_set is not None:
|
|
188
|
+
_write_roi_set(h5_file.create_group("roi_set"), roi_set)
|
|
189
|
+
if traces is not None:
|
|
190
|
+
_write_background_traces(h5_file.create_group("traces"), traces)
|
|
191
|
+
if dff is not None:
|
|
192
|
+
_write_dff(h5_file.create_group("dff"), dff)
|
|
193
|
+
if len(epoch_windows) > 0:
|
|
194
|
+
_write_epoch_windows(
|
|
195
|
+
h5_file.create_group("epoch_windows"),
|
|
196
|
+
epoch_windows,
|
|
197
|
+
)
|
|
198
|
+
if len(baseline_windows) > 0:
|
|
199
|
+
_write_frame_windows(
|
|
200
|
+
h5_file.create_group("baseline_windows"),
|
|
201
|
+
baseline_windows,
|
|
202
|
+
)
|
|
203
|
+
if grouped_responses is not None:
|
|
204
|
+
_write_grouped_responses(
|
|
205
|
+
h5_file.create_group("responses"),
|
|
206
|
+
grouped_responses,
|
|
207
|
+
)
|
|
208
|
+
if response_processing_options is not None:
|
|
209
|
+
write_response_processing_group(
|
|
210
|
+
h5_file.create_group("response_processing"),
|
|
211
|
+
options=response_processing_options,
|
|
212
|
+
normalization_factors=normalization_factors,
|
|
213
|
+
correlation_scores=correlation_scores,
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
_write_file_atomically(path, write_hdf5)
|
|
207
217
|
|
|
208
218
|
if grouped_responses is not None:
|
|
209
219
|
if response_summary_trials_csv is not None:
|
|
@@ -218,6 +228,58 @@ def save_analysis_outputs(
|
|
|
218
228
|
)
|
|
219
229
|
|
|
220
230
|
|
|
231
|
+
def _write_file_atomically(
|
|
232
|
+
path: Path,
|
|
233
|
+
write_file: Callable[[Path], None],
|
|
234
|
+
) -> None:
|
|
235
|
+
"""Write a file beside its final path, then replace the old file.
|
|
236
|
+
|
|
237
|
+
Args:
|
|
238
|
+
path: Final destination path.
|
|
239
|
+
write_file: Callback that writes a complete file at the provided
|
|
240
|
+
temporary path.
|
|
241
|
+
|
|
242
|
+
Returns:
|
|
243
|
+
None.
|
|
244
|
+
|
|
245
|
+
Existing analysis files are useful audit records. Writing through a sibling
|
|
246
|
+
temporary path keeps a failed save from replacing the last complete output.
|
|
247
|
+
"""
|
|
248
|
+
output_path = path.expanduser()
|
|
249
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
250
|
+
temp_descriptor, temp_name = tempfile.mkstemp(
|
|
251
|
+
prefix=f".{output_path.name}.",
|
|
252
|
+
suffix=".tmp",
|
|
253
|
+
dir=output_path.parent,
|
|
254
|
+
)
|
|
255
|
+
os.close(temp_descriptor)
|
|
256
|
+
temp_path = Path(temp_name)
|
|
257
|
+
try:
|
|
258
|
+
write_file(temp_path)
|
|
259
|
+
temp_path.chmod(_replacement_file_mode(output_path))
|
|
260
|
+
temp_path.replace(output_path)
|
|
261
|
+
except Exception:
|
|
262
|
+
temp_path.unlink(missing_ok=True)
|
|
263
|
+
raise
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def _replacement_file_mode(path: Path) -> int:
|
|
267
|
+
"""Return the file mode an atomic replacement should keep.
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
path: Final destination path.
|
|
271
|
+
|
|
272
|
+
Returns:
|
|
273
|
+
Existing file permissions, or normal new-file permissions after the
|
|
274
|
+
process umask.
|
|
275
|
+
"""
|
|
276
|
+
if path.exists():
|
|
277
|
+
return path.stat().st_mode & 0o777
|
|
278
|
+
current_umask = os.umask(0)
|
|
279
|
+
os.umask(current_umask)
|
|
280
|
+
return 0o666 & ~current_umask
|
|
281
|
+
|
|
282
|
+
|
|
221
283
|
def load_analysis_outputs(path: Path) -> LoadedAnalysisOutputs:
|
|
222
284
|
"""Load twopy analysis outputs from HDF5.
|
|
223
285
|
|
|
@@ -297,25 +359,31 @@ def write_response_summary_trials_csv(
|
|
|
297
359
|
|
|
298
360
|
Returns:
|
|
299
361
|
None.
|
|
362
|
+
|
|
363
|
+
The CSV is written through a temporary sibling path so a failed write leaves
|
|
364
|
+
the previous complete file in place.
|
|
300
365
|
"""
|
|
301
|
-
output_path = path.expanduser()
|
|
302
|
-
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
303
366
|
validate_grouped_roi_responses(grouped_responses)
|
|
304
367
|
time_columns = _time_columns(grouped_responses.trials)
|
|
305
368
|
fieldnames = (*_TRIAL_RESPONSE_CSV_BASE_COLUMNS, *time_columns)
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
369
|
+
|
|
370
|
+
def write_csv(output_path: Path) -> None:
|
|
371
|
+
"""Write trial-level rows to one complete CSV file."""
|
|
372
|
+
with output_path.open("w", encoding="utf-8", newline="") as csv_file:
|
|
373
|
+
writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
|
|
374
|
+
writer.writeheader()
|
|
375
|
+
for trial in grouped_responses.trials:
|
|
376
|
+
for roi_index, roi_label in enumerate(grouped_responses.roi_labels):
|
|
377
|
+
writer.writerow(
|
|
378
|
+
_trial_response_row(
|
|
379
|
+
trial,
|
|
380
|
+
roi_index=roi_index,
|
|
381
|
+
roi_label=roi_label,
|
|
382
|
+
time_columns=time_columns,
|
|
383
|
+
),
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
_write_file_atomically(path, write_csv)
|
|
319
387
|
|
|
320
388
|
|
|
321
389
|
def write_response_summary_grouped_csv(
|
|
@@ -330,17 +398,23 @@ def write_response_summary_grouped_csv(
|
|
|
330
398
|
|
|
331
399
|
Returns:
|
|
332
400
|
None.
|
|
401
|
+
|
|
402
|
+
The CSV is written through a temporary sibling path so a failed write leaves
|
|
403
|
+
the previous complete file in place.
|
|
333
404
|
"""
|
|
334
|
-
output_path = path.expanduser()
|
|
335
|
-
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
336
405
|
validate_grouped_roi_responses(grouped_responses)
|
|
337
406
|
time_columns = _time_columns(grouped_responses.trials)
|
|
338
407
|
fieldnames = (*_GROUPED_RESPONSE_CSV_BASE_COLUMNS, *time_columns)
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
writer.
|
|
408
|
+
|
|
409
|
+
def write_csv(output_path: Path) -> None:
|
|
410
|
+
"""Write grouped rows to one complete CSV file."""
|
|
411
|
+
with output_path.open("w", encoding="utf-8", newline="") as csv_file:
|
|
412
|
+
writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
|
|
413
|
+
writer.writeheader()
|
|
414
|
+
for row in _iter_grouped_response_rows(grouped_responses, time_columns):
|
|
415
|
+
writer.writerow(row)
|
|
416
|
+
|
|
417
|
+
_write_file_atomically(path, write_csv)
|
|
344
418
|
|
|
345
419
|
|
|
346
420
|
def _write_roi_set(group: h5py.Group, roi_set: RoiSet) -> None:
|
|
@@ -894,10 +968,10 @@ def _trial_response_row(
|
|
|
894
968
|
return row
|
|
895
969
|
|
|
896
970
|
|
|
897
|
-
def
|
|
971
|
+
def _iter_grouped_response_rows(
|
|
898
972
|
grouped: GroupedRoiResponses,
|
|
899
973
|
time_columns: tuple[str, ...],
|
|
900
|
-
) ->
|
|
974
|
+
) -> Iterator[dict[str, str | int | float]]:
|
|
901
975
|
"""Convert grouped trial responses to mean, SEM, and count CSV rows.
|
|
902
976
|
|
|
903
977
|
Args:
|
|
@@ -905,12 +979,12 @@ def _grouped_response_rows(
|
|
|
905
979
|
time_columns: Complete CSV time-column union.
|
|
906
980
|
|
|
907
981
|
Returns:
|
|
908
|
-
|
|
982
|
+
Iterator over rows keyed by epoch, ROI, statistic, and relative
|
|
983
|
+
timepoint.
|
|
909
984
|
|
|
910
985
|
Counts are per timepoint rather than one scalar because pre/post context or
|
|
911
986
|
clipped recording edges can make some trials shorter than others.
|
|
912
987
|
"""
|
|
913
|
-
rows: list[dict[str, str | int | float]] = []
|
|
914
988
|
for epoch_number, epoch_name, trials in _trials_by_epoch(grouped.trials):
|
|
915
989
|
for roi_index, roi_label in enumerate(grouped.roi_labels):
|
|
916
990
|
values_by_time = _values_by_time_column(
|
|
@@ -918,16 +992,13 @@ def _grouped_response_rows(
|
|
|
918
992
|
roi_index=roi_index,
|
|
919
993
|
time_columns=time_columns,
|
|
920
994
|
)
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
time_columns=time_columns,
|
|
928
|
-
),
|
|
995
|
+
yield from _epoch_roi_statistic_rows(
|
|
996
|
+
epoch_number=epoch_number,
|
|
997
|
+
epoch_name=epoch_name,
|
|
998
|
+
roi_label=roi_label,
|
|
999
|
+
values_by_time=values_by_time,
|
|
1000
|
+
time_columns=time_columns,
|
|
929
1001
|
)
|
|
930
|
-
return tuple(rows)
|
|
931
1002
|
|
|
932
1003
|
|
|
933
1004
|
def _trials_by_epoch(
|