TwoPy 0.3.9__tar.gz → 0.4.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.
Files changed (267) hide show
  1. {twopy-0.3.9 → twopy-0.4.0}/PKG-INFO +3 -3
  2. {twopy-0.3.9 → twopy-0.4.0}/README.md +2 -2
  3. {twopy-0.3.9 → twopy-0.4.0}/pyproject.toml +1 -1
  4. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/background_subtraction.py +10 -10
  5. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/dff.py +13 -13
  6. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/epoch_mapping.py +1 -1
  7. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/group_matching.py +1 -1
  8. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/kernels/__init__.py +4 -4
  9. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/persistence.py +1 -1
  10. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/response_maps.py +17 -17
  11. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/response_processing/__init__.py +1 -1
  12. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/response_processing/apply.py +5 -5
  13. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/response_processing/options.py +18 -18
  14. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/response_processing/qc.py +2 -2
  15. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/response_processing/signals.py +12 -12
  16. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/response_window_options.py +2 -2
  17. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/responses.py +16 -16
  18. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/timing.py +1 -1
  19. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/trials.py +2 -2
  20. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/workflow.py +3 -3
  21. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis_cache.py +1 -1
  22. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/config.py +3 -3
  23. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/conversion/alignment_crop.py +2 -2
  24. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/conversion/hdf5_writing.py +2 -2
  25. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/conversion/orientation.py +4 -4
  26. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/conversion/stimulus_code.py +1 -1
  27. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/conversion/types.py +2 -2
  28. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/converted.py +18 -18
  29. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/custom/context.py +6 -6
  30. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/custom/native_workflows/direction_selectivity.py +2 -2
  31. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/custom/native_workflows/response_kernels.py +2 -2
  32. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/custom/parameters.py +1 -1
  33. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/custom/provenance.py +8 -8
  34. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/custom/runner.py +1 -1
  35. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/database/cache.py +1 -1
  36. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/database/catalog.py +1 -1
  37. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/database/modeled.py +1 -1
  38. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/database/search.py +2 -2
  39. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/database/types.py +1 -1
  40. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/matlab.py +1 -1
  41. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/controls.py +44 -36
  42. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/custom_tab.py +119 -41
  43. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/database_favorite_editor.py +2 -0
  44. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/database_search.py +169 -38
  45. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/empty_state.py +24 -14
  46. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/group_matching/cards.py +2 -2
  47. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/group_matching/fov_assignment.py +24 -5
  48. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/group_matching/fov_cards.py +18 -3
  49. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/group_matching/response_preview.py +14 -5
  50. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/group_matching/roi_assignment.py +2 -2
  51. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/group_matching/roi_cards.py +5 -4
  52. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/group_matching/style.py +57 -91
  53. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/group_matching/window.py +0 -17
  54. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/launcher.py +3 -3
  55. twopy-0.4.0/src/twopy/napari/load_picker.py +184 -0
  56. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/load_progress.py +28 -90
  57. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/load_workflow.py +6 -6
  58. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/movie.py +4 -4
  59. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/output_routing.py +1 -1
  60. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/docks/dynamic_options.py +3 -0
  61. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/docks/options_panel.py +3 -0
  62. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/docks/plot_area.py +6 -4
  63. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/docks/response_map_area.py +6 -4
  64. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/docks/response_plot_widget.py +18 -8
  65. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/docks/save_actions.py +4 -4
  66. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/export.py +1 -1
  67. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/export_controls.py +6 -4
  68. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/label_visibility.py +1 -1
  69. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/motion_summary.py +25 -9
  70. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/options.py +6 -4
  71. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/panels.py +15 -4
  72. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/response_map_display.py +2 -2
  73. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/response_map_options.py +1 -1
  74. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/roi_generation/actions.py +1 -1
  75. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/roi_generation/controls.py +2 -0
  76. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/widgets.py +17 -6
  77. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/responses.py +1 -1
  78. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/roi.py +1 -1
  79. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/session.py +47 -11
  80. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/sidebar.py +51 -8
  81. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/state.py +24 -7
  82. twopy-0.4.0/src/twopy/napari/theme.py +661 -0
  83. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/trial_timeline.py +9 -4
  84. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/version_check.py +5 -0
  85. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/viewer.py +1 -1
  86. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/parity/__init__.py +1 -1
  87. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/parity/dff.py +5 -5
  88. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/parity/psycho5.py +6 -6
  89. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/parity/roi.py +2 -2
  90. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/parity/roi_extraction.py +6 -6
  91. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/parity/saved_analysis.py +1 -1
  92. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/photodiode.py +3 -3
  93. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/photodiode_classification.py +4 -4
  94. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/pixel_calibration.py +3 -3
  95. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/response_roi_extraction.py +16 -16
  96. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/roi.py +4 -4
  97. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/roi_extraction.py +7 -7
  98. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/session.py +1 -1
  99. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/stimulus.py +2 -2
  100. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/synchronization.py +1 -1
  101. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/typing_guards.py +3 -3
  102. {twopy-0.3.9 → twopy-0.4.0}/src/twopy.egg-info/PKG-INFO +3 -3
  103. {twopy-0.3.9 → twopy-0.4.0}/src/twopy.egg-info/SOURCES.txt +5 -0
  104. {twopy-0.3.9 → twopy-0.4.0}/tests/test_conversion.py +1 -1
  105. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari.py +45 -6
  106. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari_database_search.py +81 -7
  107. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari_export.py +1 -1
  108. twopy-0.4.0/tests/test_napari_load_picker.py +191 -0
  109. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari_load_progress.py +2 -1
  110. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari_load_tab.py +55 -12
  111. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari_loaded_recordings.py +61 -2
  112. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari_plot_controls.py +8 -5
  113. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari_plot_data.py +1 -1
  114. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari_plot_widgets.py +76 -21
  115. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari_processing_controls.py +37 -13
  116. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari_response_workflow.py +1 -1
  117. twopy-0.4.0/tests/test_napari_state.py +89 -0
  118. twopy-0.4.0/tests/test_napari_theme.py +302 -0
  119. {twopy-0.3.9 → twopy-0.4.0}/tests/test_version_check.py +4 -0
  120. {twopy-0.3.9 → twopy-0.4.0}/setup.cfg +0 -0
  121. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/__init__.py +0 -0
  122. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/__init__.pyi +0 -0
  123. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/_segments.py +0 -0
  124. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/_version.py +0 -0
  125. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/__init__.py +0 -0
  126. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/dff_options.py +0 -0
  127. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/kernels/_fitting.py +0 -0
  128. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/kernels/_stimulus.py +0 -0
  129. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/motion.py +0 -0
  130. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/response_context.py +0 -0
  131. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/response_plotting.py +0 -0
  132. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/analysis/response_processing/persistence.py +0 -0
  133. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/api.py +0 -0
  134. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/cache_inventory.py +0 -0
  135. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/calibrations/pixel_calibration_profiles.csv +0 -0
  136. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/calibrations/pixel_size.csv +0 -0
  137. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/config.example.yml +0 -0
  138. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/conversion/__init__.py +0 -0
  139. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/conversion/api.py +0 -0
  140. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/conversion/matlab_values.py +0 -0
  141. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/conversion/source_loading.py +0 -0
  142. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/custom/__init__.py +0 -0
  143. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/custom/discovery.py +0 -0
  144. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/custom/metadata.py +0 -0
  145. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/custom/native.py +0 -0
  146. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/custom/native_workflows/__init__.py +0 -0
  147. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/custom/registry.py +0 -0
  148. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/custom/results.py +0 -0
  149. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/custom/workflows.py +0 -0
  150. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/database/__init__.py +0 -0
  151. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/database/connection.py +0 -0
  152. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/database/generic.py +0 -0
  153. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/database/sql.py +0 -0
  154. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/filenames.py +0 -0
  155. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/frame_ranges.py +0 -0
  156. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/hdf5_utils.py +0 -0
  157. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/inspection.py +0 -0
  158. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/__init__.py +0 -0
  159. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/__main__.py +0 -0
  160. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/assets/twopy-app-icon-128.png +0 -0
  161. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/assets/twopy-app-icon-16.png +0 -0
  162. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/assets/twopy-app-icon-256.png +0 -0
  163. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/assets/twopy-app-icon-32.png +0 -0
  164. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/assets/twopy-app-icon-512.png +0 -0
  165. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/assets/twopy-app-icon-64.png +0 -0
  166. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/assets/twopy-app-icon.icns +0 -0
  167. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/assets/twopy-app-icon.png +0 -0
  168. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/database_favorites.py +0 -0
  169. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/dims.py +0 -0
  170. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/display.py +0 -0
  171. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/display_paths.py +0 -0
  172. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/errors.py +0 -0
  173. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/group_matching/__init__.py +0 -0
  174. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/group_matching/images.py +0 -0
  175. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/group_matching/protocols.py +0 -0
  176. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/group_matching/responses.py +0 -0
  177. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/group_matching/tables.py +0 -0
  178. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/interactive.py +0 -0
  179. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/latest_worker.py +0 -0
  180. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/live_analysis.py +0 -0
  181. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/load_controller.py +0 -0
  182. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/loaded_recordings_csv.py +0 -0
  183. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/loading.py +0 -0
  184. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/paths.py +0 -0
  185. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/__init__.py +0 -0
  186. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/data.py +0 -0
  187. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/dff_options.py +0 -0
  188. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/docks/__init__.py +0 -0
  189. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/docks/api.py +0 -0
  190. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/docks/paths.py +0 -0
  191. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/docks/visibility_state.py +0 -0
  192. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/form_controls.py +0 -0
  193. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/normalization_options.py +0 -0
  194. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/preview_strip.py +0 -0
  195. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/processing_options.py +0 -0
  196. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/response_map_colors.py +0 -0
  197. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/response_window_options.py +0 -0
  198. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/roi_generation/__init__.py +0 -0
  199. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/plotting/roi_generation/options.py +0 -0
  200. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/protocols.py +0 -0
  201. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/roi_signatures.py +0 -0
  202. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/text.py +0 -0
  203. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/napari/types.py +0 -0
  204. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/pixel_calibration_profiles.py +0 -0
  205. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/roi_mask_cleanup.py +0 -0
  206. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/spatial.py +0 -0
  207. {twopy-0.3.9 → twopy-0.4.0}/src/twopy/spatial_orientation.py +0 -0
  208. {twopy-0.3.9 → twopy-0.4.0}/src/twopy.egg-info/dependency_links.txt +0 -0
  209. {twopy-0.3.9 → twopy-0.4.0}/src/twopy.egg-info/entry_points.txt +0 -0
  210. {twopy-0.3.9 → twopy-0.4.0}/src/twopy.egg-info/requires.txt +0 -0
  211. {twopy-0.3.9 → twopy-0.4.0}/src/twopy.egg-info/top_level.txt +0 -0
  212. {twopy-0.3.9 → twopy-0.4.0}/tests/test_api.py +0 -0
  213. {twopy-0.3.9 → twopy-0.4.0}/tests/test_background_subtraction.py +0 -0
  214. {twopy-0.3.9 → twopy-0.4.0}/tests/test_cache_inventory.py +0 -0
  215. {twopy-0.3.9 → twopy-0.4.0}/tests/test_config.py +0 -0
  216. {twopy-0.3.9 → twopy-0.4.0}/tests/test_converted.py +0 -0
  217. {twopy-0.3.9 → twopy-0.4.0}/tests/test_custom_workflows.py +0 -0
  218. {twopy-0.3.9 → twopy-0.4.0}/tests/test_database.py +0 -0
  219. {twopy-0.3.9 → twopy-0.4.0}/tests/test_dff.py +0 -0
  220. {twopy-0.3.9 → twopy-0.4.0}/tests/test_epoch_mapping.py +0 -0
  221. {twopy-0.3.9 → twopy-0.4.0}/tests/test_filenames.py +0 -0
  222. {twopy-0.3.9 → twopy-0.4.0}/tests/test_frame_ranges.py +0 -0
  223. {twopy-0.3.9 → twopy-0.4.0}/tests/test_function_inventory.py +0 -0
  224. {twopy-0.3.9 → twopy-0.4.0}/tests/test_group_matching.py +0 -0
  225. {twopy-0.3.9 → twopy-0.4.0}/tests/test_hdf5_utils.py +0 -0
  226. {twopy-0.3.9 → twopy-0.4.0}/tests/test_import.py +0 -0
  227. {twopy-0.3.9 → twopy-0.4.0}/tests/test_inspection.py +0 -0
  228. {twopy-0.3.9 → twopy-0.4.0}/tests/test_kernels.py +0 -0
  229. {twopy-0.3.9 → twopy-0.4.0}/tests/test_load_workflow.py +0 -0
  230. {twopy-0.3.9 → twopy-0.4.0}/tests/test_matlab.py +0 -0
  231. {twopy-0.3.9 → twopy-0.4.0}/tests/test_motion.py +0 -0
  232. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari_display.py +0 -0
  233. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari_group_matching_responses.py +0 -0
  234. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari_group_matching_roi_cards.py +0 -0
  235. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari_live_controller.py +0 -0
  236. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari_load_controller.py +0 -0
  237. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari_path_resolution.py +0 -0
  238. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari_response_map_display.py +0 -0
  239. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari_roi_generation.py +0 -0
  240. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari_roi_visibility.py +0 -0
  241. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari_text.py +0 -0
  242. {twopy-0.3.9 → twopy-0.4.0}/tests/test_napari_timeline.py +0 -0
  243. {twopy-0.3.9 → twopy-0.4.0}/tests/test_packaging.py +0 -0
  244. {twopy-0.3.9 → twopy-0.4.0}/tests/test_parity.py +0 -0
  245. {twopy-0.3.9 → twopy-0.4.0}/tests/test_parity_psycho5.py +0 -0
  246. {twopy-0.3.9 → twopy-0.4.0}/tests/test_parity_roi_extraction.py +0 -0
  247. {twopy-0.3.9 → twopy-0.4.0}/tests/test_persistence.py +0 -0
  248. {twopy-0.3.9 → twopy-0.4.0}/tests/test_photodiode_classification.py +0 -0
  249. {twopy-0.3.9 → twopy-0.4.0}/tests/test_pixel_calibration.py +0 -0
  250. {twopy-0.3.9 → twopy-0.4.0}/tests/test_pixel_calibration_profiles.py +0 -0
  251. {twopy-0.3.9 → twopy-0.4.0}/tests/test_real_fixture.py +0 -0
  252. {twopy-0.3.9 → twopy-0.4.0}/tests/test_recording_timing.py +0 -0
  253. {twopy-0.3.9 → twopy-0.4.0}/tests/test_response_map_area.py +0 -0
  254. {twopy-0.3.9 → twopy-0.4.0}/tests/test_response_maps.py +0 -0
  255. {twopy-0.3.9 → twopy-0.4.0}/tests/test_response_processing.py +0 -0
  256. {twopy-0.3.9 → twopy-0.4.0}/tests/test_response_roi_extraction.py +0 -0
  257. {twopy-0.3.9 → twopy-0.4.0}/tests/test_response_window_options.py +0 -0
  258. {twopy-0.3.9 → twopy-0.4.0}/tests/test_responses.py +0 -0
  259. {twopy-0.3.9 → twopy-0.4.0}/tests/test_roi.py +0 -0
  260. {twopy-0.3.9 → twopy-0.4.0}/tests/test_roi_extraction.py +0 -0
  261. {twopy-0.3.9 → twopy-0.4.0}/tests/test_roi_mask_cleanup.py +0 -0
  262. {twopy-0.3.9 → twopy-0.4.0}/tests/test_saved_analysis.py +0 -0
  263. {twopy-0.3.9 → twopy-0.4.0}/tests/test_session.py +0 -0
  264. {twopy-0.3.9 → twopy-0.4.0}/tests/test_stimulus.py +0 -0
  265. {twopy-0.3.9 → twopy-0.4.0}/tests/test_synchronization.py +0 -0
  266. {twopy-0.3.9 → twopy-0.4.0}/tests/test_trials.py +0 -0
  267. {twopy-0.3.9 → twopy-0.4.0}/tests/test_workflow.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: twopy
