coralnet-toolbox 0.0.69__tar.gz → 0.0.71__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.
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/PKG-INFO +6 -4
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/README.md +5 -3
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Annotations/QtAnnotation.py +1 -1
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Explorer/QtExplorer.py +161 -28
- coralnet_toolbox-0.0.71/coralnet_toolbox/Icons/target.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/TrainModel/QtBase.py +57 -76
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/QtAnnotationWindow.py +28 -1
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/QtMainWindow.py +8 -3
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/__init__.py +1 -1
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox.egg-info/PKG-INFO +6 -4
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox.egg-info/SOURCES.txt +1 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/pyproject.toml +2 -2
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/.editorconfig +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/.gitallowed +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/.github/ISSUE_TEMPLATE/general_question.md +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/.github/workflows/docs-build.yml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/.github/workflows/docs.yml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/.github/workflows/installation.yml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/.github/workflows/macos.yml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/.github/workflows/pypi.yml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/.github/workflows/ubuntu.yml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/.github/workflows/windows.yml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/.gitignore +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/LICENSE.txt +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/MANIFEST.in +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Annotations/QtMultiPolygonAnnotation.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Annotations/QtPatchAnnotation.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Annotations/QtPolygonAnnotation.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Annotations/QtRectangleAnnotation.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Annotations/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/AutoDistill/Models/GroundingDINO.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/AutoDistill/Models/OWLViT.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/AutoDistill/Models/OmDetTurbo.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/AutoDistill/Models/QtBase.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/AutoDistill/Models/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/AutoDistill/QtBatchInference.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/AutoDistill/QtDeployModel.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/AutoDistill/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/BreakTime/QtBreakout.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/BreakTime/QtSnake.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/BreakTime/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Common/QtGraphicsUtility.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Common/QtMarginInput.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Common/QtOverlapInput.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Common/QtTileSizeInput.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Common/QtUpdateImagePaths.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/CoralNet/QtAuthenticate.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/CoralNet/QtDownload.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/CoralNet/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Explorer/QtDataItem.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Explorer/QtFeatureStore.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Explorer/QtSettingsWidgets.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Explorer/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/IO/QtExportAnnotations.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/IO/QtExportCoralNetAnnotations.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/IO/QtExportGeoJSONAnnotations.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/IO/QtExportLabels.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/IO/QtExportMaskAnnotations.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/IO/QtExportTagLabAnnotations.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/IO/QtExportTagLabLabels.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/IO/QtExportViscoreAnnotations.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/IO/QtImportAnnotations.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/IO/QtImportCoralNetAnnotations.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/IO/QtImportCoralNetLabels.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/IO/QtImportFrames.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/IO/QtImportImages.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/IO/QtImportLabels.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/IO/QtImportTagLabAnnotations.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/IO/QtImportTagLabLabels.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/IO/QtImportViscoreAnnotations.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/IO/QtOpenProject.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/IO/QtSaveProject.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/IO/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/1.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/2.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/3.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/4.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/5.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/add.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/all.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/apple.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/breakout.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/coral.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/edit.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/eye.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/hide.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/home.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/lock.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/machine.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/magic.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/opaque.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/parameters.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/patch.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/polygon.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/rabbit.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/rectangle.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/remove.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/rocket.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/select.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/settings.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/snake.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/tile.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/transparent.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/turtle.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/unlock.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/user.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/wizard.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/workarea.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Icons/www.png +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/BatchInference/QtBase.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/BatchInference/QtClassify.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/BatchInference/QtDetect.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/BatchInference/QtSegment.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/BatchInference/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/Community/cfg/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/Community/cfg/classify/convnext_tiny.yaml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/Community/cfg/classify/efficientnet_b0.yaml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/Community/cfg/classify/mobilenet_v3_large.yaml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/Community/cfg/classify/swin_t.yaml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/Community/cfg/detect/convnext_tiny.yaml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/Community/cfg/detect/mobilenet_v3_large-fpn.yaml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/Community/cfg/detect/mobilenet_v3_small-fpn.yaml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/Community/cfg/detect/resnet101.yaml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/Community/cfg/detect/swin_t-fpn.yaml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/Community/cfg/detect/swin_t.yaml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/Community/cfg/detect/yolo11-p2.yaml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/Community/cfg/detect/yolo11-p6.yaml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/Community/cfg/segment/convnext_tiny.yaml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/Community/cfg/segment/swin_t-fpn.yaml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/Community/cfg/segment/swin_t.yaml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/Community/cfg/segment/yolo11-p2.yaml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/Community/cfg/segment/yolo11-p6.yaml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/ConfusionMatrix.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/DeployModel/QtBase.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/DeployModel/QtClassify.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/DeployModel/QtDetect.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/DeployModel/QtSegment.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/DeployModel/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/EvaluateModel/QtBase.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/EvaluateModel/QtClassify.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/EvaluateModel/QtDetect.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/EvaluateModel/QtSegment.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/EvaluateModel/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/ExportDataset/QtBase.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/ExportDataset/QtClassify.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/ExportDataset/QtDetect.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/ExportDataset/QtSegment.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/ExportDataset/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/ImportDataset/QtBase.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/ImportDataset/QtDetect.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/ImportDataset/QtSegment.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/ImportDataset/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/MergeDatasets/QtBase.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/MergeDatasets/QtClassify.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/MergeDatasets/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/OptimizeModel/QtBase.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/OptimizeModel/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/TrainModel/QtClassify.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/TrainModel/QtDetect.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/TrainModel/QtSegment.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/TrainModel/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/TuneModel/QtBase.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/TuneModel/QtClassify.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/TuneModel/QtDetect.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/TuneModel/QtSegment.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/TuneModel/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/TuneModel/tuner.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/VideoInference/QtBase.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/VideoInference/QtClassify.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/VideoInference/QtDetect.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/VideoInference/QtInference.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/VideoInference/QtSegment.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/VideoInference/QtVideoWidget.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/VideoInference/YOLO3D/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/VideoInference/YOLO3D/bbox3d_utils.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/VideoInference/YOLO3D/depth_model.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/VideoInference/YOLO3D/detection_model.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/VideoInference/YOLO3D/load_camera_params.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/VideoInference/YOLO3D/run.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/VideoInference/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/VideoInference/analytics.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/WeightedDataset.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/MachineLearning/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/QtConfidenceWindow.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/QtEventFilter.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/QtImageWindow.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/QtLabelWindow.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/QtPatchSampling.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/QtProgressBar.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/QtWorkArea.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Rasters/ImageFilter.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Rasters/QtRaster.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Rasters/RasterManager.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Rasters/RasterTableModel.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Rasters/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Results/CombineResults.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Results/ConvertResults.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Results/MapResults.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Results/Masks.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Results/ResultsProcessor.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Results/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/SAM/QtBatchInference.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/SAM/QtDeployGenerator.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/SAM/QtDeployPredictor.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/SAM/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/SeeAnything/QtBatchInference.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/SeeAnything/QtDeployPredictor.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/SeeAnything/QtTrainModel.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/SeeAnything/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tile/QtTileBatchInference.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tile/QtTileCreation.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tile/TileDataset/QtBase.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tile/TileDataset/QtClassify.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tile/TileDataset/QtDetect.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tile/TileDataset/QtSegment.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tile/TileDataset/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tile/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tools/QtCutSubTool.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tools/QtMoveSubTool.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tools/QtPanTool.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tools/QtPatchTool.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tools/QtPolygonTool.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tools/QtRectangleTool.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tools/QtResizeSubTool.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tools/QtSAMTool.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tools/QtSeeAnythingTool.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tools/QtSelectSubTool.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tools/QtSelectTool.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tools/QtSubTool.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tools/QtTool.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tools/QtWorkAreaTool.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tools/QtZoomTool.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Tools/__init__.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/main.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/utilities.py +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox.egg-info/dependency_links.txt +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox.egg-info/entry_points.txt +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox.egg-info/requires.txt +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox.egg-info/top_level.txt +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/mkdocs.yml +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/requirements.txt +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/requirements_dev.txt +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/setup.cfg +0 -0
- {coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/uv.lock +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: coralnet-toolbox
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.71
|
4
4
|
Summary: Tools for annotating and developing ML models for benthic imagery
|
5
5
|
Author-email: Jordan Pierce <jordan.pierce@noaa.gov>
|
6
6
|
License: MIT License
|
@@ -94,10 +94,12 @@ coralnet-toolbox
|
|
94
94
|
|
95
95
|
## 📚 Guides
|
96
96
|
|
97
|
-
For further instructions please see the following guides:
|
97
|
+
For further information and instructions, please see the following guides:
|
98
|
+
- [Overview](https://jordan-pierce.github.io/CoralNet-Toolbox/overview)
|
98
99
|
- [Installation](https://jordan-pierce.github.io/CoralNet-Toolbox/installation)
|
99
100
|
- [Usage](https://jordan-pierce.github.io/CoralNet-Toolbox/usage)
|
100
|
-
-
|
101
|
+
- Community Provided:
|
102
|
+
- [Patch-based Image Classifier](https://jordan-pierce.github.io/CoralNet-Toolbox/classify)
|
101
103
|
|
102
104
|
<details open>
|
103
105
|
<summary><h2><b>🎥 Watch the Video Demos</b></h2></summary>
|
@@ -177,7 +179,7 @@ Enhance your CoralNet experience with these tools:
|
|
177
179
|
- 🚀 Optimize: Productionize models for faster inferencing
|
178
180
|
- ⚙️ Batch Inference: Perform predictions on multiple images, automatically
|
179
181
|
- 🎞️ Video Inference: Perform predictions on a video in real-time, record the output and analytics
|
180
|
-
- 🔮 Explorer: Cluster, view, and re-label annotations using embeddings, mapped from feature-space
|
182
|
+
- 🔮 [Explorer](https://youtu.be/68eZt5l_7nA): Cluster, view, and re-label annotations using embeddings, mapped from feature-space
|
181
183
|
- ↔️ I/O: Import and Export annotations from / to CoralNet, Viscore, and TagLab
|
182
184
|
- Export annotations as [GeoJSONs](https://datatracker.ietf.org/doc/html/rfc7946), segmentation masks
|
183
185
|
- 📸 YOLO: Import and Export YOLO datasets for machine learning
|
@@ -50,10 +50,12 @@ coralnet-toolbox
|
|
50
50
|
|
51
51
|
## 📚 Guides
|
52
52
|
|
53
|
-
For further instructions please see the following guides:
|
53
|
+
For further information and instructions, please see the following guides:
|
54
|
+
- [Overview](https://jordan-pierce.github.io/CoralNet-Toolbox/overview)
|
54
55
|
- [Installation](https://jordan-pierce.github.io/CoralNet-Toolbox/installation)
|
55
56
|
- [Usage](https://jordan-pierce.github.io/CoralNet-Toolbox/usage)
|
56
|
-
-
|
57
|
+
- Community Provided:
|
58
|
+
- [Patch-based Image Classifier](https://jordan-pierce.github.io/CoralNet-Toolbox/classify)
|
57
59
|
|
58
60
|
<details open>
|
59
61
|
<summary><h2><b>🎥 Watch the Video Demos</b></h2></summary>
|
@@ -133,7 +135,7 @@ Enhance your CoralNet experience with these tools:
|
|
133
135
|
- 🚀 Optimize: Productionize models for faster inferencing
|
134
136
|
- ⚙️ Batch Inference: Perform predictions on multiple images, automatically
|
135
137
|
- 🎞️ Video Inference: Perform predictions on a video in real-time, record the output and analytics
|
136
|
-
- 🔮 Explorer: Cluster, view, and re-label annotations using embeddings, mapped from feature-space
|
138
|
+
- 🔮 [Explorer](https://youtu.be/68eZt5l_7nA): Cluster, view, and re-label annotations using embeddings, mapped from feature-space
|
137
139
|
- ↔️ I/O: Import and Export annotations from / to CoralNet, Viscore, and TagLab
|
138
140
|
- Export annotations as [GeoJSONs](https://datatracker.ietf.org/doc/html/rfc7946), segmentation masks
|
139
141
|
- 📸 YOLO: Import and Export YOLO datasets for machine learning
|
{coralnet_toolbox-0.0.69 → coralnet_toolbox-0.0.71}/coralnet_toolbox/Annotations/QtAnnotation.py
RENAMED
@@ -262,7 +262,7 @@ class Annotation(QObject):
|
|
262
262
|
# [1, 2] - Very small dots with small gaps
|
263
263
|
# [2, 4] - Small dots with larger gaps
|
264
264
|
# [1, 3] - Tiny dots with medium gaps
|
265
|
-
pen = QPen(pen_color,
|
265
|
+
pen = QPen(pen_color, 4) # Width for dotted line
|
266
266
|
pen.setStyle(Qt.CustomDashLine)
|
267
267
|
pen.setDashPattern([1, 2]) # Dotted pattern: 2 pixels on, 3 pixels off
|
268
268
|
pen.setDashOffset(self._animated_line)
|
@@ -130,7 +130,7 @@ class EmbeddingViewer(QWidget):
|
|
130
130
|
# Create a QToolButton to have both a primary action and a dropdown menu
|
131
131
|
self.find_mislabels_button = QToolButton()
|
132
132
|
self.find_mislabels_button.setText("Find Potential Mislabels")
|
133
|
-
self.find_mislabels_button.setPopupMode(QToolButton.MenuButtonPopup)
|
133
|
+
self.find_mislabels_button.setPopupMode(QToolButton.MenuButtonPopup) # Key change for split-button style
|
134
134
|
self.find_mislabels_button.setToolButtonStyle(Qt.ToolButtonTextOnly)
|
135
135
|
self.find_mislabels_button.setStyleSheet(
|
136
136
|
"QToolButton::menu-indicator {"
|
@@ -186,9 +186,18 @@ class EmbeddingViewer(QWidget):
|
|
186
186
|
|
187
187
|
uncertainty_settings_widget.parameters_changed.connect(self.uncertainty_parameters_changed.emit)
|
188
188
|
toolbar_layout.addWidget(self.find_uncertain_button)
|
189
|
-
|
189
|
+
|
190
|
+
# Add a strech and separator
|
190
191
|
toolbar_layout.addStretch()
|
191
|
-
|
192
|
+
toolbar_layout.addWidget(self._create_separator())
|
193
|
+
|
194
|
+
# Center on selection button
|
195
|
+
self.center_on_selection_button = QPushButton()
|
196
|
+
self.center_on_selection_button.setIcon(get_icon("target.png"))
|
197
|
+
self.center_on_selection_button.setToolTip("Center view on selected point(s)")
|
198
|
+
self.center_on_selection_button.clicked.connect(self.center_on_selection)
|
199
|
+
toolbar_layout.addWidget(self.center_on_selection_button)
|
200
|
+
|
192
201
|
# Home button to reset view
|
193
202
|
self.home_button = QPushButton()
|
194
203
|
self.home_button.setIcon(get_icon("home.png"))
|
@@ -258,6 +267,7 @@ class EmbeddingViewer(QWidget):
|
|
258
267
|
|
259
268
|
self.find_mislabels_button.setEnabled(points_exist)
|
260
269
|
self.find_uncertain_button.setEnabled(points_exist and self.is_uncertainty_analysis_available)
|
270
|
+
self.center_on_selection_button.setEnabled(points_exist and selection_exists)
|
261
271
|
|
262
272
|
if self.isolated_mode:
|
263
273
|
self.isolate_button.hide()
|
@@ -270,12 +280,46 @@ class EmbeddingViewer(QWidget):
|
|
270
280
|
def reset_view(self):
|
271
281
|
"""Reset the view to fit all embedding points."""
|
272
282
|
self.fit_view_to_points()
|
283
|
+
|
284
|
+
def center_on_selection(self):
|
285
|
+
"""Centers the view on selected point(s) or maintains the current view if no points are selected."""
|
286
|
+
selected_items = self.graphics_scene.selectedItems()
|
287
|
+
if not selected_items:
|
288
|
+
# No selection, show a message
|
289
|
+
QMessageBox.information(self, "No Selection", "Please select one or more points first.")
|
290
|
+
return
|
291
|
+
|
292
|
+
# Create a bounding rect that encompasses all selected points
|
293
|
+
selection_rect = None
|
294
|
+
|
295
|
+
for item in selected_items:
|
296
|
+
if isinstance(item, EmbeddingPointItem):
|
297
|
+
# Get the item's bounding rect in scene coordinates
|
298
|
+
item_rect = item.sceneBoundingRect()
|
299
|
+
|
300
|
+
# Add padding around the point for better visibility
|
301
|
+
padding = 50 # pixels
|
302
|
+
item_rect = item_rect.adjusted(-padding, -padding, padding, padding)
|
303
|
+
|
304
|
+
if selection_rect is None:
|
305
|
+
selection_rect = item_rect
|
306
|
+
else:
|
307
|
+
selection_rect = selection_rect.united(item_rect)
|
308
|
+
|
309
|
+
if selection_rect:
|
310
|
+
# Add extra margin for better visibility
|
311
|
+
margin = 20
|
312
|
+
selection_rect = selection_rect.adjusted(-margin, -margin, margin, margin)
|
313
|
+
|
314
|
+
# Fit the view to the selection rect
|
315
|
+
self.graphics_view.fitInView(selection_rect, Qt.KeepAspectRatio)
|
273
316
|
|
274
317
|
def show_placeholder(self):
|
275
318
|
"""Show the placeholder message and hide the graphics view."""
|
276
319
|
self.graphics_view.setVisible(False)
|
277
320
|
self.placeholder_label.setVisible(True)
|
278
321
|
self.home_button.setEnabled(False)
|
322
|
+
self.center_on_selection_button.setEnabled(False) # Disable center button
|
279
323
|
self.find_mislabels_button.setEnabled(False)
|
280
324
|
self.find_uncertain_button.setEnabled(False)
|
281
325
|
|
@@ -346,6 +390,39 @@ class EmbeddingViewer(QWidget):
|
|
346
390
|
|
347
391
|
def mousePressEvent(self, event):
|
348
392
|
"""Handle mouse press for selection (point or rubber band) and panning."""
|
393
|
+
# Ctrl+Right-Click for context menu selection
|
394
|
+
if event.button() == Qt.RightButton and event.modifiers() == Qt.ControlModifier:
|
395
|
+
item_at_pos = self.graphics_view.itemAt(event.pos())
|
396
|
+
if isinstance(item_at_pos, EmbeddingPointItem):
|
397
|
+
# 1. Clear all selections in both viewers
|
398
|
+
self.graphics_scene.clearSelection()
|
399
|
+
item_at_pos.setSelected(True)
|
400
|
+
self.on_selection_changed() # Updates internal state and emits signals
|
401
|
+
|
402
|
+
# 2. Sync annotation viewer selection
|
403
|
+
ann_id = item_at_pos.data_item.annotation.id
|
404
|
+
self.explorer_window.annotation_viewer.render_selection_from_ids({ann_id})
|
405
|
+
|
406
|
+
# 3. Update annotation window (set image, select, center)
|
407
|
+
explorer = self.explorer_window
|
408
|
+
annotation = item_at_pos.data_item.annotation
|
409
|
+
image_path = annotation.image_path
|
410
|
+
|
411
|
+
if hasattr(explorer, 'annotation_window'):
|
412
|
+
if explorer.annotation_window.current_image_path != image_path:
|
413
|
+
if hasattr(explorer.annotation_window, 'set_image'):
|
414
|
+
explorer.annotation_window.set_image(image_path)
|
415
|
+
if hasattr(explorer.annotation_window, 'select_annotation'):
|
416
|
+
explorer.annotation_window.select_annotation(annotation)
|
417
|
+
if hasattr(explorer.annotation_window, 'center_on_annotation'):
|
418
|
+
explorer.annotation_window.center_on_annotation(annotation)
|
419
|
+
|
420
|
+
explorer.update_label_window_selection()
|
421
|
+
explorer.update_button_states()
|
422
|
+
event.accept()
|
423
|
+
return
|
424
|
+
|
425
|
+
# Handle left-click for selection or rubber band
|
349
426
|
if event.button() == Qt.LeftButton and event.modifiers() == Qt.ControlModifier:
|
350
427
|
item_at_pos = self.graphics_view.itemAt(event.pos())
|
351
428
|
if isinstance(item_at_pos, EmbeddingPointItem):
|
@@ -701,6 +778,14 @@ class AnnotationViewer(QScrollArea):
|
|
701
778
|
explorer = self.explorer_window
|
702
779
|
image_path = widget.annotation.image_path
|
703
780
|
annotation_to_select = widget.annotation
|
781
|
+
|
782
|
+
# ctrl+right click to only select this annotation (single selection):
|
783
|
+
self.clear_selection()
|
784
|
+
self.select_widget(widget)
|
785
|
+
changed_ids = [widget.data_item.annotation.id]
|
786
|
+
|
787
|
+
if changed_ids:
|
788
|
+
self.selection_changed.emit(changed_ids)
|
704
789
|
|
705
790
|
if hasattr(explorer, 'annotation_window'):
|
706
791
|
# Check if the image needs to be changed
|
@@ -710,15 +795,17 @@ class AnnotationViewer(QScrollArea):
|
|
710
795
|
|
711
796
|
# Now, select the annotation in the annotation_window
|
712
797
|
if hasattr(explorer.annotation_window, 'select_annotation'):
|
713
|
-
# This method by default unselects other annotations
|
714
798
|
explorer.annotation_window.select_annotation(annotation_to_select)
|
799
|
+
|
800
|
+
# Center the annotation window view on the selected annotation
|
801
|
+
if hasattr(explorer.annotation_window, 'center_on_annotation'):
|
802
|
+
explorer.annotation_window.center_on_annotation(annotation_to_select)
|
715
803
|
|
716
804
|
# Also clear any existing selection in the explorer window itself
|
717
|
-
explorer.
|
718
|
-
explorer.embedding_viewer.render_selection_from_ids(set())
|
805
|
+
explorer.embedding_viewer.render_selection_from_ids({widget.data_item.annotation.id})
|
719
806
|
explorer.update_label_window_selection()
|
720
807
|
explorer.update_button_states()
|
721
|
-
|
808
|
+
|
722
809
|
event.accept()
|
723
810
|
|
724
811
|
@pyqtSlot()
|
@@ -982,6 +1069,8 @@ class AnnotationViewer(QScrollArea):
|
|
982
1069
|
|
983
1070
|
self.recalculate_widget_positions()
|
984
1071
|
self._update_toolbar_state()
|
1072
|
+
# Update the label window with the new annotation count
|
1073
|
+
self.explorer_window.main_window.label_window.update_annotation_count()
|
985
1074
|
|
986
1075
|
def resizeEvent(self, event):
|
987
1076
|
"""On window resize, reflow the annotation widgets."""
|
@@ -1027,11 +1116,17 @@ class AnnotationViewer(QScrollArea):
|
|
1027
1116
|
break
|
1028
1117
|
widget = widget.parent()
|
1029
1118
|
|
1030
|
-
# If click is outside widgets
|
1031
|
-
if not is_on_widget
|
1032
|
-
|
1033
|
-
self.
|
1034
|
-
|
1119
|
+
# If click is outside widgets, clear annotation_window selection
|
1120
|
+
if not is_on_widget:
|
1121
|
+
# Clear annotation selection in the annotation_window as well
|
1122
|
+
if hasattr(self.explorer_window, 'annotation_window') and self.explorer_window.annotation_window:
|
1123
|
+
if hasattr(self.explorer_window.annotation_window, 'unselect_annotations'):
|
1124
|
+
self.explorer_window.annotation_window.unselect_annotations()
|
1125
|
+
# If there is a selection in the viewer, clear it
|
1126
|
+
if self.selected_widgets:
|
1127
|
+
changed_ids = [w.data_item.annotation.id for w in self.selected_widgets]
|
1128
|
+
self.clear_selection()
|
1129
|
+
self.selection_changed.emit(changed_ids)
|
1035
1130
|
return
|
1036
1131
|
|
1037
1132
|
elif event.modifiers() == Qt.ControlModifier:
|
@@ -1371,6 +1466,7 @@ class ExplorerWindow(QMainWindow):
|
|
1371
1466
|
|
1372
1467
|
self.device = main_window.device
|
1373
1468
|
self.loaded_model = None
|
1469
|
+
self.loaded_model_imgsz = 128
|
1374
1470
|
|
1375
1471
|
self.feature_store = FeatureStore()
|
1376
1472
|
|
@@ -1724,13 +1820,15 @@ class ExplorerWindow(QMainWindow):
|
|
1724
1820
|
"""
|
1725
1821
|
Identifies annotations whose label does not match the majority of its
|
1726
1822
|
k-nearest neighbors in the high-dimensional feature space.
|
1823
|
+
Skips any annotation or neighbor with an invalid label (id == -1).
|
1727
1824
|
"""
|
1728
1825
|
# Get parameters from the stored property instead of hardcoding
|
1729
1826
|
K = self.mislabel_params.get('k', 5)
|
1730
1827
|
agreement_threshold = self.mislabel_params.get('threshold', 0.6)
|
1731
1828
|
|
1732
1829
|
if not self.embedding_viewer.points_by_id or len(self.embedding_viewer.points_by_id) < K:
|
1733
|
-
QMessageBox.information(self,
|
1830
|
+
QMessageBox.information(self,
|
1831
|
+
"Not Enough Data",
|
1734
1832
|
f"This feature requires at least {K} points in the embedding viewer.")
|
1735
1833
|
return
|
1736
1834
|
|
@@ -1741,7 +1839,6 @@ class ExplorerWindow(QMainWindow):
|
|
1741
1839
|
model_info = self.model_settings_widget.get_selected_model()
|
1742
1840
|
model_name, feature_mode = model_info if isinstance(model_info, tuple) else (model_info, "default")
|
1743
1841
|
sanitized_model_name = os.path.basename(model_name).replace(' ', '_')
|
1744
|
-
# FIX: Also replace the forward slash to handle "N/A"
|
1745
1842
|
sanitized_feature_mode = feature_mode.replace(' ', '_').replace('/', '_')
|
1746
1843
|
model_key = f"{sanitized_model_name}_{sanitized_feature_mode}"
|
1747
1844
|
|
@@ -1751,13 +1848,17 @@ class ExplorerWindow(QMainWindow):
|
|
1751
1848
|
index = self.feature_store._get_or_load_index(model_key)
|
1752
1849
|
faiss_idx_to_ann_id = self.feature_store.get_faiss_index_to_annotation_id_map(model_key)
|
1753
1850
|
if index is None or not faiss_idx_to_ann_id:
|
1754
|
-
QMessageBox.warning(self,
|
1851
|
+
QMessageBox.warning(self,
|
1852
|
+
"Error",
|
1853
|
+
"Could not find a valid feature index for the current model.")
|
1755
1854
|
return
|
1756
1855
|
|
1757
1856
|
# Get the high-dimensional features for the points in the current view
|
1758
1857
|
features_dict, _ = self.feature_store.get_features(data_items_in_view, model_key)
|
1759
1858
|
if not features_dict:
|
1760
|
-
QMessageBox.warning(self,
|
1859
|
+
QMessageBox.warning(self,
|
1860
|
+
"Error",
|
1861
|
+
"Could not retrieve features for the items in view.")
|
1761
1862
|
return
|
1762
1863
|
|
1763
1864
|
query_ann_ids = list(features_dict.keys())
|
@@ -1768,25 +1869,33 @@ class ExplorerWindow(QMainWindow):
|
|
1768
1869
|
|
1769
1870
|
mislabeled_ann_ids = []
|
1770
1871
|
for i, ann_id in enumerate(query_ann_ids):
|
1771
|
-
|
1772
|
-
|
1872
|
+
data_item = self.data_item_cache[ann_id]
|
1873
|
+
# Use preview_label if present, else effective_label
|
1874
|
+
label_obj = getattr(data_item, "preview_label", None) or data_item.effective_label
|
1875
|
+
current_label_id = getattr(label_obj, "id", "-1")
|
1876
|
+
if current_label_id == "-1":
|
1877
|
+
continue # Skip if label is invalid
|
1878
|
+
|
1773
1879
|
# Get neighbor labels, ignoring the first result (the point itself)
|
1774
1880
|
neighbor_faiss_indices = I[i][1:]
|
1775
|
-
|
1881
|
+
|
1776
1882
|
neighbor_labels = []
|
1777
1883
|
for n_idx in neighbor_faiss_indices:
|
1778
|
-
# THIS IS THE CORRECTED LOGIC
|
1779
1884
|
if n_idx in faiss_idx_to_ann_id:
|
1780
1885
|
neighbor_ann_id = faiss_idx_to_ann_id[n_idx]
|
1781
|
-
# ADD THIS CHECK to ensure the neighbor hasn't been deleted
|
1782
1886
|
if neighbor_ann_id in self.data_item_cache:
|
1783
|
-
|
1887
|
+
neighbor_item = self.data_item_cache[neighbor_ann_id]
|
1888
|
+
neighbor_label_obj = getattr(neighbor_item, "preview_label", None)
|
1889
|
+
if neighbor_label_obj is None:
|
1890
|
+
neighbor_label_obj = neighbor_item.effective_label
|
1891
|
+
neighbor_label_id = getattr(neighbor_label_obj, "id", "-1")
|
1892
|
+
if neighbor_label_id != "-1":
|
1893
|
+
neighbor_labels.append(neighbor_label_id)
|
1784
1894
|
|
1785
1895
|
if not neighbor_labels:
|
1786
1896
|
continue
|
1787
1897
|
|
1788
|
-
|
1789
|
-
num_matching_neighbors = neighbor_labels.count(current_label)
|
1898
|
+
num_matching_neighbors = neighbor_labels.count(current_label_id)
|
1790
1899
|
agreement_ratio = num_matching_neighbors / len(neighbor_labels)
|
1791
1900
|
|
1792
1901
|
if agreement_ratio < agreement_threshold:
|
@@ -2031,16 +2140,36 @@ class ExplorerWindow(QMainWindow):
|
|
2031
2140
|
print(f"Model or mode changed. Reloading {model_name} for '{feature_mode}'.")
|
2032
2141
|
try:
|
2033
2142
|
model = YOLO(model_name)
|
2143
|
+
|
2144
|
+
# Check if the model task is compatible with the selected feature mode
|
2145
|
+
if model.task != 'classify' and feature_mode == "Predictions":
|
2146
|
+
QMessageBox.warning(self,
|
2147
|
+
"Invalid Mode for Model",
|
2148
|
+
f"The selected model is a '{model.task}' model. "
|
2149
|
+
"The 'Predictions' feature mode is only available for 'classify' models. "
|
2150
|
+
"Reverting to 'Embed Features' mode.")
|
2151
|
+
|
2152
|
+
# Force the feature mode combo box back to "Embed Features"
|
2153
|
+
self.model_settings_widget.feature_mode_combo.setCurrentText("Embed Features")
|
2154
|
+
|
2155
|
+
# On failure, reset the model cache
|
2156
|
+
self.loaded_model = None
|
2157
|
+
self.current_feature_generating_model = None
|
2158
|
+
return None, None
|
2159
|
+
|
2034
2160
|
# Update the cache key to the new successful combination
|
2035
2161
|
self.current_feature_generating_model = current_run_key
|
2036
2162
|
self.loaded_model = model
|
2037
|
-
|
2163
|
+
|
2164
|
+
# Get the imgsz, but if it's larger than 128, default to 128
|
2165
|
+
imgsz = min(getattr(model.model.args, 'imgsz', 128), 128)
|
2166
|
+
self.loaded_model_imgsz = imgsz
|
2038
2167
|
|
2039
2168
|
# Warm up the model
|
2040
2169
|
dummy_image = np.zeros((imgsz, imgsz, 3), dtype=np.uint8)
|
2041
2170
|
model.predict(dummy_image, imgsz=imgsz, half=True, device=self.device, verbose=False)
|
2042
2171
|
|
2043
|
-
return model,
|
2172
|
+
return model, self.loaded_model_imgsz
|
2044
2173
|
|
2045
2174
|
except Exception as e:
|
2046
2175
|
print(f"ERROR: Could not load YOLO model '{model_name}': {e}")
|
@@ -2049,8 +2178,8 @@ class ExplorerWindow(QMainWindow):
|
|
2049
2178
|
self.current_feature_generating_model = None
|
2050
2179
|
return None, None
|
2051
2180
|
|
2052
|
-
# Model already loaded and cached
|
2053
|
-
return self.loaded_model,
|
2181
|
+
# Model already loaded and cached, return it and its image size
|
2182
|
+
return self.loaded_model, self.loaded_model_imgsz
|
2054
2183
|
|
2055
2184
|
def _prepare_images_from_data_items(self, data_items, progress_bar=None):
|
2056
2185
|
"""
|
@@ -2488,6 +2617,10 @@ class ExplorerWindow(QMainWindow):
|
|
2488
2617
|
# Reset sort options when filters change
|
2489
2618
|
self.annotation_viewer.active_ordered_ids = []
|
2490
2619
|
self.annotation_viewer.set_confidence_sort_availability(False)
|
2620
|
+
|
2621
|
+
# Update the annotation count in the label window
|
2622
|
+
self.label_window.update_annotation_count()
|
2623
|
+
|
2491
2624
|
finally:
|
2492
2625
|
QApplication.restoreOverrideCursor()
|
2493
2626
|
|
Binary file
|
@@ -660,6 +660,10 @@ class Base(QDialog):
|
|
660
660
|
QMessageBox.warning(self, "Import Warning", "The YAML file appears to be empty or invalid.")
|
661
661
|
return
|
662
662
|
|
663
|
+
# For backward compatibility, check if the old nested 'parameters' key exists.
|
664
|
+
# If not, use the whole data dictionary.
|
665
|
+
params_to_load = data.get('parameters', data)
|
666
|
+
|
663
667
|
# Helper function to infer type from value
|
664
668
|
def infer_type_and_value(value):
|
665
669
|
"""
|
@@ -673,12 +677,9 @@ class Base(QDialog):
|
|
673
677
|
elif isinstance(value, float):
|
674
678
|
return "float", value
|
675
679
|
elif isinstance(value, str):
|
676
|
-
# Check for boolean strings
|
677
680
|
if value.lower() in ['true', 'false']:
|
678
681
|
return "bool", value.lower() == 'true'
|
679
|
-
# Check for numeric strings
|
680
682
|
try:
|
681
|
-
# Try to convert to int first
|
682
683
|
if '.' not in value:
|
683
684
|
return "int", int(value)
|
684
685
|
else:
|
@@ -686,14 +687,13 @@ class Base(QDialog):
|
|
686
687
|
except ValueError:
|
687
688
|
return "string", value
|
688
689
|
else:
|
689
|
-
# For any other type, convert to string
|
690
690
|
return "string", str(value)
|
691
691
|
|
692
692
|
# Clear existing custom parameters before importing
|
693
693
|
while self.custom_params:
|
694
694
|
self.remove_parameter_pair()
|
695
695
|
|
696
|
-
# Map parameters to UI controls
|
696
|
+
# Map standard parameters to their UI controls
|
697
697
|
param_mapping = {
|
698
698
|
'epochs': self.epochs_spinbox,
|
699
699
|
'patience': self.patience_spinbox,
|
@@ -712,37 +712,31 @@ class Base(QDialog):
|
|
712
712
|
}
|
713
713
|
|
714
714
|
# Update UI controls with imported values
|
715
|
-
for param_name, value in
|
715
|
+
for param_name, value in params_to_load.items():
|
716
716
|
param_type, converted_value = infer_type_and_value(value)
|
717
717
|
|
718
718
|
if param_name in param_mapping:
|
719
719
|
widget = param_mapping[param_name]
|
720
720
|
|
721
721
|
if isinstance(widget, QSpinBox):
|
722
|
-
if
|
722
|
+
if isinstance(converted_value, (int, float)):
|
723
723
|
widget.setValue(int(converted_value))
|
724
724
|
elif isinstance(widget, QDoubleSpinBox):
|
725
|
-
if
|
725
|
+
if isinstance(converted_value, (int, float)):
|
726
726
|
widget.setValue(float(converted_value))
|
727
727
|
elif isinstance(widget, QComboBox):
|
728
728
|
if param_name in ['multi_scale', 'save', 'weighted', 'val', 'verbose']:
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
else:
|
733
|
-
# String parameters like optimizer
|
734
|
-
if str(converted_value) in [widget.itemText(i) for i in range(widget.count())]:
|
735
|
-
widget.setCurrentText(str(converted_value))
|
729
|
+
widget.setCurrentText("True" if converted_value else "False")
|
730
|
+
elif str(converted_value) in [widget.itemText(i) for i in range(widget.count())]:
|
731
|
+
widget.setCurrentText(str(converted_value))
|
736
732
|
else:
|
737
|
-
# Add as custom parameter
|
733
|
+
# Add as a custom parameter
|
738
734
|
self.add_parameter_pair()
|
739
|
-
|
740
|
-
param_name_widget, param_value_widget, param_type_widget = param_widgets
|
735
|
+
param_name_widget, param_value_widget, param_type_widget = self.custom_params[-1]
|
741
736
|
|
742
737
|
param_name_widget.setText(param_name)
|
743
738
|
param_type_widget.setCurrentText(param_type)
|
744
739
|
|
745
|
-
# Set value based on type
|
746
740
|
if param_type == "bool":
|
747
741
|
param_value_widget.setText("True" if converted_value else "False")
|
748
742
|
else:
|
@@ -750,14 +744,14 @@ class Base(QDialog):
|
|
750
744
|
|
751
745
|
QMessageBox.information(self,
|
752
746
|
"Import Success",
|
753
|
-
"Parameters successfully imported with automatic type inference")
|
747
|
+
"Parameters successfully imported with automatic type inference.")
|
754
748
|
|
755
749
|
except Exception as e:
|
756
750
|
QMessageBox.critical(self, "Import Error", f"Failed to import parameters: {str(e)}")
|
757
751
|
|
758
752
|
def export_parameters(self):
|
759
753
|
"""
|
760
|
-
Export current parameters to a YAML file
|
754
|
+
Export current parameters to a flat YAML file.
|
761
755
|
"""
|
762
756
|
file_path, _ = QFileDialog.getSaveFileName(self,
|
763
757
|
"Export Parameters to YAML",
|
@@ -767,69 +761,56 @@ class Base(QDialog):
|
|
767
761
|
return
|
768
762
|
|
769
763
|
try:
|
770
|
-
#
|
771
|
-
export_data = {
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
'weighted': ('bool', self.weighted_combo.currentText() == "True"),
|
789
|
-
'val': ('bool', self.val_combo.currentText() == "True"),
|
790
|
-
'verbose': ('bool', self.verbose_combo.currentText() == "True"),
|
791
|
-
'optimizer': ('string', self.optimizer_combo.currentText())
|
792
|
-
}
|
793
|
-
|
794
|
-
# Add standard parameters
|
795
|
-
for param_name, (param_type, value) in standard_params.items():
|
796
|
-
export_data['types'][param_name] = param_type
|
797
|
-
export_data['parameters'][param_name] = value
|
764
|
+
# Use a single flat dictionary for export
|
765
|
+
export_data = {}
|
766
|
+
|
767
|
+
# Standard parameters
|
768
|
+
export_data['epochs'] = self.epochs_spinbox.value()
|
769
|
+
export_data['patience'] = self.patience_spinbox.value()
|
770
|
+
export_data['imgsz'] = self.imgsz_spinbox.value()
|
771
|
+
export_data['batch'] = self.batch_spinbox.value()
|
772
|
+
export_data['workers'] = self.workers_spinbox.value()
|
773
|
+
export_data['save_period'] = self.save_period_spinbox.value()
|
774
|
+
export_data['freeze_layers'] = self.freeze_layers_spinbox.value()
|
775
|
+
export_data['dropout'] = self.dropout_spinbox.value()
|
776
|
+
export_data['multi_scale'] = self.multi_scale_combo.currentText() == "True"
|
777
|
+
export_data['save'] = self.save_combo.currentText() == "True"
|
778
|
+
export_data['weighted'] = self.weighted_combo.currentText() == "True"
|
779
|
+
export_data['val'] = self.val_combo.currentText() == "True"
|
780
|
+
export_data['verbose'] = self.verbose_combo.currentText() == "True"
|
781
|
+
export_data['optimizer'] = self.optimizer_combo.currentText()
|
798
782
|
|
799
783
|
# Custom parameters
|
800
784
|
for param_info in self.custom_params:
|
801
|
-
|
802
|
-
name =
|
803
|
-
|
804
|
-
type_name =
|
785
|
+
param_name_widget, param_value_widget, param_type_widget = param_info
|
786
|
+
name = param_name_widget.text().strip()
|
787
|
+
value_str = param_value_widget.text().strip()
|
788
|
+
type_name = param_type_widget.currentText()
|
805
789
|
|
806
|
-
if name and
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
export_data['parameters'][name] = value
|
825
|
-
|
826
|
-
# Write to YAML file
|
790
|
+
if name and value_str:
|
791
|
+
# Convert value to the correct type before exporting
|
792
|
+
try:
|
793
|
+
if type_name == "bool":
|
794
|
+
value = value_str.lower() == "true"
|
795
|
+
elif type_name == "int":
|
796
|
+
value = int(value_str)
|
797
|
+
elif type_name == "float":
|
798
|
+
value = float(value_str)
|
799
|
+
else: # string type
|
800
|
+
value = value_str
|
801
|
+
export_data[name] = value
|
802
|
+
except ValueError:
|
803
|
+
# If conversion fails, save it as a string
|
804
|
+
print(f"Warning: Could not convert '{value_str}' to {type_name} for parameter '{name}'. Saving as string.")
|
805
|
+
export_data[name] = value_str
|
806
|
+
|
807
|
+
# Write the flat dictionary to the YAML file
|
827
808
|
with open(file_path, 'w') as f:
|
828
|
-
yaml.dump(export_data, f, default_flow_style=False, indent=2)
|
809
|
+
yaml.dump(export_data, f, default_flow_style=False, sort_keys=False, indent=2)
|
829
810
|
|
830
811
|
QMessageBox.information(self,
|
831
812
|
"Export Success",
|
832
|
-
"Parameters successfully exported")
|
813
|
+
"Parameters successfully exported.")
|
833
814
|
|
834
815
|
except Exception as e:
|
835
816
|
QMessageBox.critical(self,
|