TwoPy 0.1.9__tar.gz → 0.2.0__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.1.9 → twopy-0.2.0}/PKG-INFO +2 -1
- {twopy-0.1.9 → twopy-0.2.0}/README.md +1 -0
- {twopy-0.1.9 → twopy-0.2.0}/pyproject.toml +1 -1
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/__init__.py +40 -9
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/analysis/__init__.py +38 -10
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/analysis/group_matching.py +149 -0
- twopy-0.2.0/src/twopy/analysis/kernels/__init__.py +352 -0
- twopy-0.2.0/src/twopy/analysis/kernels/_fitting.py +360 -0
- twopy-0.2.0/src/twopy/analysis/kernels/_stimulus.py +432 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/analysis/persistence.py +9 -18
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/analysis/response_context.py +8 -11
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/analysis/response_maps.py +9 -7
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/analysis/response_processing/__init__.py +1 -1
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/analysis/response_processing/options.py +7 -8
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/analysis/response_processing/signals.py +7 -4
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/analysis/response_window_options.py +1 -1
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/analysis/responses.py +63 -19
- twopy-0.2.0/src/twopy/analysis/timing.py +315 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/analysis/trials.py +1 -84
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/analysis/workflow.py +9 -9
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/analysis_cache.py +23 -4
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/api.py +6 -4
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/config.py +172 -36
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/conversion/api.py +63 -6
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/conversion/hdf5_writing.py +1 -1
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/conversion/source_loading.py +26 -6
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/conversion/stimulus_code.py +1 -1
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/conversion/types.py +2 -2
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/converted.py +60 -1
- twopy-0.2.0/src/twopy/custom/__init__.py +69 -0
- twopy-0.2.0/src/twopy/custom/discovery.py +303 -0
- twopy-0.2.0/src/twopy/custom/native.py +27 -0
- twopy-0.2.0/src/twopy/custom/native_workflows/__init__.py +5 -0
- twopy-0.2.0/src/twopy/custom/native_workflows/direction_selectivity.py +201 -0
- twopy-0.2.0/src/twopy/custom/native_workflows/response_kernels.py +502 -0
- twopy-0.2.0/src/twopy/custom/parameters.py +380 -0
- twopy-0.2.0/src/twopy/custom/provenance.py +385 -0
- twopy-0.2.0/src/twopy/custom/registry.py +78 -0
- twopy-0.2.0/src/twopy/custom/types.py +838 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/database/__init__.py +4 -2
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/database/cache.py +1 -1
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/database/catalog.py +1 -1
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/database/generic.py +1 -1
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/database/modeled.py +7 -4
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/database/search.py +146 -5
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/database/types.py +0 -3
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/hdf5_utils.py +2 -2
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/controls.py +84 -268
- twopy-0.2.0/src/twopy/napari/custom_tab.py +607 -0
- twopy-0.2.0/src/twopy/napari/database_favorites.py +416 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/database_search.py +346 -67
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/display_paths.py +15 -3
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/group_matching.py +12 -1
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/group_matching_roi.py +168 -104
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/interactive.py +17 -21
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/live_analysis.py +58 -98
- twopy-0.2.0/src/twopy/napari/load_workflow.py +409 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/loading.py +33 -13
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/data.py +89 -47
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/docks/api.py +2 -2
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/docks/options_panel.py +6 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/docks/plot_area.py +46 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/docks/response_map_area.py +13 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/docks/response_plot_widget.py +561 -15
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/docks/save_actions.py +30 -67
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/export.py +37 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/export_controls.py +10 -1
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/form_controls.py +5 -1
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/normalization_options.py +6 -1
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/processing_options.py +171 -94
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/roi_generation/actions.py +2 -2
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/widgets.py +67 -0
- twopy-0.2.0/src/twopy/napari/responses.py +245 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/session.py +22 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/sidebar.py +9 -0
- twopy-0.2.0/src/twopy/napari/text.py +64 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/trial_timeline.py +3 -3
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy.egg-info/PKG-INFO +2 -1
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy.egg-info/SOURCES.txt +38 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_api.py +12 -2
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_background_subtraction.py +2 -4
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_config.py +148 -19
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_conversion.py +181 -2
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_converted.py +63 -101
- twopy-0.2.0/tests/test_custom_workflows.py +926 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_database.py +40 -3
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_epoch_mapping.py +5 -30
- twopy-0.2.0/tests/test_group_matching.py +384 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_hdf5_utils.py +1 -2
- twopy-0.2.0/tests/test_kernels.py +482 -0
- twopy-0.2.0/tests/test_load_workflow.py +617 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_motion.py +4 -33
- twopy-0.2.0/tests/test_napari.py +505 -0
- twopy-0.2.0/tests/test_napari_database_search.py +639 -0
- twopy-0.2.0/tests/test_napari_display.py +132 -0
- twopy-0.2.0/tests/test_napari_export.py +324 -0
- twopy-0.2.0/tests/test_napari_live_controller.py +574 -0
- twopy-0.2.0/tests/test_napari_load_tab.py +445 -0
- twopy-0.2.0/tests/test_napari_loaded_recordings.py +626 -0
- twopy-0.2.0/tests/test_napari_path_resolution.py +619 -0
- twopy-0.2.0/tests/test_napari_plot_controls.py +466 -0
- twopy-0.2.0/tests/test_napari_plot_data.py +366 -0
- twopy-0.2.0/tests/test_napari_plot_widgets.py +799 -0
- twopy-0.2.0/tests/test_napari_processing_controls.py +650 -0
- twopy-0.2.0/tests/test_napari_response_map_display.py +85 -0
- twopy-0.2.0/tests/test_napari_response_workflow.py +756 -0
- twopy-0.2.0/tests/test_napari_roi_generation.py +620 -0
- twopy-0.2.0/tests/test_napari_roi_visibility.py +314 -0
- twopy-0.2.0/tests/test_napari_text.py +49 -0
- twopy-0.2.0/tests/test_napari_timeline.py +251 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_packaging.py +15 -23
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_parity.py +9 -31
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_parity_psycho5.py +7 -62
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_photodiode_classification.py +4 -31
- twopy-0.2.0/tests/test_recording_timing.py +200 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_response_maps.py +6 -32
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_response_processing.py +45 -28
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_response_roi_extraction.py +7 -33
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_responses.py +21 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_roi.py +2 -6
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_stimulus.py +38 -73
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_synchronization.py +25 -57
- twopy-0.2.0/tests/test_trials.py +182 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_workflow.py +9 -72
- twopy-0.1.9/src/twopy/napari/responses.py +0 -141
- twopy-0.1.9/src/twopy/napari/text.py +0 -26
- twopy-0.1.9/tests/test_group_matching.py +0 -180
- twopy-0.1.9/tests/test_napari.py +0 -7001
- twopy-0.1.9/tests/test_trials.py +0 -372
- {twopy-0.1.9 → twopy-0.2.0}/setup.cfg +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/_segments.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/_version.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/analysis/background_subtraction.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/analysis/dff.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/analysis/dff_options.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/analysis/epoch_mapping.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/analysis/motion.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/analysis/response_processing/apply.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/analysis/response_processing/persistence.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/analysis/response_processing/qc.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/calibrations/pixel_calibration_profiles.csv +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/calibrations/pixel_size.csv +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/conversion/__init__.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/conversion/alignment_crop.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/conversion/matlab_values.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/database/connection.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/database/sql.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/filenames.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/frame_ranges.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/inspection.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/matlab.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/__init__.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/__main__.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/dims.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/display.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/errors.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/group_matching_images.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/latest_worker.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/launcher.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/loaded_recordings_csv.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/movie.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/paths.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/__init__.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/dff_options.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/docks/__init__.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/docks/dynamic_options.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/docks/paths.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/docks/visibility_state.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/label_visibility.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/options.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/panels.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/response_map_colors.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/response_map_display.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/response_map_options.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/response_window_options.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/roi_generation/__init__.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/roi_generation/controls.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/plotting/roi_generation/options.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/protocols.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/roi.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/state.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/types.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/napari/viewer.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/parity/__init__.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/parity/dff.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/parity/psycho5.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/parity/roi.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/parity/roi_extraction.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/parity/saved_analysis.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/photodiode.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/photodiode_classification.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/pixel_calibration.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/pixel_calibration_profiles.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/response_roi_extraction.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/roi.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/roi_extraction.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/roi_mask_cleanup.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/session.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/spatial.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/stimulus.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/synchronization.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy/typing_guards.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy.egg-info/dependency_links.txt +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy.egg-info/entry_points.txt +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy.egg-info/requires.txt +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/src/twopy.egg-info/top_level.txt +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_dff.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_filenames.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_frame_ranges.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_import.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_inspection.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_matlab.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_parity_roi_extraction.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_persistence.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_pixel_calibration.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_pixel_calibration_profiles.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_real_fixture.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_response_map_area.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_response_window_options.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_roi_extraction.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_roi_mask_cleanup.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_saved_analysis.py +0 -0
- {twopy-0.1.9 → twopy-0.2.0}/tests/test_session.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: twopy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Two-photon imaging analysis tool with a napari interface.
|
|
5
5
|
Author-email: Gustavo Madeira Santana <fromweb1@gumadeiras.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -75,6 +75,7 @@ When a source recording has not been converted yet, twopy converts it first. Con
|
|
|
75
75
|
|
|
76
76
|
- [GUI guide](docs/gui.md): napari loading, ROI editing, plotting, and saved outputs.
|
|
77
77
|
- [Python API guide](docs/python_api.md): find recordings, convert data, run analysis, and open napari from scripts.
|
|
78
|
+
- [Custom workflow guide](docs/custom_workflows.md): add versioned local analyses to the napari Custom tab.
|
|
78
79
|
- [Development guide](docs/development.md): source setup and local checks.
|
|
79
80
|
- [Input data spec](docs/input_data_spec.md): short recording folder contract.
|
|
80
81
|
- [Recording file reference](docs/recording_file_schema.md): detailed source and converted file schema.
|
|
@@ -55,6 +55,7 @@ When a source recording has not been converted yet, twopy converts it first. Con
|
|
|
55
55
|
|
|
56
56
|
- [GUI guide](docs/gui.md): napari loading, ROI editing, plotting, and saved outputs.
|
|
57
57
|
- [Python API guide](docs/python_api.md): find recordings, convert data, run analysis, and open napari from scripts.
|
|
58
|
+
- [Custom workflow guide](docs/custom_workflows.md): add versioned local analyses to the napari Custom tab.
|
|
58
59
|
- [Development guide](docs/development.md): source setup and local checks.
|
|
59
60
|
- [Input data spec](docs/input_data_spec.md): short recording folder contract.
|
|
60
61
|
- [Recording file reference](docs/recording_file_schema.md): detailed source and converted file schema.
|
|
@@ -22,12 +22,17 @@ from twopy.analysis import (
|
|
|
22
22
|
FrameWindow,
|
|
23
23
|
GroupedRoiResponses,
|
|
24
24
|
GroupedRoiResponseSummary,
|
|
25
|
-
|
|
25
|
+
Hemisphere,
|
|
26
|
+
KernelFitMethod,
|
|
27
|
+
KernelStimulusModality,
|
|
26
28
|
LoadedAnalysisOutputs,
|
|
27
29
|
LowPassFilterOptions,
|
|
28
30
|
ManualFovGroupRow,
|
|
31
|
+
ManualRoiMatchGroup,
|
|
29
32
|
ManualRoiMatchRow,
|
|
30
33
|
ManualRoiMatchStatus,
|
|
34
|
+
RecordingKernelFit,
|
|
35
|
+
RecordingTiming,
|
|
31
36
|
ResponseMapData,
|
|
32
37
|
ResponseMapMode,
|
|
33
38
|
ResponseMapOptions,
|
|
@@ -37,7 +42,10 @@ from twopy.analysis import (
|
|
|
37
42
|
RoiResponseSummary,
|
|
38
43
|
RoiResponseTrial,
|
|
39
44
|
SmoothingOptions,
|
|
45
|
+
StimulusKernelOptions,
|
|
46
|
+
TimingSource,
|
|
40
47
|
WindowedRoiResponse,
|
|
48
|
+
add_manual_roi_match_group,
|
|
41
49
|
analyze_recording_responses,
|
|
42
50
|
append_manual_roi_match_rows,
|
|
43
51
|
apply_motion_artifact_mask_to_delta_f_over_f,
|
|
@@ -45,11 +53,13 @@ from twopy.analysis import (
|
|
|
45
53
|
compute_recording_responses,
|
|
46
54
|
compute_roi_delta_f_over_f,
|
|
47
55
|
default_baseline_epoch_number,
|
|
56
|
+
default_kernel_stimulus_column,
|
|
48
57
|
default_recording_baseline_epoch_number,
|
|
49
58
|
extract_background_corrected_roi_traces,
|
|
50
|
-
|
|
59
|
+
finite_mean_and_sem,
|
|
60
|
+
fit_recording_stimulus_kernels,
|
|
61
|
+
fit_stimulus_kernel,
|
|
51
62
|
group_delta_f_over_f_by_epoch,
|
|
52
|
-
interpolate_stimulus_epochs_to_frame_windows,
|
|
53
63
|
is_baseline_epoch_name,
|
|
54
64
|
load_analysis_outputs,
|
|
55
65
|
load_manual_fov_group_rows,
|
|
@@ -58,10 +68,13 @@ from twopy.analysis import (
|
|
|
58
68
|
make_frame_windows,
|
|
59
69
|
make_manual_fov_group_rows,
|
|
60
70
|
make_manual_roi_match_rows,
|
|
61
|
-
|
|
71
|
+
matched_manual_roi_groups,
|
|
62
72
|
next_group_cell_id,
|
|
63
73
|
no_baseline_epoch_frame_windows,
|
|
74
|
+
remove_manual_roi_match_group,
|
|
75
|
+
replace_manual_roi_match_group,
|
|
64
76
|
resolve_baseline_frame_windows,
|
|
77
|
+
resolve_recording_timing,
|
|
65
78
|
save_analysis_outputs,
|
|
66
79
|
save_manual_fov_group_rows,
|
|
67
80
|
save_manual_roi_match_rows,
|
|
@@ -76,7 +89,11 @@ from twopy.analysis import (
|
|
|
76
89
|
)
|
|
77
90
|
from twopy.api import find_recordings
|
|
78
91
|
from twopy.conversion import convert_recording_to_twopy, load_source_conversion_inputs
|
|
79
|
-
from twopy.converted import
|
|
92
|
+
from twopy.converted import (
|
|
93
|
+
load_converted_recording,
|
|
94
|
+
recording_frame_rate_hz,
|
|
95
|
+
recording_hemisphere,
|
|
96
|
+
)
|
|
80
97
|
from twopy.napari import (
|
|
81
98
|
NapariRecordingView,
|
|
82
99
|
NapariSidebarWidgets,
|
|
@@ -161,6 +178,7 @@ __all__ = [
|
|
|
161
178
|
"AlignedPhotodiodeEvent",
|
|
162
179
|
"AnalysisResponseRun",
|
|
163
180
|
"AnalysisResponseComputation",
|
|
181
|
+
"add_manual_roi_match_group",
|
|
164
182
|
"analyze_recording_responses",
|
|
165
183
|
"add_twopy_magicgui_controls",
|
|
166
184
|
"append_manual_roi_match_rows",
|
|
@@ -181,6 +199,7 @@ __all__ = [
|
|
|
181
199
|
"DEFAULT_PIXEL_CALIBRATION_PATH",
|
|
182
200
|
"DEFAULT_PIXEL_CALIBRATION_PROFILE_PATH",
|
|
183
201
|
"default_baseline_epoch_number",
|
|
202
|
+
"default_kernel_stimulus_column",
|
|
184
203
|
"default_recording_baseline_epoch_number",
|
|
185
204
|
"detect_photodiode_events",
|
|
186
205
|
"detect_recording_photodiode_events",
|
|
@@ -194,18 +213,20 @@ __all__ = [
|
|
|
194
213
|
"extract_rois_from_image",
|
|
195
214
|
"extract_roi_traces",
|
|
196
215
|
"find_recordings",
|
|
197
|
-
"
|
|
216
|
+
"fit_recording_stimulus_kernels",
|
|
217
|
+
"fit_stimulus_kernel",
|
|
198
218
|
"FrameWindow",
|
|
199
219
|
"full_frame_crop",
|
|
200
220
|
"group_delta_f_over_f_by_epoch",
|
|
201
221
|
"GroupedRoiResponseSummary",
|
|
202
222
|
"GroupedRoiResponses",
|
|
223
|
+
"Hemisphere",
|
|
203
224
|
"grid_roi_set",
|
|
204
225
|
"grid_roi_set_microns",
|
|
205
226
|
"grid_size_pixels_from_microns",
|
|
206
|
-
"InterpolatedEpochMapping",
|
|
207
|
-
"interpolate_stimulus_epochs_to_frame_windows",
|
|
208
227
|
"is_baseline_epoch_name",
|
|
228
|
+
"KernelFitMethod",
|
|
229
|
+
"KernelStimulusModality",
|
|
209
230
|
"launch_napari",
|
|
210
231
|
"load_analysis_outputs",
|
|
211
232
|
"load_response_map_data",
|
|
@@ -219,16 +240,19 @@ __all__ = [
|
|
|
219
240
|
"LoadedAnalysisOutputs",
|
|
220
241
|
"LowPassFilterOptions",
|
|
221
242
|
"ManualFovGroupRow",
|
|
243
|
+
"ManualRoiMatchGroup",
|
|
222
244
|
"ManualRoiMatchRow",
|
|
223
245
|
"ManualRoiMatchStatus",
|
|
246
|
+
"matched_manual_roi_groups",
|
|
224
247
|
"make_roi_set_from_label_image",
|
|
225
248
|
"make_frame_windows",
|
|
226
249
|
"make_manual_fov_group_rows",
|
|
227
250
|
"make_manual_roi_match_rows",
|
|
228
251
|
"make_roi_set",
|
|
229
|
-
"map_stimulus_epochs_to_frame_windows",
|
|
230
252
|
"next_group_cell_id",
|
|
231
253
|
"no_baseline_epoch_frame_windows",
|
|
254
|
+
"remove_manual_roi_match_group",
|
|
255
|
+
"replace_manual_roi_match_group",
|
|
232
256
|
"map_stimulus_specific_column",
|
|
233
257
|
"NapariRecordingView",
|
|
234
258
|
"NapariSidebarWidgets",
|
|
@@ -255,10 +279,14 @@ __all__ = [
|
|
|
255
279
|
"ResponseStatistic",
|
|
256
280
|
"ResponseWatershedExtraction",
|
|
257
281
|
"ResponseWatershedScoreImages",
|
|
282
|
+
"RecordingKernelFit",
|
|
283
|
+
"RecordingTiming",
|
|
258
284
|
"recording_frame_rate_hz",
|
|
285
|
+
"recording_hemisphere",
|
|
259
286
|
"resolve_pixel_size_um",
|
|
260
287
|
"resolve_pixel_calibration_profile",
|
|
261
288
|
"resolve_baseline_frame_windows",
|
|
289
|
+
"resolve_recording_timing",
|
|
262
290
|
"response_watershed_roi_set",
|
|
263
291
|
"RoiExtractionConfig",
|
|
264
292
|
"RoiExtractionMethod",
|
|
@@ -282,10 +310,13 @@ __all__ = [
|
|
|
282
310
|
"SmoothingOptions",
|
|
283
311
|
"SpatialCrop",
|
|
284
312
|
"SpatialDomain",
|
|
313
|
+
"StimulusKernelOptions",
|
|
285
314
|
"StimulusSpecificColumnMapping",
|
|
286
315
|
"stimulus_epoch_names_by_number",
|
|
316
|
+
"finite_mean_and_sem",
|
|
287
317
|
"summarize_epoch_roi_responses",
|
|
288
318
|
"summarize_grouped_responses",
|
|
319
|
+
"TimingSource",
|
|
289
320
|
"validate_grouped_roi_responses",
|
|
290
321
|
"watershed_roi_set",
|
|
291
322
|
"WindowedRoiResponse",
|
|
@@ -19,23 +19,34 @@ from twopy.analysis.dff import (
|
|
|
19
19
|
compute_roi_delta_f_over_f,
|
|
20
20
|
)
|
|
21
21
|
from twopy.analysis.dff_options import DeltaFOverFBaselineMode, DeltaFOverFOptions
|
|
22
|
-
from twopy.analysis.epoch_mapping import (
|
|
23
|
-
InterpolatedEpochMapping,
|
|
24
|
-
interpolate_stimulus_epochs_to_frame_windows,
|
|
25
|
-
)
|
|
26
22
|
from twopy.analysis.group_matching import (
|
|
27
23
|
ManualFovGroupRow,
|
|
24
|
+
ManualRoiMatchGroup,
|
|
28
25
|
ManualRoiMatchRow,
|
|
29
26
|
ManualRoiMatchStatus,
|
|
27
|
+
add_manual_roi_match_group,
|
|
30
28
|
append_manual_roi_match_rows,
|
|
31
29
|
load_manual_fov_group_rows,
|
|
32
30
|
load_manual_roi_match_rows,
|
|
33
31
|
make_manual_fov_group_rows,
|
|
34
32
|
make_manual_roi_match_rows,
|
|
33
|
+
matched_manual_roi_groups,
|
|
35
34
|
next_group_cell_id,
|
|
35
|
+
remove_manual_roi_match_group,
|
|
36
|
+
replace_manual_roi_match_group,
|
|
36
37
|
save_manual_fov_group_rows,
|
|
37
38
|
save_manual_roi_match_rows,
|
|
38
39
|
)
|
|
40
|
+
from twopy.analysis.kernels import (
|
|
41
|
+
Hemisphere,
|
|
42
|
+
KernelFitMethod,
|
|
43
|
+
KernelStimulusModality,
|
|
44
|
+
RecordingKernelFit,
|
|
45
|
+
StimulusKernelOptions,
|
|
46
|
+
default_kernel_stimulus_column,
|
|
47
|
+
fit_recording_stimulus_kernels,
|
|
48
|
+
fit_stimulus_kernel,
|
|
49
|
+
)
|
|
39
50
|
from twopy.analysis.motion import apply_motion_artifact_mask_to_delta_f_over_f
|
|
40
51
|
from twopy.analysis.persistence import (
|
|
41
52
|
ANALYSIS_OUTPUT_FILE_FORMAT,
|
|
@@ -67,20 +78,24 @@ from twopy.analysis.responses import (
|
|
|
67
78
|
GroupedRoiResponseSummary,
|
|
68
79
|
RoiResponseSummary,
|
|
69
80
|
RoiResponseTrial,
|
|
81
|
+
finite_mean_and_sem,
|
|
70
82
|
group_delta_f_over_f_by_epoch,
|
|
71
83
|
summarize_epoch_roi_responses,
|
|
72
84
|
summarize_grouped_responses,
|
|
73
85
|
validate_grouped_roi_responses,
|
|
74
86
|
)
|
|
87
|
+
from twopy.analysis.timing import (
|
|
88
|
+
RecordingTiming,
|
|
89
|
+
TimingSource,
|
|
90
|
+
resolve_recording_timing,
|
|
91
|
+
)
|
|
75
92
|
from twopy.analysis.trials import (
|
|
76
93
|
EpochFrameWindow,
|
|
77
94
|
FrameWindow,
|
|
78
95
|
WindowedRoiResponse,
|
|
79
96
|
default_baseline_epoch_number,
|
|
80
|
-
frame_windows_from_photodiode_alignment,
|
|
81
97
|
is_baseline_epoch_name,
|
|
82
98
|
make_frame_windows,
|
|
83
|
-
map_stimulus_epochs_to_frame_windows,
|
|
84
99
|
no_baseline_epoch_frame_windows,
|
|
85
100
|
resolve_baseline_frame_windows,
|
|
86
101
|
select_baseline_frame_windows,
|
|
@@ -117,27 +132,33 @@ __all__ = [
|
|
|
117
132
|
"EpochResponseMap",
|
|
118
133
|
"EpochFrameWindow",
|
|
119
134
|
"extract_background_corrected_roi_traces",
|
|
120
|
-
"
|
|
135
|
+
"fit_recording_stimulus_kernels",
|
|
136
|
+
"fit_stimulus_kernel",
|
|
137
|
+
"default_kernel_stimulus_column",
|
|
138
|
+
"Hemisphere",
|
|
121
139
|
"FrameWindow",
|
|
122
140
|
"group_delta_f_over_f_by_epoch",
|
|
123
141
|
"GroupedRoiResponseSummary",
|
|
124
142
|
"GroupedRoiResponses",
|
|
125
|
-
"InterpolatedEpochMapping",
|
|
126
|
-
"interpolate_stimulus_epochs_to_frame_windows",
|
|
127
143
|
"is_baseline_epoch_name",
|
|
144
|
+
"KernelFitMethod",
|
|
145
|
+
"KernelStimulusModality",
|
|
128
146
|
"load_analysis_outputs",
|
|
129
147
|
"load_response_map_data",
|
|
130
148
|
"LoadedAnalysisOutputs",
|
|
131
149
|
"LowPassFilterOptions",
|
|
132
150
|
"ManualFovGroupRow",
|
|
151
|
+
"ManualRoiMatchGroup",
|
|
133
152
|
"ManualRoiMatchRow",
|
|
134
153
|
"ManualRoiMatchStatus",
|
|
154
|
+
"matched_manual_roi_groups",
|
|
135
155
|
"make_frame_windows",
|
|
136
156
|
"make_manual_fov_group_rows",
|
|
137
157
|
"make_manual_roi_match_rows",
|
|
138
|
-
"map_stimulus_epochs_to_frame_windows",
|
|
139
158
|
"no_baseline_epoch_frame_windows",
|
|
140
159
|
"next_group_cell_id",
|
|
160
|
+
"RecordingKernelFit",
|
|
161
|
+
"RecordingTiming",
|
|
141
162
|
"RoiDeltaFOverF",
|
|
142
163
|
"ResponseMapData",
|
|
143
164
|
"ResponseMapMode",
|
|
@@ -147,18 +168,25 @@ __all__ = [
|
|
|
147
168
|
"RoiResponseSummary",
|
|
148
169
|
"RoiResponseTrial",
|
|
149
170
|
"resolve_baseline_frame_windows",
|
|
171
|
+
"resolve_recording_timing",
|
|
172
|
+
"add_manual_roi_match_group",
|
|
150
173
|
"append_manual_roi_match_rows",
|
|
151
174
|
"load_manual_fov_group_rows",
|
|
152
175
|
"load_manual_roi_match_rows",
|
|
176
|
+
"remove_manual_roi_match_group",
|
|
177
|
+
"replace_manual_roi_match_group",
|
|
153
178
|
"save_analysis_outputs",
|
|
154
179
|
"save_response_map_data",
|
|
155
180
|
"save_manual_fov_group_rows",
|
|
156
181
|
"save_manual_roi_match_rows",
|
|
157
182
|
"select_baseline_frame_windows",
|
|
183
|
+
"finite_mean_and_sem",
|
|
158
184
|
"split_traces_by_frame_windows",
|
|
185
|
+
"StimulusKernelOptions",
|
|
159
186
|
"SmoothingOptions",
|
|
160
187
|
"summarize_epoch_roi_responses",
|
|
161
188
|
"summarize_grouped_responses",
|
|
189
|
+
"TimingSource",
|
|
162
190
|
"validate_grouped_roi_responses",
|
|
163
191
|
"WindowedRoiResponse",
|
|
164
192
|
"write_response_summary_grouped_csv",
|
|
@@ -17,14 +17,19 @@ from typing import Literal
|
|
|
17
17
|
|
|
18
18
|
__all__ = [
|
|
19
19
|
"ManualFovGroupRow",
|
|
20
|
+
"ManualRoiMatchGroup",
|
|
20
21
|
"ManualRoiMatchRow",
|
|
21
22
|
"ManualRoiMatchStatus",
|
|
23
|
+
"add_manual_roi_match_group",
|
|
22
24
|
"append_manual_roi_match_rows",
|
|
23
25
|
"load_manual_fov_group_rows",
|
|
24
26
|
"load_manual_roi_match_rows",
|
|
25
27
|
"make_manual_fov_group_rows",
|
|
26
28
|
"make_manual_roi_match_rows",
|
|
29
|
+
"matched_manual_roi_groups",
|
|
27
30
|
"next_group_cell_id",
|
|
31
|
+
"remove_manual_roi_match_group",
|
|
32
|
+
"replace_manual_roi_match_group",
|
|
28
33
|
"save_manual_fov_group_rows",
|
|
29
34
|
"save_manual_roi_match_rows",
|
|
30
35
|
]
|
|
@@ -87,6 +92,19 @@ class ManualRoiMatchRow:
|
|
|
87
92
|
note: str = ""
|
|
88
93
|
|
|
89
94
|
|
|
95
|
+
@dataclass(frozen=True)
|
|
96
|
+
class ManualRoiMatchGroup:
|
|
97
|
+
"""Matched rows for one manually assigned cell group.
|
|
98
|
+
|
|
99
|
+
Inputs: existing ``ManualRoiMatchRow`` objects from a match table.
|
|
100
|
+
Outputs: one grouped decision for display or downstream group analysis.
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
group_cell_id: int
|
|
104
|
+
rows: tuple[ManualRoiMatchRow, ...]
|
|
105
|
+
note: str = ""
|
|
106
|
+
|
|
107
|
+
|
|
90
108
|
def make_manual_fov_group_rows(
|
|
91
109
|
recording_groups: Mapping[Path, str],
|
|
92
110
|
*,
|
|
@@ -171,6 +189,112 @@ def make_manual_roi_match_rows(
|
|
|
171
189
|
return tuple(rows)
|
|
172
190
|
|
|
173
191
|
|
|
192
|
+
def matched_manual_roi_groups(
|
|
193
|
+
rows: Sequence[ManualRoiMatchRow],
|
|
194
|
+
*,
|
|
195
|
+
fov_group_id: str,
|
|
196
|
+
) -> tuple[ManualRoiMatchGroup, ...]:
|
|
197
|
+
"""Return matched ROI groups for one FOV id.
|
|
198
|
+
|
|
199
|
+
Args:
|
|
200
|
+
rows: Manual ROI match rows from memory or CSV.
|
|
201
|
+
fov_group_id: FOV id whose matched groups should be returned.
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
Groups sorted by ``group_cell_id``. Non-matched statuses and other FOVs
|
|
205
|
+
are ignored.
|
|
206
|
+
"""
|
|
207
|
+
_validate_fov_group_id(fov_group_id)
|
|
208
|
+
grouped: dict[int, list[ManualRoiMatchRow]] = {}
|
|
209
|
+
for row in rows:
|
|
210
|
+
if row.status != "matched" or row.fov_group_id != fov_group_id:
|
|
211
|
+
continue
|
|
212
|
+
grouped.setdefault(row.group_cell_id, []).append(row)
|
|
213
|
+
groups: list[ManualRoiMatchGroup] = []
|
|
214
|
+
for group_cell_id, group_rows in sorted(grouped.items()):
|
|
215
|
+
row_tuple = tuple(group_rows)
|
|
216
|
+
groups.append(
|
|
217
|
+
ManualRoiMatchGroup(
|
|
218
|
+
group_cell_id=group_cell_id,
|
|
219
|
+
rows=row_tuple,
|
|
220
|
+
note=_shared_row_note(row_tuple),
|
|
221
|
+
),
|
|
222
|
+
)
|
|
223
|
+
return tuple(groups)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def add_manual_roi_match_group(
|
|
227
|
+
rows: Sequence[ManualRoiMatchRow],
|
|
228
|
+
recording_rois: Mapping[Path, str],
|
|
229
|
+
*,
|
|
230
|
+
fov_group_id: str,
|
|
231
|
+
note: str = "",
|
|
232
|
+
) -> tuple[tuple[ManualRoiMatchRow, ...], int]:
|
|
233
|
+
"""Append one new matched ROI group to existing rows.
|
|
234
|
+
|
|
235
|
+
Args:
|
|
236
|
+
rows: Existing manual ROI match rows.
|
|
237
|
+
recording_rois: Mapping from recording path to selected ROI label.
|
|
238
|
+
fov_group_id: FOV id for the new matched group.
|
|
239
|
+
note: Optional note copied to every new row.
|
|
240
|
+
|
|
241
|
+
Returns:
|
|
242
|
+
Updated row tuple and the assigned ``group_cell_id``.
|
|
243
|
+
"""
|
|
244
|
+
_validate_fov_group_id(fov_group_id)
|
|
245
|
+
group_cell_id = next_group_cell_id(rows)
|
|
246
|
+
group_rows = make_manual_roi_match_rows(
|
|
247
|
+
recording_rois,
|
|
248
|
+
group_cell_id=group_cell_id,
|
|
249
|
+
fov_group_id=fov_group_id,
|
|
250
|
+
status="matched",
|
|
251
|
+
note=note,
|
|
252
|
+
)
|
|
253
|
+
return (*tuple(rows), *group_rows), group_cell_id
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def replace_manual_roi_match_group(
|
|
257
|
+
rows: Sequence[ManualRoiMatchRow],
|
|
258
|
+
recording_rois: Mapping[Path, str],
|
|
259
|
+
*,
|
|
260
|
+
fov_group_id: str,
|
|
261
|
+
group_cell_id: int,
|
|
262
|
+
note: str = "",
|
|
263
|
+
) -> tuple[ManualRoiMatchRow, ...]:
|
|
264
|
+
"""Replace one matched group inside one FOV while preserving other rows.
|
|
265
|
+
|
|
266
|
+
Args:
|
|
267
|
+
rows: Existing manual ROI match rows.
|
|
268
|
+
recording_rois: Replacement recording-to-ROI selections.
|
|
269
|
+
fov_group_id: FOV id containing the group.
|
|
270
|
+
group_cell_id: Existing group id to replace.
|
|
271
|
+
note: Optional note copied to every replacement row.
|
|
272
|
+
|
|
273
|
+
Returns:
|
|
274
|
+
Updated row tuple.
|
|
275
|
+
"""
|
|
276
|
+
_validate_fov_group_id(fov_group_id)
|
|
277
|
+
replacement_rows = make_manual_roi_match_rows(
|
|
278
|
+
recording_rois,
|
|
279
|
+
group_cell_id=group_cell_id,
|
|
280
|
+
fov_group_id=fov_group_id,
|
|
281
|
+
status="matched",
|
|
282
|
+
note=note,
|
|
283
|
+
)
|
|
284
|
+
retained_rows = _rows_without_matched_group(rows, fov_group_id, group_cell_id)
|
|
285
|
+
return (*retained_rows, *replacement_rows)
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def remove_manual_roi_match_group(
|
|
289
|
+
rows: Sequence[ManualRoiMatchRow],
|
|
290
|
+
*,
|
|
291
|
+
fov_group_id: str,
|
|
292
|
+
group_cell_id: int,
|
|
293
|
+
) -> tuple[ManualRoiMatchRow, ...]:
|
|
294
|
+
"""Remove one matched group inside one FOV while preserving other rows."""
|
|
295
|
+
return _rows_without_matched_group(rows, fov_group_id, group_cell_id)
|
|
296
|
+
|
|
297
|
+
|
|
174
298
|
def save_manual_fov_group_rows(
|
|
175
299
|
rows: Iterable[ManualFovGroupRow],
|
|
176
300
|
path: Path,
|
|
@@ -289,6 +413,31 @@ def next_group_cell_id(rows: Sequence[ManualRoiMatchRow]) -> int:
|
|
|
289
413
|
return max(row.group_cell_id for row in rows) + 1
|
|
290
414
|
|
|
291
415
|
|
|
416
|
+
def _rows_without_matched_group(
|
|
417
|
+
rows: Sequence[ManualRoiMatchRow],
|
|
418
|
+
fov_group_id: str,
|
|
419
|
+
group_cell_id: int,
|
|
420
|
+
) -> tuple[ManualRoiMatchRow, ...]:
|
|
421
|
+
"""Return rows after removing one matched group in one FOV."""
|
|
422
|
+
_validate_fov_group_id(fov_group_id)
|
|
423
|
+
_validate_group_cell_id(group_cell_id)
|
|
424
|
+
return tuple(
|
|
425
|
+
row
|
|
426
|
+
for row in rows
|
|
427
|
+
if not (
|
|
428
|
+
row.status == "matched"
|
|
429
|
+
and row.fov_group_id == fov_group_id
|
|
430
|
+
and row.group_cell_id == group_cell_id
|
|
431
|
+
)
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
def _shared_row_note(rows: tuple[ManualRoiMatchRow, ...]) -> str:
|
|
436
|
+
"""Return the common note for one matched group."""
|
|
437
|
+
notes = {row.note for row in rows}
|
|
438
|
+
return notes.pop() if len(notes) == 1 else ""
|
|
439
|
+
|
|
440
|
+
|
|
292
441
|
def _write_csv_rows(
|
|
293
442
|
path: Path,
|
|
294
443
|
*,
|