3
- Version: 0.3.9
3
+ Version: 0.4.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
@@ -31,7 +31,7 @@ Two-photon imaging analysis tool for the Clark Lab output format.
31
31
 
32
32
  twopy lets you open two-photon recordings, draw ROIs, plot responses in real time, process and analyze them, and save them.
33
33
 
34
- When you first load a recording, twopy converts it to HDF5 files that it owns. Those files include the aligned movie, mean image, stimulus tables, photodiode signals, and recording metadata. Analysis and the GUI both work from the converted files, so the original source files remain separate from twopy's outputs. By default, converted recordings and interactive analysis outputs are cached locally under `~/.cache/twopy/recordings` for speed; saving ROIs and analysis copies the changed output files back to the configured `analysis_output` location in the background.
34
+ When you first load a recording, twopy converts it to HDF5 files that it owns. These files contain the aligned movie, mean image, stimulus tables, photodiode signals, and recording metadata. Analysis and the GUI use only the converted files. Thus, the original source files stay separate from twopy outputs. By default, twopy uses `~/.cache/twopy/recordings` as a local cache. When you save ROIs and analysis, twopy copies changed files to `analysis_output` in the background.
35
35
 
36
36
  ## Install
37
37
 
@@ -55,7 +55,7 @@ Create the config template in your user folder:
55
55
  twopy config setup
