microeye 2.4.62__tar.gz → 2.4.63__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.4.62/src/microeye.egg-info → microeye-2.4.63}/PKG-INFO +24 -6
- {microeye-2.4.62 → microeye-2.4.63}/README.md +21 -5
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/__init__.py +70 -8
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/_version.py +1 -1
- microeye-2.4.62/src/microEye/analysis/clustering/dbscan.py → microeye-2.4.63/src/microEye/analysis/clustering/core.py +48 -69
- microeye-2.4.63/src/microEye/analysis/clustering/dataclasses.py +212 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/clustering/density.py +0 -45
- microeye-2.4.63/src/microEye/analysis/clustering/dialogs.py +715 -0
- microeye-2.4.63/src/microEye/analysis/clustering/grid.py +189 -0
- microeye-2.4.63/src/microEye/analysis/clustering/io.py +105 -0
- microeye-2.4.63/src/microEye/analysis/clustering/model.py +316 -0
- microeye-2.4.63/src/microEye/analysis/clustering/pipeline.py +161 -0
- microeye-2.4.63/src/microEye/analysis/clustering/plot.py +1013 -0
- microeye-2.4.63/src/microEye/analysis/clustering/rulers.py +181 -0
- microeye-2.4.63/src/microEye/analysis/clustering/viewer.py +530 -0
- microeye-2.4.63/src/microEye/analysis/drift/__init__.py +16 -0
- {microeye-2.4.62/src/microEye/analysis/fitting → microeye-2.4.63/src/microEye/analysis/drift}/aim.py +25 -71
- microeye-2.4.63/src/microEye/analysis/drift/comet.py +528 -0
- microeye-2.4.63/src/microEye/analysis/drift/core.py +62 -0
- microeye-2.4.63/src/microEye/analysis/drift/phase.py +22 -0
- microeye-2.4.63/src/microEye/analysis/drift/plot.py +92 -0
- {microeye-2.4.62/src/microEye/analysis/fitting → microeye-2.4.63/src/microEye/analysis/drift}/rcc.py +9 -0
- microeye-2.4.63/src/microEye/analysis/drift/segment.py +291 -0
- microeye-2.4.63/src/microEye/analysis/drift/widgets.py +260 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/processing.py +0 -117
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/results.py +122 -22
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/multi_viewer.py +10 -3
- microeye-2.4.63/src/microEye/analysis/processing/frc.py +363 -0
- microeye-2.4.63/src/microEye/analysis/rendering/__init__.py +9 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/rendering/base.py +101 -14
- microeye-2.4.63/src/microEye/analysis/rendering/navigator.py +48 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/batch.py +125 -101
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/utils/__init__.py +4 -1
- microeye-2.4.63/src/microEye/analysis/utils/coordinates.py +40 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/viewer/localizations.py +502 -360
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/mieye/miEye.py +1 -1
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/misc/reglo.py +3 -1
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/launcher.py +32 -7
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/utils/parameter_tree.py +5 -7
- {microeye-2.4.62 → microeye-2.4.63/src/microeye.egg-info}/PKG-INFO +24 -6
- {microeye-2.4.62 → microeye-2.4.63}/src/microeye.egg-info/SOURCES.txt +18 -3
- {microeye-2.4.62 → microeye-2.4.63}/src/microeye.egg-info/requires.txt +2 -0
- microeye-2.4.62/src/microEye/analysis/clustering/plot.py +0 -1401
- microeye-2.4.62/src/microEye/analysis/clustering/rulers.py +0 -425
- microeye-2.4.62/src/microEye/analysis/processing/frc.py +0 -203
- microeye-2.4.62/src/microEye/analysis/rendering/__init__.py +0 -3
- microeye-2.4.62/src/microEye/analysis/utils/coordinates.py +0 -18
- {microeye-2.4.62 → microeye-2.4.63}/LICENSE +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/MANIFEST.in +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/pyproject.toml +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/setup.cfg +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/setup.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/checklist_dialog.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/clustering/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/cmosMaps.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/file_system.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/filters/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/filters/base.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/filters/spatial.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/filters/temporal.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/fit.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/nena.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/phasor_fit.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/psf/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/psf/extract.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/psf/rubost_mean.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/psf/spline.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/psf/stats/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/psf/stats/core.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/psf/stats/curve_fit.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/psf/stats/io.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/psf/stats/slope_fit.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/psf/temp.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/psf/test.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUfunctions.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUmleFit_LM.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUsplineLib.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/pyfit3Dcspline/CPU/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUfunctions.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_EMCCD.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_sCMOS.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUsplineLib.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/pyfit3Dcspline/GPU/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/pyfit3Dcspline/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/pyfit3Dcspline/constants.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/pyfit3Dcspline/mainfunctions.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/results_stats.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/fitting/tardis.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/processing/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/rendering/cloud.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/rendering/core.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/rendering/volumetric.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/common.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/dark_cal/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/dark_cal/analysis.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/dark_cal/compare.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/dark_cal/constants.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/dark_cal/core.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/dark_cal/io.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/dark_cal/plotting.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/kymograms.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/photon_cal/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/photon_cal/analysis.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/photon_cal/compare.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/photon_cal/constants.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/photon_cal/core.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/photon_cal/io.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/photon_cal/models.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/photon_cal/plotting.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/photon_cal/table.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/registration.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/roi_selectors.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/tools/sphere_cal.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/utils/images.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/utils/windows.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/viewer/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/viewer/image_options_widget.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/viewer/images.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/viewer/layers_widget.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/viewer/psf.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/analysis/viewer/volume.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/basler/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/basler/basler_cam.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/basler/basler_panel.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/camera_calibration.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/camera_list.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/camera_options.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/camera_panel.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/dcam/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/dcam/dcam.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/dcam/dcam_panel.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/dcam/dcamapi4.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/dcam/funcs.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/dcam/meta.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/dummy/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/dummy/dummy_panel.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/jobs.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/line_profiler.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/linescan/IR_Cam.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/linescan/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/micam.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/pco/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/pco/enums.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/pco/pco_cam.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/pco/pco_panel.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/peak/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/peak/peak_camera.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/peak/peak_panel.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/pycromanager/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/pycromanager/pycro_cam.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/pycromanager/pycro_panel.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/shortcuts.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/thorlabs/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/thorlabs/thorlabs.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/thorlabs/thorlabs_panel.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/ueye/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/ueye/ueye_camera.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/ueye/ueye_panel.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/vimba/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/vimba/vimba_cam.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/cams/vimba/vimba_panel.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/device.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/lasers/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/lasers/io_matchbox.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/lasers/io_params.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/lasers/io_single_laser.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/lasers/laser_relay.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/mieye/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/mieye/acquisition_manager.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/mieye/devices_manager.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/misc/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/misc/acquisition_view.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/misc/temp.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/port_config.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/protocols/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/protocols/actions.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/protocols/actions_items.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/protocols/designer.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/protocols/scene_manager.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/protocols/serialization.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/pycromanager/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/pycromanager/core.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/pycromanager/devices.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/pycromanager/enums.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/pycromanager/headless.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/pycromanager/utils.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/pycromanager/widgets/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/pycromanager/widgets/bridges.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/pycromanager/widgets/headless_manager.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/pycromanager/widgets/headless_options.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/elliptec/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/elliptec/baseDevice.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/elliptec/device.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/elliptec/deviceID.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/elliptec/devicePort.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/elliptec/deviceStatus.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/elliptec/devicesView.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/elliptec/ellDevices.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/elliptec/messageUpdater.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/elliptec/motorInfo.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/elliptec/stage.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/elliptec/test.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/kinesis/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/kinesis/kdc101/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/kinesis/kdc101/enums.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/kinesis/kdc101/factory.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/kinesis/kdc101/kdc101.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/kinesis/kinesis.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/manager.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/piezon_concept/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/piezon_concept/foc.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/pycromanager/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/pycromanager/core.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/smaract/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/smaract/mcs2.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/stabilization/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/stabilization/controller.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/stabilization/methods.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/stabilizer.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/stage.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/stages/view.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/widgets/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/widgets/controller.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/widgets/devices.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/widgets/focusWidget.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/widgets/indicator.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/widgets/qlist_slider.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/widgets/scan_acquisition.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/hardware/widgets/slides.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/icons/1024.png +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/icons/128.png +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/icons/16.png +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/icons/24.png +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/icons/256.png +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/icons/32.png +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/icons/48.png +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/icons/512.png +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/icons/64.png +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/icons/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/icons/close.svg +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/icons/mieye.png +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/icons/min.svg +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/icons/viewer.png +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/images/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/images/handlers.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/images/uImage.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/images/zarr.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/qt.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/tools/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/tools/color.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/tools/microscopy.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/utils/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/utils/display.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/utils/enum_encoder.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/utils/expandable_groupbox.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/utils/gui_helper.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/utils/hid_utils/__init__.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/utils/hid_utils/controller.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/utils/hid_utils/device.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/utils/hid_utils/enums.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/utils/hid_utils/utils.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/utils/labelled_slider.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/utils/metadata.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/utils/metadata_tree.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/utils/micro_launcher.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/utils/pyqt2mplt.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/utils/pyscripting.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/utils/retry_exec.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/utils/start_gui.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microEye/utils/thread_worker.py +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microeye.egg-info/dependency_links.txt +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/src/microeye.egg-info/entry_points.txt +0 -0
- {microeye-2.4.62 → microeye-2.4.63}/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.4.
|
|
3
|
+
Version: 2.4.63
|
|
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
|
|
@@ -14,6 +14,7 @@ Requires-Python: >=3.9.4, <3.12
|
|
|
14
14
|
Description-Content-Type: text/markdown
|
|
15
15
|
License-File: LICENSE
|
|
16
16
|
Requires-Dist: autopep8==2.3.2
|
|
17
|
+
Requires-Dist: cupy-cuda13x==14.2.0
|
|
17
18
|
Requires-Dist: dask==2025.9.1
|
|
18
19
|
Requires-Dist: h5py==3.15.0
|
|
19
20
|
Requires-Dist: hdbscan==0.8.44
|
|
@@ -22,6 +23,7 @@ Requires-Dist: ids-peak==1.11.1.0.5
|
|
|
22
23
|
Requires-Dist: matplotlib==3.10.7
|
|
23
24
|
Requires-Dist: mmpycorex==0.3.16
|
|
24
25
|
Requires-Dist: numba==0.62.1
|
|
26
|
+
Requires-Dist: numba-cuda==0.30.4
|
|
25
27
|
Requires-Dist: numpy==2.2.6
|
|
26
28
|
Requires-Dist: ome_types==0.5.2
|
|
27
29
|
Requires-Dist: opencv_python==4.12.0.88
|
|
@@ -69,11 +71,15 @@ Dynamic: summary
|
|
|
69
71
|
<!--  -->
|
|
70
72
|
|
|
71
73
|
```bash
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
/_
|
|
76
|
-
|
|
74
|
+
╭─────────────────────────────────────────────────────────────────────╮
|
|
75
|
+
│ │
|
|
76
|
+
│ __ ____ ____ ___ ____ ____ ____ │
|
|
77
|
+
│ / |/ (_)__________ / __/_ _____ _ __|_ |/ / / / __/|_ / │
|
|
78
|
+
│ / /|_/ / / __/ __/ _ \/ _// // / -_) | |/ / __//_ _// _ \_/_ < │
|
|
79
|
+
│ /_/ /_/_/\__/_/ \___/___/\_, /\__/ |___/____(_)_/(_)___/____/ │
|
|
80
|
+
│ /___/ │
|
|
81
|
+
│ │
|
|
82
|
+
╰─────────────────────────────────────────────────────────────────────╯
|
|
77
83
|
```
|
|
78
84
|
|
|
79
85
|
The **`microEye`** is a Python toolkit for fluorescence microscopy that supports super-resolution single-molecule localization microscopy and single-particle tracking. It features hardware control, data analysis, and visualization.
|
|
@@ -597,6 +603,18 @@ Special thanks to the following projects and libraries that make this work possi
|
|
|
597
603
|
|
|
598
604
|
> _Martens et al., “Temporal analysis of relative distances (TARDIS) is a robust, parameter-free alternative to single-particle tracking”, Nature Methods (2024). [Article](https://rdcu.be/dv1sr)_
|
|
599
605
|
|
|
606
|
+
- **RCC (Robust Cross-Correlation)**: We have implemented the RCC algorithm in Python for drift correction in SMLM data.
|
|
607
|
+
|
|
608
|
+
> _Y. Wang, J. Schnitzbauer, Z. Hu, X. Li, Y. Cheng, Z.-L. Huang, and B. Huang, “Localization events-based sample drift correction for localization microscopy with redundant cross-correlation algorithm,” Opt. Express 22(13), 15982 (2014)._ [Paper](https://doi.org/10.1364/OE.22.015982) [GitHub](https://github.com/yinawang28/RCC)
|
|
609
|
+
|
|
610
|
+
- **AIM (Adaptive Intersection Maximization)**: We have implemented the AIM algorithm in Python for drift correction in SMLM data.
|
|
611
|
+
|
|
612
|
+
> _H. Ma, M. Chen, P. Nguyen, and Y. Liu, “Toward drift-free high-throughput nanoscopy through adaptive intersection maximization,” Sci. Adv. 10(21), eadm7765 (2024)._ [Paper](www.science.org/doi/10.1126/sciadv.adm7765) [GitHub](https://github.com/YangLiuLab/AIM)
|
|
613
|
+
|
|
614
|
+
- **COMET (Cost-function Optimized Maximal overlap drift EsTimation)**: We have implemented the COMET algorithm in Python for drift correction in SMLM data.
|
|
615
|
+
|
|
616
|
+
> _L. Reinkensmeier, S. Aufmkolk, I. Farabella, A. Egner, and M. Bates, “Cost-function Optimized Maximal Overlap Drift Estimation for Single Molecule Localization Microscopy,” (2026)._ [Paper](https://doi.org/10.64898/2026.03.27.714864) [GitHub](https://github.com/gpufit/Comet/tree/master)
|
|
617
|
+
|
|
600
618
|
> [!IMPORTANT]
|
|
601
619
|
> **Disclaimer**
|
|
602
620
|
> _I'm committed to maintaining an accurate acknowledgment list for our project. However, if I inadvertently miss acknowledging your work, please don't hesitate to reach out to us. I appreciate your understanding, and I'm doing my best to manage all acknowledgments amidst my other responsibilities._
|
|
@@ -3,11 +3,15 @@
|
|
|
3
3
|
<!--  -->
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/_
|
|
10
|
-
|
|
6
|
+
╭─────────────────────────────────────────────────────────────────────╮
|
|
7
|
+
│ │
|
|
8
|
+
│ __ ____ ____ ___ ____ ____ ____ │
|
|
9
|
+
│ / |/ (_)__________ / __/_ _____ _ __|_ |/ / / / __/|_ / │
|
|
10
|
+
│ / /|_/ / / __/ __/ _ \/ _// // / -_) | |/ / __//_ _// _ \_/_ < │
|
|
11
|
+
│ /_/ /_/_/\__/_/ \___/___/\_, /\__/ |___/____(_)_/(_)___/____/ │
|
|
12
|
+
│ /___/ │
|
|
13
|
+
│ │
|
|
14
|
+
╰─────────────────────────────────────────────────────────────────────╯
|
|
11
15
|
```
|
|
12
16
|
|
|
13
17
|
The **`microEye`** is a Python toolkit for fluorescence microscopy that supports super-resolution single-molecule localization microscopy and single-particle tracking. It features hardware control, data analysis, and visualization.
|
|
@@ -531,6 +535,18 @@ Special thanks to the following projects and libraries that make this work possi
|
|
|
531
535
|
|
|
532
536
|
> _Martens et al., “Temporal analysis of relative distances (TARDIS) is a robust, parameter-free alternative to single-particle tracking”, Nature Methods (2024). [Article](https://rdcu.be/dv1sr)_
|
|
533
537
|
|
|
538
|
+
- **RCC (Robust Cross-Correlation)**: We have implemented the RCC algorithm in Python for drift correction in SMLM data.
|
|
539
|
+
|
|
540
|
+
> _Y. Wang, J. Schnitzbauer, Z. Hu, X. Li, Y. Cheng, Z.-L. Huang, and B. Huang, “Localization events-based sample drift correction for localization microscopy with redundant cross-correlation algorithm,” Opt. Express 22(13), 15982 (2014)._ [Paper](https://doi.org/10.1364/OE.22.015982) [GitHub](https://github.com/yinawang28/RCC)
|
|
541
|
+
|
|
542
|
+
- **AIM (Adaptive Intersection Maximization)**: We have implemented the AIM algorithm in Python for drift correction in SMLM data.
|
|
543
|
+
|
|
544
|
+
> _H. Ma, M. Chen, P. Nguyen, and Y. Liu, “Toward drift-free high-throughput nanoscopy through adaptive intersection maximization,” Sci. Adv. 10(21), eadm7765 (2024)._ [Paper](www.science.org/doi/10.1126/sciadv.adm7765) [GitHub](https://github.com/YangLiuLab/AIM)
|
|
545
|
+
|
|
546
|
+
- **COMET (Cost-function Optimized Maximal overlap drift EsTimation)**: We have implemented the COMET algorithm in Python for drift correction in SMLM data.
|
|
547
|
+
|
|
548
|
+
> _L. Reinkensmeier, S. Aufmkolk, I. Farabella, A. Egner, and M. Bates, “Cost-function Optimized Maximal Overlap Drift Estimation for Single Molecule Localization Microscopy,” (2026)._ [Paper](https://doi.org/10.64898/2026.03.27.714864) [GitHub](https://github.com/gpufit/Comet/tree/master)
|
|
549
|
+
|
|
534
550
|
> [!IMPORTANT]
|
|
535
551
|
> **Disclaimer**
|
|
536
552
|
> _I'm committed to maintaining an accurate acknowledgment list for our project. However, if I inadvertently miss acknowledging your work, please don't hesitate to reach out to us. I appreciate your understanding, and I'm doing my best to manage all acknowledgments amidst my other responsibilities._
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
import argparse
|
|
1
2
|
import importlib.util
|
|
2
3
|
import logging
|
|
3
4
|
import os
|
|
4
5
|
|
|
6
|
+
from rich.console import Console
|
|
7
|
+
from rich.logging import RichHandler
|
|
8
|
+
from rich.traceback import install
|
|
9
|
+
|
|
5
10
|
from microEye._version import __version__, version_info
|
|
6
11
|
|
|
7
12
|
# QT bindings affect camera libraries' DLL loading.
|
|
@@ -11,6 +16,8 @@ from microEye.hardware import cams
|
|
|
11
16
|
|
|
12
17
|
PREFERRED_QT_APIS = ('PySide6', 'PyQt6', 'PyQt5')
|
|
13
18
|
|
|
19
|
+
HELP_MESSAGE = ''
|
|
20
|
+
|
|
14
21
|
|
|
15
22
|
def _select_qt_api(cli_choice: str | None) -> str:
|
|
16
23
|
candidates = (cli_choice,) + PREFERRED_QT_APIS if cli_choice else PREFERRED_QT_APIS
|
|
@@ -23,11 +30,16 @@ def _select_qt_api(cli_choice: str | None) -> str:
|
|
|
23
30
|
|
|
24
31
|
|
|
25
32
|
def getArgs():
|
|
26
|
-
import argparse
|
|
27
33
|
import os
|
|
34
|
+
import re
|
|
28
35
|
import sys
|
|
29
36
|
|
|
30
|
-
parser = argparse.ArgumentParser(
|
|
37
|
+
parser = argparse.ArgumentParser(
|
|
38
|
+
add_help=False,
|
|
39
|
+
)
|
|
40
|
+
parser.add_argument(
|
|
41
|
+
'-h', '--help', action='store_true', help='Show this help message and exit.'
|
|
42
|
+
)
|
|
31
43
|
parser.add_argument(
|
|
32
44
|
'--module',
|
|
33
45
|
help='The module to launch [mieye|viewer], '
|
|
@@ -63,6 +75,34 @@ def getArgs():
|
|
|
63
75
|
action='store_true',
|
|
64
76
|
)
|
|
65
77
|
|
|
78
|
+
lines = []
|
|
79
|
+
for line in parser.format_help().splitlines():
|
|
80
|
+
# format flags (cyan)
|
|
81
|
+
line = re.sub(r'(?<=\s|\[)(-\S+)', r'[bold #00d7ff]\1[/bold #00d7ff]', line)
|
|
82
|
+
line = re.sub(r'(?<=\s|\[)(--\S+)', r'[bold #00d7ff]\1[/bold #00d7ff]', line)
|
|
83
|
+
|
|
84
|
+
# format scripts & files (warm yellow)
|
|
85
|
+
line = re.sub(r'(?<=\s)(\S+\.py)', r'[#ffb86c]\1[/#ffb86c]', line)
|
|
86
|
+
line = re.sub(r'(?<=\s)(\S+\.exe)', r'[#ffb86c]\1[/#ffb86c]', line)
|
|
87
|
+
line = re.sub(r'(?<=\s)(\S+\.dll)', r'[#ffb86c]\1[/#ffb86c]', line)
|
|
88
|
+
line = re.sub(r'(?<=\s)(\S+\.so)', r'[#ffb86c]\1[/#ffb86c]', line)
|
|
89
|
+
line = re.sub(r'(?<=\s)(\S+\.dylib)', r'[#ffb86c]\1[/#ffb86c]', line)
|
|
90
|
+
|
|
91
|
+
# format curly braces (bright green)
|
|
92
|
+
line = re.sub(r'(?<=\s)(\{.*?\})', r'[bold #5af78e]\1[/bold #5af78e]', line)
|
|
93
|
+
|
|
94
|
+
# format flags within brackets (cyan)
|
|
95
|
+
line = re.sub(r'(?<=\[)(--\S+)', r'[bold #00d7ff]\1[/bold #00d7ff]', line)
|
|
96
|
+
line = re.sub(r'(?<=\[)(-\S+)', r'[bold #00d7ff]\1[/bold #00d7ff]', line)
|
|
97
|
+
|
|
98
|
+
line = line.replace('usage:', '[bold #dcdcaa]usage:[/bold #dcdcaa]')
|
|
99
|
+
line = line.replace('options:', '[bold #dcdcaa]options:[/bold #dcdcaa]')
|
|
100
|
+
|
|
101
|
+
lines.append(line)
|
|
102
|
+
|
|
103
|
+
global HELP_MESSAGE
|
|
104
|
+
HELP_MESSAGE = '\n'.join(lines) + '\n'
|
|
105
|
+
|
|
66
106
|
args, _ = parser.parse_known_args(sys.argv)
|
|
67
107
|
|
|
68
108
|
# access the parsed arguments
|
|
@@ -75,6 +115,7 @@ def getArgs():
|
|
|
75
115
|
|
|
76
116
|
return args
|
|
77
117
|
|
|
118
|
+
|
|
78
119
|
def configure_logger(args):
|
|
79
120
|
import os
|
|
80
121
|
import sys
|
|
@@ -93,15 +134,31 @@ def configure_logger(args):
|
|
|
93
134
|
and args.module
|
|
94
135
|
):
|
|
95
136
|
os.makedirs(os.path.dirname(log_filename))
|
|
137
|
+
|
|
138
|
+
if not args.no_log_file and args.module:
|
|
139
|
+
console = Console(
|
|
140
|
+
file=open(log_filename, 'a', encoding='utf-8') # noqa: SIM115, W291
|
|
141
|
+
)
|
|
142
|
+
file_handler = RichHandler(
|
|
143
|
+
console=console,
|
|
144
|
+
rich_tracebacks=True,
|
|
145
|
+
tracebacks_show_locals=True,
|
|
146
|
+
markup=True,
|
|
147
|
+
)
|
|
148
|
+
else:
|
|
149
|
+
file_handler = logging.NullHandler()
|
|
150
|
+
|
|
96
151
|
# set the logging configuration with both file and console handlers
|
|
97
152
|
logging.basicConfig(
|
|
98
153
|
level=level,
|
|
99
|
-
format='%(
|
|
154
|
+
format='%(message)s',
|
|
100
155
|
handlers=[
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
156
|
+
file_handler,
|
|
157
|
+
RichHandler(
|
|
158
|
+
rich_tracebacks=True,
|
|
159
|
+
tracebacks_show_locals=True,
|
|
160
|
+
markup=True,
|
|
161
|
+
)
|
|
105
162
|
if not args.no_log_console
|
|
106
163
|
else logging.NullHandler(),
|
|
107
164
|
],
|
|
@@ -110,5 +167,10 @@ def configure_logger(args):
|
|
|
110
167
|
logging.getLogger().debug('Log level set to %s', level_name)
|
|
111
168
|
|
|
112
169
|
|
|
113
|
-
|
|
170
|
+
install(
|
|
171
|
+
show_locals=False,
|
|
172
|
+
code_width=150,
|
|
173
|
+
width=200,
|
|
174
|
+
extra_lines=2,
|
|
175
|
+
)
|
|
114
176
|
ARGS = getArgs()
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
version_info = (2, 4,
|
|
1
|
+
version_info = (2, 4, 63)
|
|
2
2
|
__version__ = '.'.join(map(str, version_info))
|
|
@@ -1,33 +1,17 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from dataclasses import dataclass
|
|
3
|
-
from enum import Enum
|
|
4
2
|
|
|
5
3
|
import numba as nb
|
|
6
4
|
import numpy as np
|
|
7
5
|
from hdbscan import HDBSCAN
|
|
8
|
-
from scipy.spatial import ConvexHull, Delaunay, Voronoi
|
|
9
6
|
from sklearn.cluster import DBSCAN, OPTICS, cluster_optics_dbscan
|
|
10
|
-
from sklearn.preprocessing import StandardScaler
|
|
11
|
-
|
|
12
|
-
logger = logging.getLogger(__name__)
|
|
13
7
|
|
|
8
|
+
from microEye.analysis.clustering.dataclasses import (
|
|
9
|
+
CenteringMode,
|
|
10
|
+
CenteringOptions,
|
|
11
|
+
ClusterCenterResult,
|
|
12
|
+
)
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
def geometric_median(points, max_iter=128, tol=1e-6, eps=1e-12):
|
|
17
|
-
guess = np.median(points, axis=0)
|
|
18
|
-
for _ in range(max_iter):
|
|
19
|
-
try:
|
|
20
|
-
deltas = points - guess
|
|
21
|
-
distances = np.linalg.norm(deltas, axis=1)
|
|
22
|
-
weights = 1.0 / np.maximum(distances, eps)
|
|
23
|
-
new_guess = np.sum(points * weights[:, None], axis=0) / np.sum(weights)
|
|
24
|
-
if np.linalg.norm(new_guess - guess) < tol:
|
|
25
|
-
return new_guess
|
|
26
|
-
guess = new_guess
|
|
27
|
-
except Exception as e:
|
|
28
|
-
logger.error(f'Error in geometric_median: {e}')
|
|
29
|
-
break
|
|
30
|
-
return guess
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
31
15
|
|
|
32
16
|
|
|
33
17
|
@nb.njit(fastmath=True, cache=True)
|
|
@@ -159,11 +143,16 @@ def huber_center(points, delta=2.0, max_iter=64, tol=1e-5):
|
|
|
159
143
|
return guess
|
|
160
144
|
|
|
161
145
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
146
|
+
def scale_data(x, y, z, sigma_xy=10.0, sigma_z=10.0):
|
|
147
|
+
'''
|
|
148
|
+
Scales the input coordinates for clustering algorithms
|
|
149
|
+
that require isotropic distances.
|
|
150
|
+
'''
|
|
151
|
+
if z is None:
|
|
152
|
+
return np.column_stack((x, y)), 1.0
|
|
153
|
+
else:
|
|
154
|
+
scale = sigma_xy / sigma_z
|
|
155
|
+
return np.column_stack((x, y, z * scale)), scale
|
|
167
156
|
|
|
168
157
|
|
|
169
158
|
def get_center(
|
|
@@ -178,13 +167,14 @@ def get_center(
|
|
|
178
167
|
'''
|
|
179
168
|
Computes the center of clusters based on the specified centering mode.
|
|
180
169
|
|
|
181
|
-
|
|
170
|
+
**Methods**
|
|
182
171
|
|
|
183
|
-
-
|
|
172
|
+
- **_CRLB_WEIGHTED_MEAN_**: Computes the center using a weighted mean based on the
|
|
184
173
|
Cramer-Rao Lower Bound (CRLB) variances for x and y coordinates.
|
|
185
|
-
-
|
|
186
|
-
-
|
|
187
|
-
|
|
174
|
+
- **_GEOMETRIC_MEDIAN_**: Computes the center as the geometric median of the points.
|
|
175
|
+
- **_HUBER_CENTER_**: Computes the center using
|
|
176
|
+
M-estimation with a Huber loss function.
|
|
177
|
+
- **_MEAN_**: Computes the center as the arithmetic mean of the points.
|
|
188
178
|
|
|
189
179
|
Parameters
|
|
190
180
|
-----------
|
|
@@ -261,24 +251,6 @@ def get_center(
|
|
|
261
251
|
return mu_x, mu_y, mu_z, sigma_com
|
|
262
252
|
|
|
263
253
|
|
|
264
|
-
@dataclass
|
|
265
|
-
class ClusterCenterResult:
|
|
266
|
-
x: np.ndarray
|
|
267
|
-
y: np.ndarray
|
|
268
|
-
z: np.ndarray | None
|
|
269
|
-
labels: np.ndarray
|
|
270
|
-
intensity: np.ndarray | None
|
|
271
|
-
crlb_x: np.ndarray | None
|
|
272
|
-
crlb_y: np.ndarray | None
|
|
273
|
-
cx: np.ndarray
|
|
274
|
-
cy: np.ndarray
|
|
275
|
-
cz: np.ndarray | None
|
|
276
|
-
c_sigma: np.ndarray | None
|
|
277
|
-
c_label: np.ndarray
|
|
278
|
-
n_points: np.ndarray
|
|
279
|
-
rejected: int
|
|
280
|
-
|
|
281
|
-
|
|
282
254
|
def get_centers(
|
|
283
255
|
x: np.ndarray,
|
|
284
256
|
y: np.ndarray,
|
|
@@ -287,14 +259,19 @@ def get_centers(
|
|
|
287
259
|
intensity: np.ndarray | None = None,
|
|
288
260
|
crlb_x: np.ndarray | None = None,
|
|
289
261
|
crlb_y: np.ndarray | None = None,
|
|
290
|
-
|
|
291
|
-
eps: float = 1e-12,
|
|
292
|
-
rejection_threshold: float | None = None,
|
|
293
|
-
min_points: int | None = None,
|
|
294
|
-
max_points: int | None = None,
|
|
295
|
-
subtract_com: bool = False,
|
|
296
|
-
**kwargs,
|
|
262
|
+
options: CenteringOptions | None = None,
|
|
297
263
|
) -> ClusterCenterResult | None:
|
|
264
|
+
if options is None:
|
|
265
|
+
options = CenteringOptions()
|
|
266
|
+
|
|
267
|
+
rejection_threshold = options.rejection_threshold or None
|
|
268
|
+
min_points = (
|
|
269
|
+
options.min_points
|
|
270
|
+
or (options.min_points is not None and options.min_points > 1)
|
|
271
|
+
or None
|
|
272
|
+
)
|
|
273
|
+
max_points = options.max_points or None
|
|
274
|
+
|
|
298
275
|
try:
|
|
299
276
|
# Filter out noise (label < 0) safely
|
|
300
277
|
valid_mask = labels >= 0
|
|
@@ -353,10 +330,10 @@ def get_centers(
|
|
|
353
330
|
x_cluster,
|
|
354
331
|
y_cluster,
|
|
355
332
|
z_cluster,
|
|
356
|
-
center_mode=center_mode,
|
|
333
|
+
center_mode=options.center_mode,
|
|
357
334
|
crlb_x=crlb_x[s] if crlb_x is not None else None,
|
|
358
335
|
crlb_y=crlb_y[s] if crlb_y is not None else None,
|
|
359
|
-
eps=eps,
|
|
336
|
+
eps=options.eps,
|
|
360
337
|
)
|
|
361
338
|
|
|
362
339
|
# Reject clusters with large uncertainty
|
|
@@ -376,7 +353,7 @@ def get_centers(
|
|
|
376
353
|
c_labels.append(i)
|
|
377
354
|
n_points.append(len(x_cluster))
|
|
378
355
|
|
|
379
|
-
if subtract_com:
|
|
356
|
+
if options.subtract_com:
|
|
380
357
|
x[s] -= mu_x
|
|
381
358
|
y[s] -= mu_y
|
|
382
359
|
if z is not None:
|
|
@@ -419,14 +396,6 @@ def get_centers(
|
|
|
419
396
|
return None
|
|
420
397
|
|
|
421
398
|
|
|
422
|
-
def scale_data(x, y, z, sigma_xy=10.0, sigma_z=10.0):
|
|
423
|
-
if z is None:
|
|
424
|
-
return np.column_stack((x, y)), 1.0
|
|
425
|
-
else:
|
|
426
|
-
scale = sigma_xy / sigma_z
|
|
427
|
-
return np.column_stack((x, y, z * scale)), scale
|
|
428
|
-
|
|
429
|
-
|
|
430
399
|
def perform_dbscan_clustering(X, Y, Z, eps=50, min_samples=2, **kwargs):
|
|
431
400
|
'''
|
|
432
401
|
Performs DBSCAN clustering on 3D localization data.
|
|
@@ -456,7 +425,10 @@ def perform_dbscan_clustering(X, Y, Z, eps=50, min_samples=2, **kwargs):
|
|
|
456
425
|
else:
|
|
457
426
|
logger.warning('Standard deviation of data is zero. Skipping scaling.')
|
|
458
427
|
|
|
459
|
-
|
|
428
|
+
# remove any not need kwargs that are not relevant to DBSCAN
|
|
429
|
+
relevant_kwargs = {k: v for k, v in kwargs.items() if k in DBSCAN().get_params()}
|
|
430
|
+
|
|
431
|
+
dbscan_model = DBSCAN(eps=eps, min_samples=min_samples, **relevant_kwargs)
|
|
460
432
|
dbscan_model.fit(VECTORS)
|
|
461
433
|
|
|
462
434
|
labels = dbscan_model.labels_
|
|
@@ -483,6 +455,10 @@ def perform_hdbscan_clustering(X, Y, Z, **kwargs):
|
|
|
483
455
|
'''
|
|
484
456
|
sigma_xy = kwargs.pop('sigma_xy', 10.0)
|
|
485
457
|
sigma_z = kwargs.pop('sigma_z', 10.0)
|
|
458
|
+
min_samples = kwargs.pop('min_samples', None)
|
|
459
|
+
min_samples = min_samples or (min_samples is not None and min_samples > 0) or None
|
|
460
|
+
if min_samples:
|
|
461
|
+
kwargs['min_samples'] = min_samples
|
|
486
462
|
|
|
487
463
|
VECTORS, scale = scale_data(X, Y, Z, sigma_xy, sigma_z)
|
|
488
464
|
|
|
@@ -544,6 +520,9 @@ def perform_optics_clustering(X, Y, Z, min_samples=10, xi=0.05, **kwargs):
|
|
|
544
520
|
'''
|
|
545
521
|
sigma_xy = kwargs.pop('sigma_xy', 10.0)
|
|
546
522
|
sigma_z = kwargs.pop('sigma_z', 10.0)
|
|
523
|
+
max_eps = kwargs.pop('max_eps', np.inf)
|
|
524
|
+
max_eps = max_eps or (max_eps is not None and max_eps > 0) or np.inf
|
|
525
|
+
kwargs['max_eps'] = max_eps
|
|
547
526
|
|
|
548
527
|
VECTORS, scale = scale_data(X, Y, Z, sigma_xy, sigma_z)
|
|
549
528
|
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
from dataclasses import asdict, dataclass, field
|
|
2
|
+
from enum import StrEnum
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
import pyqtgraph as pg
|
|
6
|
+
|
|
7
|
+
from microEye.analysis.rendering.base import RenderModes
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class CenteringMode(StrEnum):
|
|
11
|
+
CRLB_WEIGHTED_MEAN = 'crlb_weighted_mean'
|
|
12
|
+
MEAN = 'mean'
|
|
13
|
+
GEOMETRIC_MEDIAN = 'geometric_median'
|
|
14
|
+
HUBER_CENTER = 'huber_center'
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class CenteringOptions:
|
|
19
|
+
center_mode: CenteringMode = CenteringMode.CRLB_WEIGHTED_MEAN
|
|
20
|
+
eps: float = 1e-12
|
|
21
|
+
rejection_threshold: float | None = None
|
|
22
|
+
min_points: int | None = None
|
|
23
|
+
max_points: int | None = None
|
|
24
|
+
subtract_com: bool = False
|
|
25
|
+
|
|
26
|
+
def __post_init__(self):
|
|
27
|
+
if isinstance(self.center_mode, str):
|
|
28
|
+
self.center_mode = CenteringMode(self.center_mode)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class ClusterCenterResult:
|
|
33
|
+
x: np.ndarray
|
|
34
|
+
y: np.ndarray
|
|
35
|
+
z: np.ndarray | None
|
|
36
|
+
labels: np.ndarray
|
|
37
|
+
intensity: np.ndarray | None
|
|
38
|
+
crlb_x: np.ndarray | None
|
|
39
|
+
crlb_y: np.ndarray | None
|
|
40
|
+
cx: np.ndarray
|
|
41
|
+
cy: np.ndarray
|
|
42
|
+
cz: np.ndarray | None
|
|
43
|
+
c_sigma: np.ndarray | None
|
|
44
|
+
c_label: np.ndarray
|
|
45
|
+
n_points: np.ndarray
|
|
46
|
+
rejected: int
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass
|
|
50
|
+
class ClusteringOptions:
|
|
51
|
+
grouping_method: str = 'dbscan'
|
|
52
|
+
distance_threshold: float | None = None
|
|
53
|
+
sigma_xy: float = 15.0
|
|
54
|
+
sigma_z: float = 45.0
|
|
55
|
+
scale_data: bool = False
|
|
56
|
+
xi : float = 0.05
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclass
|
|
60
|
+
class RenderOptions:
|
|
61
|
+
mode: str = 'superimposed'
|
|
62
|
+
rasterized: bool = True
|
|
63
|
+
render_mode: RenderModes = RenderModes.HISTOGRAM
|
|
64
|
+
pixel_size: float = 1.0
|
|
65
|
+
extent: float = 200.0
|
|
66
|
+
scalebar_length: float = 80.0
|
|
67
|
+
|
|
68
|
+
def __post_init__(self):
|
|
69
|
+
if isinstance(self.render_mode, int):
|
|
70
|
+
self.render_mode = RenderModes(self.render_mode)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@dataclass
|
|
74
|
+
class RunOptions:
|
|
75
|
+
clustering: ClusteringOptions
|
|
76
|
+
rendering: RenderOptions
|
|
77
|
+
model: dict
|
|
78
|
+
export: dict
|
|
79
|
+
|
|
80
|
+
def __post_init__(self):
|
|
81
|
+
if isinstance(self.clustering, dict):
|
|
82
|
+
self.clustering = ClusteringOptions(**self.clustering)
|
|
83
|
+
if isinstance(self.rendering, dict):
|
|
84
|
+
self.rendering = RenderOptions(**self.rendering)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@dataclass
|
|
88
|
+
class FitResult:
|
|
89
|
+
'''Generic outcome of fitting ANY geometric model to a candidate site set.'''
|
|
90
|
+
|
|
91
|
+
R: np.ndarray
|
|
92
|
+
'''
|
|
93
|
+
The rotation matrix that transforms the raw coordinates into the canonical frame.
|
|
94
|
+
'''
|
|
95
|
+
origin: np.ndarray
|
|
96
|
+
'''
|
|
97
|
+
The origin of the canonical frame, expressed in raw coordinates.
|
|
98
|
+
'''
|
|
99
|
+
inlier_mask: np.ndarray
|
|
100
|
+
'''
|
|
101
|
+
A boolean array (K,) indicating which input sites were used in the fit.
|
|
102
|
+
'''
|
|
103
|
+
indices: np.ndarray
|
|
104
|
+
'''
|
|
105
|
+
The integer indices (n_inliers, d) of the canonical positions
|
|
106
|
+
corresponding to each inlier site.
|
|
107
|
+
|
|
108
|
+
Examples:
|
|
109
|
+
- For a ruler, d=1 and the indices are the slot numbers.
|
|
110
|
+
- For a grid, d=2 and the indices are (row, col) pairs
|
|
111
|
+
- For a ring, d=1 and the indices are the angular slot numbers.
|
|
112
|
+
'''
|
|
113
|
+
n_matched: int
|
|
114
|
+
'''
|
|
115
|
+
The number of distinct canonical positions that were explained by the inlier sites.
|
|
116
|
+
'''
|
|
117
|
+
residual: float
|
|
118
|
+
'''
|
|
119
|
+
The fit residual.
|
|
120
|
+
'''
|
|
121
|
+
meta: dict = field(default_factory=dict)
|
|
122
|
+
'''
|
|
123
|
+
Model-specific metadata for logging and debugging purposes.
|
|
124
|
+
'''
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@dataclass
|
|
128
|
+
class InstanceStats:
|
|
129
|
+
n_localizations: int
|
|
130
|
+
'''All input localizations, including noise.'''
|
|
131
|
+
n_input_clusters: int
|
|
132
|
+
'''Distinct non-negative labels in the original localization table.'''
|
|
133
|
+
n_input_cluster_localizations: int
|
|
134
|
+
'''Localizations belonging to those original clusters.'''
|
|
135
|
+
|
|
136
|
+
n_cluster_centers: int
|
|
137
|
+
'''Centers created by get_centers() after filtering.'''
|
|
138
|
+
n_rejected_centers: int
|
|
139
|
+
'''Centers rejected by center-level QC.'''
|
|
140
|
+
|
|
141
|
+
n_candidates: int
|
|
142
|
+
'''Candidate geometric groups produced by DBSCAN/HDBSCAN/OPTICS.'''
|
|
143
|
+
n_candidate_centers: int
|
|
144
|
+
'''Total site centers across all candidates.'''
|
|
145
|
+
n_rejected_candidates: int
|
|
146
|
+
'''Candidates where model.fit() returned None or residual QC failed.'''
|
|
147
|
+
|
|
148
|
+
n_passed_instances: int
|
|
149
|
+
'''Candidates that passed the geometric model.'''
|
|
150
|
+
n_passed_centers: int
|
|
151
|
+
'''Centers belonging to passed instances.'''
|
|
152
|
+
n_passed_localizations: int
|
|
153
|
+
'''Raw localizations belonging to passed instances.'''
|
|
154
|
+
|
|
155
|
+
candidate_log: list[dict] = field(default_factory=list)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@dataclass
|
|
159
|
+
class PlotResult:
|
|
160
|
+
'''
|
|
161
|
+
Unified return type for all ClustersScatter render methods.
|
|
162
|
+
|
|
163
|
+
raster : pg.ImageItem or None — 2D rasterized render
|
|
164
|
+
scatter : list[pg.ScatterPlotItem] — raw scatter layers (when not rasterized)
|
|
165
|
+
histogram_x : list[pg.GraphicsObject] — X-projection histogram + KDE items
|
|
166
|
+
histogram_y : list[pg.GraphicsObject] — Y-projection histogram + KDE items
|
|
167
|
+
title : str — plot title
|
|
168
|
+
pixel_size : float — nm per pixel (carried from rasterized_2d)
|
|
169
|
+
'''
|
|
170
|
+
|
|
171
|
+
raster: pg.ImageItem | None = None
|
|
172
|
+
scatter: list[pg.ScatterPlotItem | pg.PlotCurveItem] = field(default_factory=list)
|
|
173
|
+
histogram_x: list[pg.GraphicsObject] = field(default_factory=list)
|
|
174
|
+
histogram_y: list[pg.GraphicsObject] = field(default_factory=list)
|
|
175
|
+
title: str = ''
|
|
176
|
+
pixel_size: float = 1.0
|
|
177
|
+
|
|
178
|
+
histogram_angle: list[pg.GraphicsObject] = field(default_factory=list)
|
|
179
|
+
histogram_intensity: list[pg.GraphicsObject] = field(default_factory=list)
|
|
180
|
+
histogram_n_matched: list[pg.GraphicsObject] = field(default_factory=list)
|
|
181
|
+
|
|
182
|
+
@property
|
|
183
|
+
def is_rasterized(self) -> bool:
|
|
184
|
+
return self.raster is not None
|
|
185
|
+
|
|
186
|
+
@property
|
|
187
|
+
def has_histograms(self) -> bool:
|
|
188
|
+
return bool(self.histogram_x or self.histogram_y or self.histogram_angle)
|
|
189
|
+
|
|
190
|
+
@dataclass
|
|
191
|
+
class LabeledLocalizations:
|
|
192
|
+
x: np.ndarray
|
|
193
|
+
y: np.ndarray
|
|
194
|
+
z: np.ndarray | None
|
|
195
|
+
labels: np.ndarray
|
|
196
|
+
intensity: np.ndarray | None
|
|
197
|
+
crlb_x: np.ndarray | None
|
|
198
|
+
crlb_y: np.ndarray | None
|
|
199
|
+
crlb_z: np.ndarray | None
|
|
200
|
+
|
|
201
|
+
@dataclass
|
|
202
|
+
class ClusterRenderData:
|
|
203
|
+
tables: list[LabeledLocalizations]
|
|
204
|
+
run_meta: dict = field(default_factory=dict)
|
|
205
|
+
|
|
206
|
+
@dataclass
|
|
207
|
+
class PipelineResult:
|
|
208
|
+
stats: list[InstanceStats]
|
|
209
|
+
instances: list[dict]
|
|
210
|
+
model_meta: dict
|
|
211
|
+
run_meta: dict
|
|
212
|
+
|