spacr 0.4.12__tar.gz → 0.4.60__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.
- {spacr-0.4.12 → spacr-0.4.60}/MANIFEST.in +10 -0
- {spacr-0.4.12/spacr.egg-info → spacr-0.4.60}/PKG-INFO +2 -1
- {spacr-0.4.12 → spacr-0.4.60}/setup.py +2 -1
- {spacr-0.4.12 → spacr-0.4.60}/spacr/core.py +54 -8
- {spacr-0.4.12 → spacr-0.4.60}/spacr/deep_spacr.py +2 -3
- {spacr-0.4.12 → spacr-0.4.60}/spacr/gui_core.py +259 -75
- {spacr-0.4.12 → spacr-0.4.60}/spacr/gui_elements.py +133 -2
- {spacr-0.4.12 → spacr-0.4.60}/spacr/gui_utils.py +24 -20
- {spacr-0.4.12 → spacr-0.4.60}/spacr/io.py +553 -61
- {spacr-0.4.12 → spacr-0.4.60}/spacr/measure.py +11 -12
- {spacr-0.4.12 → spacr-0.4.60}/spacr/ml.py +141 -258
- {spacr-0.4.12 → spacr-0.4.60}/spacr/plot.py +76 -34
- {spacr-0.4.12 → spacr-0.4.60}/spacr/sequencing.py +73 -38
- {spacr-0.4.12 → spacr-0.4.60}/spacr/settings.py +160 -93
- {spacr-0.4.12 → spacr-0.4.60}/spacr/submodules.py +620 -214
- {spacr-0.4.12 → spacr-0.4.60}/spacr/timelapse.py +25 -25
- {spacr-0.4.12 → spacr-0.4.60}/spacr/toxo.py +23 -23
- {spacr-0.4.12 → spacr-0.4.60}/spacr/utils.py +249 -95
- {spacr-0.4.12 → spacr-0.4.60/spacr.egg-info}/PKG-INFO +2 -1
- {spacr-0.4.12 → spacr-0.4.60}/spacr.egg-info/requires.txt +1 -0
- {spacr-0.4.12 → spacr-0.4.60}/.readthedocs.yaml +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/LICENSE +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/README.rst +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/deploy_docs.sh +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/requirements.txt +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/Makefile +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/doctrees/environment.pickle +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_sources/index.rst.txt +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/_sphinx_javascript_frameworks_compat.js +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/basic.css +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/css/badge_only.css +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff2 +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff2 +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/css/fonts/fontawesome-webfont.eot +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/css/fonts/fontawesome-webfont.svg +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/css/fonts/fontawesome-webfont.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/css/fonts/fontawesome-webfont.woff +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/css/fonts/fontawesome-webfont.woff2 +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/css/fonts/lato-bold-italic.woff +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/css/fonts/lato-bold-italic.woff2 +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/css/fonts/lato-bold.woff +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/css/fonts/lato-bold.woff2 +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/css/fonts/lato-normal-italic.woff +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/css/fonts/lato-normal-italic.woff2 +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/css/fonts/lato-normal.woff +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/css/fonts/lato-normal.woff2 +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/css/theme.css +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/doctools.js +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/documentation_options.js +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/file.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/Lato/lato-bold.eot +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/Lato/lato-bold.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/Lato/lato-bold.woff +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/Lato/lato-bold.woff2 +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/Lato/lato-bolditalic.eot +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/Lato/lato-bolditalic.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/Lato/lato-bolditalic.woff +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/Lato/lato-bolditalic.woff2 +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/Lato/lato-italic.eot +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/Lato/lato-italic.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/Lato/lato-italic.woff +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/Lato/lato-italic.woff2 +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/Lato/lato-regular.eot +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/Lato/lato-regular.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/Lato/lato-regular.woff +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/Lato/lato-regular.woff2 +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/jquery.js +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/js/badge_only.js +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/js/theme.js +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/js/versions.js +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/language_data.js +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/minus.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/plus.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/pygments.css +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/searchtools.js +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/_static/sphinx_highlight.js +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/genindex.html +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/index.html +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/objects.inv +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/search.html +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/_build/html/searchindex.js +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/conf.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/index.rst +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/docs/source/make.bat +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/environment.yaml +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/fonts/OpenSans-Regular.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/path/home/carruthers/datasets/plate1/measurements/measurements.db +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/path/home/carruthers/datasets/plate1/settings/measure_crop_settings.csv +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/path/settings/preprocess_generate_masks_settings.csv +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/requirements.txt +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/settings/measure_crop_settings.csv +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/setup.cfg +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/setup_docs.sh +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/source/conf.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/source/index.rst +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/source/modules.rst +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/source/setup.rst +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/source/spacr.rst +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/__init__.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/__main__.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/app_annotate.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/app_classify.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/app_make_masks.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/app_mask.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/app_measure.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/app_sequencing.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/app_umap.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/cellpose.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/chat_bot.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/gui.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/logger.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/mediar.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/openai.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/.gitignore +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/LICENSE +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/README.md +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/SetupDict.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/config/baseline.json +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/config/mediar_example.json +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/config/pred/pred_mediar.json +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/config/step1_pretraining/phase1.json +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/config/step1_pretraining/phase2.json +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/config/step2_finetuning/finetuning1.json +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/config/step2_finetuning/finetuning2.json +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/config/step3_prediction/base_prediction.json +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/config/step3_prediction/ensemble_tta.json +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/core/BasePredictor.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/core/BaseTrainer.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/core/Baseline/Predictor.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/core/Baseline/Trainer.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/core/Baseline/__init__.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/core/Baseline/utils.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/core/MEDIAR/EnsemblePredictor.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/core/MEDIAR/Predictor.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/core/MEDIAR/Trainer.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/core/MEDIAR/__init__.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/core/MEDIAR/utils.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/core/__init__.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/core/utils.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/evaluate.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/generate_mapping.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/image/examples/img1.tiff +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/image/examples/img2.tif +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/image/failure_cases.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/image/mediar_framework.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/image/mediar_model.PNG +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/image/mediar_results.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/main.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/predict.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/requirements.txt +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/train_tools/__init__.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/train_tools/data_utils/__init__.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/train_tools/data_utils/custom/CellAware.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/train_tools/data_utils/custom/LoadImage.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/train_tools/data_utils/custom/NormalizeImage.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/train_tools/data_utils/custom/__init__.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/train_tools/data_utils/custom/modalities.pkl +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/train_tools/data_utils/datasetter.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/train_tools/data_utils/transforms.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/train_tools/data_utils/utils.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/train_tools/measures.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/train_tools/models/MEDIARFormer.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/train_tools/models/__init__.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/MEDIAR/train_tools/utils.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/data/lopit.csv +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/data/toxoplasma_metadata.csv +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/OFL.txt +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/OpenSans-Italic-VariableFont_wdth,wght.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/OpenSans-VariableFont_wdth,wght.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/README.txt +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans-Bold.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans-BoldItalic.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans-ExtraBold.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans-ExtraBoldItalic.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans-Italic.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans-Light.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans-LightItalic.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans-Medium.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans-MediumItalic.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans-Regular.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans-SemiBold.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans-SemiBoldItalic.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_Condensed-Bold.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_Condensed-BoldItalic.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_Condensed-ExtraBold.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_Condensed-ExtraBoldItalic.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_Condensed-Italic.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_Condensed-Light.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_Condensed-LightItalic.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_Condensed-Medium.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_Condensed-MediumItalic.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_Condensed-Regular.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_Condensed-SemiBold.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_Condensed-SemiBoldItalic.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Bold.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-BoldItalic.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-ExtraBold.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-ExtraBoldItalic.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Italic.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Light.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-LightItalic.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Medium.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-MediumItalic.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Regular.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-SemiBold.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-SemiBoldItalic.ttf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/abort.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/annotate.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/cellpose_all.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/cellpose_masks.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/classify.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/convert.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/default.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/dna_matrix.mp4 +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/download.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/logo.pdf +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/logo_spacr.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/logo_spacr_1.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/make_masks.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/map_barcodes.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/mask.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/measure.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/ml_analyze.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/plaque.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/recruitment.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/regression.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/run.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/sequencing.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/settings.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/train_cellpose.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/icons/umap.png +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/images/plate1_E01_T0001F001L01A01Z01C02.tif +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/images/plate1_E01_T0001F001L01A02Z01C01.tif +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/resources/images/plate1_E01_T0001F001L01A03Z01C03.tif +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/sim.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/sp_stats.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr/version.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr.egg-info/SOURCES.txt +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr.egg-info/dependency_links.txt +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr.egg-info/entry_points.txt +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/spacr.egg-info/top_level.txt +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/tests/test_annotate_app.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/tests/test_core.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/tests/test_gui_classify_app.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/tests/test_gui_mask_app.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/tests/test_gui_measure_app.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/tests/test_gui_sim_app.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/tests/test_gui_utils.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/tests/test_io.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/tests/test_mask_app.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/tests/test_measure.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/tests/test_plot.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/tests/test_sim.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/tests/test_timelapse.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/tests/test_train.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/tests/test_umap.py +0 -0
- {spacr-0.4.12 → spacr-0.4.60}/tests/test_utils.py +0 -0
@@ -35,3 +35,13 @@ prune notebooks
|
|
35
35
|
prune spacr/notebooks
|
36
36
|
prune spacr/datasets
|
37
37
|
|
38
|
+
# Exclude model files from distribution
|
39
|
+
#exclude spacr/resources/models/cp/*
|
40
|
+
#prune spacr/resources/models/cp
|
41
|
+
|
42
|
+
# Exclude all notebooks (including old ones)
|
43
|
+
prune notebooks
|
44
|
+
prune spacr/notebooks
|
45
|
+
prune spacr/notebooks/submodules
|
46
|
+
prune spacr/notebooks/old
|
47
|
+
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: spacr
|
3
|
-
Version: 0.4.
|
3
|
+
Version: 0.4.60
|
4
4
|
Summary: Spatial phenotype analysis of crisp screens (SpaCr)
|
5
5
|
Home-page: https://github.com/EinarOlafsson/spacr
|
6
6
|
Author: Einar Birnir Olafsson
|
@@ -41,6 +41,7 @@ Requires-Dist: pillow<11.0,>=10.2.0
|
|
41
41
|
Requires-Dist: tifffile>=2023.4.12
|
42
42
|
Requires-Dist: nd2reader<4.0,>=3.3.0
|
43
43
|
Requires-Dist: czifile
|
44
|
+
Requires-Dist: readlif
|
44
45
|
Requires-Dist: imageio<3.0,>=2.34.0
|
45
46
|
Requires-Dist: pingouin<1.0,>=0.5.5
|
46
47
|
Requires-Dist: umap-learn<1.0,>=0.5.6
|
@@ -37,6 +37,7 @@ dependencies = [
|
|
37
37
|
'tifffile>=2023.4.12',
|
38
38
|
'nd2reader>=3.3.0, <4.0',
|
39
39
|
'czifile',
|
40
|
+
'readlif',
|
40
41
|
'imageio>=2.34.0,<3.0',
|
41
42
|
'pingouin>=0.5.5,<1.0',
|
42
43
|
'umap-learn>=0.5.6,<1.0',
|
@@ -70,7 +71,7 @@ dependencies = [
|
|
70
71
|
|
71
72
|
setup(
|
72
73
|
name="spacr",
|
73
|
-
version="0.4.
|
74
|
+
version="0.4.60",
|
74
75
|
author="Einar Birnir Olafsson",
|
75
76
|
author_email="olafsson@med.umich.com",
|
76
77
|
description="Spatial phenotype analysis of crisp screens (SpaCr)",
|
@@ -9,12 +9,11 @@ warnings.filterwarnings("ignore", message="3D stack used, but stitch_threshold=0
|
|
9
9
|
|
10
10
|
def preprocess_generate_masks(settings):
|
11
11
|
|
12
|
-
from .io import preprocess_img_data, _load_and_concatenate_arrays
|
12
|
+
from .io import preprocess_img_data, _load_and_concatenate_arrays, convert_to_yokogawa, convert_separate_files_to_yokogawa
|
13
13
|
from .plot import plot_image_mask_overlay, plot_arrays
|
14
|
-
from .utils import _pivot_counts_table, check_mask_folder, adjust_cell_masks, print_progress, save_settings, delete_intermedeate_files
|
14
|
+
from .utils import _pivot_counts_table, check_mask_folder, adjust_cell_masks, print_progress, save_settings, delete_intermedeate_files, format_path_for_system, normalize_src_path, generate_image_path_map, copy_images_to_consolidated
|
15
15
|
from .settings import set_default_settings_preprocess_generate_masks
|
16
|
-
|
17
|
-
|
16
|
+
|
18
17
|
if 'src' in settings:
|
19
18
|
if not isinstance(settings['src'], (str, list)):
|
20
19
|
ValueError(f'src must be a string or a list of strings')
|
@@ -23,18 +22,53 @@ def preprocess_generate_masks(settings):
|
|
23
22
|
ValueError(f'src is a required parameter')
|
24
23
|
return
|
25
24
|
|
25
|
+
settings['src'] = normalize_src_path(settings['src'])
|
26
|
+
|
27
|
+
if settings['consolidate']:
|
28
|
+
image_map = generate_image_path_map(settings['src'])
|
29
|
+
copy_images_to_consolidated(image_map, settings['src'])
|
30
|
+
settings['src'] = os.path.join(settings['src'], 'consolidated')
|
31
|
+
|
26
32
|
if isinstance(settings['src'], str):
|
27
33
|
settings['src'] = [settings['src']]
|
28
34
|
|
29
35
|
if isinstance(settings['src'], list):
|
30
36
|
source_folders = settings['src']
|
31
37
|
for source_folder in source_folders:
|
38
|
+
|
32
39
|
print(f'Processing folder: {source_folder}')
|
40
|
+
|
41
|
+
source_folder = format_path_for_system(source_folder)
|
33
42
|
settings['src'] = source_folder
|
34
43
|
src = source_folder
|
35
44
|
settings = set_default_settings_preprocess_generate_masks(settings)
|
45
|
+
|
46
|
+
if settings['metadata_type'] == 'auto':
|
47
|
+
if settings['custom_regex'] != None:
|
48
|
+
try:
|
49
|
+
print(f"using regex: {settings['custom_regex']}")
|
50
|
+
convert_separate_files_to_yokogawa(folder=source_folder, regex=settings['custom_regex'])
|
51
|
+
except:
|
52
|
+
try:
|
53
|
+
convert_to_yokogawa(folder=source_folder)
|
54
|
+
except Exception as e:
|
55
|
+
print(f"Error: Tried to convert image files and image file name metadata with regex {settings['custom_regex']} then without regex but failed both.")
|
56
|
+
print(f'Error: {e}')
|
57
|
+
return
|
58
|
+
else:
|
59
|
+
try:
|
60
|
+
convert_to_yokogawa(folder=source_folder)
|
61
|
+
except Exception as e:
|
62
|
+
print(f"Error: Tried to convert image files and image file name metadata without regex but failed.")
|
63
|
+
print(f'Error: {e}')
|
64
|
+
return
|
65
|
+
|
66
|
+
if settings['cell_channel'] is None and settings['nucleus_channel'] is None and settings['pathogen_channel'] is None:
|
67
|
+
print(f'Error: At least one of cell_channel, nucleus_channel or pathogen_channel must be defined')
|
68
|
+
return
|
69
|
+
|
36
70
|
save_settings(settings, name='gen_mask_settings')
|
37
|
-
|
71
|
+
|
38
72
|
if not settings['pathogen_channel'] is None:
|
39
73
|
custom_model_ls = ['toxo_pv_lumen','toxo_cyto']
|
40
74
|
if settings['pathogen_model'] not in custom_model_ls:
|
@@ -54,7 +88,7 @@ def preprocess_generate_masks(settings):
|
|
54
88
|
settings_df = pd.DataFrame(list(settings.items()), columns=['setting_key', 'setting_value'])
|
55
89
|
settings_df['setting_value'] = settings_df['setting_value'].apply(str)
|
56
90
|
display(settings_df)
|
57
|
-
|
91
|
+
|
58
92
|
if settings['test_mode']:
|
59
93
|
print(f'Starting Test mode ...')
|
60
94
|
|
@@ -164,6 +198,7 @@ def preprocess_generate_masks(settings):
|
|
164
198
|
gc.collect()
|
165
199
|
|
166
200
|
if settings['delete_intermediate']:
|
201
|
+
print(f"deleting intermediate files")
|
167
202
|
delete_intermedeate_files(settings)
|
168
203
|
|
169
204
|
print("Successfully completed run")
|
@@ -285,6 +320,17 @@ def generate_cellpose_masks(src, settings, object_type):
|
|
285
320
|
continue
|
286
321
|
|
287
322
|
batch = prepare_batch_for_segmentation(batch)
|
323
|
+
|
324
|
+
|
325
|
+
#if settings['denoise']:
|
326
|
+
# if object_type == 'cell':
|
327
|
+
# model_type = "denoise_cyto3"
|
328
|
+
# elif object_type == 'nucleus':
|
329
|
+
# model_type = "denoise_nucleus"
|
330
|
+
# else:
|
331
|
+
# raise ValueError(f"No denoise model for object_type: {object_type}")
|
332
|
+
# dn = denoise.DenoiseModel(model_type=model_type, gpu=device)
|
333
|
+
# batch = dn.eval(imgs=batch, channels=chans, diameter=object_settings['diameter'])
|
288
334
|
|
289
335
|
if timelapse:
|
290
336
|
movie_path = os.path.join(os.path.dirname(src), 'movies')
|
@@ -486,7 +532,7 @@ def generate_image_umap(settings={}):
|
|
486
532
|
all_df = pd.concat([all_df, df], axis=0)
|
487
533
|
#image_paths.extend(image_paths_tmp)
|
488
534
|
|
489
|
-
all_df['cond'] = all_df['
|
535
|
+
all_df['cond'] = all_df['columnID'].apply(map_condition, neg=settings['neg'], pos=settings['pos'], mix=settings['mix'])
|
490
536
|
|
491
537
|
if settings['exclude_conditions']:
|
492
538
|
if isinstance(settings['exclude_conditions'], str):
|
@@ -670,7 +716,7 @@ def reducer_hyperparameter_search(settings={}, reduction_params=None, dbscan_par
|
|
670
716
|
df = _read_and_join_tables(db_path, table_names=tables)
|
671
717
|
all_df = pd.concat([all_df, df], axis=0)
|
672
718
|
|
673
|
-
all_df['cond'] = all_df['
|
719
|
+
all_df['cond'] = all_df['columnID'].apply(map_condition, neg=settings['neg'], pos=settings['pos'], mix=settings['mix'])
|
674
720
|
|
675
721
|
if settings['exclude_conditions']:
|
676
722
|
if isinstance(settings['exclude_conditions'], str):
|
@@ -1144,7 +1144,7 @@ def model_fusion(model_paths,save_path,device='cpu',model_name='maxvit_t',pretra
|
|
1144
1144
|
|
1145
1145
|
def annotate_filter_vision(settings):
|
1146
1146
|
|
1147
|
-
from .utils import annotate_conditions
|
1147
|
+
from .utils import annotate_conditions, correct_metadata
|
1148
1148
|
|
1149
1149
|
def filter_csv_by_png(csv_file):
|
1150
1150
|
"""
|
@@ -1188,8 +1188,7 @@ def annotate_filter_vision(settings):
|
|
1188
1188
|
|
1189
1189
|
df = pd.read_csv(src)
|
1190
1190
|
|
1191
|
-
|
1192
|
-
df['column_name'] = df['column']
|
1191
|
+
df = correct_metadata(df)
|
1193
1192
|
|
1194
1193
|
df = annotate_conditions(df,
|
1195
1194
|
cells=settings['cells'],
|
@@ -170,68 +170,11 @@ def display_figure(fig):
|
|
170
170
|
#flash_feedback("right")
|
171
171
|
show_next_figure()
|
172
172
|
|
173
|
-
def zoom_v1(event):
|
174
|
-
nonlocal scale_factor
|
175
|
-
|
176
|
-
zoom_speed = 0.1 # Adjust the zoom speed for smoother experience
|
177
|
-
|
178
|
-
# Determine the zoom direction based on the scroll event
|
179
|
-
if event.num == 4 or event.delta > 0: # Scroll up (zoom in)
|
180
|
-
scale_factor /= (1 + zoom_speed) # Divide to zoom in
|
181
|
-
elif event.num == 5 or event.delta < 0: # Scroll down (zoom out)
|
182
|
-
scale_factor *= (1 + zoom_speed) # Multiply to zoom out
|
183
|
-
|
184
|
-
# Adjust the axes limits based on the new scale factor
|
185
|
-
for ax in canvas.figure.get_axes():
|
186
|
-
xlim = ax.get_xlim()
|
187
|
-
ylim = ax.get_ylim()
|
188
|
-
|
189
|
-
x_center = (xlim[1] + xlim[0]) / 2
|
190
|
-
y_center = (ylim[1] + ylim[0]) / 2
|
191
|
-
|
192
|
-
x_range = (xlim[1] - xlim[0]) * scale_factor
|
193
|
-
y_range = (ylim[1] - ylim[0]) * scale_factor
|
194
|
-
|
195
|
-
# Set the new limits
|
196
|
-
ax.set_xlim([x_center - x_range / 2, x_center + x_range / 2])
|
197
|
-
ax.set_ylim([y_center - y_range / 2, y_center + y_range / 2])
|
198
|
-
|
199
|
-
# Redraw the figure efficiently
|
200
|
-
canvas.draw_idle()
|
201
|
-
|
202
173
|
def zoom_test(event):
|
203
174
|
if event.num == 4: # Scroll up
|
204
175
|
print("zoom in")
|
205
176
|
elif event.num == 5: # Scroll down
|
206
177
|
print("zoom out")
|
207
|
-
|
208
|
-
def zoom_2(event):
|
209
|
-
zoom_speed = 0.1 # Change this to control how fast you zoom
|
210
|
-
|
211
|
-
# Determine the zoom direction based on the scroll event
|
212
|
-
if event.num == 4 or (hasattr(event, 'delta') and event.delta > 0): # Scroll up = zoom in
|
213
|
-
factor = 1 - zoom_speed
|
214
|
-
elif event.num == 5 or (hasattr(event, 'delta') and event.delta < 0): # Scroll down = zoom out
|
215
|
-
factor = 1 + zoom_speed
|
216
|
-
else:
|
217
|
-
return # No recognized scroll direction
|
218
|
-
|
219
|
-
for ax in canvas.figure.get_axes():
|
220
|
-
xlim = ax.get_xlim()
|
221
|
-
ylim = ax.get_ylim()
|
222
|
-
|
223
|
-
x_center = (xlim[1] + xlim[0]) / 2
|
224
|
-
y_center = (ylim[1] + ylim[0]) / 2
|
225
|
-
|
226
|
-
x_range = (xlim[1] - xlim[0]) * factor
|
227
|
-
y_range = (ylim[1] - ylim[0]) * factor
|
228
|
-
|
229
|
-
# Set the new limits
|
230
|
-
ax.set_xlim([x_center - x_range / 2, x_center + x_range / 2])
|
231
|
-
ax.set_ylim([y_center - y_range / 2, y_center + y_range / 2])
|
232
|
-
|
233
|
-
# Redraw the figure efficiently
|
234
|
-
canvas.draw_idle()
|
235
178
|
|
236
179
|
def zoom(event):
|
237
180
|
# Fixed zoom factors (adjust these if you want faster or slower zoom)
|
@@ -247,23 +190,28 @@ def display_figure(fig):
|
|
247
190
|
return # No recognized scroll direction
|
248
191
|
|
249
192
|
for ax in canvas.figure.get_axes():
|
193
|
+
# Get the current mouse position in pixel coordinates
|
194
|
+
mouse_x, mouse_y = event.x, event.y
|
195
|
+
|
196
|
+
# Convert pixel coordinates to data coordinates
|
197
|
+
inv = ax.transData.inverted()
|
198
|
+
data_x, data_y = inv.transform((mouse_x, mouse_y))
|
199
|
+
|
200
|
+
# Get the current axis limits
|
250
201
|
xlim = ax.get_xlim()
|
251
202
|
ylim = ax.get_ylim()
|
252
203
|
|
253
|
-
|
254
|
-
y_center = (ylim[1] + ylim[0]) / 2
|
255
|
-
|
204
|
+
# Calculate the zooming range around the cursor position
|
256
205
|
x_range = (xlim[1] - xlim[0]) * factor
|
257
206
|
y_range = (ylim[1] - ylim[0]) * factor
|
258
207
|
|
259
|
-
#
|
260
|
-
ax.set_xlim([
|
261
|
-
ax.set_ylim([
|
208
|
+
# Adjust the limits while keeping the mouse position fixed
|
209
|
+
ax.set_xlim([data_x - (data_x - xlim[0]) * factor, data_x + (xlim[1] - data_x) * factor])
|
210
|
+
ax.set_ylim([data_y - (data_y - ylim[0]) * factor, data_y + (ylim[1] - data_y) * factor])
|
262
211
|
|
263
212
|
# Redraw the figure efficiently
|
264
213
|
canvas.draw_idle()
|
265
214
|
|
266
|
-
|
267
215
|
# Bind events for hover, click interactions, and zoom
|
268
216
|
canvas_widget.bind("<Motion>", on_hover)
|
269
217
|
canvas_widget.bind("<Leave>", on_leave)
|
@@ -854,7 +802,7 @@ def initiate_abort():
|
|
854
802
|
global thread_control, q, parent_frame
|
855
803
|
if thread_control.get("run_thread") is not None:
|
856
804
|
try:
|
857
|
-
q.put("Aborting processes...")
|
805
|
+
#q.put("Aborting processes...")
|
858
806
|
thread_control.get("run_thread").terminate()
|
859
807
|
thread_control["run_thread"] = None
|
860
808
|
q.put("Processes aborted.")
|
@@ -862,22 +810,164 @@ def initiate_abort():
|
|
862
810
|
q.put(f"Error aborting process: {e}")
|
863
811
|
|
864
812
|
thread_control = {"run_thread": None, "stop_requested": False}
|
813
|
+
|
814
|
+
def check_src_folders_files(settings, settings_type, q):
|
815
|
+
"""
|
816
|
+
Checks if 'src' is a key in the settings dictionary and if it exists as a valid path.
|
817
|
+
If 'src' is a list, iterates through the list and checks each path.
|
818
|
+
If any path is missing, prompts the user to edit or remove invalid paths.
|
819
|
+
"""
|
820
|
+
|
821
|
+
request_stop = False
|
822
|
+
|
823
|
+
def _folder_has_images(folder_path, image_extensions = {".png", ".jpg", ".jpeg", ".bmp", ".gif", ".tiff", ".tif", ".webp", ".npy", ".npz", "nd2", "czi", "lif"}):
|
824
|
+
"""Check if a folder contains any image files."""
|
825
|
+
return any(file.lower().endswith(tuple(image_extensions)) for file in os.listdir(folder_path))
|
826
|
+
|
827
|
+
def _has_folder(parent_folder, sub_folder="measure"):
|
828
|
+
"""Check if a specific sub-folder exists inside the given folder."""
|
829
|
+
return os.path.isdir(os.path.join(parent_folder, sub_folder))
|
830
|
+
|
831
|
+
from .utils import normalize_src_path, generate_image_path_map
|
832
|
+
|
833
|
+
settings['src'] = normalize_src_path(settings['src'])
|
834
|
+
|
835
|
+
src_value = settings.get("src")
|
836
|
+
|
837
|
+
# **Skip if 'src' is missing**
|
838
|
+
if src_value is None:
|
839
|
+
return request_stop
|
840
|
+
|
841
|
+
# Convert single string src to a list for uniform handling
|
842
|
+
if isinstance(src_value, str):
|
843
|
+
src_list = [src_value]
|
844
|
+
elif isinstance(src_value, list):
|
845
|
+
src_list = src_value
|
846
|
+
else:
|
847
|
+
request_stop = True
|
848
|
+
return request_stop # Ensure early exit
|
849
|
+
|
850
|
+
# Identify missing paths
|
851
|
+
missing_paths = {i: path for i, path in enumerate(src_list) if not os.path.exists(path)}
|
852
|
+
|
853
|
+
if missing_paths:
|
854
|
+
q.put(f'Error: The following paths are missing: {missing_paths}')
|
855
|
+
request_stop = True
|
856
|
+
return request_stop # Ensure early exit
|
857
|
+
|
858
|
+
conditions = [True] # Initialize conditions list
|
859
|
+
|
860
|
+
for path in src_list: # Fixed: Use src_list instead of src_value
|
861
|
+
if settings_type == 'mask':
|
862
|
+
if settings['consolidate']:
|
863
|
+
image_map = generate_image_path_map(path)
|
864
|
+
if len(image_map) > 0:
|
865
|
+
request_stop = False
|
866
|
+
return request_stop
|
867
|
+
else:
|
868
|
+
q.put(f"Error: Missing subfolders with images for: {path}")
|
869
|
+
request_stop = True
|
870
|
+
return request_stop
|
871
|
+
else:
|
872
|
+
pictures_continue = _folder_has_images(path)
|
873
|
+
folder_chan_continue = _has_folder(path, "1")
|
874
|
+
folder_stack_continue = _has_folder(path, "stack")
|
875
|
+
folder_npz_continue = _has_folder(path, "norm_channel_stack")
|
876
|
+
|
877
|
+
if not pictures_continue:
|
878
|
+
if not any([folder_chan_continue, folder_stack_continue, folder_npz_continue]):
|
879
|
+
if not folder_chan_continue:
|
880
|
+
q.put(f"Error: Missing channel folder in folder: {path}")
|
881
|
+
|
882
|
+
if not folder_stack_continue:
|
883
|
+
q.put(f"Error: Missing stack folder in folder: {path}")
|
884
|
+
|
885
|
+
if not folder_npz_continue:
|
886
|
+
q.put(f"Error: Missing norm_channel_stack folder in folder: {path}")
|
887
|
+
else:
|
888
|
+
q.put(f"Error: No images in folder: {path}")
|
889
|
+
|
890
|
+
#q.put(f"path:{path}")
|
891
|
+
#q.put(f"pictures_continue:{pictures_continue}, folder_chan_continue:{folder_chan_continue}, folder_stack_continue:{folder_stack_continue}, folder_npz_continue:{folder_npz_continue}")
|
892
|
+
|
893
|
+
conditions = [pictures_continue, folder_chan_continue, folder_stack_continue, folder_npz_continue]
|
894
|
+
|
895
|
+
if settings_type == 'measure':
|
896
|
+
if not os.path.basename(path) == 'merged':
|
897
|
+
path = os.path.join(path, "merged")
|
898
|
+
npy_continue = _folder_has_images(path, image_extensions={".npy"})
|
899
|
+
conditions = [npy_continue]
|
900
|
+
|
901
|
+
#if settings_type == 'recruitment':
|
902
|
+
# if not os.path.basename(path) == 'measurements':
|
903
|
+
# path = os.path.join(path, "measurements")
|
904
|
+
# db_continue = _folder_has_images(path, image_extensions={".db"})
|
905
|
+
# conditions = [db_continue]
|
906
|
+
|
907
|
+
#if settings_type == 'umap':
|
908
|
+
# if not os.path.basename(path) == 'measurements':
|
909
|
+
# path = os.path.join(path, "measurements")
|
910
|
+
# db_continue = _folder_has_images(path, image_extensions={".db"})
|
911
|
+
# conditions = [db_continue]
|
912
|
+
|
913
|
+
#if settings_type == 'analyze_plaques':
|
914
|
+
# if not os.path.basename(path) == 'measurements':
|
915
|
+
# path = os.path.join(path, "measurements")
|
916
|
+
# db_continue = _folder_has_images(path, image_extensions={".db"})
|
917
|
+
# conditions = [db_continue]
|
918
|
+
|
919
|
+
#if settings_type == 'map_barcodes':
|
920
|
+
# if not os.path.basename(path) == 'measurements':
|
921
|
+
# path = os.path.join(path, "measurements")
|
922
|
+
# db_continue = _folder_has_images(path, image_extensions={".db"})
|
923
|
+
# conditions = [db_continue]
|
924
|
+
|
925
|
+
#if settings_type == 'regression':
|
926
|
+
# if not os.path.basename(path) == 'measurements':
|
927
|
+
# path = os.path.join(path, "measurements")
|
928
|
+
# db_continue = _folder_has_images(path, image_extensions={".db"})
|
929
|
+
# conditions = [db_continue]
|
930
|
+
|
931
|
+
#if settings_type == 'classify':
|
932
|
+
# if not os.path.basename(path) == 'measurements':
|
933
|
+
# path = os.path.join(path, "measurements")
|
934
|
+
# db_continue = _folder_has_images(path, image_extensions={".db"})
|
935
|
+
# conditions = [db_continue]
|
936
|
+
|
937
|
+
#if settings_type == 'analyze_plaques':
|
938
|
+
# if not os.path.basename(path) == 'measurements':
|
939
|
+
# path = os.path.join(path, "measurements")
|
940
|
+
# db_continue = _folder_has_images(path, image_extensions={".db"})
|
941
|
+
# conditions = [db_continue]
|
942
|
+
|
943
|
+
if not any(conditions):
|
944
|
+
q.put(f"Error: The following path(s) is missing images or folders: {path}")
|
945
|
+
request_stop = True
|
946
|
+
|
947
|
+
return request_stop
|
865
948
|
|
866
949
|
def start_process(q=None, fig_queue=None, settings_type='mask'):
|
867
950
|
global thread_control, vars_dict, parent_frame
|
868
951
|
from .settings import check_settings, expected_types
|
869
952
|
from .gui_utils import run_function_gui, set_cpu_affinity, initialize_cuda, display_gif_in_plot_frame, print_widget_structure
|
870
|
-
|
953
|
+
|
871
954
|
if q is None:
|
872
955
|
q = Queue()
|
873
956
|
if fig_queue is None:
|
874
957
|
fig_queue = Queue()
|
875
958
|
try:
|
876
|
-
settings = check_settings(vars_dict, expected_types, q)
|
959
|
+
settings, errors = check_settings(vars_dict, expected_types, q)
|
960
|
+
|
961
|
+
if len(errors) > 0:
|
962
|
+
return
|
963
|
+
|
964
|
+
if check_src_folders_files(settings, settings_type, q):
|
965
|
+
return
|
966
|
+
|
877
967
|
except ValueError as e:
|
878
968
|
q.put(f"Error: {e}")
|
879
969
|
return
|
880
|
-
|
970
|
+
|
881
971
|
if isinstance(thread_control, dict) and thread_control.get("run_thread") is not None:
|
882
972
|
initiate_abort()
|
883
973
|
|
@@ -902,10 +992,11 @@ def start_process(q=None, fig_queue=None, settings_type='mask'):
|
|
902
992
|
|
903
993
|
# Store the process in thread_control for future reference
|
904
994
|
thread_control["run_thread"] = process
|
995
|
+
|
905
996
|
else:
|
906
997
|
q.put(f"Error: Unknown settings type '{settings_type}'")
|
907
998
|
return
|
908
|
-
|
999
|
+
|
909
1000
|
def process_console_queue():
|
910
1001
|
global q, console_output, parent_frame, progress_bar, process_console_queue
|
911
1002
|
|
@@ -916,13 +1007,105 @@ def process_console_queue():
|
|
916
1007
|
process_console_queue.current_maximum = None
|
917
1008
|
|
918
1009
|
ansi_escape_pattern = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')
|
1010
|
+
|
1011
|
+
spacing = 5
|
1012
|
+
|
1013
|
+
# **Configure styles for different message types**
|
1014
|
+
console_output.tag_configure("error", foreground="red", spacing3 = spacing)
|
1015
|
+
console_output.tag_configure("warning", foreground="orange", spacing3 = spacing)
|
1016
|
+
console_output.tag_configure("normal", foreground="white", spacing3 = spacing)
|
919
1017
|
|
920
1018
|
while not q.empty():
|
921
1019
|
message = q.get_nowait()
|
922
1020
|
clean_message = ansi_escape_pattern.sub('', message)
|
923
|
-
|
924
|
-
#
|
1021
|
+
|
1022
|
+
# **Detect Error Messages (Red)**
|
1023
|
+
if clean_message.startswith("Error:"):
|
1024
|
+
console_output.insert(tk.END, clean_message + "\n", "error")
|
1025
|
+
console_output.see(tk.END)
|
1026
|
+
#print("Run aborted due to error:", clean_message) # Debug message
|
1027
|
+
#return # **Exit immediately to stop further execution**
|
1028
|
+
|
1029
|
+
# **Detect Warning Messages (Orange)**
|
1030
|
+
elif clean_message.startswith("Warning:"):
|
1031
|
+
console_output.insert(tk.END, clean_message + "\n", "warning")
|
925
1032
|
|
1033
|
+
# **Process Progress Messages Normally**
|
1034
|
+
elif clean_message.startswith("Progress:"):
|
1035
|
+
try:
|
1036
|
+
# Extract the progress information
|
1037
|
+
match = re.search(r'Progress: (\d+)/(\d+), operation_type: ([\w\s]*),(.*)', clean_message)
|
1038
|
+
|
1039
|
+
if match:
|
1040
|
+
current_progress = int(match.group(1))
|
1041
|
+
total_progress = int(match.group(2))
|
1042
|
+
operation_type = match.group(3).strip()
|
1043
|
+
additional_info = match.group(4).strip() # Capture everything after operation_type
|
1044
|
+
|
1045
|
+
# Check if the maximum value has changed
|
1046
|
+
if process_console_queue.current_maximum != total_progress:
|
1047
|
+
process_console_queue.current_maximum = total_progress
|
1048
|
+
process_console_queue.completed_tasks = []
|
1049
|
+
|
1050
|
+
# Add the task to the completed set
|
1051
|
+
process_console_queue.completed_tasks.append(current_progress)
|
1052
|
+
|
1053
|
+
# Calculate the unique progress count
|
1054
|
+
unique_progress_count = len(np.unique(process_console_queue.completed_tasks))
|
1055
|
+
|
1056
|
+
# Update the progress bar
|
1057
|
+
if progress_bar:
|
1058
|
+
progress_bar['maximum'] = total_progress
|
1059
|
+
progress_bar['value'] = unique_progress_count
|
1060
|
+
|
1061
|
+
# Store operation type and additional info
|
1062
|
+
if operation_type:
|
1063
|
+
progress_bar.operation_type = operation_type
|
1064
|
+
progress_bar.additional_info = additional_info
|
1065
|
+
|
1066
|
+
# Update the progress label
|
1067
|
+
if progress_bar.progress_label:
|
1068
|
+
progress_bar.update_label()
|
1069
|
+
|
1070
|
+
# Clear completed tasks when progress is complete
|
1071
|
+
if unique_progress_count >= total_progress:
|
1072
|
+
process_console_queue.completed_tasks.clear()
|
1073
|
+
|
1074
|
+
except Exception as e:
|
1075
|
+
print(f"Error parsing progress message: {e}")
|
1076
|
+
|
1077
|
+
# **Insert Normal Messages with Extra Line Spacing**
|
1078
|
+
else:
|
1079
|
+
console_output.insert(tk.END, clean_message + "\n", "normal")
|
1080
|
+
|
1081
|
+
console_output.see(tk.END)
|
1082
|
+
|
1083
|
+
# **Continue processing if no error was detected**
|
1084
|
+
after_id = console_output.after(uppdate_frequency, process_console_queue)
|
1085
|
+
parent_frame.after_tasks.append(after_id)
|
1086
|
+
|
1087
|
+
def process_console_queue_v2():
|
1088
|
+
global q, console_output, parent_frame, progress_bar, process_console_queue
|
1089
|
+
|
1090
|
+
# Initialize function attribute if it doesn't exist
|
1091
|
+
if not hasattr(process_console_queue, "completed_tasks"):
|
1092
|
+
process_console_queue.completed_tasks = []
|
1093
|
+
if not hasattr(process_console_queue, "current_maximum"):
|
1094
|
+
process_console_queue.current_maximum = None
|
1095
|
+
|
1096
|
+
ansi_escape_pattern = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')
|
1097
|
+
|
1098
|
+
while not q.empty():
|
1099
|
+
message = q.get_nowait()
|
1100
|
+
clean_message = ansi_escape_pattern.sub('', message)
|
1101
|
+
|
1102
|
+
# **Abort Execution if an Error Message is Detected**
|
1103
|
+
if clean_message.startswith("Error:"):
|
1104
|
+
console_output.insert(tk.END, clean_message + "\n", "error")
|
1105
|
+
console_output.see(tk.END)
|
1106
|
+
print("Run aborted due to error:", clean_message) # Debug message
|
1107
|
+
return # **Exit immediately to stop further execution**
|
1108
|
+
|
926
1109
|
# Check if the message contains progress information
|
927
1110
|
if clean_message.startswith("Progress:"):
|
928
1111
|
try:
|
@@ -950,8 +1133,7 @@ def process_console_queue():
|
|
950
1133
|
if progress_bar:
|
951
1134
|
progress_bar['maximum'] = total_progress
|
952
1135
|
progress_bar['value'] = unique_progress_count
|
953
|
-
|
954
|
-
|
1136
|
+
|
955
1137
|
# Store operation type and additional info
|
956
1138
|
if operation_type:
|
957
1139
|
progress_bar.operation_type = operation_type
|
@@ -967,11 +1149,13 @@ def process_console_queue():
|
|
967
1149
|
|
968
1150
|
except Exception as e:
|
969
1151
|
print(f"Error parsing progress message: {e}")
|
1152
|
+
|
970
1153
|
else:
|
971
|
-
#
|
1154
|
+
# Insert non-progress messages into the console
|
972
1155
|
console_output.insert(tk.END, clean_message + "\n")
|
973
1156
|
console_output.see(tk.END)
|
974
|
-
|
1157
|
+
|
1158
|
+
# **Continue processing if no error was detected**
|
975
1159
|
after_id = console_output.after(uppdate_frequency, process_console_queue)
|
976
1160
|
parent_frame.after_tasks.append(after_id)
|
977
1161
|
|