microeye 2.3.9__tar.gz → 2.3.11__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.
- {microeye-2.3.9/src/microeye.egg-info → microeye-2.3.11}/PKG-INFO +7 -6
- {microeye-2.3.9 → microeye-2.3.11}/README.md +5 -5
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/_version.py +1 -1
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/filters/spatial.py +52 -48
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/processing.py +34 -7
- microeye-2.3.11/src/microEye/analysis/fitting/rcc.py +183 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/results.py +66 -11
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/viewer/localizations.py +32 -11
- microeye-2.3.11/src/microEye/hardware/cams/basler/basler_cam.py +413 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/camera_options.py +1 -1
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/mieye/devices_manager.py +15 -1
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/pycromanager/core.py +12 -9
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/stages/stabilizer.py +197 -200
- microeye-2.3.11/src/microEye/tools/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11/src/microeye.egg-info}/PKG-INFO +7 -6
- {microeye-2.3.9 → microeye-2.3.11}/src/microeye.egg-info/SOURCES.txt +3 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microeye.egg-info/requires.txt +1 -0
- {microeye-2.3.9 → microeye-2.3.11}/LICENSE +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/MANIFEST.in +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/pyproject.toml +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/setup.cfg +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/setup.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/checklist_dialog.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/cmosMaps.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/filters/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/filters/base.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/filters/temporal.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/fit.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/nena.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/phasor_fit.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/psf/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/psf/extract.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/psf/rubost_mean.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/psf/spline.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/psf/stats/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/psf/stats/core.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/psf/stats/curve_fit.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/psf/stats/io.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/psf/stats/slope_fit.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/psf/temp.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/psf/test.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUfunctions.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUmleFit_LM.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUsplineLib.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/pyfit3Dcspline/CPU/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUfunctions.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_EMCCD.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_sCMOS.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUsplineLib.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/pyfit3Dcspline/GPU/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/pyfit3Dcspline/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/pyfit3Dcspline/constants.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/pyfit3Dcspline/mainfunctions.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/results_stats.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/fitting/tardis.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/multi_viewer.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/processing/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/processing/frc.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/rendering/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/rendering/base.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/rendering/cloud.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/rendering/core.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/rendering/volumetric.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/tools/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/tools/kymograms.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/tools/roi_selectors.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/utils/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/utils/coordinates.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/utils/images.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/utils/windows.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/viewer/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/viewer/image_options_widget.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/viewer/images.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/viewer/layers_widget.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/viewer/psf.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/analysis/viewer/volume.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/__init__.py +0 -0
- {microeye-2.3.9/src/microEye/hardware/misc → microeye-2.3.11/src/microEye/hardware/cams/basler}/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/camera_calibration.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/camera_list.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/camera_panel.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/dummy/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/dummy/dummy_panel.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/jobs.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/line_profiler.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/linescan/IR_Cam.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/linescan/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/micam.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/pco/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/pco/enums.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/pco/pco_cam.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/pco/pco_panel.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/shortcuts.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/thorlabs/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/thorlabs/thorlabs.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/thorlabs/thorlabs_panel.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/ueye/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/ueye/ueye_camera.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/ueye/ueye_panel.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/vimba/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/vimba/vimba_cam.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/cams/vimba/vimba_panel.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/device.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/lasers/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/lasers/io_matchbox.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/lasers/io_params.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/lasers/io_single_laser.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/lasers/laser_relay.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/mieye/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/mieye/acquisition_manager.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/mieye/miEye.py +0 -0
- {microeye-2.3.9/src/microEye/hardware/protocols → microeye-2.3.11/src/microEye/hardware/misc}/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/misc/acquisition_view.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/misc/reglo.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/misc/temp.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/port_config.py +0 -0
- {microeye-2.3.9/src/microEye/hardware/stages → microeye-2.3.11/src/microEye/hardware/protocols}/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/protocols/actions.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/protocols/actions_items.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/protocols/designer.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/protocols/scene_manager.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/protocols/serialization.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/pycromanager/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/pycromanager/devices.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/pycromanager/enums.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/pycromanager/headless.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/pycromanager/utils.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/pycromanager/widgets/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/pycromanager/widgets/bridges.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/pycromanager/widgets/headless_manager.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/pycromanager/widgets/headless_options.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/pycromanager/widgets/pycro_panel.py +0 -0
- {microeye-2.3.9/src/microEye/icons → microeye-2.3.11/src/microEye/hardware/stages}/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/stages/elliptec/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/stages/elliptec/baseDevice.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/stages/elliptec/device.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/stages/elliptec/deviceID.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/stages/elliptec/devicePort.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/stages/elliptec/deviceStatus.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/stages/elliptec/devicesView.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/stages/elliptec/ellDevices.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/stages/elliptec/messageUpdater.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/stages/elliptec/motorInfo.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/stages/elliptec/stage.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/stages/elliptec/test.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/stages/kinesis/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/stages/kinesis/kdc101/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/stages/kinesis/kdc101/enums.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/stages/kinesis/kdc101/factory.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/stages/kinesis/kdc101/kdc101.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/stages/kinesis/kinesis.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/stages/piezo_concept.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/stages/stage.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/widgets/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/widgets/controller.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/widgets/devices.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/widgets/focusWidget.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/widgets/qlist_slider.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/hardware/widgets/scan_acquisition.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/icons/1024.png +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/icons/128.png +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/icons/16.png +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/icons/24.png +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/icons/256.png +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/icons/32.png +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/icons/48.png +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/icons/512.png +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/icons/64.png +0 -0
- {microeye-2.3.9/src/microEye/tools → microeye-2.3.11/src/microEye/icons}/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/icons/close.svg +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/icons/mieye.png +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/icons/min.svg +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/icons/viewer.png +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/launcher.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/qt.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/tools/microscopy.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/utils/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/utils/display.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/utils/enum_encoder.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/utils/expandable_groupbox.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/utils/gui_helper.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/utils/hid_utils/__init__.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/utils/hid_utils/controller.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/utils/hid_utils/device.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/utils/hid_utils/enums.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/utils/hid_utils/utils.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/utils/labelled_slider.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/utils/metadata.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/utils/metadata_tree.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/utils/micro_launcher.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/utils/parameter_tree.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/utils/pyscripting.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/utils/retry_exec.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/utils/start_gui.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/utils/thread_worker.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microEye/utils/uImage.py +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microeye.egg-info/dependency_links.txt +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/src/microeye.egg-info/entry_points.txt +0 -0
- {microeye-2.3.9 → microeye-2.3.11}/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
|
+
Version: 2.3.11
|
|
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
|
|
@@ -32,6 +32,7 @@ Requires-Dist: pyfiglet==1.0.2
|
|
|
32
32
|
Requires-Dist: pyflakes==3.2.0
|
|
33
33
|
Requires-Dist: pyjokes==0.6.0
|
|
34
34
|
Requires-Dist: PyOpenGL==3.1.7
|
|
35
|
+
Requires-Dist: pypylon==4.2.0
|
|
35
36
|
Requires-Dist: pyqtdarktheme==2.1.0
|
|
36
37
|
Requires-Dist: pyqtgraph==0.13.7
|
|
37
38
|
Requires-Dist: pyserial==3.5
|
|
@@ -71,11 +72,11 @@ The **`microEye`** is a Python toolkit for fluorescence microscopy that supports
|
|
|
71
72
|
This toolkit is compatible with the [hardware](#hardware) used in our microscope. For further details, refer to the [miEye microscope paper](https://doi.org/10.1016/j.ohx.2022.e00368) and [OSF project](http://doi.org/10.17605/osf.io/j2fqy).
|
|
72
73
|
|
|
73
74
|
```bash
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
__ ____ ____ ___ ____ ______
|
|
76
|
+
/ |/ (_)__________ / __/_ _____ _ __|_ | |_ / < < /
|
|
77
|
+
/ /|_/ / / __/ __/ _ \/ _// // / -_) | |/ / __/_ _/_ <_ / // /
|
|
78
|
+
/_/ /_/_/\__/_/ \___/___/\_, /\__/ |___/____(_)____(_)_//_/
|
|
79
|
+
/___/
|
|
79
80
|
```
|
|
80
81
|
|
|
81
82
|

|
|
@@ -7,11 +7,11 @@ The **`microEye`** is a Python toolkit for fluorescence microscopy that supports
|
|
|
7
7
|
This toolkit is compatible with the [hardware](#hardware) used in our microscope. For further details, refer to the [miEye microscope paper](https://doi.org/10.1016/j.ohx.2022.e00368) and [OSF project](http://doi.org/10.17605/osf.io/j2fqy).
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
__ ____ ____ ___ ____ ______
|
|
11
|
+
/ |/ (_)__________ / __/_ _____ _ __|_ | |_ / < < /
|
|
12
|
+
/ /|_/ / / __/ __/ _ \/ _// // / -_) | |/ / __/_ _/_ <_ / // /
|
|
13
|
+
/_/ /_/_/\__/_/ \___/___/\_, /\__/ |___/____(_)____(_)_//_/
|
|
14
|
+
/___/
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|

|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
version_info = (2, 3,
|
|
1
|
+
version_info = (2, 3, 11)
|
|
2
2
|
__version__ = '.'.join(map(str, version_info))
|
|
@@ -117,54 +117,58 @@ class DoG_Filter(SpatialFilter):
|
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
120
|
+
class PointGaussFilter(SpatialFilter):
|
|
121
|
+
def __init__(self, sigma=1) -> None:
|
|
122
|
+
'''Gaussian filter initialization.'''
|
|
123
|
+
params = {'sigma': sigma}
|
|
124
|
+
super().__init__(name='Point Gaussian Filter', parameters=params)
|
|
125
|
+
self.set_params(sigma)
|
|
126
|
+
|
|
127
|
+
self.point_kernel = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]])
|
|
128
|
+
|
|
129
|
+
def set_params(self, sigma):
|
|
130
|
+
'''Set the sigma parameter for the Gaussian filter.'''
|
|
131
|
+
self._show_filter = False
|
|
132
|
+
self.parameters['sigma'] = sigma
|
|
133
|
+
self.gauss = PointGaussFilter.gaussian_kernel(
|
|
134
|
+
max(3, math.ceil(3 * sigma + 1)), sigma
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
def gaussian_kernel(dim, sigma):
|
|
138
|
+
x = cv2.getGaussianKernel(dim, sigma)
|
|
139
|
+
kernel = x.dot(x.T)
|
|
140
|
+
return kernel
|
|
141
|
+
|
|
142
|
+
def run(self, image: np.ndarray) -> np.ndarray:
|
|
143
|
+
point = signal.fftconvolve(image, np.rot90(self.point_kernel), mode='same')
|
|
144
|
+
|
|
145
|
+
return cv2.normalize(
|
|
146
|
+
signal.fftconvolve(point, np.rot90(self.gauss), mode='same'),
|
|
147
|
+
None,
|
|
148
|
+
0,
|
|
149
|
+
255,
|
|
150
|
+
cv2.NORM_MINMAX,
|
|
151
|
+
cv2.CV_8U,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
def get_tree_parameters(self):
|
|
155
|
+
'''Return the parameters for the pyqtgraph tree view.'''
|
|
156
|
+
return {
|
|
157
|
+
'name': self.name,
|
|
158
|
+
'type': 'group',
|
|
159
|
+
'visible': False,
|
|
160
|
+
'children': [
|
|
161
|
+
{
|
|
162
|
+
'name': 'Sigma',
|
|
163
|
+
'type': 'float',
|
|
164
|
+
'value': self.parameters['sigma'],
|
|
165
|
+
'limits': [0.0, 100.0],
|
|
166
|
+
'step': 0.1,
|
|
167
|
+
'decimals': 2,
|
|
168
|
+
'tip': 'Standard deviation (\u03c3) for the filter',
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
}
|
|
168
172
|
|
|
169
173
|
|
|
170
174
|
class FourierFilter(SpatialFilter):
|
|
@@ -249,7 +249,14 @@ def shift_correction(interpx, interpy, frame_bins, datax, datay):
|
|
|
249
249
|
datay[mask] -= shift_y
|
|
250
250
|
|
|
251
251
|
|
|
252
|
-
def plot_drift(
|
|
252
|
+
def plot_drift(
|
|
253
|
+
frames_new,
|
|
254
|
+
interpx,
|
|
255
|
+
interpy,
|
|
256
|
+
error_x=None,
|
|
257
|
+
error_y=None,
|
|
258
|
+
title='Drift Cross-Correlation',
|
|
259
|
+
):
|
|
253
260
|
print('Shift Plot ...', end='\r')
|
|
254
261
|
|
|
255
262
|
# plot results
|
|
@@ -272,8 +279,29 @@ def plot_drift(frames_new, interpx, interpy, title='Drift Cross-Correlation'):
|
|
|
272
279
|
# setting vertical range
|
|
273
280
|
# plt.setYRange(0, 1)
|
|
274
281
|
|
|
275
|
-
|
|
276
|
-
|
|
282
|
+
# Plot x-drift with error bars
|
|
283
|
+
if error_x is not None:
|
|
284
|
+
err_x = pg.ErrorBarItem(
|
|
285
|
+
x=frames_new, y=interpx, top=error_x, bottom=error_x, beam=0.5,
|
|
286
|
+
pen=pg.mkPen(color=(255, 0, 0, 24)) # red color with transparency
|
|
287
|
+
)
|
|
288
|
+
plt.addItem(err_x)
|
|
289
|
+
|
|
290
|
+
# Plot y-drift with error bars
|
|
291
|
+
if error_y is not None:
|
|
292
|
+
err_y = pg.ErrorBarItem(
|
|
293
|
+
x=frames_new, y=interpy, top=error_y, bottom=error_y, beam=0.5,
|
|
294
|
+
pen=pg.mkPen(color=(255, 255, 0, 24)) # yellow color with transparency
|
|
295
|
+
)
|
|
296
|
+
plt.addItem(err_y)
|
|
297
|
+
|
|
298
|
+
# Plot x and y drift curves
|
|
299
|
+
x_curve = plt.plot(
|
|
300
|
+
frames_new, interpx, pen='r', symbol=None, symbolBrush=0.2, name='x-drift'
|
|
301
|
+
)
|
|
302
|
+
y_curve = plt.plot(
|
|
303
|
+
frames_new, interpy, pen='y', symbol=None, symbolBrush=0.2, name='y-drift'
|
|
304
|
+
)
|
|
277
305
|
|
|
278
306
|
print('Done ...', end='\r')
|
|
279
307
|
|
|
@@ -285,10 +313,9 @@ def plot_animation_stats(
|
|
|
285
313
|
|
|
286
314
|
# Calculate bin edges from centers
|
|
287
315
|
bin_width = frame_bin_centers[1] - frame_bin_centers[0]
|
|
288
|
-
bin_edges = np.concatenate(
|
|
289
|
-
frame_bin_centers - bin_width/2,
|
|
290
|
-
|
|
291
|
-
])
|
|
316
|
+
bin_edges = np.concatenate(
|
|
317
|
+
[frame_bin_centers - bin_width / 2, [frame_bin_centers[-1] + bin_width / 2]]
|
|
318
|
+
)
|
|
292
319
|
|
|
293
320
|
# plot results
|
|
294
321
|
plt = pg.plot()
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import cv2
|
|
2
|
+
import numba as nb
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from microEye.analysis.fitting.pyfit3Dcspline.CPU.CPUmleFit_LM import (
|
|
6
|
+
kernel_MLEFit_LM_Sigma,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def cross_correlation(image1, image2):
|
|
11
|
+
"""
|
|
12
|
+
Compute the cross-correlation of two images using FFT.
|
|
13
|
+
Equivalent to MATLAB's CrossCorrelation function.
|
|
14
|
+
"""
|
|
15
|
+
f1 = np.fft.fft2(image1)
|
|
16
|
+
f2 = np.fft.fft2(image2)
|
|
17
|
+
corr = np.fft.fftshift(np.real(np.fft.ifft2(f1 * np.conj(f2))))
|
|
18
|
+
return corr
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@nb.njit
|
|
22
|
+
def _process_single_image(image, reference, pixelSize, box):
|
|
23
|
+
with nb.objmode(result='float32[:]'):
|
|
24
|
+
xcorr = cross_correlation(image, reference)
|
|
25
|
+
y_max_, x_max_ = np.unravel_index(xcorr.argmax(), xcorr.shape)
|
|
26
|
+
|
|
27
|
+
halfBoxSize = int(box / 2)
|
|
28
|
+
|
|
29
|
+
xcorr = xcorr[
|
|
30
|
+
y_max_ - halfBoxSize : y_max_ + halfBoxSize + 1,
|
|
31
|
+
x_max_ - halfBoxSize : x_max_ + halfBoxSize + 1,
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
result, crb, ll = kernel_MLEFit_LM_Sigma(
|
|
35
|
+
xcorr.flatten().astype(np.float32), 1.0, int(box + 1), 60, None
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
result[0] += x_max_ - halfBoxSize
|
|
39
|
+
result[1] += y_max_ - halfBoxSize
|
|
40
|
+
|
|
41
|
+
shift = result[0:2] * pixelSize
|
|
42
|
+
|
|
43
|
+
return shift
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@nb.njit(parallel=True, cache=True)
|
|
47
|
+
def rcc_shift_estimation(sub_images, pixelSize, box=12):
|
|
48
|
+
n_bins = sub_images.shape[0]
|
|
49
|
+
total_pairs = n_bins * (n_bins - 1) // 2
|
|
50
|
+
|
|
51
|
+
# Pre-compute all (i,j) pairs and their corresponding linear indices
|
|
52
|
+
pairs = []
|
|
53
|
+
for i in range(n_bins - 1):
|
|
54
|
+
for j in range(i + 1, n_bins):
|
|
55
|
+
pairs.append((i, j))
|
|
56
|
+
|
|
57
|
+
imshift = np.zeros((total_pairs, 2), dtype=np.float32)
|
|
58
|
+
A = np.zeros((total_pairs, n_bins - 1), dtype=np.float32)
|
|
59
|
+
|
|
60
|
+
# Process reference image once
|
|
61
|
+
origins = {}
|
|
62
|
+
for i in nb.prange(n_bins - 1):
|
|
63
|
+
yorigin, xorigin = _process_single_image(
|
|
64
|
+
sub_images[i], sub_images[i], pixelSize, box
|
|
65
|
+
)
|
|
66
|
+
origins[i] = (yorigin, xorigin)
|
|
67
|
+
|
|
68
|
+
# Process all pairs
|
|
69
|
+
for idx in nb.prange(len(pairs)):
|
|
70
|
+
i, j = pairs[idx]
|
|
71
|
+
y, x = _process_single_image(sub_images[i], sub_images[j], pixelSize, box)
|
|
72
|
+
yorigin, xorigin = origins[i]
|
|
73
|
+
imshift[idx, 0] = xorigin - x
|
|
74
|
+
imshift[idx, 1] = yorigin - y
|
|
75
|
+
A[idx, i:j] = 1
|
|
76
|
+
|
|
77
|
+
return imshift, A
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def rcc_solve(imshift, A, n_bins, rmax=10.0):
|
|
81
|
+
# imshift: (N, 2) or (N, 3)
|
|
82
|
+
# A: (N, n_bins-1)
|
|
83
|
+
# use_z: if True, expects imshift.shape[1] == 3
|
|
84
|
+
|
|
85
|
+
# Initial solve
|
|
86
|
+
drift = np.matmul(np.linalg.pinv(A), imshift)
|
|
87
|
+
error = np.matmul(A, drift) - imshift
|
|
88
|
+
|
|
89
|
+
# Compute error magnitude
|
|
90
|
+
rowerr = np.zeros((A.shape[0], 2))
|
|
91
|
+
if error.shape[1] == 3:
|
|
92
|
+
rowerr[:, 0] = np.sqrt(error[:, 0] ** 2 + error[:, 1] ** 2 + error[:, 2] ** 2)
|
|
93
|
+
else:
|
|
94
|
+
rowerr[:, 0] = np.sqrt(error[:, 0] ** 2 + error[:, 1] ** 2)
|
|
95
|
+
rowerr[:, 1] = np.arange(A.shape[0])
|
|
96
|
+
|
|
97
|
+
# Sort by error (descending)
|
|
98
|
+
rowerr = np.flipud(np.sort(rowerr, axis=0))
|
|
99
|
+
|
|
100
|
+
# Outlier rejection
|
|
101
|
+
mask = rowerr[:, 0] > rmax
|
|
102
|
+
index = rowerr[mask, 1].astype(np.int64)
|
|
103
|
+
|
|
104
|
+
# Remove outliers (one by one, check rank)
|
|
105
|
+
for idx in range(len(index)):
|
|
106
|
+
flag = int(index[idx])
|
|
107
|
+
tmp = np.delete(A, flag, axis=0)
|
|
108
|
+
if np.linalg.matrix_rank(tmp, tol=1) == (n_bins - 1):
|
|
109
|
+
A = np.delete(A, flag, axis=0)
|
|
110
|
+
imshift = np.delete(imshift, flag, axis=0)
|
|
111
|
+
index[index > flag] -= 1
|
|
112
|
+
|
|
113
|
+
# Final solve and cumulative sum
|
|
114
|
+
return np.cumsum(np.matmul(np.linalg.pinv(A), imshift), axis=0)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@nb.njit(parallel=True, cache=True)
|
|
118
|
+
def dcc_shift_estimation(sub_images, pixelSize, box=12):
|
|
119
|
+
n_bins = sub_images.shape[0]
|
|
120
|
+
|
|
121
|
+
imshift = np.zeros((n_bins - 1, 2), dtype=np.float32)
|
|
122
|
+
|
|
123
|
+
yorigin, xorigin = _process_single_image(
|
|
124
|
+
sub_images[0], sub_images[0], pixelSize, box
|
|
125
|
+
)
|
|
126
|
+
# Process
|
|
127
|
+
for i in range(1, n_bins):
|
|
128
|
+
y, x = _process_single_image(sub_images[0], sub_images[i], pixelSize, box)
|
|
129
|
+
imshift[i - 1, 0] = xorigin - x
|
|
130
|
+
imshift[i - 1, 1] = yorigin - y
|
|
131
|
+
|
|
132
|
+
return imshift
|
|
133
|
+
|
|
134
|
+
@nb.njit(parallel=True, cache=True)
|
|
135
|
+
def mcc_shift_estimation(sub_images, pixelSize, box=12):
|
|
136
|
+
n_bins = sub_images.shape[0]
|
|
137
|
+
total_pairs = n_bins * (n_bins - 1) // 2
|
|
138
|
+
|
|
139
|
+
# Pre-compute all (i,j) pairs and their corresponding linear indices
|
|
140
|
+
pairs = []
|
|
141
|
+
for i in range(n_bins - 1):
|
|
142
|
+
for j in range(i + 1, n_bins):
|
|
143
|
+
pairs.append((i, j))
|
|
144
|
+
|
|
145
|
+
imshift = np.zeros((total_pairs, 2), dtype=np.float32)
|
|
146
|
+
drift = np.zeros((n_bins, 2), dtype=np.float32)
|
|
147
|
+
|
|
148
|
+
# Process reference image once
|
|
149
|
+
origins = {}
|
|
150
|
+
for i in nb.prange(n_bins - 1):
|
|
151
|
+
yorigin, xorigin = _process_single_image(
|
|
152
|
+
sub_images[i], sub_images[i], pixelSize, box
|
|
153
|
+
)
|
|
154
|
+
origins[i] = (yorigin, xorigin)
|
|
155
|
+
|
|
156
|
+
# Process all pairs
|
|
157
|
+
for idx in nb.prange(len(pairs)):
|
|
158
|
+
i, j = pairs[idx]
|
|
159
|
+
y, x = _process_single_image(sub_images[i], sub_images[j], pixelSize, box)
|
|
160
|
+
yorigin, xorigin = origins[i]
|
|
161
|
+
imshift[idx, 0] = xorigin - x
|
|
162
|
+
imshift[idx, 1] = yorigin - y
|
|
163
|
+
|
|
164
|
+
# For each bin, sum the shifts as per MCC
|
|
165
|
+
for i in nb.prange(n_bins):
|
|
166
|
+
# Subtract shifts to later bins
|
|
167
|
+
for j in range(i + 1, n_bins):
|
|
168
|
+
idx = (i * (2 * n_bins - i - 1)) // 2 + (j - i - 1)
|
|
169
|
+
drift[i, 0] -= imshift[idx, 0]
|
|
170
|
+
drift[i, 1] -= imshift[idx, 1]
|
|
171
|
+
# Add shifts from earlier bins
|
|
172
|
+
for j in range(i):
|
|
173
|
+
idx = (j * (2 * n_bins - j - 1)) // 2 + (i - j - 1)
|
|
174
|
+
drift[i, 0] += imshift[idx, 0]
|
|
175
|
+
drift[i, 1] += imshift[idx, 1]
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
drift /= n_bins
|
|
179
|
+
|
|
180
|
+
drift[:, 0] -= drift[0, 0]
|
|
181
|
+
drift[:, 1] -= drift[0, 1]
|
|
182
|
+
|
|
183
|
+
return drift
|
|
@@ -6,6 +6,12 @@ from numpy.core._exceptions import _ArrayMemoryError
|
|
|
6
6
|
from scipy.interpolate import interp1d
|
|
7
7
|
|
|
8
8
|
from microEye.analysis.fitting.processing import *
|
|
9
|
+
from microEye.analysis.fitting.rcc import (
|
|
10
|
+
dcc_shift_estimation,
|
|
11
|
+
mcc_shift_estimation,
|
|
12
|
+
rcc_shift_estimation,
|
|
13
|
+
rcc_solve,
|
|
14
|
+
)
|
|
9
15
|
from microEye.analysis.rendering import BaseRenderer, Projection, RenderModes
|
|
10
16
|
|
|
11
17
|
UNIQUE_COLUMNS = [
|
|
@@ -584,10 +590,16 @@ class FittingResults:
|
|
|
584
590
|
sub_images.append(image)
|
|
585
591
|
print(f'Bins: {f + 1:d}/{n_bins:d}', end='\r')
|
|
586
592
|
|
|
587
|
-
return
|
|
593
|
+
return (
|
|
594
|
+
np.array(sub_images),
|
|
595
|
+
np.array(frames),
|
|
596
|
+
np.array(locs_per_bin),
|
|
597
|
+
)
|
|
588
598
|
|
|
589
|
-
def drift_cross_correlation(
|
|
590
|
-
|
|
599
|
+
def drift_cross_correlation(
|
|
600
|
+
self, n_bins=10, pixelSize=10, upsampling=100, rmax=20, method='phase'
|
|
601
|
+
):
|
|
602
|
+
"""Corrects the XY drift using cross-correlation measurments
|
|
591
603
|
|
|
592
604
|
Parameters
|
|
593
605
|
----------
|
|
@@ -598,12 +610,31 @@ class FittingResults:
|
|
|
598
610
|
upsampling : int, optional
|
|
599
611
|
phase_cross_correlation upsampling (check skimage.registration),
|
|
600
612
|
by default 100
|
|
613
|
+
rmax : int, optional
|
|
614
|
+
Maximum error for redundant cross-correlation, by default 20, should be
|
|
615
|
+
0.2 of projected pixel size.
|
|
616
|
+
method : str, optional
|
|
617
|
+
Drift estimation method, by default 'phase'
|
|
618
|
+
Options: 'rcc', 'mcc', 'dcc', 'phase'
|
|
619
|
+
|
|
620
|
+
- 'rcc' - redundant cross-correlation [1]
|
|
621
|
+
- 'mcc' - mean cross-correlation [1]
|
|
622
|
+
- 'dcc' - drift cross-correlation [1]
|
|
623
|
+
- 'phase' - phase cross-correlation
|
|
601
624
|
|
|
602
625
|
Returns
|
|
603
626
|
-------
|
|
604
627
|
tuple(FittingResults, np.ndarray)
|
|
605
628
|
returns the drift corrected fittingResults and recontructed image
|
|
606
|
-
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
References
|
|
632
|
+
----------
|
|
633
|
+
[1] Yina Wang, Joerg Schnitzbauer, Zhe Hu, Xueming Li, Yifan Cheng,
|
|
634
|
+
Zhen-Li Huang, and Bo Huang, "Localization events-based sample
|
|
635
|
+
drift correction for localization microscopy with redundant
|
|
636
|
+
cross-correlation algorithm," Opt. Express 22, 15982-15991 (2014)
|
|
637
|
+
"""
|
|
607
638
|
unique_frames = np.unique(self.data[DataColumns.FRAME])
|
|
608
639
|
if len(unique_frames) < 2:
|
|
609
640
|
print('Drift cross-correlation failed: no frame info.')
|
|
@@ -625,9 +656,7 @@ class FittingResults:
|
|
|
625
656
|
)
|
|
626
657
|
max_frame = np.max(self.data[DataColumns.FRAME])
|
|
627
658
|
|
|
628
|
-
# grouped_data = []
|
|
629
659
|
sub_images = []
|
|
630
|
-
shifts = []
|
|
631
660
|
frames = []
|
|
632
661
|
|
|
633
662
|
for f in range(0, n_bins):
|
|
@@ -647,23 +676,46 @@ class FittingResults:
|
|
|
647
676
|
sub_images.append(image)
|
|
648
677
|
print(f'Bins: {f + 1:d}/{n_bins:d}', end='\r')
|
|
649
678
|
|
|
679
|
+
sub_images = np.array(sub_images)
|
|
680
|
+
|
|
650
681
|
print('Shift Estimation ...', end='\r')
|
|
651
682
|
try:
|
|
652
|
-
|
|
683
|
+
if method == 'rcc':
|
|
684
|
+
imshift, A = rcc_shift_estimation(sub_images, pixelSize)
|
|
685
|
+
|
|
686
|
+
print('Shift Optimization ...', end='\r')
|
|
687
|
+
drift = rcc_solve(imshift, A, n_bins, rmax=rmax)
|
|
688
|
+
elif method == 'mcc':
|
|
689
|
+
drift = mcc_shift_estimation(sub_images, pixelSize)
|
|
690
|
+
elif method == 'dcc':
|
|
691
|
+
drift = dcc_shift_estimation(sub_images, pixelSize)
|
|
692
|
+
elif method == 'phase':
|
|
693
|
+
drift = shift_estimation(np.array(sub_images), pixelSize, upsampling)
|
|
694
|
+
else:
|
|
695
|
+
raise ValueError(f'Unknown drift estimation method: {method}')
|
|
653
696
|
except _ArrayMemoryError as e:
|
|
654
697
|
print(f'Drift cross-correlation failed: {e}')
|
|
655
698
|
return
|
|
656
699
|
|
|
657
|
-
shifts = np.c_[shifts, np.array(frames)]
|
|
658
700
|
print('Shift Correction ...', end='\r')
|
|
659
701
|
|
|
702
|
+
frames_interp = np.concatenate(([0], np.array(frames), [max_frame - 1]))
|
|
703
|
+
|
|
704
|
+
# Prepare drift arrays with padding zeros at start and last value at end
|
|
705
|
+
base = [
|
|
706
|
+
0,
|
|
707
|
+
] * (1 if method in ['mcc', 'phase'] else 2)
|
|
708
|
+
|
|
709
|
+
drift_x = np.concatenate((base, drift[:, 0], [drift[-1, 0]]))
|
|
710
|
+
drift_y = np.concatenate((base, drift[:, 1], [drift[-1, 1]]))
|
|
711
|
+
|
|
660
712
|
# An one-dimensional interpolation is applied
|
|
661
713
|
# to drift traces in X and Y dimensions separately.
|
|
662
714
|
interpy = interp1d(
|
|
663
|
-
|
|
715
|
+
frames_interp, drift_x, kind='cubic', fill_value='extrapolate'
|
|
664
716
|
)
|
|
665
717
|
interpx = interp1d(
|
|
666
|
-
|
|
718
|
+
frames_interp, drift_y, kind='cubic', fill_value='extrapolate'
|
|
667
719
|
)
|
|
668
720
|
# And this interpolation is used to get the shift at every frame-point
|
|
669
721
|
frames_new = np.arange(0, max_frame, 1)
|
|
@@ -848,6 +900,9 @@ class FittingResults:
|
|
|
848
900
|
drift_x = np.mean(fiducial_markers[:, :, 0], axis=0)
|
|
849
901
|
drift_y = np.mean(fiducial_markers[:, :, 1], axis=0)
|
|
850
902
|
|
|
903
|
+
error_bar_x = np.std(fiducial_markers[:, :, 0], axis=0)
|
|
904
|
+
error_bar_y = np.std(fiducial_markers[:, :, 1], axis=0)
|
|
905
|
+
|
|
851
906
|
print('Drift correction ... ', end='\r')
|
|
852
907
|
ids = np.cumsum(np.bincount(self.data[DataColumns.FRAME].astype(np.int64)))
|
|
853
908
|
|
|
@@ -863,7 +918,7 @@ class FittingResults:
|
|
|
863
918
|
|
|
864
919
|
# drift_corrected = FittingResults.fromDataFrame(df, self.pixelSize)
|
|
865
920
|
|
|
866
|
-
return self, (unique_frames, drift_x, drift_y)
|
|
921
|
+
return self, (unique_frames, drift_x, drift_y, error_bar_x, error_bar_y)
|
|
867
922
|
|
|
868
923
|
def zero_coordinates(self):
|
|
869
924
|
# Use vectorized operations with optional masking
|
|
@@ -488,10 +488,11 @@ class LocalizationsView(QtWidgets.QWidget):
|
|
|
488
488
|
def work_func(**kwargs):
|
|
489
489
|
try:
|
|
490
490
|
return self.currentResults.toAnimation(
|
|
491
|
-
self.frame_bins.value(),
|
|
491
|
+
self.frame_bins.value(),
|
|
492
|
+
self.xy_binsize.value(),
|
|
492
493
|
z_pixel_size=self.z_binsize.value(),
|
|
493
494
|
projection=Projection(self.projection_cbox.currentData()),
|
|
494
|
-
renderMode=RenderModes(self.render_cbox.currentData())
|
|
495
|
+
renderMode=RenderModes(self.render_cbox.currentData()),
|
|
495
496
|
)
|
|
496
497
|
except Exception:
|
|
497
498
|
traceback.print_exc()
|
|
@@ -668,16 +669,24 @@ class LocalizationsView(QtWidgets.QWidget):
|
|
|
668
669
|
self.drift_cross_up = create_spin_box(
|
|
669
670
|
min_value=0, max_value=1000, initial_value=100
|
|
670
671
|
)
|
|
672
|
+
self.drift_rmax = create_spin_box(min_value=0, max_value=1000, initial_value=23)
|
|
671
673
|
|
|
672
674
|
self.drift_cross_args.addWidget(self.drift_cross_bins)
|
|
673
675
|
self.drift_cross_args.addWidget(self.drift_cross_px)
|
|
674
676
|
self.drift_cross_args.addWidget(self.drift_cross_up)
|
|
677
|
+
self.drift_cross_args.addWidget(self.drift_rmax)
|
|
678
|
+
|
|
679
|
+
self.cross_method_cbox = QtWidgets.QComboBox()
|
|
680
|
+
self.cross_method_cbox.addItem('Phase', 'phase')
|
|
681
|
+
self.cross_method_cbox.addItem('Direct', 'dcc')
|
|
682
|
+
self.cross_method_cbox.addItem('Mean', 'mcc')
|
|
683
|
+
self.cross_method_cbox.addItem('Redundant', 'rcc')
|
|
675
684
|
|
|
676
685
|
self.drift_cross_btn = QtWidgets.QPushButton(
|
|
677
|
-
'Drift
|
|
686
|
+
'Drift X-Corr', clicked=lambda: self.drift_cross()
|
|
678
687
|
)
|
|
679
688
|
self.drift_fdm_btn = QtWidgets.QPushButton(
|
|
680
|
-
'Fiducial
|
|
689
|
+
'Fiducial markers', clicked=lambda: self.drift_fdm()
|
|
681
690
|
)
|
|
682
691
|
|
|
683
692
|
# Drift GroupBox
|
|
@@ -685,9 +694,15 @@ class LocalizationsView(QtWidgets.QWidget):
|
|
|
685
694
|
fdrift = QtWidgets.QFormLayout()
|
|
686
695
|
drift.setLayout(fdrift)
|
|
687
696
|
|
|
688
|
-
fdrift.addRow(
|
|
697
|
+
fdrift.addRow(
|
|
698
|
+
QtWidgets.QLabel('Drift X-Corr. (bins, pixelSize, upsampling, rmax):')
|
|
699
|
+
)
|
|
689
700
|
fdrift.addRow(self.drift_cross_args)
|
|
690
|
-
fdrift.addRow(
|
|
701
|
+
fdrift.addRow(
|
|
702
|
+
create_hbox_layout(
|
|
703
|
+
self.cross_method_cbox, self.drift_cross_btn, self.drift_fdm_btn
|
|
704
|
+
)
|
|
705
|
+
)
|
|
691
706
|
# End Drift GroupBox
|
|
692
707
|
|
|
693
708
|
self.frc_cbox = QtWidgets.QComboBox()
|
|
@@ -961,9 +976,7 @@ class LocalizationsView(QtWidgets.QWidget):
|
|
|
961
976
|
self.currentResults.locY,
|
|
962
977
|
self.currentResults.locZ,
|
|
963
978
|
)
|
|
964
|
-
self.tardis.startWorker.connect(
|
|
965
|
-
lambda worker: self._threadpool.start(worker)
|
|
966
|
-
)
|
|
979
|
+
self.tardis.startWorker.connect(lambda worker: self._threadpool.start(worker))
|
|
967
980
|
self.tardis.show()
|
|
968
981
|
|
|
969
982
|
def drift_cross(self):
|
|
@@ -974,12 +987,17 @@ class LocalizationsView(QtWidgets.QWidget):
|
|
|
974
987
|
if len(self.currentResults) <= 0:
|
|
975
988
|
return
|
|
976
989
|
|
|
990
|
+
method = self.cross_method_cbox.currentData()
|
|
991
|
+
label = self.cross_method_cbox.currentText()
|
|
992
|
+
|
|
977
993
|
def work_func(**kwargs):
|
|
978
994
|
try:
|
|
979
995
|
return self.currentResults.drift_cross_correlation(
|
|
980
996
|
self.drift_cross_bins.value(),
|
|
981
997
|
self.drift_cross_px.value(),
|
|
982
998
|
self.drift_cross_up.value(),
|
|
999
|
+
self.drift_rmax.value(),
|
|
1000
|
+
method=method,
|
|
983
1001
|
)
|
|
984
1002
|
except Exception:
|
|
985
1003
|
traceback.print_exc()
|
|
@@ -991,7 +1009,10 @@ class LocalizationsView(QtWidgets.QWidget):
|
|
|
991
1009
|
self.render_loc()
|
|
992
1010
|
self.currentResults = results[0]
|
|
993
1011
|
self.results_plot.setData(self.currentResults.dataFrame())
|
|
994
|
-
plot_drift(
|
|
1012
|
+
plot_drift(
|
|
1013
|
+
*results[2],
|
|
1014
|
+
title=f'{label} Cross-Correlation',
|
|
1015
|
+
)
|
|
995
1016
|
|
|
996
1017
|
self.worker = QThreadWorker(work_func)
|
|
997
1018
|
self.worker.signals.result.connect(done)
|
|
@@ -1019,7 +1040,7 @@ class LocalizationsView(QtWidgets.QWidget):
|
|
|
1019
1040
|
if results is not None:
|
|
1020
1041
|
self.currentResults = results[0]
|
|
1021
1042
|
self.results_plot.setData(self.currentResults.dataFrame())
|
|
1022
|
-
plot_drift(*results[1])
|
|
1043
|
+
plot_drift(*results[1], title='Fiducial Marker Drift Correction')
|
|
1023
1044
|
self.render_loc()
|
|
1024
1045
|
|
|
1025
1046
|
self.worker = QThreadWorker(work_func)
|