TwoPy 0.3.0__tar.gz → 0.3.1__tar.gz

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