microeye 2.3.3__tar.gz → 2.3.4__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 (205) hide show
  1. {microeye-2.3.3/src/microeye.egg-info → microeye-2.3.4}/PKG-INFO +5 -5
  2. {microeye-2.3.3 → microeye-2.3.4}/README.md +4 -4
  3. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/_version.py +1 -1
  4. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/filters/__init__.py +3 -4
  5. microeye-2.3.4/src/microEye/analysis/filters/base.py +62 -0
  6. microeye-2.3.4/src/microEye/analysis/filters/spatial.py +576 -0
  7. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/filters/temporal.py +2 -2
  8. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/fit.py +9 -9
  9. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/viewer/image_options_widget.py +62 -112
  10. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/viewer/images.py +1 -1
  11. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/camera_list.py +9 -0
  12. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/camera_options.py +1 -1
  13. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/camera_panel.py +104 -8
  14. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/dummy/dummy_panel.py +3 -68
  15. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/pco/pco_panel.py +0 -68
  16. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/shortcuts.py +8 -1
  17. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/thorlabs/thorlabs_panel.py +0 -68
  18. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/ueye/ueye_panel.py +0 -68
  19. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/vimba/vimba_panel.py +0 -68
  20. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/mieye/devices_manager.py +37 -16
  21. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/mieye/miEye.py +4 -0
  22. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/pycromanager/devices.py +53 -20
  23. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/pycromanager/widgets/pycro_panel.py +8 -68
  24. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/stages/__init__.py +2 -7
  25. microeye-2.3.4/src/microEye/hardware/stages/piezo_concept.py +141 -0
  26. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/stages/stabilizer.py +1 -1
  27. microeye-2.3.4/src/microEye/hardware/stages/stage.py +849 -0
  28. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/widgets/controller.py +19 -9
  29. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/widgets/devices.py +8 -1
  30. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/widgets/focusWidget.py +1 -1
  31. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/widgets/scan_acquisition.py +1 -1
  32. microeye-2.3.4/src/microEye/tools/__init__.py +0 -0
  33. microeye-2.3.4/src/microEye/tools/microscopy.py +731 -0
  34. microeye-2.3.4/src/microEye/utils/display.py +278 -0
  35. microeye-2.3.4/src/microEye/utils/hid_utils/__init__.py +8 -0
  36. {microeye-2.3.3/src/microEye/utils/hid → microeye-2.3.4/src/microEye/utils/hid_utils}/controller.py +7 -3
  37. {microeye-2.3.3 → microeye-2.3.4/src/microeye.egg-info}/PKG-INFO +5 -5
  38. {microeye-2.3.3 → microeye-2.3.4}/src/microeye.egg-info/SOURCES.txt +8 -5
  39. microeye-2.3.3/src/microEye/analysis/filters/base.py +0 -21
  40. microeye-2.3.3/src/microEye/analysis/filters/spatial.py +0 -338
  41. microeye-2.3.3/src/microEye/hardware/stages/piezo_concept.py +0 -607
  42. microeye-2.3.3/src/microEye/hardware/stages/stage.py +0 -89
  43. microeye-2.3.3/src/microEye/utils/hid/__init__.py +0 -8
  44. {microeye-2.3.3 → microeye-2.3.4}/LICENSE +0 -0
  45. {microeye-2.3.3 → microeye-2.3.4}/MANIFEST.in +0 -0
  46. {microeye-2.3.3 → microeye-2.3.4}/pyproject.toml +0 -0
  47. {microeye-2.3.3 → microeye-2.3.4}/setup.cfg +0 -0
  48. {microeye-2.3.3 → microeye-2.3.4}/setup.py +0 -0
  49. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/__init__.py +0 -0
  50. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/__init__.py +0 -0
  51. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/checklist_dialog.py +0 -0
  52. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/cmosMaps.py +0 -0
  53. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/__init__.py +0 -0
  54. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/nena.py +0 -0
  55. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/phasor_fit.py +0 -0
  56. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/processing.py +0 -0
  57. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/psf/__init__.py +0 -0
  58. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/psf/extract.py +0 -0
  59. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/psf/rubost_mean.py +0 -0
  60. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/psf/spline.py +0 -0
  61. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/psf/stats/__init__.py +0 -0
  62. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/psf/stats/core.py +0 -0
  63. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/psf/stats/curve_fit.py +0 -0
  64. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/psf/stats/io.py +0 -0
  65. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/psf/stats/slope_fit.py +0 -0
  66. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/psf/temp.py +0 -0
  67. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/psf/test.py +0 -0
  68. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUfunctions.py +0 -0
  69. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUmleFit_LM.py +0 -0
  70. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUsplineLib.py +0 -0
  71. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/pyfit3Dcspline/CPU/__init__.py +0 -0
  72. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUfunctions.py +0 -0
  73. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_EMCCD.py +0 -0
  74. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_sCMOS.py +0 -0
  75. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUsplineLib.py +0 -0
  76. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/pyfit3Dcspline/GPU/__init__.py +0 -0
  77. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/pyfit3Dcspline/__init__.py +0 -0
  78. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/pyfit3Dcspline/constants.py +0 -0
  79. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/pyfit3Dcspline/mainfunctions.py +0 -0
  80. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/results.py +0 -0
  81. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/results_stats.py +0 -0
  82. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/fitting/tardis.py +0 -0
  83. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/multi_viewer.py +0 -0
  84. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/processing/__init__.py +0 -0
  85. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/processing/frc.py +0 -0
  86. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/rendering/__init__.py +0 -0
  87. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/rendering/base.py +0 -0
  88. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/rendering/cloud.py +0 -0
  89. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/rendering/core.py +0 -0
  90. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/rendering/volumetric.py +0 -0
  91. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/tools/__init__.py +0 -0
  92. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/tools/kymograms.py +0 -0
  93. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/tools/roi_selectors.py +0 -0
  94. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/utils/__init__.py +0 -0
  95. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/utils/coordinates.py +0 -0
  96. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/utils/images.py +0 -0
  97. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/utils/windows.py +0 -0
  98. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/viewer/__init__.py +0 -0
  99. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/viewer/layers_widget.py +0 -0
  100. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/viewer/localizations.py +0 -0
  101. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/viewer/psf.py +0 -0
  102. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/analysis/viewer/volume.py +0 -0
  103. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/__init__.py +0 -0
  104. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/__init__.py +0 -0
  105. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/camera_calibration.py +0 -0
  106. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/dummy/__init__.py +0 -0
  107. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/jobs.py +0 -0
  108. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/line_profiler.py +0 -0
  109. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/linescan/IR_Cam.py +0 -0
  110. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/linescan/__init__.py +0 -0
  111. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/micam.py +0 -0
  112. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/pco/__init__.py +0 -0
  113. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/pco/enums.py +0 -0
  114. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/pco/pco_cam.py +0 -0
  115. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/thorlabs/__init__.py +0 -0
  116. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/thorlabs/thorlabs.py +0 -0
  117. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/ueye/__init__.py +0 -0
  118. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/ueye/ueye_camera.py +0 -0
  119. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/vimba/__init__.py +0 -0
  120. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/cams/vimba/vimba_cam.py +0 -0
  121. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/device.py +0 -0
  122. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/lasers/__init__.py +0 -0
  123. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/lasers/io_matchbox.py +0 -0
  124. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/lasers/io_params.py +0 -0
  125. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/lasers/io_single_laser.py +0 -0
  126. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/lasers/laser_relay.py +0 -0
  127. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/mieye/__init__.py +0 -0
  128. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/mieye/acquisition_manager.py +0 -0
  129. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/misc/__init__.py +0 -0
  130. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/misc/acquisition_view.py +0 -0
  131. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/misc/reglo.py +0 -0
  132. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/misc/temp.py +0 -0
  133. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/port_config.py +0 -0
  134. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/protocols/__init__.py +0 -0
  135. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/protocols/actions.py +0 -0
  136. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/protocols/actions_items.py +0 -0
  137. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/protocols/designer.py +0 -0
  138. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/protocols/scene_manager.py +0 -0
  139. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/protocols/serialization.py +0 -0
  140. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/pycromanager/__init__.py +0 -0
  141. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/pycromanager/core.py +0 -0
  142. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/pycromanager/enums.py +0 -0
  143. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/pycromanager/headless.py +0 -0
  144. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/pycromanager/utils.py +0 -0
  145. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/pycromanager/widgets/__init__.py +0 -0
  146. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/pycromanager/widgets/bridges.py +0 -0
  147. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/pycromanager/widgets/headless_manager.py +0 -0
  148. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/pycromanager/widgets/headless_options.py +0 -0
  149. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/stages/elliptec/__init__.py +0 -0
  150. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/stages/elliptec/baseDevice.py +0 -0
  151. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/stages/elliptec/device.py +0 -0
  152. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/stages/elliptec/deviceID.py +0 -0
  153. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/stages/elliptec/devicePort.py +0 -0
  154. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/stages/elliptec/deviceStatus.py +0 -0
  155. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/stages/elliptec/devicesView.py +0 -0
  156. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/stages/elliptec/ellDevices.py +0 -0
  157. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/stages/elliptec/messageUpdater.py +0 -0
  158. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/stages/elliptec/motorInfo.py +0 -0
  159. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/stages/elliptec/stage.py +0 -0
  160. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/stages/elliptec/test.py +0 -0
  161. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/stages/kinesis/__init__.py +0 -0
  162. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/stages/kinesis/kdc101/__init__.py +0 -0
  163. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/stages/kinesis/kdc101/enums.py +0 -0
  164. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/stages/kinesis/kdc101/factory.py +0 -0
  165. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/stages/kinesis/kdc101/kdc101.py +0 -0
  166. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/stages/kinesis/kinesis.py +0 -0
  167. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/widgets/__init__.py +0 -0
  168. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/hardware/widgets/qlist_slider.py +0 -0
  169. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/icons/1024.png +0 -0
  170. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/icons/128.png +0 -0
  171. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/icons/16.png +0 -0
  172. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/icons/24.png +0 -0
  173. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/icons/256.png +0 -0
  174. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/icons/32.png +0 -0
  175. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/icons/48.png +0 -0
  176. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/icons/512.png +0 -0
  177. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/icons/64.png +0 -0
  178. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/icons/__init__.py +0 -0
  179. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/icons/close.svg +0 -0
  180. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/icons/mieye.png +0 -0
  181. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/icons/min.svg +0 -0
  182. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/icons/viewer.png +0 -0
  183. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/launcher.py +0 -0
  184. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/qt.py +0 -0
  185. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/utils/__init__.py +0 -0
  186. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/utils/enum_encoder.py +0 -0
  187. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/utils/expandable_groupbox.py +0 -0
  188. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/utils/gui_helper.py +0 -0
  189. {microeye-2.3.3/src/microEye/utils/hid → microeye-2.3.4/src/microEye/utils/hid_utils}/device.py +0 -0
  190. {microeye-2.3.3/src/microEye/utils/hid → microeye-2.3.4/src/microEye/utils/hid_utils}/enums.py +0 -0
  191. {microeye-2.3.3/src/microEye/utils/hid → microeye-2.3.4/src/microEye/utils/hid_utils}/utils.py +0 -0
  192. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/utils/labelled_slider.py +0 -0
  193. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/utils/metadata.py +0 -0
  194. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/utils/metadata_tree.py +0 -0
  195. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/utils/micro_launcher.py +0 -0
  196. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/utils/parameter_tree.py +0 -0
  197. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/utils/pyscripting.py +0 -0
  198. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/utils/retry_exec.py +0 -0
  199. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/utils/start_gui.py +0 -0
  200. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/utils/thread_worker.py +0 -0
  201. {microeye-2.3.3 → microeye-2.3.4}/src/microEye/utils/uImage.py +0 -0
  202. {microeye-2.3.3 → microeye-2.3.4}/src/microeye.egg-info/dependency_links.txt +0 -0
  203. {microeye-2.3.3 → microeye-2.3.4}/src/microeye.egg-info/entry_points.txt +0 -0
  204. {microeye-2.3.3 → microeye-2.3.4}/src/microeye.egg-info/requires.txt +0 -0
  205. {microeye-2.3.3 → microeye-2.3.4}/src/microeye.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: microeye