56
56
  ```
57
57
 
58
- twopy prints the config path it wrote. On macOS and Linux the default is `~/.config/twopy/config.yml`; on Windows it is under `%APPDATA%\twopy\config.yml`. Edit that file with your database, data, and output paths before launching twopy. If you launch `twopy` before a config exists, twopy creates the same template, prints the path, and stops so you can edit it.
58
+ twopy prints the config path that it wrote. The default path on macOS and Linux is `~/.config/twopy/config.yml`. On Windows, the path is under `%APPDATA%\twopy\config.yml`. Before you start twopy, add your database, data, and output paths to that file. If the config does not exist, twopy creates the template and prints its path. Then, twopy stops so you can edit it.
59
59
 
60
60
  Validate the active config and show its path and file contents:
61
61
 
@@ -8,7 +8,7 @@ Two-photon imaging analysis tool for the Clark Lab output format.
8
8
 
9
9
  twopy lets you open two-photon recordings, draw ROIs, plot responses in real time, process and analyze them, and save them.
10
10
 
11
- When you first load a recording, twopy converts it to HDF5 files that it owns. Those files include the aligned movie, mean image, stimulus tables, photodiode signals, and recording metadata. Analysis and the GUI both work from the converted files, so the original source files remain separate from twopy's outputs. By default, converted recordings and interactive analysis outputs are cached locally under `~/.cache/twopy/recordings` for speed; saving ROIs and analysis copies the changed output files back to the configured `analysis_output` location in the background.
11
+ When you first load a recording, twopy converts it to HDF5 files that it owns. These files contain the aligned movie, mean image, stimulus tables, photodiode signals, and recording metadata. Analysis and the GUI use only the converted files. Thus, the original source files stay separate from twopy outputs. By default, twopy uses `~/.cache/twopy/recordings` as a local cache. When you save ROIs and analysis, twopy copies changed files to `analysis_output` in the background.
12
12
 
13
13
  ## Install
14
14
 
@@ -32,7 +32,7 @@ Create the config template in your user folder:
32
32
  twopy config setup
33
33
  ```
