TwoPy 0.1.7__tar.gz → 0.1.9__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.7 → twopy-0.1.9}/PKG-INFO +3 -3
- {twopy-0.1.7 → twopy-0.1.9}/README.md +2 -2
- {twopy-0.1.7 → twopy-0.1.9}/pyproject.toml +4 -1
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/__init__.py +106 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/analysis/__init__.py +46 -1
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/analysis/background_subtraction.py +53 -2
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/analysis/dff_options.py +9 -4
- twopy-0.1.9/src/twopy/analysis/group_matching.py +463 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/analysis/persistence.py +19 -73
- twopy-0.1.9/src/twopy/analysis/response_context.py +280 -0
- twopy-0.1.9/src/twopy/analysis/response_maps.py +726 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/analysis/response_processing/persistence.py +19 -48
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/analysis/trials.py +39 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/analysis/workflow.py +174 -142
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/analysis_cache.py +10 -1
- twopy-0.1.9/src/twopy/calibrations/pixel_calibration_profiles.csv +4 -0
- twopy-0.1.9/src/twopy/calibrations/pixel_size.csv +21 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/config.py +36 -2
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/conversion/api.py +3 -4
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/conversion/hdf5_writing.py +6 -7
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/converted.py +15 -49
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/database/__init__.py +2 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/database/search.py +34 -1
- twopy-0.1.9/src/twopy/filenames.py +46 -0
- twopy-0.1.9/src/twopy/hdf5_utils.py +147 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/controls.py +433 -73
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/database_search.py +52 -7
- twopy-0.1.9/src/twopy/napari/dims.py +113 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/display_paths.py +42 -1
- twopy-0.1.9/src/twopy/napari/group_matching.py +585 -0
- twopy-0.1.9/src/twopy/napari/group_matching_images.py +283 -0
- twopy-0.1.9/src/twopy/napari/group_matching_roi.py +1147 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/interactive.py +41 -11
- twopy-0.1.9/src/twopy/napari/latest_worker.py +144 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/launcher.py +5 -1
- twopy-0.1.9/src/twopy/napari/live_analysis.py +362 -0
- twopy-0.1.9/src/twopy/napari/loaded_recordings_csv.py +110 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/loading.py +51 -3
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/paths.py +6 -5
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/data.py +142 -4
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/dff_options.py +43 -8
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/docks/options_panel.py +71 -20
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/docks/paths.py +14 -7
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/docks/plot_area.py +20 -2
- twopy-0.1.9/src/twopy/napari/plotting/docks/response_map_area.py +450 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/docks/response_plot_widget.py +390 -19
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/docks/save_actions.py +25 -2
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/export.py +151 -28
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/export_controls.py +24 -3
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/label_visibility.py +58 -20
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/panels.py +24 -21
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/processing_options.py +27 -0
- twopy-0.1.9/src/twopy/napari/plotting/response_map_colors.py +24 -0
- twopy-0.1.9/src/twopy/napari/plotting/response_map_display.py +131 -0
- twopy-0.1.9/src/twopy/napari/plotting/response_map_options.py +350 -0
- twopy-0.1.9/src/twopy/napari/plotting/roi_generation/__init__.py +26 -0
- twopy-0.1.9/src/twopy/napari/plotting/roi_generation/actions.py +130 -0
- twopy-0.1.9/src/twopy/napari/plotting/roi_generation/controls.py +706 -0
- twopy-0.1.9/src/twopy/napari/plotting/roi_generation/options.py +62 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/widgets.py +12 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/responses.py +7 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/roi.py +58 -1
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/session.py +69 -13
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/sidebar.py +88 -3
- twopy-0.1.9/src/twopy/napari/trial_timeline.py +719 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/types.py +1 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/viewer.py +14 -1
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/parity/__init__.py +12 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/parity/psycho5.py +88 -2
- twopy-0.1.9/src/twopy/parity/roi_extraction.py +302 -0
- twopy-0.1.9/src/twopy/pixel_calibration.py +573 -0
- twopy-0.1.9/src/twopy/pixel_calibration_profiles.py +563 -0
- twopy-0.1.9/src/twopy/response_roi_extraction.py +750 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/roi.py +3 -21
- twopy-0.1.9/src/twopy/roi_extraction.py +550 -0
- twopy-0.1.9/src/twopy/roi_mask_cleanup.py +74 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy.egg-info/PKG-INFO +3 -3
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy.egg-info/SOURCES.txt +40 -1
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_api.py +3 -2
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_background_subtraction.py +41 -12
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_config.py +41 -12
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_conversion.py +13 -13
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_converted.py +10 -10
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_database.py +55 -12
- twopy-0.1.9/tests/test_filenames.py +104 -0
- twopy-0.1.9/tests/test_group_matching.py +180 -0
- twopy-0.1.9/tests/test_hdf5_utils.py +83 -0
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_inspection.py +3 -3
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_matlab.py +5 -5
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_napari.py +2796 -111
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_parity.py +3 -3
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_parity_psycho5.py +47 -4
- twopy-0.1.9/tests/test_parity_roi_extraction.py +183 -0
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_persistence.py +9 -9
- twopy-0.1.9/tests/test_pixel_calibration.py +225 -0
- twopy-0.1.9/tests/test_pixel_calibration_profiles.py +226 -0
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_real_fixture.py +2 -2
- twopy-0.1.9/tests/test_response_map_area.py +98 -0
- twopy-0.1.9/tests/test_response_maps.py +311 -0
- twopy-0.1.9/tests/test_response_roi_extraction.py +354 -0
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_roi.py +7 -7
- twopy-0.1.9/tests/test_roi_extraction.py +171 -0
- twopy-0.1.9/tests/test_roi_mask_cleanup.py +65 -0
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_saved_analysis.py +2 -2
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_session.py +7 -6
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_stimulus.py +6 -6
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_synchronization.py +2 -2
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_trials.py +20 -0
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_workflow.py +142 -4
- twopy-0.1.7/src/twopy/napari/constants.py +0 -13
- {twopy-0.1.7 → twopy-0.1.9}/setup.cfg +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/_segments.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/_version.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/analysis/dff.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/analysis/epoch_mapping.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/analysis/motion.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/analysis/response_processing/__init__.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/analysis/response_processing/apply.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/analysis/response_processing/options.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/analysis/response_processing/qc.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/analysis/response_processing/signals.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/analysis/response_window_options.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/analysis/responses.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/api.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/conversion/__init__.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/conversion/alignment_crop.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/conversion/matlab_values.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/conversion/source_loading.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/conversion/stimulus_code.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/conversion/types.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/database/cache.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/database/catalog.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/database/connection.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/database/generic.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/database/modeled.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/database/sql.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/database/types.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/frame_ranges.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/inspection.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/matlab.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/__init__.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/__main__.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/display.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/errors.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/movie.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/__init__.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/docks/__init__.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/docks/api.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/docks/dynamic_options.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/docks/visibility_state.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/form_controls.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/normalization_options.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/options.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/plotting/response_window_options.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/protocols.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/state.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/napari/text.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/parity/dff.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/parity/roi.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/parity/saved_analysis.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/photodiode.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/photodiode_classification.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/session.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/spatial.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/stimulus.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/synchronization.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy/typing_guards.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy.egg-info/dependency_links.txt +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy.egg-info/entry_points.txt +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy.egg-info/requires.txt +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/src/twopy.egg-info/top_level.txt +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_dff.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_epoch_mapping.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_frame_ranges.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_import.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_motion.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_packaging.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_photodiode_classification.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_response_processing.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_response_window_options.py +0 -0
- {twopy-0.1.7 → twopy-0.1.9}/tests/test_responses.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: twopy
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.9
|
|
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
|
|
@@ -64,10 +64,10 @@ twopy /path/to/recording_data.h5
|
|
|
64
64
|
|
|
65
65
|
Basic GUI flow:
|
|
66
66
|
|
|
67
|
-
1.
|
|
67
|
+
1. Search the database or load a recording manually.
|
|
68
68
|
2. Draw or edit ROIs in the `rois` Labels layer.
|
|
69
69
|
3. Update response plots from the current ROIs.
|
|
70
|
-
4. Click Save ROIs + analysis when the plots look right.
|
|
70
|
+
4. Click Save ROIs + analysis in Export when the plots look right.
|
|
71
71
|
|
|
72
72
|
When a source recording has not been converted yet, twopy converts it first. Converted data includes the aligned movie, mean image, stimulus tables, photodiode signals, and recording metadata.
|
|
73
73
|
|
|
@@ -44,10 +44,10 @@ twopy /path/to/recording_data.h5
|
|
|
44
44
|
|
|
45
45
|
Basic GUI flow:
|
|
46
46
|
|
|
47
|
-
1.
|
|
47
|
+
1. Search the database or load a recording manually.
|
|
48
48
|
2. Draw or edit ROIs in the `rois` Labels layer.
|
|
49
49
|
3. Update response plots from the current ROIs.
|
|
50
|
-
4. Click Save ROIs + analysis when the plots look right.
|
|
50
|
+
4. Click Save ROIs + analysis in Export when the plots look right.
|
|
51
51
|
|
|
52
52
|
When a source recording has not been converted yet, twopy converts it first. Converted data includes the aligned movie, mean image, stimulus tables, photodiode signals, and recording metadata.
|
|
53
53
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "twopy"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.9"
|
|
8
8
|
description = "Two-photon imaging analysis tool with a napari interface."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.13,<3.14"
|
|
@@ -32,6 +32,9 @@ twopy = "twopy.napari:main"
|
|
|
32
32
|
[tool.setuptools.packages.find]
|
|
33
33
|
where = ["src"]
|
|
34
34
|
|
|
35
|
+
[tool.setuptools.package-data]
|
|
36
|
+
twopy = ["calibrations/*.csv"]
|
|
37
|
+
|
|
35
38
|
[tool.ruff]
|
|
36
39
|
line-length = 88
|
|
37
40
|
src = ["src", "tests"]
|
|
@@ -14,15 +14,23 @@ from twopy.analysis import (
|
|
|
14
14
|
BackgroundCorrectedRoiTraces,
|
|
15
15
|
BackgroundCorrectionMethod,
|
|
16
16
|
CorrelationFilterOptions,
|
|
17
|
+
DeltaFOverFBaselineMode,
|
|
17
18
|
DeltaFOverFFitMode,
|
|
18
19
|
DeltaFOverFOptions,
|
|
19
20
|
EpochFrameWindow,
|
|
21
|
+
EpochResponseMap,
|
|
20
22
|
FrameWindow,
|
|
21
23
|
GroupedRoiResponses,
|
|
22
24
|
GroupedRoiResponseSummary,
|
|
23
25
|
InterpolatedEpochMapping,
|
|
24
26
|
LoadedAnalysisOutputs,
|
|
25
27
|
LowPassFilterOptions,
|
|
28
|
+
ManualFovGroupRow,
|
|
29
|
+
ManualRoiMatchRow,
|
|
30
|
+
ManualRoiMatchStatus,
|
|
31
|
+
ResponseMapData,
|
|
32
|
+
ResponseMapMode,
|
|
33
|
+
ResponseMapOptions,
|
|
26
34
|
ResponseProcessingOptions,
|
|
27
35
|
RoiCorrelationScores,
|
|
28
36
|
RoiDeltaFOverF,
|
|
@@ -31,20 +39,33 @@ from twopy.analysis import (
|
|
|
31
39
|
SmoothingOptions,
|
|
32
40
|
WindowedRoiResponse,
|
|
33
41
|
analyze_recording_responses,
|
|
42
|
+
append_manual_roi_match_rows,
|
|
34
43
|
apply_motion_artifact_mask_to_delta_f_over_f,
|
|
44
|
+
compute_recording_response_maps,
|
|
35
45
|
compute_recording_responses,
|
|
36
46
|
compute_roi_delta_f_over_f,
|
|
37
47
|
default_baseline_epoch_number,
|
|
48
|
+
default_recording_baseline_epoch_number,
|
|
38
49
|
extract_background_corrected_roi_traces,
|
|
39
50
|
frame_windows_from_photodiode_alignment,
|
|
40
51
|
group_delta_f_over_f_by_epoch,
|
|
41
52
|
interpolate_stimulus_epochs_to_frame_windows,
|
|
42
53
|
is_baseline_epoch_name,
|
|
43
54
|
load_analysis_outputs,
|
|
55
|
+
load_manual_fov_group_rows,
|
|
56
|
+
load_manual_roi_match_rows,
|
|
57
|
+
load_response_map_data,
|
|
44
58
|
make_frame_windows,
|
|
59
|
+
make_manual_fov_group_rows,
|
|
60
|
+
make_manual_roi_match_rows,
|
|
45
61
|
map_stimulus_epochs_to_frame_windows,
|
|
62
|
+
next_group_cell_id,
|
|
63
|
+
no_baseline_epoch_frame_windows,
|
|
46
64
|
resolve_baseline_frame_windows,
|
|
47
65
|
save_analysis_outputs,
|
|
66
|
+
save_manual_fov_group_rows,
|
|
67
|
+
save_manual_roi_match_rows,
|
|
68
|
+
save_response_map_data,
|
|
48
69
|
select_baseline_frame_windows,
|
|
49
70
|
split_traces_by_frame_windows,
|
|
50
71
|
summarize_epoch_roi_responses,
|
|
@@ -73,6 +94,33 @@ from twopy.photodiode_classification import (
|
|
|
73
94
|
PhotodiodeEventType,
|
|
74
95
|
classify_recording_photodiode_events,
|
|
75
96
|
)
|
|
97
|
+
from twopy.pixel_calibration import (
|
|
98
|
+
DEFAULT_PIXEL_CALIBRATION_PATH,
|
|
99
|
+
PixelCalibrationResolution,
|
|
100
|
+
PixelCalibrationResolutionMethod,
|
|
101
|
+
PixelCalibrationRow,
|
|
102
|
+
load_pixel_calibrations,
|
|
103
|
+
resolve_pixel_size_um,
|
|
104
|
+
)
|
|
105
|
+
from twopy.pixel_calibration_profiles import (
|
|
106
|
+
DEFAULT_PIXEL_CALIBRATION_PROFILE_PATH,
|
|
107
|
+
PixelCalibrationGroup,
|
|
108
|
+
PixelCalibrationProfile,
|
|
109
|
+
PixelCalibrationProfileMapping,
|
|
110
|
+
PixelCalibrationProfileSource,
|
|
111
|
+
load_pixel_calibration_profile_mappings,
|
|
112
|
+
resolve_pixel_calibration_profile,
|
|
113
|
+
select_pixel_calibration_group,
|
|
114
|
+
)
|
|
115
|
+
from twopy.response_roi_extraction import (
|
|
116
|
+
ResponseNormalization,
|
|
117
|
+
ResponsePolarity,
|
|
118
|
+
ResponseStatistic,
|
|
119
|
+
ResponseWatershedExtraction,
|
|
120
|
+
ResponseWatershedScoreImages,
|
|
121
|
+
extract_response_watershed_rois,
|
|
122
|
+
response_watershed_roi_set,
|
|
123
|
+
)
|
|
76
124
|
from twopy.roi import (
|
|
77
125
|
RoiSet,
|
|
78
126
|
RoiTraces,
|
|
@@ -83,6 +131,15 @@ from twopy.roi import (
|
|
|
83
131
|
roi_set_to_label_image,
|
|
84
132
|
save_roi_set,
|
|
85
133
|
)
|
|
134
|
+
from twopy.roi_extraction import (
|
|
135
|
+
RoiExtractionConfig,
|
|
136
|
+
RoiExtractionMethod,
|
|
137
|
+
extract_rois_from_image,
|
|
138
|
+
grid_roi_set,
|
|
139
|
+
grid_roi_set_microns,
|
|
140
|
+
grid_size_pixels_from_microns,
|
|
141
|
+
watershed_roi_set,
|
|
142
|
+
)
|
|
86
143
|
from twopy.spatial import SpatialCrop, SpatialDomain, full_frame_crop
|
|
87
144
|
from twopy.stimulus import (
|
|
88
145
|
StimulusSpecificColumnMapping,
|
|
@@ -106,6 +163,7 @@ __all__ = [
|
|
|
106
163
|
"AnalysisResponseComputation",
|
|
107
164
|
"analyze_recording_responses",
|
|
108
165
|
"add_twopy_magicgui_controls",
|
|
166
|
+
"append_manual_roi_match_rows",
|
|
109
167
|
"apply_motion_artifact_mask_to_delta_f_over_f",
|
|
110
168
|
"BackgroundCorrectedRoiTraces",
|
|
111
169
|
"BackgroundCorrectionMethod",
|
|
@@ -114,18 +172,26 @@ __all__ = [
|
|
|
114
172
|
"ClassifiedStimulusWindow",
|
|
115
173
|
"classify_recording_photodiode_events",
|
|
116
174
|
"compute_roi_delta_f_over_f",
|
|
175
|
+
"compute_recording_response_maps",
|
|
117
176
|
"compute_recording_responses",
|
|
118
177
|
"CorrelationFilterOptions",
|
|
119
178
|
"convert_recording_to_twopy",
|
|
120
179
|
"DEFAULT_RESPONSE_POST_WINDOW_SECONDS",
|
|
121
180
|
"DEFAULT_RESPONSE_PRE_WINDOW_SECONDS",
|
|
181
|
+
"DEFAULT_PIXEL_CALIBRATION_PATH",
|
|
182
|
+
"DEFAULT_PIXEL_CALIBRATION_PROFILE_PATH",
|
|
122
183
|
"default_baseline_epoch_number",
|
|
184
|
+
"default_recording_baseline_epoch_number",
|
|
123
185
|
"detect_photodiode_events",
|
|
124
186
|
"detect_recording_photodiode_events",
|
|
187
|
+
"DeltaFOverFBaselineMode",
|
|
125
188
|
"DeltaFOverFFitMode",
|
|
126
189
|
"DeltaFOverFOptions",
|
|
190
|
+
"EpochResponseMap",
|
|
127
191
|
"EpochFrameWindow",
|
|
128
192
|
"extract_background_corrected_roi_traces",
|
|
193
|
+
"extract_response_watershed_rois",
|
|
194
|
+
"extract_rois_from_image",
|
|
129
195
|
"extract_roi_traces",
|
|
130
196
|
"find_recordings",
|
|
131
197
|
"frame_windows_from_photodiode_alignment",
|
|
@@ -134,20 +200,35 @@ __all__ = [
|
|
|
134
200
|
"group_delta_f_over_f_by_epoch",
|
|
135
201
|
"GroupedRoiResponseSummary",
|
|
136
202
|
"GroupedRoiResponses",
|
|
203
|
+
"grid_roi_set",
|
|
204
|
+
"grid_roi_set_microns",
|
|
205
|
+
"grid_size_pixels_from_microns",
|
|
137
206
|
"InterpolatedEpochMapping",
|
|
138
207
|
"interpolate_stimulus_epochs_to_frame_windows",
|
|
139
208
|
"is_baseline_epoch_name",
|
|
140
209
|
"launch_napari",
|
|
141
210
|
"load_analysis_outputs",
|
|
211
|
+
"load_response_map_data",
|
|
212
|
+
"load_manual_fov_group_rows",
|
|
213
|
+
"load_manual_roi_match_rows",
|
|
142
214
|
"load_converted_recording",
|
|
215
|
+
"load_pixel_calibrations",
|
|
216
|
+
"load_pixel_calibration_profile_mappings",
|
|
143
217
|
"load_roi_set",
|
|
144
218
|
"load_source_conversion_inputs",
|
|
145
219
|
"LoadedAnalysisOutputs",
|
|
146
220
|
"LowPassFilterOptions",
|
|
221
|
+
"ManualFovGroupRow",
|
|
222
|
+
"ManualRoiMatchRow",
|
|
223
|
+
"ManualRoiMatchStatus",
|
|
147
224
|
"make_roi_set_from_label_image",
|
|
148
225
|
"make_frame_windows",
|
|
226
|
+
"make_manual_fov_group_rows",
|
|
227
|
+
"make_manual_roi_match_rows",
|
|
149
228
|
"make_roi_set",
|
|
150
229
|
"map_stimulus_epochs_to_frame_windows",
|
|
230
|
+
"next_group_cell_id",
|
|
231
|
+
"no_baseline_epoch_frame_windows",
|
|
151
232
|
"map_stimulus_specific_column",
|
|
152
233
|
"NapariRecordingView",
|
|
153
234
|
"NapariSidebarWidgets",
|
|
@@ -158,9 +239,29 @@ __all__ = [
|
|
|
158
239
|
"PhotodiodeEvent",
|
|
159
240
|
"PhotodiodeEventType",
|
|
160
241
|
"PhotodiodeEventSet",
|
|
242
|
+
"PixelCalibrationResolution",
|
|
243
|
+
"PixelCalibrationResolutionMethod",
|
|
244
|
+
"PixelCalibrationGroup",
|
|
245
|
+
"PixelCalibrationProfile",
|
|
246
|
+
"PixelCalibrationProfileMapping",
|
|
247
|
+
"PixelCalibrationProfileSource",
|
|
248
|
+
"PixelCalibrationRow",
|
|
249
|
+
"ResponseNormalization",
|
|
250
|
+
"ResponsePolarity",
|
|
251
|
+
"ResponseMapData",
|
|
252
|
+
"ResponseMapMode",
|
|
253
|
+
"ResponseMapOptions",
|
|
161
254
|
"ResponseProcessingOptions",
|
|
255
|
+
"ResponseStatistic",
|
|
256
|
+
"ResponseWatershedExtraction",
|
|
257
|
+
"ResponseWatershedScoreImages",
|
|
162
258
|
"recording_frame_rate_hz",
|
|
259
|
+
"resolve_pixel_size_um",
|
|
260
|
+
"resolve_pixel_calibration_profile",
|
|
163
261
|
"resolve_baseline_frame_windows",
|
|
262
|
+
"response_watershed_roi_set",
|
|
263
|
+
"RoiExtractionConfig",
|
|
264
|
+
"RoiExtractionMethod",
|
|
164
265
|
"RoiDeltaFOverF",
|
|
165
266
|
"RoiCorrelationScores",
|
|
166
267
|
"RoiResponseSummary",
|
|
@@ -170,9 +271,13 @@ __all__ = [
|
|
|
170
271
|
"roi_label_image_from_layer",
|
|
171
272
|
"roi_set_to_label_image",
|
|
172
273
|
"save_analysis_outputs",
|
|
274
|
+
"save_response_map_data",
|
|
275
|
+
"save_manual_fov_group_rows",
|
|
276
|
+
"save_manual_roi_match_rows",
|
|
173
277
|
"save_napari_label_rois",
|
|
174
278
|
"save_roi_set",
|
|
175
279
|
"select_baseline_frame_windows",
|
|
280
|
+
"select_pixel_calibration_group",
|
|
176
281
|
"split_traces_by_frame_windows",
|
|
177
282
|
"SmoothingOptions",
|
|
178
283
|
"SpatialCrop",
|
|
@@ -182,6 +287,7 @@ __all__ = [
|
|
|
182
287
|
"summarize_epoch_roi_responses",
|
|
183
288
|
"summarize_grouped_responses",
|
|
184
289
|
"validate_grouped_roi_responses",
|
|
290
|
+
"watershed_roi_set",
|
|
185
291
|
"WindowedRoiResponse",
|
|
186
292
|
"write_response_summary_grouped_csv",
|
|
187
293
|
"write_response_summary_trials_csv",
|
|
@@ -18,11 +18,24 @@ from twopy.analysis.dff import (
|
|
|
18
18
|
RoiDeltaFOverF,
|
|
19
19
|
compute_roi_delta_f_over_f,
|
|
20
20
|
)
|
|
21
|
-
from twopy.analysis.dff_options import DeltaFOverFOptions
|
|
21
|
+
from twopy.analysis.dff_options import DeltaFOverFBaselineMode, DeltaFOverFOptions
|
|
22
22
|
from twopy.analysis.epoch_mapping import (
|
|
23
23
|
InterpolatedEpochMapping,
|
|
24
24
|
interpolate_stimulus_epochs_to_frame_windows,
|
|
25
25
|
)
|
|
26
|
+
from twopy.analysis.group_matching import (
|
|
27
|
+
ManualFovGroupRow,
|
|
28
|
+
ManualRoiMatchRow,
|
|
29
|
+
ManualRoiMatchStatus,
|
|
30
|
+
append_manual_roi_match_rows,
|
|
31
|
+
load_manual_fov_group_rows,
|
|
32
|
+
load_manual_roi_match_rows,
|
|
33
|
+
make_manual_fov_group_rows,
|
|
34
|
+
make_manual_roi_match_rows,
|
|
35
|
+
next_group_cell_id,
|
|
36
|
+
save_manual_fov_group_rows,
|
|
37
|
+
save_manual_roi_match_rows,
|
|
38
|
+
)
|
|
26
39
|
from twopy.analysis.motion import apply_motion_artifact_mask_to_delta_f_over_f
|
|
27
40
|
from twopy.analysis.persistence import (
|
|
28
41
|
ANALYSIS_OUTPUT_FILE_FORMAT,
|
|
@@ -32,6 +45,16 @@ from twopy.analysis.persistence import (
|
|
|
32
45
|
write_response_summary_grouped_csv,
|
|
33
46
|
write_response_summary_trials_csv,
|
|
34
47
|
)
|
|
48
|
+
from twopy.analysis.response_context import default_recording_baseline_epoch_number
|
|
49
|
+
from twopy.analysis.response_maps import (
|
|
50
|
+
EpochResponseMap,
|
|
51
|
+
ResponseMapData,
|
|
52
|
+
ResponseMapMode,
|
|
53
|
+
ResponseMapOptions,
|
|
54
|
+
compute_recording_response_maps,
|
|
55
|
+
load_response_map_data,
|
|
56
|
+
save_response_map_data,
|
|
57
|
+
)
|
|
35
58
|
from twopy.analysis.response_processing import (
|
|
36
59
|
CorrelationFilterOptions,
|
|
37
60
|
LowPassFilterOptions,
|
|
@@ -58,6 +81,7 @@ from twopy.analysis.trials import (
|
|
|
58
81
|
is_baseline_epoch_name,
|
|
59
82
|
make_frame_windows,
|
|
60
83
|
map_stimulus_epochs_to_frame_windows,
|
|
84
|
+
no_baseline_epoch_frame_windows,
|
|
61
85
|
resolve_baseline_frame_windows,
|
|
62
86
|
select_baseline_frame_windows,
|
|
63
87
|
split_traces_by_frame_windows,
|
|
@@ -83,10 +107,14 @@ __all__ = [
|
|
|
83
107
|
"BackgroundCorrectionMethod",
|
|
84
108
|
"compute_roi_delta_f_over_f",
|
|
85
109
|
"compute_recording_responses",
|
|
110
|
+
"compute_recording_response_maps",
|
|
86
111
|
"CorrelationFilterOptions",
|
|
87
112
|
"default_baseline_epoch_number",
|
|
113
|
+
"default_recording_baseline_epoch_number",
|
|
114
|
+
"DeltaFOverFBaselineMode",
|
|
88
115
|
"DeltaFOverFOptions",
|
|
89
116
|
"DeltaFOverFFitMode",
|
|
117
|
+
"EpochResponseMap",
|
|
90
118
|
"EpochFrameWindow",
|
|
91
119
|
"extract_background_corrected_roi_traces",
|
|
92
120
|
"frame_windows_from_photodiode_alignment",
|
|
@@ -98,17 +126,34 @@ __all__ = [
|
|
|
98
126
|
"interpolate_stimulus_epochs_to_frame_windows",
|
|
99
127
|
"is_baseline_epoch_name",
|
|
100
128
|
"load_analysis_outputs",
|
|
129
|
+
"load_response_map_data",
|
|
101
130
|
"LoadedAnalysisOutputs",
|
|
102
131
|
"LowPassFilterOptions",
|
|
132
|
+
"ManualFovGroupRow",
|
|
133
|
+
"ManualRoiMatchRow",
|
|
134
|
+
"ManualRoiMatchStatus",
|
|
103
135
|
"make_frame_windows",
|
|
136
|
+
"make_manual_fov_group_rows",
|
|
137
|
+
"make_manual_roi_match_rows",
|
|
104
138
|
"map_stimulus_epochs_to_frame_windows",
|
|
139
|
+
"no_baseline_epoch_frame_windows",
|
|
140
|
+
"next_group_cell_id",
|
|
105
141
|
"RoiDeltaFOverF",
|
|
142
|
+
"ResponseMapData",
|
|
143
|
+
"ResponseMapMode",
|
|
144
|
+
"ResponseMapOptions",
|
|
106
145
|
"ResponseProcessingOptions",
|
|
107
146
|
"RoiCorrelationScores",
|
|
108
147
|
"RoiResponseSummary",
|
|
109
148
|
"RoiResponseTrial",
|
|
110
149
|
"resolve_baseline_frame_windows",
|
|
150
|
+
"append_manual_roi_match_rows",
|
|
151
|
+
"load_manual_fov_group_rows",
|
|
152
|
+
"load_manual_roi_match_rows",
|
|
111
153
|
"save_analysis_outputs",
|
|
154
|
+
"save_response_map_data",
|
|
155
|
+
"save_manual_fov_group_rows",
|
|
156
|
+
"save_manual_roi_match_rows",
|
|
112
157
|
"select_baseline_frame_windows",
|
|
113
158
|
"split_traces_by_frame_windows",
|
|
114
159
|
"SmoothingOptions",
|
|
@@ -9,6 +9,7 @@ trace extraction stay in ``twopy.roi``; dF/F and trial analysis can consume the
|
|
|
9
9
|
auditable outputs produced here.
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
|
+
from collections.abc import Callable
|
|
12
13
|
from dataclasses import dataclass
|
|
13
14
|
from typing import Literal
|
|
14
15
|
|
|
@@ -75,6 +76,7 @@ def extract_background_corrected_roi_traces(
|
|
|
75
76
|
local_y_radius: int | None = None,
|
|
76
77
|
local_percentile: float = 20.0,
|
|
77
78
|
spatial_domain: SpatialDomain = "alignment_valid_crop",
|
|
79
|
+
check_cancelled: Callable[[], None] | None = None,
|
|
78
80
|
) -> BackgroundCorrectedRoiTraces:
|
|
79
81
|
"""Extract ROI traces plus an explicit background correction.
|
|
80
82
|
|
|
@@ -108,6 +110,8 @@ def extract_background_corrected_roi_traces(
|
|
|
108
110
|
uses the alignment-valid crop saved during conversion, matching the
|
|
109
111
|
crop-domain analysis contract while keeping ROI masks stored in
|
|
110
112
|
full-frame coordinates.
|
|
113
|
+
check_cancelled: Optional callback that raises ``CancelledError`` when
|
|
114
|
+
an interactive caller has superseded this computation.
|
|
111
115
|
|
|
112
116
|
Returns:
|
|
113
117
|
``BackgroundCorrectedRoiTraces`` with raw, background, and corrected
|
|
@@ -115,7 +119,10 @@ def extract_background_corrected_roi_traces(
|
|
|
115
119
|
|
|
116
120
|
Raises:
|
|
117
121
|
ValueError: If masks do not match the movie or a background mask is
|
|
118
|
-
empty.
|
|
122
|
+
empty. ROI y-stripe background correction also raises when the
|
|
123
|
+
selected spatial domain has no unlabeled pixels outside all ROIs,
|
|
124
|
+
which is expected for dense grid ROIs that cover the whole analysis
|
|
125
|
+
crop.
|
|
119
126
|
|
|
120
127
|
The function streams movie chunks from HDF5 and never loads the full movie
|
|
121
128
|
into memory. Each method records enough metadata to audit how the background
|
|
@@ -124,6 +131,7 @@ def extract_background_corrected_roi_traces(
|
|
|
124
131
|
_validate_background_method(method)
|
|
125
132
|
validate_trace_statistic(statistic)
|
|
126
133
|
_validate_roi_movie_shape(roi_set, recording)
|
|
134
|
+
_check_cancelled(check_cancelled)
|
|
127
135
|
|
|
128
136
|
frame_start, frame_stop = normalize_frame_range(
|
|
129
137
|
frame_count=recording.movie.shape[0],
|
|
@@ -144,6 +152,7 @@ def extract_background_corrected_roi_traces(
|
|
|
144
152
|
frame_stop=frame_stop,
|
|
145
153
|
chunk_frames=chunk_frames,
|
|
146
154
|
spatial_crop=crop,
|
|
155
|
+
check_cancelled=check_cancelled,
|
|
147
156
|
)
|
|
148
157
|
background_values = np.zeros_like(raw_values)
|
|
149
158
|
corrected_values = raw_values.copy()
|
|
@@ -162,6 +171,7 @@ def extract_background_corrected_roi_traces(
|
|
|
162
171
|
percentile=global_percentile,
|
|
163
172
|
spatial_crop=crop,
|
|
164
173
|
spatial_domain=spatial_domain,
|
|
174
|
+
check_cancelled=check_cancelled,
|
|
165
175
|
)
|
|
166
176
|
)
|
|
167
177
|
elif method == "movie_y_stripe_percentile":
|
|
@@ -176,6 +186,7 @@ def extract_background_corrected_roi_traces(
|
|
|
176
186
|
percentile=stripe_percentile,
|
|
177
187
|
spatial_crop=crop,
|
|
178
188
|
spatial_domain=spatial_domain,
|
|
189
|
+
check_cancelled=check_cancelled,
|
|
179
190
|
)
|
|
180
191
|
)
|
|
181
192
|
elif method == "roi_y_stripe_percentile":
|
|
@@ -191,6 +202,7 @@ def extract_background_corrected_roi_traces(
|
|
|
191
202
|
local_percentile=local_percentile,
|
|
192
203
|
spatial_crop=crop,
|
|
193
204
|
spatial_domain=spatial_domain,
|
|
205
|
+
check_cancelled=check_cancelled,
|
|
194
206
|
)
|
|
195
207
|
)
|
|
196
208
|
|
|
@@ -244,6 +256,7 @@ def _extract_mean_traces_from_indices(
|
|
|
244
256
|
frame_stop: int,
|
|
245
257
|
chunk_frames: int,
|
|
246
258
|
spatial_crop: SpatialCrop,
|
|
259
|
+
check_cancelled: Callable[[], None] | None = None,
|
|
247
260
|
) -> npt.NDArray[np.float64]:
|
|
248
261
|
"""Extract mean traces for arbitrary flattened pixel-index groups.
|
|
249
262
|
|
|
@@ -255,6 +268,7 @@ def _extract_mean_traces_from_indices(
|
|
|
255
268
|
frame_stop: Exclusive stop frame.
|
|
256
269
|
chunk_frames: Maximum number of frames per HDF5 read.
|
|
257
270
|
spatial_crop: Spatial domain read from each movie frame.
|
|
271
|
+
check_cancelled: Optional callback that raises when work is obsolete.
|
|
258
272
|
|
|
259
273
|
Returns:
|
|
260
274
|
Array shaped ``(frames, traces)``.
|
|
@@ -264,12 +278,14 @@ def _extract_mean_traces_from_indices(
|
|
|
264
278
|
rather than total recording length.
|
|
265
279
|
"""
|
|
266
280
|
traces = np.empty((frame_stop - frame_start, len(pixel_indices_by_trace)))
|
|
281
|
+
_check_cancelled(check_cancelled)
|
|
267
282
|
for chunk_start, chunk_stop, frames in recording.movie.iter_frame_batches(
|
|
268
283
|
chunk_frames=chunk_frames,
|
|
269
284
|
start=frame_start,
|
|
270
285
|
stop=frame_stop,
|
|
271
286
|
spatial_crop=spatial_crop,
|
|
272
287
|
):
|
|
288
|
+
_check_cancelled(check_cancelled)
|
|
273
289
|
chunk_offset = chunk_start - frame_start
|
|
274
290
|
chunk_slice = slice(chunk_offset, chunk_offset + (chunk_stop - chunk_start))
|
|
275
291
|
chunk_flat = frames.reshape(frames.shape[0], -1)
|
|
@@ -277,6 +293,7 @@ def _extract_mean_traces_from_indices(
|
|
|
277
293
|
traces[chunk_slice, trace_index] = chunk_flat[:, pixel_indices].mean(
|
|
278
294
|
axis=1,
|
|
279
295
|
)
|
|
296
|
+
_check_cancelled(check_cancelled)
|
|
280
297
|
|
|
281
298
|
return traces
|
|
282
299
|
|
|
@@ -291,6 +308,7 @@ def _extract_movie_global_percentile_corrected_traces(
|
|
|
291
308
|
percentile: float,
|
|
292
309
|
spatial_crop: SpatialCrop,
|
|
293
310
|
spatial_domain: SpatialDomain,
|
|
311
|
+
check_cancelled: Callable[[], None] | None = None,
|
|
294
312
|
) -> tuple[
|
|
295
313
|
npt.NDArray[np.float64],
|
|
296
314
|
npt.NDArray[np.float64],
|
|
@@ -308,6 +326,7 @@ def _extract_movie_global_percentile_corrected_traces(
|
|
|
308
326
|
percentile: Mean-image percentile used to define background pixels.
|
|
309
327
|
spatial_crop: Spatial domain used for background and ROI pixels.
|
|
310
328
|
spatial_domain: User-facing name of ``spatial_crop``.
|
|
329
|
+
check_cancelled: Optional callback that raises when work is obsolete.
|
|
311
330
|
|
|
312
331
|
Returns:
|
|
313
332
|
Raw ROI traces, repeated background traces, corrected ROI traces, and
|
|
@@ -317,6 +336,7 @@ def _extract_movie_global_percentile_corrected_traces(
|
|
|
317
336
|
negatives to zero, and then averages corrected pixels inside each ROI.
|
|
318
337
|
"""
|
|
319
338
|
_validate_percentile(percentile)
|
|
339
|
+
_check_cancelled(check_cancelled)
|
|
320
340
|
mean_image = spatial_crop.crop_image(recording.mean_image)
|
|
321
341
|
background_indices, threshold = _global_background_pixel_indices(
|
|
322
342
|
mean_image,
|
|
@@ -334,6 +354,7 @@ def _extract_movie_global_percentile_corrected_traces(
|
|
|
334
354
|
stop=frame_stop,
|
|
335
355
|
spatial_crop=spatial_crop,
|
|
336
356
|
):
|
|
357
|
+
_check_cancelled(check_cancelled)
|
|
337
358
|
chunk_offset = chunk_start - frame_start
|
|
338
359
|
chunk_slice = slice(chunk_offset, chunk_offset + (chunk_stop - chunk_start))
|
|
339
360
|
chunk_flat = frames.reshape(frames.shape[0], -1)
|
|
@@ -346,6 +367,7 @@ def _extract_movie_global_percentile_corrected_traces(
|
|
|
346
367
|
# corrected ROI trace below zero.
|
|
347
368
|
corrected_pixels = np.maximum(roi_pixels - background_trace[:, None], 0.0)
|
|
348
369
|
corrected_values[chunk_slice, roi_index] = corrected_pixels.mean(axis=1)
|
|
370
|
+
_check_cancelled(check_cancelled)
|
|
349
371
|
|
|
350
372
|
metadata: dict[str, BackgroundMetadataValue] = {
|
|
351
373
|
"method": "movie_global_percentile",
|
|
@@ -369,6 +391,7 @@ def _extract_movie_y_stripe_percentile_corrected_traces(
|
|
|
369
391
|
percentile: float,
|
|
370
392
|
spatial_crop: SpatialCrop,
|
|
371
393
|
spatial_domain: SpatialDomain,
|
|
394
|
+
check_cancelled: Callable[[], None] | None = None,
|
|
372
395
|
) -> tuple[
|
|
373
396
|
npt.NDArray[np.float64],
|
|
374
397
|
npt.NDArray[np.float64],
|
|
@@ -388,6 +411,7 @@ def _extract_movie_y_stripe_percentile_corrected_traces(
|
|
|
388
411
|
percentile: Percentile used inside each frame stripe.
|
|
389
412
|
spatial_crop: Spatial domain used for background and ROI pixels.
|
|
390
413
|
spatial_domain: User-facing name of ``spatial_crop``.
|
|
414
|
+
check_cancelled: Optional callback that raises when work is obsolete.
|
|
391
415
|
|
|
392
416
|
Returns:
|
|
393
417
|
Raw ROI traces, stripe-field background traces, corrected traces, and
|
|
@@ -404,6 +428,7 @@ def _extract_movie_y_stripe_percentile_corrected_traces(
|
|
|
404
428
|
near one ROI are safe neuropil reference pixels.
|
|
405
429
|
"""
|
|
406
430
|
_validate_percentile(percentile)
|
|
431
|
+
_check_cancelled(check_cancelled)
|
|
407
432
|
crop_shape = spatial_crop.crop_image(recording.mean_image).shape
|
|
408
433
|
stripe_height = _resolve_stripe_y_height(
|
|
409
434
|
row_count=crop_shape[0],
|
|
@@ -425,6 +450,7 @@ def _extract_movie_y_stripe_percentile_corrected_traces(
|
|
|
425
450
|
stop=frame_stop,
|
|
426
451
|
spatial_crop=spatial_crop,
|
|
427
452
|
):
|
|
453
|
+
_check_cancelled(check_cancelled)
|
|
428
454
|
chunk_offset = chunk_start - frame_start
|
|
429
455
|
chunk_slice = slice(chunk_offset, chunk_offset + (chunk_stop - chunk_start))
|
|
430
456
|
background_field = _framewise_y_stripe_background_field(
|
|
@@ -443,6 +469,7 @@ def _extract_movie_y_stripe_percentile_corrected_traces(
|
|
|
443
469
|
)
|
|
444
470
|
corrected_pixels = np.maximum(roi_pixels - roi_background_pixels, 0.0)
|
|
445
471
|
corrected_values[chunk_slice, roi_index] = corrected_pixels.mean(axis=1)
|
|
472
|
+
_check_cancelled(check_cancelled)
|
|
446
473
|
|
|
447
474
|
metadata: dict[str, BackgroundMetadataValue] = {
|
|
448
475
|
"method": "movie_y_stripe_percentile",
|
|
@@ -467,6 +494,7 @@ def _extract_roi_y_stripe_percentile_corrected_traces(
|
|
|
467
494
|
local_percentile: float,
|
|
468
495
|
spatial_crop: SpatialCrop,
|
|
469
496
|
spatial_domain: SpatialDomain,
|
|
497
|
+
check_cancelled: Callable[[], None] | None = None,
|
|
470
498
|
) -> tuple[
|
|
471
499
|
npt.NDArray[np.float64],
|
|
472
500
|
npt.NDArray[np.float64],
|
|
@@ -487,6 +515,7 @@ def _extract_roi_y_stripe_percentile_corrected_traces(
|
|
|
487
515
|
y-stripe.
|
|
488
516
|
spatial_crop: Spatial domain used for background and ROI pixels.
|
|
489
517
|
spatial_domain: User-facing name of ``spatial_crop``.
|
|
518
|
+
check_cancelled: Optional callback that raises when work is obsolete.
|
|
490
519
|
|
|
491
520
|
Returns:
|
|
492
521
|
Raw ROI traces, local background traces, corrected traces, and metadata.
|
|
@@ -508,6 +537,7 @@ def _extract_roi_y_stripe_percentile_corrected_traces(
|
|
|
508
537
|
local_y_radius=local_y_radius,
|
|
509
538
|
)
|
|
510
539
|
_validate_percentile(local_percentile)
|
|
540
|
+
_check_cancelled(check_cancelled)
|
|
511
541
|
background_indices_by_roi = _roi_y_stripe_background_pixel_indices(
|
|
512
542
|
roi_masks=roi_masks,
|
|
513
543
|
mean_image=spatial_crop.crop_image(recording.mean_image),
|
|
@@ -521,6 +551,7 @@ def _extract_roi_y_stripe_percentile_corrected_traces(
|
|
|
521
551
|
frame_stop=frame_stop,
|
|
522
552
|
chunk_frames=chunk_frames,
|
|
523
553
|
spatial_crop=spatial_crop,
|
|
554
|
+
check_cancelled=check_cancelled,
|
|
524
555
|
)
|
|
525
556
|
background_values = _extract_mean_traces_from_indices(
|
|
526
557
|
recording=recording,
|
|
@@ -529,6 +560,7 @@ def _extract_roi_y_stripe_percentile_corrected_traces(
|
|
|
529
560
|
frame_stop=frame_stop,
|
|
530
561
|
chunk_frames=chunk_frames,
|
|
531
562
|
spatial_crop=spatial_crop,
|
|
563
|
+
check_cancelled=check_cancelled,
|
|
532
564
|
)
|
|
533
565
|
corrected_values = raw_values - background_values
|
|
534
566
|
background_counts = tuple(
|
|
@@ -561,6 +593,13 @@ def _roi_pixel_indices_from_masks(
|
|
|
561
593
|
return tuple(np.flatnonzero(mask).astype(np.int64) for mask in flat_masks)
|
|
562
594
|
|
|
563
595
|
|
|
596
|
+
def _check_cancelled(check_cancelled: Callable[[], None] | None) -> None:
|
|
597
|
+
"""Raise ``CancelledError`` when an interactive caller superseded this work."""
|
|
598
|
+
if check_cancelled is None:
|
|
599
|
+
return
|
|
600
|
+
check_cancelled()
|
|
601
|
+
|
|
602
|
+
|
|
564
603
|
def _crop_roi_masks_for_domain(
|
|
565
604
|
roi_set: RoiSet,
|
|
566
605
|
spatial_crop: SpatialCrop,
|
|
@@ -770,6 +809,15 @@ def _roi_y_stripe_background_pixel_indices(
|
|
|
770
809
|
"""
|
|
771
810
|
occupied_mask = np.any(roi_masks, axis=0)
|
|
772
811
|
background_mask = ~occupied_mask
|
|
812
|
+
if not np.any(background_mask):
|
|
813
|
+
msg = (
|
|
814
|
+
"ROI y-stripe P% background subtraction needs unlabeled background "
|
|
815
|
+
"pixels outside all ROIs in the selected spatial domain. The current "
|
|
816
|
+
"ROI masks cover every pixel, which is common for dense grid ROIs; "
|
|
817
|
+
"use shared y-stripe P% or leave unlabeled background pixels."
|
|
818
|
+
)
|
|
819
|
+
raise ValueError(msg)
|
|
820
|
+
|
|
773
821
|
row_grid = np.arange(background_mask.shape[0])[:, None]
|
|
774
822
|
background_indices: list[npt.NDArray[np.int64]] = []
|
|
775
823
|
|
|
@@ -782,7 +830,10 @@ def _roi_y_stripe_background_pixel_indices(
|
|
|
782
830
|
if local_candidate_values.size == 0:
|
|
783
831
|
msg = (
|
|
784
832
|
f"ROI {roi_index} has no local background candidates within "
|
|
785
|
-
f"{local_y_radius} rows"
|
|
833
|
+
f"{local_y_radius} rows. ROI y-stripe P% only uses unlabeled "
|
|
834
|
+
"pixels outside all ROIs; increase the local y radius, use "
|
|
835
|
+
"shared y-stripe P%, or leave unlabeled background pixels near "
|
|
836
|
+
"this ROI."
|
|
786
837
|
)
|
|
787
838
|
raise ValueError(msg)
|
|
788
839
|
local_threshold = float(np.percentile(local_candidate_values, local_percentile))
|
|
@@ -7,19 +7,23 @@ without hiding the scientific workflow parameters.
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
from dataclasses import dataclass
|
|
10
|
+
from typing import Literal
|
|
10
11
|
|
|
11
12
|
from twopy.analysis.background_subtraction import BackgroundCorrectionMethod
|
|
12
13
|
from twopy.analysis.dff import DeltaFOverFFitMode
|
|
13
14
|
|
|
14
|
-
__all__ = ["DeltaFOverFOptions"]
|
|
15
|
+
__all__ = ["DeltaFOverFBaselineMode", "DeltaFOverFOptions"]
|
|
16
|
+
|
|
17
|
+
DeltaFOverFBaselineMode = Literal["epoch", "no_baseline_epoch"]
|
|
15
18
|
|
|
16
19
|
|
|
17
20
|
@dataclass(frozen=True)
|
|
18
21
|
class DeltaFOverFOptions:
|
|
19
22
|
"""Options that control ROI dF/F computation before response grouping.
|
|
20
23
|
|
|
21
|
-
Inputs: baseline epoch selection, background correction
|
|
22
|
-
window sampling, dF/F fit mode, and motion-artifact
|
|
24
|
+
Inputs: baseline epoch selection, baseline mode, background correction
|
|
25
|
+
method, baseline window sampling, dF/F fit mode, and motion-artifact
|
|
26
|
+
masking choice.
|
|
23
27
|
Outputs: typed parameters that map directly to
|
|
24
28
|
``compute_recording_responses`` and ``analyze_recording_responses``.
|
|
25
29
|
|
|
@@ -27,8 +31,9 @@ class DeltaFOverFOptions:
|
|
|
27
31
|
response processing choices such as smoothing and correlation filtering.
|
|
28
32
|
"""
|
|
29
33
|
|
|
30
|
-
baseline_epoch_number: int =
|
|
34
|
+
baseline_epoch_number: int | None = None
|
|
31
35
|
baseline_epoch_name: str | None = None
|
|
36
|
+
baseline_mode: DeltaFOverFBaselineMode = "epoch"
|
|
32
37
|
background_method: BackgroundCorrectionMethod = "movie_global_percentile"
|
|
33
38
|
baseline_sample_seconds: float | None = 1.0
|
|
34
39
|
fit_mode: DeltaFOverFFitMode = "direct_bounded_tau"
|