3
- Version: 2.3.3
3
+ Version: 2.3.4
4
4
  Summary: A python toolkit for fluorescence microscopy that features hardware control, data analysis and vizualization for super-resolution single-molecule localization microscopy and single-partical tracking.
5
5
  Home-page: https://github.com/samhitech/microEye
6
6
  Author: Mohammad Nour Alsamsam
@@ -96,10 +96,10 @@ This toolkit is compatible with the [hardware](#hardware) used in our microscope
96
96
  ![GitHub Stars](https://img.shields.io/github/stars/samhitech/microEye.svg)
97
97
 
98
98
  ```bash
99
- __ ____ ____ ___ ____ ____
100
- / |/ (_)__________ / __/_ _____ _ __|_ | |_ / |_ /
101
- / /|_/ / / __/ __/ _ \/ _// // / -_) | |/ / __/_ _/_ <_ _/_ <
102
- /_/ /_/_/\__/_/ \___/___/\_, /\__/ |___/____(_)____(_)____/
99
+ __ ____ ____ ___ ____ ____
100
+ / |/ (_)__________ / __/_ _____ _ __|_ | |_ // / /
101
+ / /|_/ / / __/ __/ _ \/ _// // / -_) | |/ / __/_ _/_ </_ _/
102
+ /_/ /_/_/\__/_/ \___/___/\_, /\__/ |___/____(_)____(_)_/
103
103
  /___/
104
104
  ```
105
105
 
@@ -31,10 +31,10 @@ This toolkit is compatible with the [hardware](#hardware) used in our microscope
31
31
  ![GitHub Stars](https://img.shields.io/github/stars/samhitech/microEye.svg)
32
32
 
33
33
  ```bash
34
- __ ____ ____ ___ ____ ____
35
- / |/ (_)__________ / __/_ _____ _ __|_ | |_ / |_ /
36
- / /|_/ / / __/ __/ _ \/ _// // / -_) | |/ / __/_ _/_ <_ _/_ <
37
- /_/ /_/_/\__/_/ \___/___/\_, /\__/ |___/____(_)____(_)____/
34
+ __ ____ ____ ___ ____ ____
35
+ / |/ (_)__________ / __/_ _____ _ __|_ | |_ // / /
36
+ / /|_/ / / __/ __/ _ \/ _// // / -_) | |/ / __/_ _/_ </_ _/
37
+ /_/ /_/_/\__/_/ \___/___/\_, /\__/ |___/____(_)____(_)_/
38
38
  /___/
39
39
  ```
40
40
 
@@ -1,2 +1,2 @@
1
- version_info = (2, 3, 3)
1
+ version_info = (2, 3, 4)
2
2
  __version__ = '.'.join(map(str, version_info))
@@ -1,9 +1,8 @@
1
- from microEye.analysis.filters.base import AbstractFilter
1
+ from microEye.analysis.filters.base import AbstractFilter, SpatialFilter, TemporalFilter
2
2
  from microEye.analysis.filters.spatial import (
3
- BANDPASS_TYPES,
4
- BandpassFilter,
3
+ BackgroundReduction,
5
4
  DoG_Filter,
6
- GaussFilter,
5
+ FourierFilter,
7
6
  PassFilter,
8
7
  )
9
8
  from microEye.analysis.filters.temporal import TemporalMedianFilter
@@ -0,0 +1,62 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Optional
3
+
4
+ import numpy as np
5
+ from PyQt5 import QtWidgets
6
+
7
+
8
+ class AbstractFilter(ABC):
9
+ def __init__(self, name: str = 'Abstract Base Filter', parameters: dict = None):
10
+ self._name = name
11
+ self._parameters = parameters or {}
12
+ self._show_filter = False
13
+
14
+ @abstractmethod
15
+ def run(self, image: np.ndarray) -> np.ndarray:
16
+ '''Apply the filter to the input image.'''
17
+ pass
18
+
19
+ def getWidget(self):
20
+ '''Return the QWidget for configuring the filter.'''
21
+ return QtWidgets.QWidget()
22
+
23
+ def get_metadata(self) -> dict:
24
+ '''Return metadata about the filter.'''
25
+ return {
26
+ 'name': self.name,
27
+ 'parameters': self._parameters,
28
+ }
29
+
30
+ @classmethod
31
+ def get_tree_parameters(cls) -> dict:
32
+ '''Return the parameters for the pyqtgraph tree view.'''
33
+ return None
34
+
35
+ @property
36
+ def name(self):
37
+ return self._name
38
+
39
+ @property
40
+ def parameters(self) -> Optional[dict]:
41
+ return self._parameters
42
+
43
+ class SpatialFilter(AbstractFilter):
44
+ '''Base class for spatial filters.'''
45
+ def __init__(self, name: str = 'Spatial Filter', parameters: dict = None):
46
+ super().__init__(name=name, parameters=parameters)
47
+
48
+ @abstractmethod
49
+ def run(self, image: np.ndarray) -> np.ndarray:
50
+ '''Apply the spatial filter to the input image.'''
51
+ pass
52
+
53
+
54
+ class TemporalFilter(AbstractFilter):
55
+ '''Base class for temporal filters.'''
56
+ def __init__(self, name: str = 'Temporal Filter', parameters: dict = None):
57
+ super().__init__(name=name, parameters=parameters)
58
+
59
+ @abstractmethod
60
+ def run(self, image: np.ndarray) -> np.ndarray:
61
+ '''Apply the temporal filter to the input image.'''
62
+ pass
@@ -0,0 +1,576 @@
1
+ import math
2
+ from enum import Enum
3
+ from typing import Optional
4
+
5
+ import cv2
6
+ import numpy as np
7
+ from scipy import signal
8
+ from scipy.fftpack import fft2, fftshift, ifft2, ifftshift
9
+ from skimage import filters
10
+ from skimage.morphology import disk, white_tophat
11
+ from skimage.restoration import rolling_ball
12
+
13
+ from microEye.analysis.filters.base import SpatialFilter
14
+
15
+
16
+ class PassFilter(SpatialFilter):
17
+ def __init__(self) -> None:
18
+ '''Pass filter initialization.'''
19
+ super().__init__(name='No Filter (Pass)')
20
+
21
+ def run(self, image: np.ndarray) -> np.ndarray:
22
+ return image
23
+
24
+
25
+ class DoG_Filter(SpatialFilter):
26
+ def __init__(self, sigma: float = 1, factor: float = 2.5) -> None:
27
+ '''Difference of Gauss init
28
+
29
+ Parameters
30
+ ----------
31
+ sigma : float, optional
32
+ sigma_min, by default 1
33
+ factor : float, optional
34
+ factor = sigma_max/sigma_min, by default 2.5
35
+ '''
36
+ params = {
37
+ 'sigma': sigma,
38
+ 'factor': factor,
39
+ }
40
+ super().__init__(name='Difference of Gaussians', parameters=params)
41
+ self.set_params(sigma, factor)
42
+
43
+ def set_params(self, sigma: float, factor: float):
44
+ '''Set filter parameters.
45
+
46
+ Parameters
47
+ ----------
48
+ sigma : float
49
+ sigma_min
50
+ factor : float
51
+ factor = sigma_max/sigma_min
52
+ '''
53
+ self._show_filter = False
54
+ self.parameters['sigma'] = sigma
55
+ self.parameters['factor'] = factor
56
+ self.rsize = max(math.ceil(6 * sigma + 1), 3)
57
+ self.dog = DoG_Filter.gaussian_kernel(
58
+ self.rsize, sigma
59
+ ) - DoG_Filter.gaussian_kernel(self.rsize, max(1, factor * sigma))
60
+
61
+ def gaussian_kernel(dim, sigma):
62
+ x = cv2.getGaussianKernel(dim, sigma)
63
+ kernel = x.dot(x.T)
64
+ return kernel
65
+
66
+ def run(self, image: np.ndarray) -> np.ndarray:
67
+ rows, cols = image.shape
68
+ nrows = cv2.getOptimalDFTSize(rows)
69
+ ncols = cv2.getOptimalDFTSize(cols)
70
+ pad_rows = nrows - rows
71
+ pad_cols = ncols - cols
72
+
73
+ # Ensure that pad_cols[1] and pad_rows[1] are at least 1
74
+ pad_rows = (pad_rows // 2, max(1, pad_rows - pad_rows // 2))
75
+ pad_cols = (pad_cols // 2, max(1, pad_cols - pad_cols // 2))
76
+
77
+ nimg = np.pad(image, (pad_rows, pad_cols), mode='reflect')
78
+
79
+ res = cv2.normalize(
80
+ signal.convolve2d(nimg, np.rot90(self.dog), mode='same')[
81
+ pad_rows[0] : -pad_rows[1], pad_cols[0] : -pad_cols[1]
82
+ ],
83
+ None,
84
+ 0,
85
+ 255,
86
+ cv2.NORM_MINMAX,
87
+ cv2.CV_8U,
88
+ )
89
+ return res
90
+
91
+ def get_tree_parameters(self):
92
+ '''Return the parameters for the pyqtgraph tree view.'''
93
+ return {
94
+ 'name': self.name,
95
+ 'type': 'group',
96
+ 'visible': False,
97
+ 'children': [
98
+ {
99
+ 'name': 'Sigma',
100
+ 'type': 'float',
101
+ 'value': self.parameters['sigma'],
102
+ 'limits': [0.0, 100.0],
103
+ 'step': 0.1,
104
+ 'decimals': 2,
105
+ 'tip': 'Standard deviation (\u03c3) min for the filter',
106
+ },
107
+ {
108
+ 'name': 'Factor',
109
+ 'type': 'float',
110
+ 'value': self.parameters['factor'],
111
+ 'limits': [0.0, 100.0],
112
+ 'step': 0.1,
113
+ 'decimals': 2,
114
+ 'tip': 'Ratio of max \u03c3 to min \u03c3.',
115
+ },
116
+ ],
117
+ }
118
+
119
+
120
+ # class GaussFilter(SpatialFilter):
121
+ # def __init__(self, sigma=1) -> None:
122
+ # '''Gaussian filter initialization.'''
123
+ # params = {'sigma': sigma}
124
+ # super().__init__(name='Gaussian Filter', parameters=params)
125
+ # self.set_params(sigma)
126
+
127
+ # def set_params(self, sigma):
128
+ # '''Set the sigma parameter for the Gaussian filter.'''
129
+ # self._show_filter = False
130
+ # self.parameters['sigma'] = sigma
131
+ # self.gauss = GaussFilter.gaussian_kernel(
132
+ # max(3, math.ceil(3 * sigma + 1)), sigma
133
+ # )
134
+
135
+ # def gaussian_kernel(dim, sigma):
136
+ # x = cv2.getGaussianKernel(dim, sigma)
137
+ # kernel = x.dot(x.T)
138
+ # return kernel
139
+
140
+ # def run(self, image: np.ndarray) -> np.ndarray:
141
+ # return cv2.normalize(
142
+ # signal.convolve2d(image, np.rot90(self.gauss), mode='same'),
143
+ # None,
144
+ # 0,
145
+ # 255,
146
+ # cv2.NORM_MINMAX,
147
+ # cv2.CV_8U,
148
+ # )
149
+
150
+ # def get_tree_parameters(self):
151
+ # '''Return the parameters for the pyqtgraph tree view.'''
152
+ # return {
153
+ # 'name': self.name,
154
+ # 'type': 'group',
155
+ # 'visible': False,
156
+ # 'children': [
157
+ # {
158
+ # 'name': 'Sigma',
159
+ # 'type': 'float',
160
+ # 'value': self.parameters['sigma'],
161
+ # 'limits': [0.0, 100.0],
162
+ # 'step': 0.1,
163
+ # 'decimals': 2,
164
+ # 'tip': 'Standard deviation (\u03c3) for the filter',
165
+ # },
166
+ # ],
167
+ # }
168
+
169
+
170
+ class FourierFilter(SpatialFilter):
171
+ class PROFILES(Enum):
172
+ Gaussian = 1
173
+ Butterworth = 2
174
+ Ideal = 3
175
+
176
+ @classmethod
177
+ def from_string(cls, s: str):
178
+ for column in cls:
179
+ if column.name.lower() == s.lower() or s.lower() in column.name.lower():
180
+ return column
181
+ raise ValueError(f'{cls.__name__} has no value matching "{s}"')
182
+
183
+ @classmethod
184
+ def values(cls):
185
+ return [column.name for column in cls]
186
+
187
+ class PASS_TYPES(Enum):
188
+ Band = 0
189
+ Low = 1
190
+ High = 2
191
+
192
+ @classmethod
193
+ def from_string(cls, s: str):
194
+ for column in cls:
195
+ if column.name.lower() == s.lower() or s.lower() in column.name.lower():
196
+ return column
197
+ raise ValueError(f'{cls.__name__} has no value matching "{s}"')
198
+
199
+ @classmethod
200
+ def values(cls):
201
+ return [column.name for column in cls]
202
+
203
+ def __init__(
204
+ self,
205
+ center=40.0,
206
+ width=90.0,
207
+ filter_type=PROFILES.Gaussian,
208
+ pass_type=PASS_TYPES.Band,
209
+ order=5,
210
+ show_filter=False,
211
+ ) -> None:
212
+ '''Fourier filter initialization.'''
213
+ params = {
214
+ 'center': center,
215
+ 'width': width,
216
+ 'type': filter_type.name
217
+ if isinstance(filter_type, FourierFilter.PROFILES)
218
+ else filter_type,
219
+ 'pass_type': pass_type.name
220
+ if isinstance(pass_type, FourierFilter.PASS_TYPES)
221
+ else pass_type,
222
+ 'order': order,
223
+ }
224
+ super().__init__(name='Fourier Filter', parameters=params)
225
+ self._radial_coordinates = None
226
+ self._filter: Optional[np.ndarray] = None
227
+ self._show_filter = show_filter
228
+ self._refresh = True
229
+
230
+ def radial_coordinates(self, shape):
231
+ '''Generates a 2D array with radial cordinates
232
+ with according to the first two axis of the
233
+ supplied shape tuple
234
+
235
+ Returns
236
+ -------
237
+ R, Rsq
238
+ Radius 2d matrix (R) and radius squared matrix (Rsq)
239
+ '''
240
+ y_len = np.arange(-shape[0] // 2, shape[0] // 2)
241
+ x_len = np.arange(-shape[1] // 2, shape[1] // 2)
242
+
243
+ X, Y = np.meshgrid(x_len, y_len)
244
+
245
+ Rsq = X**2 + Y**2
246
+
247
+ self._radial_coordinates = (np.sqrt(Rsq), Rsq)
248
+
249
+ return self._radial_coordinates
250
+
251
+ def ideal_filter(self, shape, cutoff, cuton):
252
+ '''Generates an ideal pass filter of shape
253
+
254
+ Params
255
+ -------
256
+ shape
257
+ the shape of filter matrix
258
+ cutoff
259
+ the cutoff frequency (low)
260
+ cuton
261
+ the cuton frequency (high)
262
+
263
+ Returns
264
+ -------
265
+ filter (np.ndarray)
266
+ the filter in fourier space
267
+ '''
268
+
269
+ cir_filter = np.zeros((shape[0], shape[1]), dtype=np.float32)
270
+ cir_center = (shape[1] // 2, shape[0] // 2)
271
+
272
+ if self.parameters['pass_type'] == FourierFilter.PASS_TYPES.Low.name:
273
+ cir_filter = cv2.circle(cir_filter, cir_center, cutoff, 1, -1)
274
+ elif self.parameters['pass_type'] == FourierFilter.PASS_TYPES.High.name:
275
+ cir_filter = cv2.circle(1 + cir_filter, cir_center, cutoff, 0, -1)
276
+ else:
277
+ cir_filter = cv2.circle(cir_filter, cir_center, cuton, 1, -1)
278
+ cir_filter = cv2.circle(cir_filter, cir_center, cutoff, 0, -1)
279
+
280
+ return cir_filter
281
+
282
+ def gaussian_filter(self, shape, center, width):
283
+ '''Generates a Gaussian pass filter of shape
284
+
285
+ Params
286
+ -------
287
+ shape
288
+ the shape of filter matrix
289
+ center
290
+ the center frequency
291
+ width
292
+ the filter bandwidth
293
+
294
+ Returns
295
+ -------
296
+ filter (np.ndarray)
297
+ the filter in fourier space
298
+ '''
299
+ if self._radial_coordinates is None:
300
+ R, Rsq = self.radial_coordinates(shape)
301
+ elif self._radial_coordinates[0].shape != shape[:2]:
302
+ R, Rsq = self.radial_coordinates(shape)
303
+ else:
304
+ R, Rsq = self._radial_coordinates
305
+
306
+ with np.errstate(divide='ignore', invalid='ignore'):
307
+ if self.parameters['pass_type'] == FourierFilter.PASS_TYPES.Low.name:
308
+ filter = np.exp(-(Rsq) / (2 * (center**2)))
309
+ elif self.parameters['pass_type'] == FourierFilter.PASS_TYPES.High.name:
310
+ filter = 1 - np.exp(-(Rsq) / (2 * (center**2)))
311
+ else:
312
+ filter = np.exp(-(((Rsq - center**2) / (R * width)) ** 2))
313
+
314
+ filter[filter == np.inf] = 0
315
+
316
+ a, b = np.unravel_index(R.argmin(), R.shape)
317
+
318
+ filter[a, b] = 1
319
+
320
+ return filter
321
+
322
+ def butterworth_filter(self, shape, center, width, order=5):
323
+ '''Generates a Gaussian pass filter of shape
324
+
325
+ Params
326
+ -------
327
+ shape
328
+ the shape of filter matrix
329
+ center
330
+ the center frequency
331
+ width
332
+ the filter bandwidth
333
+
334
+ Returns
335
+ -------
336
+ filter (np.ndarray)
337
+ the filter in fourier space
338
+ '''
339
+ if self._radial_coordinates is None:
340
+ R, Rsq = self.radial_coordinates(shape)
341
+ elif self._radial_coordinates[0].shape != shape[:2]:
342
+ R, Rsq = self.radial_coordinates(shape)
343
+ else:
344
+ R, Rsq = self._radial_coordinates
345
+
346
+ with np.errstate(divide='ignore', invalid='ignore'):
347
+ if self.parameters['pass_type'] == FourierFilter.PASS_TYPES.Low.name:
348
+ filter = 1 / (1 + (R / center) ** (2 * order))
349
+ elif self.parameters['pass_type'] == FourierFilter.PASS_TYPES.High.name:
350
+ filter = 1 / (1 + (center / np.where(R == 0, 1e-10, R)) ** (2 * order))
351
+ else:
352
+ filter = 1 - (
353
+ 1 / (1 + ((R * width) / (Rsq - center**2)) ** (2 * order))
354
+ )
355
+
356
+ filter[filter == np.inf] = 0
357
+
358
+ a, b = np.unravel_index(R.argmin(), R.shape)
359
+
360
+ filter[a, b] = 1
361
+
362
+ return filter
363
+
364
+ def run(self, image: np.ndarray):
365
+ '''Applies an FFT pass filter to the 2D image.
366
+
367
+ Params
368
+ -------
369
+ image (np.ndarray)
370
+ the image to be filtered.
371
+ '''
372
+
373
+ # time = QDateTime.currentDateTime()
374
+
375
+ rows, cols = image.shape
376
+ nrows = cv2.getOptimalDFTSize(rows)
377
+ ncols = cv2.getOptimalDFTSize(cols)
378
+ pad_rows = nrows - rows
379
+ pad_cols = ncols - cols
380
+
381
+ # Ensure that pad_cols[1] and pad_rows[1] are at least 1
382
+ pad_rows = (pad_rows // 2, max(1, pad_rows - pad_rows // 2))
383
+ pad_cols = (pad_cols // 2, max(1, pad_cols - pad_cols // 2))
384
+
385
+ nimg = np.pad(image, (pad_rows, pad_cols), mode='reflect')
386
+ # nimg = np.zeros((nrows, ncols))
387
+ # nimg[:rows, :cols] = image
388
+
389
+ ft = fftshift(cv2.dft(np.float64(nimg), flags=cv2.DFT_COMPLEX_OUTPUT))
390
+
391
+ filter = np.ones(ft.shape[:2])
392
+
393
+ refresh = self._refresh
394
+
395
+ if self._filter is None:
396
+ refresh = True
397
+ elif self._filter.shape != ft.shape[:2]:
398
+ refresh = True
399
+
400
+ if refresh:
401
+ if self.parameters['type'] == FourierFilter.PROFILES.Gaussian.name:
402
+ filter = self.gaussian_filter(
403
+ ft.shape, self.parameters['center'], self.parameters['width']
404
+ )
405
+ elif self.parameters['type'] == FourierFilter.PROFILES.Butterworth.name:
406
+ filter = self.butterworth_filter(
407
+ ft.shape,
408
+ self.parameters['center'],
409
+ self.parameters['width'],
410
+ self.parameters['order'],
411
+ )
412
+ else:
413
+ cutoff = int(
414
+ max(0, self.parameters['center'] - self.parameters['width'] // 2)
415
+ )
416
+ cuton = int(self.parameters['center'] + self.parameters['width'] // 2)
417
+ filter = self.ideal_filter(ft.shape, cutoff, cuton)
418
+
419
+ self._filter = filter
420
+ else:
421
+ filter = self._filter
422
+
423
+ if self._show_filter:
424
+ cv2.namedWindow(self.name, cv2.WINDOW_NORMAL)
425
+ cv2.imshow(self.name, (filter * 255).astype(np.uint8))
426
+
427
+ img = np.zeros(nimg.shape, dtype=np.uint8)
428
+ ft[:, :, 0] *= filter
429
+ ft[:, :, 1] *= filter
430
+ idft = cv2.idft(ifftshift(ft))
431
+ idft = cv2.magnitude(idft[:, :, 0], idft[:, :, 1])
432
+ cv2.normalize(idft, img, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U)
433
+
434
+ # exex = time.msecsTo(QDateTime.currentDateTime())
435
+ return img[pad_rows[0] : -pad_rows[1], pad_cols[0] : -pad_cols[1]]
436
+
437
+ def set_params(
438
+ self,
439
+ center: float,
440
+ width: float,
441
+ filter_type: PROFILES,
442
+ pass_type: PASS_TYPES,
443
+ show_filter: bool,
444
+ order: int = 5,
445
+ ):
446
+ '''
447
+ Set the parameters for the filter.
448
+ '''
449
+ self.parameters['center'] = center
450
+ self.parameters['width'] = width
451
+ self.parameters['order'] = order
452
+ self.parameters['type'] = (
453
+ filter_type.name
454
+ if isinstance(filter_type, FourierFilter.PROFILES)
455
+ else filter_type
456
+ )
457
+ self.parameters['pass_type'] = (
458
+ pass_type.name
459
+ if isinstance(pass_type, FourierFilter.PASS_TYPES)
460
+ else pass_type
461
+ )
462
+ self._show_filter = show_filter
463
+
464
+ def get_tree_parameters(self):
465
+ return {
466
+ 'name': self.name,
467
+ 'type': 'group',
468
+ 'visible': False,
469
+ 'children': [
470
+ {
471
+ 'name': 'Filter Type',
472
+ 'type': 'list',
473
+ 'limits': FourierFilter.PROFILES.values(),
474
+ 'value': FourierFilter.PROFILES.Gaussian.name,
475
+ 'tip': 'Select the type of fourier filter',
476
+ },
477
+ {
478
+ 'name': 'Pass Type',
479
+ 'type': 'list',
480
+ 'limits': FourierFilter.PASS_TYPES.values(),
481
+ 'value': FourierFilter.PASS_TYPES.Band.name,
482
+ 'tip': 'Select the type of pass filter',
483
+ },
484
+ {
485
+ 'name': 'Center',
486
+ 'type': 'float',
487
+ 'value': self.parameters['center'],
488
+ 'limits': [0.0, 2096.0],
489
+ 'step': 0.5,
490
+ 'decimals': 2,
491
+ 'tip': 'Center frequency in pixels.',
492
+ },
493
+ {
494
+ 'name': 'Width',
495
+ 'type': 'float',
496
+ 'value': 90,
497
+ 'limits': [0.0, 2096.0],
498
+ 'step': 0.5,
499
+ 'decimals': 2,
500
+ 'tip': 'The width of the band in pixels',
501
+ },
502
+ {
503
+ 'name': 'Order',
504
+ 'type': 'int',
505
+ 'value': 5,
506
+ 'limits': [1, 10],
507
+ 'step': 1,
508
+ 'tip': 'The order of the Butterworth filter',
509
+ },
510
+ {
511
+ 'name': 'Show Filter',
512
+ 'type': 'bool',
513
+ 'value': self._show_filter,
514
+ 'tip': 'Toggle to show or hide the filter',
515
+ },
516
+ ],
517
+ }
518
+
519
+
520
+ class BackgroundReduction(SpatialFilter):
521
+ METHODS = [
522
+ 'Rolling Ball',
523
+ 'White Top Hat',
524
+ ]
525
+
526
+ def __init__(self, radius: float = 30.0) -> None:
527
+ '''Rolling ball filter initialization.'''
528
+ params = {
529
+ 'radius': radius,
530
+ 'method': 'Rolling Ball',
531
+ }
532
+ super().__init__(name='Background Reduction', parameters=params)
533
+ self.set_params(radius)
534
+
535
+ def set_params(self, radius: float, method='Rolling Ball'):
536
+ '''Set the radius parameter fand the method.'''
537
+ self.parameters['radius'] = radius
538
+
539
+ if method not in self.METHODS:
540
+ raise ValueError(f'Method {method} not supported.')
541
+
542
+ self.parameters['method'] = method
543
+
544
+ def run(self, image: np.ndarray) -> np.ndarray:
545
+ if self.parameters['method'] == self.METHODS[0]:
546
+ return image - rolling_ball(image, radius=self.parameters['radius'])
547
+ elif self.parameters['method'] == self.METHODS[1]:
548
+ return white_tophat(image, disk(self.parameters['radius']))
549
+
550
+ return image
551
+
552
+ def get_tree_parameters(self):
553
+ '''Return the parameters for the pyqtgraph tree view.'''
554
+ return {
555
+ 'name': self.name,
556
+ 'type': 'group',
557
+ 'visible': False,
558
+ 'children': [
559
+ {
560
+ 'name': 'Radius',
561
+ 'type': 'float',
562
+ 'value': self.parameters['radius'],
563
+ 'limits': [0.0, 250.0],
564
+ 'step': 0.1,
565
+ 'decimals': 2,
566
+ 'tip': 'Radius of the rolling ball in pixels',
567
+ },
568
+ {
569
+ 'name': 'Method',
570
+ 'type': 'list',
571
+ 'limits': self.METHODS,
572
+ 'value': self.parameters['method'],
573
+ 'tip': 'Select the method for background reduction',
574
+ },
575
+ ],
576
+ }