34
34
 
35
- twopy prints the config path it wrote. On macOS and Linux the default is `~/.config/twopy/config.yml`; on Windows it is under `%APPDATA%\twopy\config.yml`. Edit that file with your database, data, and output paths before launching twopy. If you launch `twopy` before a config exists, twopy creates the same template, prints the path, and stops so you can edit it.
35
+ twopy prints the config path that it wrote. The default path on macOS and Linux is `~/.config/twopy/config.yml`. On Windows, the path is under `%APPDATA%\twopy\config.yml`. Before you start twopy, add your database, data, and output paths to that file. If the config does not exist, twopy creates the template and prints its path. Then, twopy stops so you can edit it.
36
36
 
37
37
  Validate the active config and show its path and file contents:
38
38
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "twopy"
7
- version = "0.3.9"
7
+ version = "0.4.0"
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"
@@ -5,7 +5,7 @@ Outputs: raw ROI traces, estimated background traces, corrected traces, and
5
5
  method metadata.
6
6
 
7
7
  This module owns analysis-time background correction. ROI storage and raw ROI
8
- trace extraction stay in ``twopy.roi``; dF/F and trial analysis can consume the
8
+ trace extraction stay in ``twopy.roi``. dF/F and trial analysis can use the
9
9
  auditable outputs produced here.
10
10
  """
11
11
 
@@ -243,8 +243,8 @@ def _validate_background_method(method: BackgroundCorrectionMethod) -> None:
243
243
  }
244
244
  if method not in allowed_methods:
245
245
  msg = (
246
- f"Unknown background correction method {method!r}; "
247
- f"supported methods: {', '.join(sorted(allowed_methods))}"
246
+ f"Unknown background correction method {method!r}. "
247
+ f"Supported methods: {', '.join(sorted(allowed_methods))}"
248
248
  )
249
249
  raise ValueError(msg)
250
250
 
@@ -722,7 +722,7 @@ def _crop_roi_masks_for_domain(
722
722
  if outside.size:
723
723
  msg = (
724
724
  "ROI pixels fall outside the selected spatial domain "
725
- f"{spatial_crop.source}; affected ROI indices: {outside.tolist()}"
725
+ f"{spatial_crop.source}. Affected ROI indices: {outside.tolist()}"
726
726
  )
727
727
  raise ValueError(msg)
728
728
  return cropped_masks
@@ -759,7 +759,7 @@ def _validate_percentile(percentile: float) -> None:
759
759
  rule at the extremes.
760
760
  """
761
761
  if not 0.0 < percentile < 100.0:
762
- msg = f"Background percentile must be between 0 and 100; got {percentile}"
762
+ msg = f"Background percentile must be between 0 and 100. Got {percentile}"
763
763
  raise ValueError(msg)
764
764
 
765
765
 
@@ -808,7 +808,7 @@ def _resolve_roi_y_stripe_radius(
808
808
  """
809
809
  radius = max(1, round(row_count / 20)) if local_y_radius is None else local_y_radius
810
810
  if radius < 0:
811
- msg = f"local_y_radius must be nonnegative; got {radius}"
811
+ msg = f"local_y_radius must be nonnegative. Got {radius}"
812
812
  raise ValueError(msg)
813
813
  return radius
814
814
 
@@ -831,7 +831,7 @@ def _resolve_stripe_y_height(
831
831
  max(1, round(row_count / 20)) if stripe_y_height is None else stripe_y_height
832
832
  )
833
833
  if height <= 0:
834
- msg = f"stripe_y_height must be positive; got {height}"
834
+ msg = f"stripe_y_height must be positive. Got {height}"
835
835
  raise ValueError(msg)
836
836
  return height
837
837
 
@@ -912,8 +912,8 @@ def _roi_y_stripe_background_pixel_indices(
912
912
  msg = (
913
913
  "ROI y-stripe P% background subtraction needs unlabeled background "
914
914
  "pixels outside all ROIs in the selected spatial domain. The current "
915
- "ROI masks cover every pixel, which is common for dense grid ROIs; "
916
- "use shared y-stripe P% or leave unlabeled background pixels."
915
+ "ROI masks cover every pixel, which is common for dense grid ROIs. "
916
+ "Use shared y-stripe P% or leave unlabeled background pixels."
917
917
  )
918
918
  raise ValueError(msg)
919
919
 
@@ -930,7 +930,7 @@ def _roi_y_stripe_background_pixel_indices(
930
930
  msg = (
931
931
  f"ROI {roi_index} has no local background candidates within "
932
932
  f"{local_y_radius} rows. ROI y-stripe P% only uses unlabeled "
933
- "pixels outside all ROIs; increase the local y radius, use "
933
+ "pixels outside all ROIs. Increase the local y radius, use "
934
934
  "shared y-stripe P%, or leave unlabeled background pixels near "
935
935
  "this ROI."
936
936
  )
@@ -6,7 +6,7 @@ Outputs: ROI dF/F traces, fitted baselines, shared exponential tau, and
6
6
  per-ROI amplitudes.
7
7
 
8
8
  This module owns ROI-level dF/F calculation from twopy Python objects. It does
9
- not decide which stimulus events are baseline epochs; callers pass explicit
9
+ not decide which stimulus events are baseline epochs. Callers pass explicit
10
10
  baseline windows derived from converted data and photodiode alignment.
11
11
  """
12
12
 
@@ -200,8 +200,8 @@ def _validate_dff_inputs(
200
200
  raise ValueError(msg)
201
201
  if traces.corrected_values.shape[1] != len(traces.labels):
202
202
  msg = (
203
- "ROI labels must match corrected_values width; "
204
- f"got {len(traces.labels)} labels for "
203
+ "ROI labels must match corrected_values width. "
204
+ f"Got {len(traces.labels)} labels for "
205
205
  f"{traces.corrected_values.shape[1]} ROIs"
206
206
  )
207
207
  raise ValueError(msg)
@@ -209,12 +209,12 @@ def _validate_dff_inputs(
209
209
  msg = "At least one baseline window is required for dF/F"
210
210
  raise ValueError(msg)
211
211
  if data_rate_hz <= 0:
212
- msg = f"data_rate_hz must be positive; got {data_rate_hz}"
212
+ msg = f"data_rate_hz must be positive. Got {data_rate_hz}"
213
213
  raise ValueError(msg)
214
214
  if baseline_sample_seconds is not None and baseline_sample_seconds <= 0:
215
215
  msg = (
216
- "baseline_sample_seconds must be positive or None; "
217
- f"got {baseline_sample_seconds}"
216
+ "baseline_sample_seconds must be positive or None. "
217
+ f"Got {baseline_sample_seconds}"
218
218
  )
219
219
  raise ValueError(msg)
220
220
  if fit_mode not in _FIT_MODES:
@@ -267,7 +267,7 @@ def _baseline_samples(
267
267
  duration = sample_stop - sample_start
268
268
  absolute_sample_start = trace_start_frame + sample_start
269
269
  # The fit uses one-based movie frame numbers centered on the averaged
270
- # half-open sample range. Local indices slice the trace array; absolute
270
+ # half-open sample range. Local indices slice the trace array. Absolute
271
271
  # frame numbers preserve the recording-wide time coordinate.
272
272
  frame_numbers.append(float(absolute_sample_start + 1) + (duration / 2.0))
273
273
  values.append(fluorescence[sample_start:sample_stop, :].mean(axis=0))
@@ -298,7 +298,7 @@ def _validate_baseline_samples_for_background_method(
298
298
  minimum = float(np.nanmin(baseline_samples.values[:, roi_indices]))
299
299
  msg = (
300
300
  "ROI y-stripe P% background subtraction over-subtracted baseline "
301
- f"fluorescence for {labels}; minimum corrected baseline sample is "
301
+ f"fluorescence for {labels}. Minimum corrected baseline sample is "
302
302
  f"{minimum:.6g}. dF/F needs positive baseline fluorescence, so the "
303
303
  "local y-stripe pixels are not a valid additive background for those "
304
304
  "ROIs. Use shared y-stripe P%, global percentile, or revise the ROIs "
@@ -383,10 +383,10 @@ def _fit_shared_tau(
383
383
  Shared exponential ``tau``.
384
384
 
385
385
  The fit model is ``exp(tau * t + b)`` on the ROI-averaged baseline trace.
386
- Only ``tau`` is shared; per-ROI amplitudes are computed in a separate
386
+ Only ``tau`` is shared. Per-ROI amplitudes are computed in a separate
387
387
  transparent step. ``direct_bounded_tau`` handles nonpositive outliers
388
- defensively; ``direct_bounded_tau_and_log_amplitude`` preserves a bounded
389
- log-amplitude contract; and ``log_linear`` fits in log space.
388
+ defensively. ``direct_bounded_tau_and_log_amplitude`` preserves a bounded
389
+ log-amplitude contract. The ``log_linear`` method fits in log space.
390
390
  """
391
391
  if fit_mode == "log_linear":
392
392
  return _fit_shared_tau_log_linear(
@@ -532,8 +532,8 @@ def _fit_shared_tau_with_bounded_log_amplitude(
532
532
  msg = (
533
533
  "direct_bounded_tau_and_log_amplitude dF/F fit requires first "
534
534
  "baseline fluorescence greater than 1.0 to define an ordered "
535
- "log-amplitude bound; "
536
- f"got {first_value}"
535
+ "log-amplitude bound. "
536
+ f"Got {first_value}"
537
537
  )
538
538
  raise ValueError(msg)
539
539
  if np.any(mean_fluorescence <= 0):
@@ -118,7 +118,7 @@ def _interpolate_epoch_numbers(
118
118
  Integer epoch number per imaging frame.
119
119
  """
120
120
  if frame_count < 1:
121
- msg = f"frame_count must be positive; got {frame_count}"
121
+ msg = f"frame_count must be positive. Got {frame_count}"
122
122
  raise ValueError(msg)
123
123
 
124
124
  positive = epoch_values != 0
@@ -588,7 +588,7 @@ def _validate_status(status: ManualRoiMatchStatus) -> ManualRoiMatchStatus:
588
588
  def _validate_group_cell_id(group_cell_id: int) -> int:
589
589
  """Return a positive group-cell id."""
590
590
  if group_cell_id < 1:
591
- msg = f"Manual ROI group_cell_id must be positive; got {group_cell_id}."
591
+ msg = f"Manual ROI group_cell_id must be positive. Got {group_cell_id}."
592
592
  raise ValueError(msg)
593
593
  return group_cell_id
594
594
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Inputs: converted stimulus tables plus ROI response traces computed by twopy.
4
4
  Outputs: per-ROI temporal kernels on the stimulus sample clock. Olfactory
5
- recordings expose left/right and ipsi/contra kernels; visual recordings expose
5
+ recordings expose left/right and ipsi/contra kernels. Visual recordings expose
6
6
  one contrast kernel.
7
7
 
8
8
  This package keeps reverse-correlation analysis native to twopy data. It does
@@ -65,7 +65,7 @@ class StimulusKernelOptions:
65
65
  epochs and applies ``discard_first_stimulus_epoch``.
66
66
  num_stim_past: Number of stimulus samples before a response sample.
67
67
  num_stim_future: Number of stimulus samples after a response sample.
68
- method: Fitting method. ``"ols"`` solves a least-squares design matrix;
68
+ method: Fitting method. ``"ols"`` solves a least-squares design matrix.
69
69
  ``"xcorr"`` computes reverse correlation.
70
70
  hemisphere: Recording hemisphere used to map raw left/right streams to
71
71
  ipsi/contra. ``None`` reads the value from converted recording
@@ -93,7 +93,7 @@ class RecordingKernelFit:
93
93
  Args:
94
94
  roi_labels: Labels for the fitted ROI rows.
95
95
  time_seconds: Kernel sample times. Negative times are future stimulus
96
- samples; positive times are stimulus samples before the response.
96
+ samples. Positive times are stimulus samples before the response.
97
97
  stimulus_modality: Sensory modality used to interpret the stimulus.
98
98
  stimulus_column: Converted stimulus column used for fitting.
99
99
  epoch_names: Unique readable epoch names fitted independently.
@@ -347,6 +347,6 @@ def _validate_options(options: StimulusKernelOptions) -> None:
347
347
  raise ValueError(msg)
348
348
  if options.hemisphere is not None and options.hemisphere not in {"left", "right"}:
349
349
  msg = (
350
- f"hemisphere must be 'left', 'right', or None; got {options.hemisphere!r}."
350
+ f"hemisphere must be 'left', 'right', or None. Got {options.hemisphere!r}."
351
351
  )
352
352
  raise ValueError(msg)
@@ -164,7 +164,7 @@ def save_analysis_outputs(
164
164
  The HDF5 file is the complete audit trail. CSV files are derived exports for
165
165
  quick spreadsheet plotting and checks, and are written after the HDF5 file.
166
166
  Each output file is written through a temporary sibling path so a failed
167
- write leaves the previous complete file in place; the HDF5 and CSV files are
167
+ write leaves the previous complete file in place. The HDF5 and CSV files are
168
168
  not replaced as one multi-file transaction.
169
169
  """
170
170
  summary_outputs = (
@@ -86,7 +86,7 @@ class ResponseMapOptions:
86
86
  finite response across all epochs has magnitude 1. The original dF/F divisor
87
87
  is stored on ``ResponseMapData``.
88
88
 
89
- Pixel mode is the default because it preserves spatial detail; its default
89
+ Pixel mode is the default because it preserves spatial detail. Its default
90
90
  two-pixel Gaussian smoothing reduces isolated noisy pixels without changing
91
91
  the saved analysis contract. Window mode is useful when users want explicit
92
92
  block averaging before dF/F. Window size and stride are constrained by the
@@ -110,7 +110,7 @@ class EpochResponseMap:
110
110
  epoch_number: One-based stimulus epoch number.
111
111
  response_values: Movie-coordinate signed response map for the displayed
112
112
  crop. Values are normalized by ``ResponseMapData.response_scale``
113
- after epoch averaging; multiply by that scale to recover the
113
+ after epoch averaging. Multiply by that scale to recover the
114
114
  original dF/F magnitude.
115
115
  trial_count: Number of trials averaged into the map.
116
116
  """
@@ -165,7 +165,7 @@ def compute_recording_response_maps(
165
165
 
166
166
  This reads the converted aligned movie for the valid crop, not microscope
167
167
  source MAT/TIFF files. Callers can pass explicit epoch windows for tests or
168
- audits; normal workflows let twopy derive photodiode-aligned windows from
168
+ audits. Normal workflows let twopy derive photodiode-aligned windows from
169
169
  converted synchronization metadata.
170
170
  """
171
171
  resolved_options = options or ResponseMapOptions()
@@ -398,20 +398,20 @@ def _require_response_map_shapes(map_data: ResponseMapData) -> None:
398
398
  """Require heatmap spatial arrays to match their recorded crop."""
399
399
  if map_data.mean_image.ndim != 2:
400
400
  msg = (
401
- f"response heatmap mean_image must be 2-D; got {map_data.mean_image.shape}"
401
+ f"response heatmap mean_image must be 2-D. Got {map_data.mean_image.shape}"
402
402
  )
403
403
  raise ValueError(msg)
404
404
  if map_data.mean_image.shape != map_data.spatial_crop.shape:
405
405
  msg = (
406
- "response heatmap mean_image shape must match spatial_crop shape; "
407
- f"got {map_data.mean_image.shape} and {map_data.spatial_crop.shape}"
406
+ "response heatmap mean_image shape must match spatial_crop shape. "
407
+ f"Got {map_data.mean_image.shape} and {map_data.spatial_crop.shape}"
408
408
  )
409
409
  raise ValueError(msg)
410
410
  for epoch in map_data.epochs:
411
411
  if epoch.response_values.shape != map_data.mean_image.shape:
412
412
  msg = (
413
413
  "response heatmap response_values shape must match mean_image "
414
- f"shape; got {epoch.response_values.shape} for "
414
+ f"shape. Got {epoch.response_values.shape} for "
415
415
  f"{epoch.epoch_name!r} and {map_data.mean_image.shape}"
416
416
  )
417
417
  raise ValueError(msg)
@@ -454,22 +454,22 @@ def _validate_options(options: ResponseMapOptions, shape: tuple[int, int]) -> No
454
454
  or options.pixel_smoothing_sigma < 0
455
455
  ):
456
456
  msg = (
457
- "pixel_smoothing_sigma must be finite and nonnegative; "
458
- f"got {options.pixel_smoothing_sigma}"
457
+ "pixel_smoothing_sigma must be finite and nonnegative. "
458
+ f"Got {options.pixel_smoothing_sigma}"
459
459
  )
460
460
  raise ValueError(msg)
461
461
  if options.window_size_pixels < 1:
462
- msg = f"window_size_pixels must be positive; got {options.window_size_pixels}"
462
+ msg = f"window_size_pixels must be positive. Got {options.window_size_pixels}"
463
463
  raise ValueError(msg)
464
464
  if options.window_stride_pixels < 1:
465
465
  msg = (
466
- f"window_stride_pixels must be positive; got {options.window_stride_pixels}"
466
+ f"window_stride_pixels must be positive. Got {options.window_stride_pixels}"
467
467
  )
468
468
  raise ValueError(msg)
469
469
  if options.window_stride_pixels > options.window_size_pixels:
470
470
  msg = (
471
- "window_stride_pixels cannot exceed window_size_pixels; "
472
- f"got {options.window_stride_pixels} > {options.window_size_pixels}"
471
+ "window_stride_pixels cannot exceed window_size_pixels. "
472
+ f"Got {options.window_stride_pixels} > {options.window_size_pixels}"
473
473
  )
474
474
  raise ValueError(msg)
475
475
  if options.window_size_pixels > min(shape):
@@ -482,14 +482,14 @@ def _validate_options(options: ResponseMapOptions, shape: tuple[int, int]) -> No
482
482
  options.baseline_sample_seconds <= 0
483
483
  ):
484
484
  msg = (
485
- "baseline_sample_seconds must be finite and positive; "
486
- f"got {options.baseline_sample_seconds}"
485
+ "baseline_sample_seconds must be finite and positive. "
486
+ f"Got {options.baseline_sample_seconds}"
487
487
  )
488
488
  raise ValueError(msg)
489
489
  if not 0.0 <= options.foreground_percentile <= 100.0:
490
490
  msg = (
491
- "foreground_percentile must be between 0 and 100; "
492
- f"got {options.foreground_percentile}"
491
+ "foreground_percentile must be between 0 and 100. "
492
+ f"Got {options.foreground_percentile}"
493
493
  )
494
494
  raise ValueError(msg)
495
495
 
@@ -6,7 +6,7 @@ Outputs: processed response objects plus optional quality-control scores.
6
6
 
7
7
  This package is GUI-independent. It owns the math and validates option values
8
8
  for response smoothing, low-pass filtering, and correlation-based response
9
- quality control. Workflow code decides when to call it; persistence code decides
9
+ quality control. Workflow code decides when to call it. Persistence code decides
10
10
  how to save the resulting audit trail.
11
11
  """
12
12
 
@@ -367,8 +367,8 @@ def _normalization_factors(
367
367
  if len(bad_indices) > 0:
368
368
  bad_labels = ", ".join(grouped.roi_labels[index] for index in bad_indices)
369
369
  msg = (
370
- "Normalization epoch must have a nonzero response for every ROI; "
371
- f"invalid ROI labels: {bad_labels}"
370
+ "Normalization epoch must have a nonzero response for every ROI. "
371
+ f"Invalid ROI labels: {bad_labels}"
372
372
  )
373
373
  raise ValueError(msg)
374
374
  return RoiNormalizationFactors(
@@ -387,8 +387,8 @@ def _mask_excluded_rois(
387
387
  """Return grouped responses with excluded ROI columns set to NaN."""
388
388
  if included_mask.shape != (len(grouped.roi_labels),):
389
389
  msg = (
390
- "included_mask must match ROI label count; "
391
- f"got {included_mask.shape} for {len(grouped.roi_labels)} labels"
390
+ "included_mask must match ROI label count. "
391
+ f"Got {included_mask.shape} for {len(grouped.roi_labels)} labels"
392
392
  )
393
393
  raise ValueError(msg)
394
394
  trials: list[RoiResponseTrial] = []
@@ -427,7 +427,7 @@ def _copy_trial_with_values(
427
427
  def _validate_dff_for_processing(dff: RoiDeltaFOverF) -> None:
428
428
  """Validate a dF/F object before value-only processing."""
429
429
  if dff.values.ndim != 2:
430
- msg = f"dF/F values must have shape (frames, rois); got {dff.values.shape}"
430
+ msg = f"dF/F values must have shape (frames, rois). Got {dff.values.shape}"
431
431
  raise ValueError(msg)
432
432
  if dff.values.shape[1] != len(dff.labels):
433
433
  msg = (
@@ -156,25 +156,25 @@ def _validate_smoothing_options(options: SmoothingOptions) -> None:
156
156
  msg = f"Unknown smoothing method {options.method!r}"
157
157
  raise ValueError(msg)
158
158
  if options.window_frames < 1:
159
- msg = f"smoothing window_frames must be at least 1; got {options.window_frames}"
159
+ msg = f"smoothing window_frames must be at least 1. Got {options.window_frames}"
160
160
  raise ValueError(msg)
161
161
  if options.polynomial_order < 0:
162
162
  msg = (
163
- "smoothing polynomial_order must be non-negative; "
164
- f"got {options.polynomial_order}"
163
+ "smoothing polynomial_order must be non-negative. "
164
+ f"Got {options.polynomial_order}"
165
165
  )
166
166
  raise ValueError(msg)
167
167
  if options.method == "savgol":
168
168
  if options.window_frames % 2 == 0:
169
169
  msg = (
170
- "Savitzky-Golay smoothing window_frames must be odd; "
171
- f"got {options.window_frames}"
170
+ "Savitzky-Golay smoothing window_frames must be odd. "
171
+ f"Got {options.window_frames}"
172
172
  )
173
173
  raise ValueError(msg)
174
174
  if options.polynomial_order >= options.window_frames:
175
175
  msg = (
176
- "Savitzky-Golay polynomial_order must be below window_frames; "
177
- f"got order {options.polynomial_order} and window "
176
+ "Savitzky-Golay polynomial_order must be below window_frames. "
177
+ f"Got order {options.polynomial_order} and window "
178
178
  f"{options.window_frames}"
179
179
  )
180
180
  raise ValueError(msg)
@@ -190,7 +190,7 @@ def _validate_low_pass_options(
190
190
  msg = f"Unknown low-pass method {options.method!r}"
191
191
  raise ValueError(msg)
192
192
  if options.order < 1:
193
- msg = f"low-pass order must be at least 1; got {options.order}"
193
+ msg = f"low-pass order must be at least 1. Got {options.order}"
194
194
  raise ValueError(msg)
195
195
  if options.method == "none":
196
196
  return
@@ -199,13 +199,13 @@ def _validate_low_pass_options(
199
199
  raise ValueError(msg)
200
200
  if data_rate_hz is not None:
201
201
  if data_rate_hz <= 0:
202
- msg = f"data_rate_hz must be positive; got {data_rate_hz}"
202
+ msg = f"data_rate_hz must be positive. Got {data_rate_hz}"
203
203
  raise ValueError(msg)
204
204
  nyquist_hz = data_rate_hz / 2.0
205
205
  if options.cutoff_hz >= nyquist_hz:
206
206
  msg = (
207
- "low-pass cutoff_hz must be below Nyquist; "
208
- f"got {options.cutoff_hz} Hz for {data_rate_hz} Hz data"
207
+ "low-pass cutoff_hz must be below Nyquist. "
208
+ f"Got {options.cutoff_hz} Hz for {data_rate_hz} Hz data"
209
209
  )
210
210
  raise ValueError(msg)
211
211
 
@@ -216,7 +216,7 @@ def _validate_normalization_options(options: NormalizationOptions) -> None:
216
216
  msg = f"Unknown normalization method {options.method!r}"
217
217
  raise ValueError(msg)
218
218
  if options.epoch_number is not None and options.epoch_number < 1:
219
- msg = f"normalization epoch_number must be positive; got {options.epoch_number}"
219
+ msg = f"normalization epoch_number must be positive. Got {options.epoch_number}"
220
220
  raise ValueError(msg)
221
221
  if options.method == "epoch_abs_peak" and options.epoch_number is None:
222
222
  msg = "response-size normalization requires an epoch_number"
@@ -230,16 +230,16 @@ def _validate_correlation_options(options: CorrelationFilterOptions) -> None:
230
230
  raise ValueError(msg)
231
231
  if not -1.0 <= options.minimum_correlation <= 1.0:
232
232
  msg = (
233
- "minimum_correlation must be between -1 and 1; "
234
- f"got {options.minimum_correlation}"
233
+ "minimum_correlation must be between -1 and 1. "
234
+ f"Got {options.minimum_correlation}"
235
235
  )
236
236
  raise ValueError(msg)
237
237
  start_seconds, stop_seconds = options.window_seconds
238
238
  if start_seconds is not None and not np.isfinite(start_seconds):
239
- msg = f"correlation window start must be finite or None; got {start_seconds}"
239
+ msg = f"correlation window start must be finite or None. Got {start_seconds}"
240
240
  raise ValueError(msg)
241
241
  if stop_seconds is not None and not np.isfinite(stop_seconds):
242
- msg = f"correlation window stop must be finite or None; got {stop_seconds}"
242
+ msg = f"correlation window stop must be finite or None. Got {stop_seconds}"
243
243
  raise ValueError(msg)
244
244
  if (
245
245
  start_seconds is not None
@@ -247,7 +247,7 @@ def _validate_correlation_options(options: CorrelationFilterOptions) -> None:
247
247
  and start_seconds >= stop_seconds
248
248
  ):
249
249
  msg = (
250
- "correlation window start must be before stop; "
251
- f"got ({start_seconds}, {stop_seconds})"
250
+ "correlation window start must be before stop. "
251
+ f"Got ({start_seconds}, {stop_seconds})"
252
252
  )
253
253
  raise ValueError(msg)
@@ -3,7 +3,7 @@
3
3
  Inputs: grouped trial responses with explicit relative time vectors.
4
4
  Outputs: ROI-level correlation scores and inclusion masks.
5
5
 
6
- The functions here score response consistency; they do not delete raw data.
6
+ The functions here score response consistency. They do not delete raw data.
7
7
  Callers can use the inclusion mask for plotting or summaries while preserving
8
8
  the scores as an audit trail.
9
9
  """
@@ -179,7 +179,7 @@ def _validate_correlation_inputs(
179
179
  ) -> None:
180
180
  """Validate grouped-response correlation inputs."""
181
181
  if not -1.0 <= minimum_correlation <= 1.0:
182
- msg = f"minimum_correlation must be between -1 and 1; got {minimum_correlation}"
182
+ msg = f"minimum_correlation must be between -1 and 1. Got {minimum_correlation}"
183
183
  raise ValueError(msg)
184
184
  if reference not in {"epoch_mean", "epoch_peak"}:
185
185
  msg = f"Unknown correlation reference {reference!r}"
@@ -44,7 +44,7 @@ def nan_aware_moving_average(
44
44
  whose whole window is NaN remain NaN.
45
45
  """
46
46
  if window_frames < 1:
47
- msg = f"window_frames must be at least 1; got {window_frames}"
47
+ msg = f"window_frames must be at least 1. Got {window_frames}"
48
48
  raise ValueError(msg)
49
49
  matrix, was_1d = _as_frame_channel_matrix(values)
50
50
  if window_frames == 1:
@@ -155,7 +155,7 @@ def _as_frame_channel_matrix(
155
155
  return array.reshape(-1, 1), True
156
156
  if array.ndim == 2:
157
157
  return array, False
158
- msg = f"response values must be 1D or 2D; got shape {array.shape}"
158
+ msg = f"response values must be 1D or 2D. Got shape {array.shape}"
159
159
  raise ValueError(msg)
160
160
 
161
161
 
@@ -208,20 +208,20 @@ def _validate_low_pass_parameters(
208
208
  ) -> None:
209
209
  """Validate Butterworth filter parameters."""
210
210
  if sample_rate_hz <= 0:
211
- msg = f"sample_rate_hz must be positive; got {sample_rate_hz}"
211
+ msg = f"sample_rate_hz must be positive. Got {sample_rate_hz}"
212
212
  raise ValueError(msg)
213
213
  if cutoff_hz <= 0:
214
- msg = f"cutoff_hz must be positive; got {cutoff_hz}"
214
+ msg = f"cutoff_hz must be positive. Got {cutoff_hz}"
215
215
  raise ValueError(msg)
216
216
  nyquist_hz = sample_rate_hz / 2.0
217
217
  if cutoff_hz >= nyquist_hz:
218
218
  msg = (
219
- "cutoff_hz must be below Nyquist; "
220
- f"got {cutoff_hz} Hz for {sample_rate_hz} Hz data"
219
+ "cutoff_hz must be below Nyquist. "
220
+ f"Got {cutoff_hz} Hz for {sample_rate_hz} Hz data"
221
221
  )
222
222
  raise ValueError(msg)
223
223
  if order < 1:
224
- msg = f"order must be at least 1; got {order}"
224
+ msg = f"order must be at least 1. Got {order}"
225
225
  raise ValueError(msg)
226
226
 
227
227
 
@@ -232,18 +232,18 @@ def _validate_savgol_parameters(
232
232
  ) -> None:
233
233
  """Validate Savitzky-Golay smoothing parameters."""
234
234
  if window_frames < 1:
235
- msg = f"window_frames must be at least 1; got {window_frames}"
235
+ msg = f"window_frames must be at least 1. Got {window_frames}"
236
236
  raise ValueError(msg)
237
237
  if window_frames % 2 == 0:
238
- msg = f"window_frames must be odd for Savitzky-Golay; got {window_frames}"
238
+ msg = f"window_frames must be odd for Savitzky-Golay. Got {window_frames}"
239
239
  raise ValueError(msg)
240
240
  if polynomial_order < 0:
241
- msg = f"polynomial_order must be non-negative; got {polynomial_order}"
241
+ msg = f"polynomial_order must be non-negative. Got {polynomial_order}"
242
242
  raise ValueError(msg)
243
243
  if polynomial_order >= window_frames:
244
244
  msg = (
245
- "polynomial_order must be below window_frames; "
246
- f"got {polynomial_order} and {window_frames}"
245
+ "polynomial_order must be below window_frames. "
246
+ f"Got {polynomial_order} and {window_frames}"
247
247
  )
248
248
  raise ValueError(msg)
249
249
 
@@ -65,7 +65,7 @@ def resolve_response_window_seconds(
65
65
  ValueError: If any supplied window duration is negative.
66
66
  """
67
67
  if max_window_seconds is not None and max_window_seconds < 0.0:
68
- msg = f"max_window_seconds must be non-negative; got {max_window_seconds}"
68
+ msg = f"max_window_seconds must be non-negative. Got {max_window_seconds}"
69
69
  raise ValueError(msg)
70
70
  if options.auto:
71
71
  pre = _validate_non_negative(
@@ -94,6 +94,6 @@ def _validate_non_negative(value: float, *, name: str) -> float:
94
94
  """Return ``value`` as a float after enforcing the response-window domain."""
95
95
  resolved = float(value)
96
96
  if resolved < 0.0:
97
- msg = f"{name} must be non-negative; got {resolved}"
97
+ msg = f"{name} must be non-negative. Got {resolved}"
98
98
  raise ValueError(msg)
99
99
  return resolved