diff --git a/.gitignore b/.gitignore
index eedfc72..c4cc3b8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,15 @@
 model-weights/
 test_img/
+napari_organoid_counter/experiments
+napari_organoid_counter/timing_logs
+notebooks/
+data/
+onnx/
+data/
+notebooks/
 
 # Byte-compiled / optimized / DLL files
-__pycache__/
+*/__pycache__/
 *.py[cod]
 *$py.class
 
diff --git a/.napari/DESCRIPTION.md b/.napari/DESCRIPTION.md
index da6cb33..a2d0cbd 100644
--- a/.napari/DESCRIPTION.md
+++ b/.napari/DESCRIPTION.md
@@ -1,18 +1,24 @@
 ## Description
 
-A napari plugin to automatically count lung organoids from microscopy imaging data. Several object detection DL models were trained on patches of 2D microscopy data. Model inference is run using a sliding window approach, with a 50% overlap and the option for predicting on multiple window sizes and scales, the results of which are then merged using NMS.
+A napari plugin to automatically count lung organoids from microscopy imaging data. Several deep learning (DL) models were trained on patches of 2D microscopy data—some for object detection only, and one for both detection and binary classification. Model inference is run using a sliding window approach, with a 50% overlap and the option for predicting on multiple window sizes and scales, the results of which are then merged using NMS.
 
-![Alt Text](https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter/blob/main/readme-content/demo-plugin-v2.gif)
+## What's new in v3?
+Here is a list of the main changes v3 of napari-organoid-counter offers:
 
-## What's new in v2?
-Here is a list of the main changes v2 of napari-organoid-counter offers:
-* Use of DL models for object detection - pretrained models: Faster R-CNN, YOLOv3, SSD, and RTMDet. The data used for training these models along with the code for training can be found [here](https://www.kaggle.com/datasets/christinabukas/mutliorg).
-* Pyramid model inference with a sliding window approach and tunable parameters for window size and window downsampling rate
-* Model confidence added as tunable parameter
-* Allow to load and correct existing annotations (note: these must have been saved previously from v2 of this plugin)
-* Object ID along with model confidence displayed in the viewer - this can now be related to box id in csv file of extracted features
-* _Fixed:_ box thickness changing at different donwsampling rates
-* Possibility to work interactively with different shape layers at the same time, go back adjust parameters and switch between shape layers from layer list selection
+Support for multiple DL models: 
+
+* **Object Detection Only (DO)** - pretrained models: Faster R-CNN (DO), YOLOv3 (DO), SSD (DO), and RTMDet (DO). The data used for training these models along with the code for training can be found [here](https://www.kaggle.com/datasets/christinabukas/mutliorg).
+
+* **Detection and Binary Classification (BC)** - pretrained models: Currently, YOLOv3 (BC) is supported, which not only detects organoids but also differentiates between two types of organoids (Class 0 and Class 1). Class 0 organoids are represented with Green and Class 1 with Blue. Bounding boxes for low confidence predictions will remain in Magenta.
+
+* **Pyramid Model Inference** – Run inference using a sliding window approach, with tunable parameters for window size and downsampling rate.
+* **Model Confidence** – A new tunable parameter to adjust and refine predictions based on confidence levels.
+* **Annotation of Up to 10 Classes** – You can now annotate up to 10 different organoid classes, each with a unique color. Bounding box colors for each class can be adjusted using key bindings (see [Quickstart guide](https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter/blob/ten_classes_annotation/.napari/DESCRIPTION.md#quickstart) for details).
+* **Saving Annotations with Class Labels** – When saving annotations, the class label is recorded in the .json file based on the bounding box color.
+* **Load and Correct Existing Annotations** – You can now load and modify previously saved annotations (note: these must have been saved using v3 of the plugin).
+* **Improved Readability** – Only model confidence is displayed in the viewer for better readability.
+* **Bug Fixed** – Fixed an issue where box thickness varied at different downsampling rates.
+* **Interactive Workflow** – Work seamlessly with multiple shape layers, adjusting parameters and switching between layers as needed.
 
 Technical Extensions:
 * Allows for Python 3.10
@@ -34,29 +40,79 @@ This plugin has been tested with python 3.9 and 3.10 - you may consider using co
 
   ``` mim install "mmcv<2.2.0,>=2.0.0rc4" ```
 
-For installing on a Windows machine directly from within napari, follow the instuctions [here](https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter/blob/main/readme-content/How%20to%20install%20on%20a%20Windows%20machine.pdf). Step 2 additionally needs to be performed here too (mim install "mmcv<2.2.0,>=2.0.0rc4").
+**Note:** mmcv requires **Microsoft Visual Studio 2022 Build Tools**. Download and install Visual Studio Build Tools here https://visualstudio.microsoft.com/es/visual-cpp-build-tools/ and make sure to select **"Desktop development with C++"** option: 
+
+![Visual Studio Build Tools](https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter/blob/ten_classes_annotation/readme-content/visual_studio_build_tools.png)
+
+For installing on a Windows machine directly from within napari, follow the instuctions [here](https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter/blob/ten_classes_annotation/readme-content/How%20to%20install%20on%20a%20Windows%20machine.pdf). Step 2 additionally needs to be performed here too (mim install "mmcv<2.2.0,>=2.0.0rc4").
 
 ## Quickstart
 
 After installation, you can start napari (either by typing ```napari``` in your terminal or by launching the application) and select the plugin from the drop down menu.
 
 The use of the napari-organoid-counter plugin is straightforward. Here is a step-to-step guide of the standard workflow:
-1. You can load the image or images you wish to process into the napari viewer with a simple drag and drop
-2. You can then select the layer you wish to work on by the drop-down box at the top of the input configurations
-3. To improve the way the image is visualised you can pre-process them by clicking the _Preprocess_ button and the image layer will automatically be updated with the result
-4. If you have a Faster R-CNN model you wish to use for the prediction, you can browser and select this by clicking on the _Choose_ button. Otherwise, the default model will be automatically downloaded from [here](https://zenodo.org/record/7708763#.ZDe6pS8Rpqs). Note that your own model must follow the specifications described here _(TODO)_.
-5. You can adjust the _Window sizes_ and _Downsampling_ parameters to define the window size in the sliding window inference and the downsampling that is performed on the image. If you have multiple objects with different sizes, it might be good to set multiple window sizes, with corresponding downsampling rates. You can seperate these with a comma in the text box (e.g. ```2048, 512```). After you have set _Window sizes_ and _Downsampling_ hit **Enter** for each for the changes to be accepted. 
 
-**_Downsampling parameter:_** To detect large organoids (and ignore smaller structures) you may need to increase the downsampling rate, whereas if your organoids are small and are being missed by the algorithm, consider reducing the downsampling rate. 
+**1. Load and Select an Image**
+* Drag and drop the image(s) you wish to process into the napari viewer.
+* Select the layer you want to work on using the drop-down box at the top of the input configurations.
+
+**2. Preprocessing (Optional)**
+* To improve the way the image is visualised you can pre-process them by clicking the _Preprocess_ button and the image layer will automatically be updated with the result.
+
+**3. Model Selection**
+
+You can use either:
+* Your own model: If you have a Faster R-CNN model you wish to use for the prediction, you can browser and select this by clicking on the _Choose_ button..
+* Pre-trained models: The plugin provides the following models, automatically downloaded if needed.
+
+* **Detection Only (DO):** Faster R-CNN (DO), YOLOv3 (DO), SSD (DO), RTMDet (DO). These models will be automatically downloaded from Zenodo. Predicted bounding boxes will appear in default color magenta.
+
+* **Binary Classification (BC):** YOLOv3 (BC). This model is also automatically downloaded from Zenodo. It predicts bounding boxes and classifies organoids as Green (Class 0) or Blue (Class 1), while low confidence cases remain in Magenta.
+
+**4. Annotation Mode & Model Constraints**
+* If a DO model is selected, all annotations modes are available.
+* If a BC model is selected, the DO annotation mode is disabled. If you attempt to run the detection by clicking _Run Organoid Counter_, the following error message will appear.
+
+![Error Model and Annotation Mode Mismatch](https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter/blob/ten_classes_annotation/readme-content/warning_BC_model_DO_annotation.png)
+
+**5. Adjust Model Parameters**
+You can adjust the _Window sizes_ and _Downsampling_ parameters to define the window size in the sliding window inference and the downsampling that is performed on the image. If you have multiple objects with different sizes, it might be good to set multiple window sizes, with corresponding downsampling rates. You can seperate these with a comma in the text box (e.g. ```2048, 512```). After you have set _Window sizes_ and _Downsampling_ hit **Enter** for each for the changes to be accepted. 
+* **_Downsampling parameter:_** To detect large organoids (and ignore smaller structures) you may need to increase the downsampling rate, whereas if your organoids are small and are being missed by the algorithm, consider reducing the downsampling rate. 
+* **_Window size parameter:_** The window size can also impact the number of objects detected: typically a ratio of 512 to 1 between window size and downsampling rate would give optimal results, while larger window sizes would lead to a drop in performance. However, please note that small window sizes will signicantly impact the runtime of the algorithm.
+
+**6. Running the Organoid Counter**
+
+By clicking the _Run Organoid Counter_ button the detection algorithm will run and a new shapes layer will be added to the viewer, with bounding boxes are placed around the detected organoid. 
+
+**7. Correcting & Annotating Bounding Boxes**
+* You can add, edit or remove boxes using the _layer controls_ window (top left). Make sure the _Select vertices_ tool is clicked to select bounding boxes. 
+* Multiple bounding boxes can be selected at the same time holding _Shift_ and clicking on the bounding boxes. 
+* The _Number of detected organoids_ will show you the number of organoids in the layer in real time. 
+* You can switch between viewing the model confidence for each box by toggling the _display text_ box in the _layer controls_ window. Boxes added by the user will by default have a confidence of 1.
+* You can choose between different annotation modes and annotate up to 10 classes, based on your preferences. To change the color of the bounding boxes, the following key bindings are assigned for each specific class. 
+
+![Key Bindings](https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter/blob/ten_classes_annotation/readme-content/key-bindings.png)
+
+* When selecting an annotation mode, an information pop-up will appear, displaying the key bindings associated with that specific mode.
+
+![Annotation Mode Info](https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter/blob/ten_classes_annotation/readme-content/annotation_mode_info.png)
+
+* If using an annotation mode (other than DO), you must assign the correct colors before saving. If any bounding boxes are missing a valid class color, a warning appears.
+
+![Valid Colors Warning](https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter/blob/ten_classes_annotation/readme-content/valid_colors_warning.png)
 
-**_Window size parameter:_** The window size can also impact the number of objects detected: typically a ratio of 512 to 1 between window size and downsampling rate would give optimal results, while larger window sizes would lead to a drop in performance. However, please note that small window sizes will signicantly impact the runtime of the algorithm.
+**8. Adjusting Confidence & Object Size Thresholds**
+* If you feel that your model is over- or under-predicting you can use the _Model confidence_ scroll bar and select the value which best suits your problem. Default confidence is set to 0.8.
+* If you objects are typically bigger or smaller than those displayed you can use the _Minimum Diameter_ slider to set the minimum diameter of your objects. Default value is 30 um.
 
-6. By clicking the _Run Organoid Counter_ button the detection algorithm will run and a new shapes layer will be added to the viewer, with bounding boxes are placed around the detected organoid. You can add, edit or remove boxes using the _layer controls_ window (top left). The _Number of detected organoids_ will show you the number of organoids in the layer in real time. You can switch between viewing the box ids and model confidence for each box by toggling the _display text_ box in the _layer controls_ window. Boxes added by the user will by default have a confidence of 1.
-7. If you feel that your model is over- or under-predicting you can use the _Model confidence_ scroll bar and select the value which best suits your problem. Default confidence is set to 0.8.
-8. If you objects are typically bigger or smaller than those displayed you can use the _Minimum Diameter_ slider to set the minimum diameter of your objects. Default value is 30 um.
-9. After you are happy with the detection results (and your manual corrections if any), you can select which shapes layer results to save via the dropdown box. To save the bounding box coordinates (along with the box id, model confidence for that box, and x and y scale for that image) as a json file click _Save boxes_ and select where to save your file. The features can be saved in a csv file by clicking on the _Save features_. The saved features will include the organoid id, the two lengths of the boundig box (which corresponds to the min. and max. diameter of the organoid, approximated as an ellipse), the area of the organoid (again approximated as an ellipse).
-10. Additional options: The _Take Screenshot_ button has the same functionality as _File -> Save screenshot_. The _Reset Configs_ button will reset the image and all parameters to the original settings. To save features of the detected organoids (diameters when approximating organoid as an ellipse and organoid area) in a csv file click _Save features_. 
+**9. Saving Results**
+* After you are happy with the detection results (and your manual corrections if any), you can select which shapes layer results to save via the dropdown box. 
+* _Save boxes_: saves the bounding box coordinates (along with the box id, model confidence for that box, x and y scale for that image, and class labels) as a json file. You can select where to save your file. The class is indicated by the color of the bounding box. In DO mode, class is 'null'. 
+*  _Save features_: saves the features in a csv file. The saved features will include the organoid id, the two lengths of the boundig box (which corresponds to the min. and max. diameter of the organoid, approximated as an ellipse), the area of the organoid (again approximated as an ellipse).
 
+**10. Additional Options**
+* _Take Screenshot_ button has the same functionality as _File -> Save screenshot_. 
+* _Reset Configs_ button will reset the image and all parameters to the original settings. 
 
 ## Getting Help
 
@@ -64,7 +120,7 @@ If you encounter any problems, please [file an issue](https://github.com/Helmhol
 
 ## Intended Audience & Supported Data
 
-This plugin has been developed and tested with 2D CZI microscopy images of lunch organoids. The images have been previously converted from a 3D stack to 2D using an extended focus algorithm. This plugin only supports single channel grayscale images. This plugin may be used as a baseline for developers who wish to extend the plugin to work with other types of input images and/or improve the detection algorithm. 
+This plugin has been developed and tested with 2D CZI microscopy images of lung organoids. The images have been previously converted from a 3D stack to 2D using an extended focus algorithm. This plugin only supports single channel grayscale images. This plugin may be used as a baseline for developers who wish to extend the plugin to work with other types of input images and/or improve the detection algorithm. 
 
 ## Dependencies
 
diff --git a/README.md b/README.md
index b316267..26c5536 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Napari Organoid Counter - Version 0.2 is out! 
+# Napari Organoid Counter - Version 0.3 is out! 
 
 [![napari hub](https://img.shields.io/endpoint?url=https://api.napari-hub.org/shields/napari-organoid-counter)](https://napari-hub.org/plugins/napari-organoid-counter)
 ![stability-stable](https://img.shields.io/badge/stability-stable-green.svg)
@@ -14,7 +14,9 @@ A napari plugin to automatically count lung organoids from microscopy imaging da
 
 ***Hold it for the demo!***
 
-![Alt Text](https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter/blob/main/readme-content/demo-plugin-v2.gif)
+![Alt Text](https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter/blob/ten_classes_annotation/readme-content/demo-plugin-v2.gif)
+
+This demo showcases the features of Version 0.2, while the new functionalities of Version 0.3 are detailed in the "What's New in V3?" section.
 
 ----------------------------------
 
@@ -33,19 +35,15 @@ This plugin has been tested with python 3.9 and 3.10 - you may consider using co
 
     ```pip install git+https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter.git```
 
-2. Additionally, you will then need to install one additional dependency:
-
-     ``` mim install "mmcv<2.2.0,>=2.0.0rc4" ```
-
-For installing on a Windows machine directly from within napari, follow the instuctions [here](https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter/blob/main/readme-content/How%20to%20install%20on%20a%20Windows%20machine.pdf). Step 2 additionally needs to be performed here too (mim install "mmcv<2.2.0,>=2.0.0rc4").
+For installing on a Windows machine directly from within napari, follow the instuctions [here](https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter/blob/ten_classes_annotation/readme-content/How%20to%20install%20on%20a%20Windows%20machine.pdf).
 
-## What's new in v2?
-Checkout our *What's New in v2* [here](https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter/blob/main/.napari/DESCRIPTION.md#whats-new-in-v2).
+## What's new in v3?
+Checkout our *What's New in v3* [here](https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter/blob/ten_classes_annotation/.napari/DESCRIPTION.md#whats-new-in-v3).
 
 ## How to use?
 After installing, you can start napari (either by typing ```napari``` in your terminal or by launching the application) and select the plugin from the drop down menu.
 
-For more information on this plugin, its' intended audience, as well as Quickstart guide go to our [Quickstart guide](https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter/blob/main/.napari/DESCRIPTION.md#quickstart).
+For more information on this plugin, its' intended audience, as well as Quickstart guide go to our [Quickstart guide](https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter/blob/ten_classes_annotation/.napari/DESCRIPTION.md#quickstart).
 
 ## Contributing
 
@@ -66,9 +64,6 @@ Distributed under the terms of the [MIT] license,
 
 [2] Eva Maxfield Brown, Talley Lambert, Peter Sobolewski, Napari-AICSImageIO Contributors (2021). Napari-AICSImageIO: Image Reading in Napari using AICSImageIO [Computer software]. GitHub. https://github.com/AllenCellModeling/napari-aicsimageio
 
-The latest version also uses models developed with the ```mmdetection``` package <sup>[3]</sup>, see [here](https://github.com/open-mmlab/mmdetection)
-
-[3] Chen, Kai, et al. "MMDetection: Open mmlab detection toolbox and benchmark." arXiv preprint arXiv:1906.07155 (2019).
 
 ## Issues
 
@@ -112,4 +107,3 @@ bibtex:
   url          = {https://doi.org/10.5281/zenodo.7859571}
 }
 ```
-
diff --git a/napari_organoid_counter/_orgacount.py b/napari_organoid_counter/_orgacount.py
index 8e655a2..13f4164 100644
--- a/napari_organoid_counter/_orgacount.py
+++ b/napari_organoid_counter/_orgacount.py
@@ -4,10 +4,36 @@ from napari.utils import progress
 from napari_organoid_counter._utils import *
 from napari_organoid_counter import settings
 
-#update_version_in_mmdet_init_file('mmdet', '2.2.0', '2.3.0')
+
+
 import torch
-import mmdet
-from mmdet.apis import DetInferencer
+import onnxruntime as ort
+
+import time
+from contextlib import contextmanager
+import cv2
+
+def get_best_provider():
+    # List all available providers on this machine
+    available_providers = ort.get_available_providers()
+    # print("Available ONNX Runtime providers:", available_providers)
+
+    # Priority order: CUDA > CoreML > CPU
+    if "CUDAExecutionProvider" in available_providers:
+        return "CUDAExecutionProvider"
+    elif "CoreMLExecutionProvider" in available_providers:
+        return "CoreMLExecutionProvider"
+    else:
+        return "CPUExecutionProvider"
+
+@contextmanager
+def profile_section(name, stats_dict):
+    """Context manager for timing code sections"""
+    start = time.perf_counter()
+    yield
+    elapsed = time.perf_counter() - start
+    stats_dict[name] = stats_dict.get(name, 0) + elapsed
+    stats_dict[f"{name}_count"] = stats_dict.get(f"{name}_count", 0) + 1
 
 class OrganoiDL():
     '''
@@ -20,8 +46,10 @@ class OrganoiDL():
             The confidence threshold of the model
         cur_min_diam: float
             The minimum diameter of the organoids
-        model: frcnn
-            The Faster R-CNN model
+        model: ort.InferenceSession
+            The detection model loaded from an onnx checkpoint
+        model_expect_size: tuple
+            The size of the input image the model expects
         img_scale: list of floats
             A list holding the image resolution in x and y
         pred_bboxes: dict
@@ -45,10 +73,19 @@ class OrganoiDL():
         self.cur_confidence = 0.05
         self.cur_min_diam = 30
 
+        self.cancel_requested = False
+
         self.model = None
+        self.model_name = None
+        self.model_expect_size = (416, 416)
+        self.input_name = None
+        self.output_names = None
+        self.mean = np.array([0.0, 0.0, 0.0], dtype=np.float32)
+        self.std = np.array([255.0, 255.0, 255.0], dtype=np.float32)
         self.img_scale = [0., 0.]
         self.pred_bboxes = {}
         self.pred_scores = {}
+        self.pred_labels = {}
         self.pred_ids = {}
         self.next_id = {}
 
@@ -59,15 +96,22 @@ class OrganoiDL():
     def set_model(self, model_name):
         ''' Initialise  model instance and load model checkpoint and send to device. '''
 
+        self.model_name = model_name
         model_checkpoint = join_paths(str(settings.MODELS_DIR), settings.MODELS[model_name]["filename"])
-        mmdet_path = os.path.dirname(mmdet.__file__)
-        config_dst = join_paths(mmdet_path, str(settings.CONFIGS[model_name]["destination"]))
-        # download the corresponding config if it doesn't exist already
-        if not os.path.exists(config_dst):
-            urlretrieve(settings.CONFIGS[model_name]["source"], config_dst, self.handle_progress)
-        self.model = DetInferencer(config_dst, model_checkpoint, self.device, show_progress=False)
-
-    def download_model(self, model_name='yolov3'):
+        if not model_checkpoint.endswith('.onnx'):
+            raise ValueError(f"Only ONNX models are supported, got: {model_checkpoint}")
+
+        provider = get_best_provider()
+        self.model = ort.InferenceSession(model_checkpoint, providers=[provider])
+        self.input_name = self.model.get_inputs()[0].name
+        self.output_names = [o.name for o in self.model.get_outputs()]
+
+        preprocess = settings.ONNX_PREPROCESS.get(model_name, {})
+        self.model_expect_size = tuple(preprocess.get("input_size", (416, 416)))
+        self.mean = np.array(preprocess.get("mean", [0.0, 0.0, 0.0]), dtype=np.float32)
+        self.std = np.array(preprocess.get("std", [255.0, 255.0, 255.0]), dtype=np.float32)
+
+    def download_model(self, model_name='yolov3 (DO)'):
         ''' Downloads the model from zenodo and stores it in settings.MODELS_DIR '''
         # specify the url of the model which is to be downloaded
         down_url = settings.MODELS[model_name]["source"]
@@ -77,14 +121,15 @@ class OrganoiDL():
         urlretrieve(down_url, save_loc, self.handle_progress)
 
     def sliding_window(self,
-                       test_img,
-                       step,
-                       window_size,
-                       rescale_factor,
-                       prepadded_height,
-                       prepadded_width,
-                       pred_bboxes=[],
-                       scores_list=[]):
+                    test_img,
+                    step,
+                    window_size,
+                    rescale_factor,
+                    prepadded_height,
+                    prepadded_width,
+                    pred_bboxes=None,
+                    scores_list=None, 
+                    labels_list=None):
         ''' Runs sliding window inference and returns predicting bounding boxes and confidence scores for each box.
         Inputs
         ----------
@@ -100,10 +145,12 @@ class OrganoiDL():
             The image height before padding was applied
         prepadded_width: int
             The image width before padding was applied
-        pred_bboxes: list of
-            The
-        scores_list: list of
-            The
+        pred_bboxes: List
+            The list of existing predictions
+        scores_list: List
+            The list of existing confidence scores for corresponding boxes
+        labels_list: List
+            The list of existing labels for corresponding boxes
         Outputs
         ----------
         pred_bboxes: list of Tensors, default is an empty list
@@ -114,24 +161,84 @@ class OrganoiDL():
             The  resulting confidence scores of the model for the predicted boxes are appended here 
             Same as pred_bboxes, can be empty on first run but stores results of all runs.
         '''
-        for i in progress(range(0, prepadded_height, step)):
+        # None defaults prevent mutable default argument sharing across calls (Python gotcha)
+        if pred_bboxes is None:
+            pred_bboxes = []
+        if scores_list is None:
+            scores_list = []
+        if labels_list is None:
+            labels_list = []    
+        
+        # Profiling variables
+        start_time = time.perf_counter()
+        profiling_stats = {}
+
+        target_h, target_w = self.model_expect_size
+
+        # go across entire image using sliding window approach with a given window size and step
+        for i in progress(range(0, prepadded_height, step)):            
             for j in progress(range(0, prepadded_width, step)):
-                # crop
-                img_crop = test_img[i:(i+window_size), j:(j+window_size)]
-                # get predictions
-                output = self.model(img_crop)
-                preds = output['predictions'][0]['bboxes']
-                if len(preds)==0: continue
-                else:
-                    for bbox_id in range(len(preds)):
-                        y1, x1, y2, x2 = preds[bbox_id] # predictions from model will be in form x1,y1,x2,y2
-                        x1_real = torch.div(x1+i, rescale_factor, rounding_mode='floor')
-                        x2_real = torch.div(x2+i, rescale_factor, rounding_mode='floor')
-                        y1_real = torch.div(y1+j, rescale_factor, rounding_mode='floor')
-                        y2_real = torch.div(y2+j, rescale_factor, rounding_mode='floor')
-                        pred_bboxes.append(torch.Tensor([x1_real, y1_real, x2_real, y2_real]))
-                        scores_list.append(output['predictions'][0]['scores'][bbox_id])
-        return pred_bboxes, scores_list
+                if self.cancel_requested:
+                    print("Cancellation requested, stopping inference...")
+                    return pred_bboxes, scores_list, labels_list  # Return what we have so far   
+                img_crop = test_img[:, :, i:(i+window_size), j:(j+window_size)]
+
+                # Fit crop within model_expect_size preserving aspect ratio.
+                _, _, crop_h, crop_w = img_crop.shape
+                scale_factor = min(target_w / crop_w, target_h / crop_h)
+                new_h, new_w = int(crop_h * scale_factor), int(crop_w * scale_factor)
+                resize_factor_x = window_size / new_h
+                resize_factor_y = window_size / new_w
+
+                with profile_section('resize', profiling_stats):
+                    img_hwc_uint8 = (img_crop[0].cpu().numpy().transpose(1, 2, 0) * 255.0).astype(np.uint8)
+                    img_resized = cv2.resize(img_hwc_uint8, (new_w, new_h), interpolation=cv2.INTER_LINEAR)
+                    img_crop = img_resized.transpose(2, 0, 1)[np.newaxis, :].astype(np.float32)
+
+                mean_bchw = self.mean.reshape(1, 3, 1, 1)
+                std_bchw = self.std.reshape(1, 3, 1, 1)
+                img_crop = (img_crop - mean_bchw) / std_bchw
+                img_crop = img_crop.astype(np.float32)
+
+                outputs = self.model.run(self.output_names, {self.input_name: img_crop})
+                dets, labels = outputs
+                dets = dets[0]
+                labels = labels[0]
+                if dets.shape[0] == 0:
+                    continue
+
+                for bbox_id in range(dets.shape[0]):
+                    y1, x1, y2, x2, score = dets[bbox_id]
+                    x1 *= resize_factor_x
+                    x2 *= resize_factor_x
+                    y1 *= resize_factor_y
+                    y2 *= resize_factor_y
+                    x1_real = torch.div(x1 + i, rescale_factor, rounding_mode='floor')
+                    x2_real = torch.div(x2 + i, rescale_factor, rounding_mode='floor')
+                    y1_real = torch.div(y1 + j, rescale_factor, rounding_mode='floor')
+                    y2_real = torch.div(y2 + j, rescale_factor, rounding_mode='floor')
+                    pred_bboxes.append(torch.Tensor([x1_real, y1_real, x2_real, y2_real]))
+                    scores_list.append(score)
+                    labels_list.append(labels[bbox_id])
+
+        # Calculate and print profiling results
+        total_time = time.perf_counter() - start_time
+        resize_time = profiling_stats.get('resize', 0)
+        resize_count = profiling_stats.get('resize_count', 0)
+        resize_percentage = (resize_time / total_time * 100) if total_time > 0 else 0
+
+        print(f"\n{'='*60}")
+        print(f"Profiling Results for sliding_window()")
+        print(f"{'='*60}")
+        print(f"Total function time:        {total_time:.4f} seconds")
+        print(f"resize_keep_ratio_numpy:")
+        print(f"  - Total time:             {resize_time:.4f} seconds")
+        print(f"  - Percentage of total:    {resize_percentage:.2f}%")
+        print(f"  - Number of calls:        {resize_count}")
+        print(f"  - Average time per call:  {resize_time/resize_count:.6f} seconds" if resize_count > 0 else "  - Average time per call:  N/A")
+        print(f"{'='*60}\n")
+
+        return pred_bboxes, scores_list, labels_list
 
     def run(self, 
             img, 
@@ -156,6 +263,7 @@ class OrganoiDL():
         ''' 
         bboxes = []
         scores = []
+        labels = []
         # run for all window sizes
         for window_size, downsampling in zip(window_sizes, downsampling_sizes):
             # compute the step for the sliding window, based on window overlap
@@ -164,51 +272,86 @@ class OrganoiDL():
             window_size = round(window_size * rescale_factor)
             step = round(window_size * window_overlap)
             # prepare image for model - norm, tensor, etc.
-            ready_img, prepadded_height, prepadded_width  = prepare_img(img,
-                                                                        step,
-                                                                        window_size,
-                                                                        rescale_factor)
+            ready_img, prepadded_height, prepadded_width = prepare_img_onnx(
+                img,
+                step,
+                window_size,
+                rescale_factor,
+            )
             # and run sliding window over whole image
-            bboxes, scores = self.sliding_window(ready_img,
+            bboxes, scores, labels = self.sliding_window(ready_img,
                                                  step,
                                                  window_size,
                                                  rescale_factor,
                                                  prepadded_height,
                                                  prepadded_width,
                                                  bboxes,
-                                                 scores)
+                                                 scores, 
+                                                 labels)
+        
+        # if no predictions, store empty tensors so that downstream code still works
+        if len(bboxes) == 0:
+            self.pred_bboxes[shapes_name] = torch.empty((0, 4))
+            self.pred_scores[shapes_name] = torch.empty((0,))
+            self.pred_labels[shapes_name] = torch.empty((0,), dtype=torch.long)
+            self.pred_ids[shapes_name] = []
+            self.next_id[shapes_name] = 1
+            return
+
         # stack results
         bboxes = torch.stack(bboxes)
         scores = torch.Tensor(scores)
+        labels = torch.Tensor(labels)
         # apply NMS to remove overlaping boxes
-        bboxes, pred_scores = apply_nms(bboxes, scores)
+        bboxes, pred_scores, pred_labels = apply_nms(bboxes, scores, labels)
+        # For Detection Only models, set all boxes to class -1 (uncertain/unassigned)
+        # For classification models (BC/multiclass), keep the predicted classes
+        if self.model_name and "(DO)" in self.model_name:  # TODO: what about the annotation mode?
+            pred_labels = torch.full_like(pred_labels, -1)
+
         self.pred_bboxes[shapes_name] = bboxes
         self.pred_scores[shapes_name] = pred_scores
+        self.pred_labels[shapes_name] = pred_labels
         num_predictions = bboxes.size(0)
         self.pred_ids[shapes_name] = [(i+1) for i in range(num_predictions)]
         self.next_id[shapes_name] = num_predictions+1
 
-    def apply_params(self, shapes_name, confidence, min_diameter_um):
+    def apply_params(self, shapes_name, confidence, min_diameter_um, model_name):
         """ After results have been stored in dict this function will filter the dicts based on the confidence
         and min_diameter_um thresholds for the given results defined by shape_name and return the filtered dicts. """
         self.cur_confidence = confidence
         self.cur_min_diam = min_diameter_um
-        pred_bboxes, pred_scores, pred_ids = self._apply_confidence_thresh(shapes_name)
+        pred_bboxes, pred_scores, pred_labels, pred_ids = self._apply_confidence_thresh(shapes_name, model_name)
+
+        # If we are using binary classification (yolov3 (BC)), mark low-confidence boxes as uncertain
+        if model_name== 'yolov3 (BC)':
+           for idx, score in enumerate(pred_scores):
+                if score <= settings.CONFIDENCE_THRESHOLD_CLASS: # TODO: check what the score refers to: objectiness or class confidence?
+                    pred_labels[idx] = -1
+
+        # Filter small organoids based on diameter after labeling uncertain predictions
         if pred_bboxes.size(0)!=0:
-            pred_bboxes, pred_scores, pred_ids = self._filter_small_organoids(pred_bboxes, pred_scores, pred_ids)
+            pred_bboxes, pred_scores, pred_labels, pred_ids = self._filter_small_organoids(pred_bboxes, pred_scores, pred_labels, pred_ids)
         pred_bboxes = convert_boxes_to_napari_view(pred_bboxes)
-        return pred_bboxes, pred_scores, pred_ids
+        return pred_bboxes, pred_scores, pred_labels, pred_ids
 
-    def _apply_confidence_thresh(self, shapes_name):
+    def _apply_confidence_thresh(self, shapes_name, model_name):
         """ Filters out results of shapes_name based on the current confidence threshold. """
         if shapes_name not in self.pred_bboxes.keys(): return torch.empty((0))
-        keep = (self.pred_scores[shapes_name]>self.cur_confidence).nonzero(as_tuple=True)[0]
+
+        # Apply confidence threshold
+        keep = (self.pred_scores[shapes_name] > self.cur_confidence).nonzero(as_tuple=True)[0]
         result_bboxes = self.pred_bboxes[shapes_name][keep]
         result_scores = self.pred_scores[shapes_name][keep]
+        result_labels = self.pred_labels[shapes_name][keep]
         result_ids = [self.pred_ids[shapes_name][int(i)] for i in keep.tolist()]
-        return result_bboxes, result_scores, result_ids
-    
-    def _filter_small_organoids(self, pred_bboxes, pred_scores, pred_ids):
+
+        # Ensure next_id remains monotonic by setting it to one higher than the max kept ID
+        self.next_id[shapes_name] = max(self.pred_ids[shapes_name], default=0) + 1
+
+        return result_bboxes, result_scores, result_labels, result_ids
+
+    def _filter_small_organoids(self, pred_bboxes, pred_scores, pred_labels, pred_ids):
         """ Filters out small result boxes of shapes_name based on the current min diameter size. """
         if pred_bboxes is None: return None
         if len(pred_bboxes)==0: return None
@@ -220,10 +363,11 @@ class OrganoiDL():
             if (dx >= min_diameter_x and dy >= min_diameter_y) or pred_scores[idx] == 1: keep.append(idx) 
         pred_bboxes = pred_bboxes[keep]
         pred_scores = pred_scores[keep]
+        pred_labels = pred_labels[keep]
         pred_ids = [pred_ids[i] for i in keep]
-        return pred_bboxes, pred_scores, pred_ids
+        return pred_bboxes, pred_scores, pred_labels, pred_ids
 
-    def update_bboxes_scores(self, shapes_name, new_bboxes, new_scores, new_ids):
+    def update_bboxes_scores(self, shapes_name, new_bboxes, new_scores, new_labels, new_ids):
         ''' Updated the results dicts, self.pred_bboxes, self.pred_scores and self.pred_ids with new results.
         If the shapes name doesn't exist as a key in the dicts the results are added with the new key. If the
         key exists then new_bboxes, new_scores and new_ids are compared to the class result dicts and the dicts 
@@ -231,13 +375,15 @@ class OrganoiDL():
         
         new_bboxes = convert_boxes_from_napari_view(new_bboxes)
         new_scores =  torch.Tensor(list(new_scores))
+        new_labels = torch.Tensor(list(new_labels))
         new_ids = list(new_ids)
         # if run hasn't been run
         if shapes_name not in self.pred_bboxes.keys():
             self.pred_bboxes[shapes_name] = new_bboxes
             self.pred_scores[shapes_name] = new_scores
+            self.pred_labels[shapes_name] = new_labels
             self.pred_ids[shapes_name] = new_ids
-            self.next_id[shapes_name] = len(new_ids)+1
+            self.next_id[shapes_name] = max(new_ids, default=0) + 1
 
         elif len(new_ids)==0: return
 
@@ -251,9 +397,23 @@ class OrganoiDL():
                 #  and add them
                 self.pred_bboxes[shapes_name] = torch.cat((self.pred_bboxes[shapes_name], new_bboxes[added_ids]))
                 self.pred_scores[shapes_name] = torch.cat((self.pred_scores[shapes_name], new_scores[added_ids]))
+                self.pred_labels[shapes_name] = torch.cat((self.pred_labels[shapes_name], new_labels[added_ids]))
                 new_ids_to_add = [new_ids[i] for i in added_ids]
                 self.pred_ids[shapes_name].extend(new_ids_to_add)
             
+            # Update existing boxes that have been modified (resized or class changed)
+            # For each box_id that exists in both old and new, update its geometry and label
+            common_box_ids = list(set(new_ids).intersection(self.pred_ids[shapes_name]))
+            for box_id in common_box_ids:
+                new_idx = new_ids.index(box_id)
+                old_idx = self.pred_ids[shapes_name].index(box_id)
+                # Update bbox coordinates (handles resizing)
+                self.pred_bboxes[shapes_name][old_idx] = new_bboxes[new_idx]
+                # Update scores (in case user modified manually added boxes)
+                self.pred_scores[shapes_name][old_idx] = new_scores[new_idx]
+                # Update labels (handles class assignment changes)
+                self.pred_labels[shapes_name][old_idx] = new_labels[new_idx]
+            
             # and find ids that are in self.pred_ids and not in new_ids
             potential_removed_box_ids = list(set(self.pred_ids[shapes_name]).difference(new_ids))
             if len(potential_removed_box_ids) > 0:
@@ -267,6 +427,7 @@ class OrganoiDL():
                 for idx in reversed(remove_ids):
                     self.pred_bboxes[shapes_name] = torch.cat((self.pred_bboxes[shapes_name][:idx, :], self.pred_bboxes[shapes_name][idx+1:, :]))
                     self.pred_scores[shapes_name] = torch.cat((self.pred_scores[shapes_name][:idx], self.pred_scores[shapes_name][idx+1:]))
+                    self.pred_labels[shapes_name] = torch.cat((self.pred_labels[shapes_name][:idx], self.pred_labels[shapes_name][idx+1:]))
                     new_pred_ids = self.pred_ids[shapes_name][:idx]
                     new_pred_ids.extend(self.pred_ids[shapes_name][idx+1:])
                     self.pred_ids[shapes_name] = new_pred_ids
@@ -275,11 +436,25 @@ class OrganoiDL():
         """ Updates the next id to append to result dicts. If input c is given then that will be the next id. """
         if c!=0:
             self.next_id[shapes_name] = c
-        else: self.next_id[shapes_name] += 1
+        else: 
+            # Reset next_id to one higher than the current max ID (or 1 if no boxes remain)
+            pred_ids = self.pred_ids.get(shapes_name, [])
+            self.pred_ids.setdefault(shapes_name, pred_ids)
+            self.next_id[shapes_name] = max(pred_ids, default=0) + 1
 
     def remove_shape_from_dict(self, shapes_name):
         """ Removes results of shapes_name from all result dicts. """
         del self.pred_bboxes[shapes_name]
         del self.pred_scores[shapes_name]
+        del self.pred_labels[shapes_name]
         del self.pred_ids[shapes_name]
         del self.next_id[shapes_name]
+
+    def rename_shape_key(self, old_name: str, new_name: str):
+        """Rename a prediction set across all internal dicts."""
+        for d in (self.pred_bboxes, self.pred_scores, self.pred_labels, self.pred_ids, self.next_id):
+            if old_name in d and new_name not in d:
+                d[new_name] = d.pop(old_name)
+            elif old_name in d and new_name in d:
+                # merge conservatively: prefer existing 'new_name' and drop 'old_name'
+                d.pop(old_name)
diff --git a/napari_organoid_counter/_reader.py b/napari_organoid_counter/_reader.py
index d061be7..2644da1 100644
--- a/napari_organoid_counter/_reader.py
+++ b/napari_organoid_counter/_reader.py
@@ -3,17 +3,27 @@ import numpy as np
 from napari import layers
 from pathlib import Path
 
-readable_extensions = '.json'
+from napari_organoid_counter import settings
+from napari_organoid_counter._utils import get_edge_color
+
+# Ensure settings constants are loaded when the reader is imported standalone
+try:
+    settings.init()
+except Exception:
+    pass
+
+
+readable_extensions = ('.json', '.json.draft')
 
 def get_reader(path):
     """ A basic implementation of the napari_get_reader hook specification """
     # if we know we cannot read the file, we immediately return None.
-    if not path.endswith(readable_extensions):
+    if not any(path.endswith(ext) for ext in readable_extensions):
         return None
     # otherwise we return the *function* that can read ``path``.
     return reader_function
 
-def reader_function(path: str) -> layers.Shapes:
+def reader_function_data_management(path: str) -> layers.Shapes:
     """ Reads the labels in the json file and adds a shapes layer to the napari viewer """
     # laod json
     f = open(path)
@@ -22,6 +32,8 @@ def reader_function(path: str) -> layers.Shapes:
     bboxes = []
     ids = []
     scores = []
+    lables = []
+    # scale = (1.0, 1.0)  # default
     # for each box
     for key in annot.keys():
         # read coordinates
@@ -37,24 +49,44 @@ def reader_function(path: str) -> layers.Shapes:
         # and append scores and ids whihc will be used to display as text
         ids.append(int(annot[key]['box_id']))
         scores.append(float(annot[key]['confidence']))
+        if 'label' in annot[key].keys():
+            # if label is present, append it
+            lables.append(annot[key]['label'])
+        else:
+            # if not, append a default label
+            # this is useful for models trained on only one class
+            lables.append(-1)
 
     # scale will adjust boxes according to physical resolution of image
     scale = (float(annot[key]['scale_x']), float(annot[key]['scale_y'])) # do only once
     # name of layer which will be created
-    labels_name = 'Labels-'+Path(path).stem
+    p = Path(path)
+    stem = p.stem  # strips last suffix
+    if p.suffix == '.draft':
+        stem = Path(stem).stem  # strips remaining .json from .json.draft
+    labels_name = 'Labels-' + stem
     # properties used for dusplaying text
-    properties = {'box_id': ids,'scores': scores}
+    properties = {'box_id': ids,'scores': scores, 'labels': lables}
     text_params = {'string': 'ID: {box_id}\nConf.: {scores:.2f}',
                     'size': 12,
                     'anchor': 'upper_left',}
+    # edge colors for boxes
+    edge_colors = get_edge_color(lables, False)
     layer_attributes = {'name': labels_name,
                         'scale': scale,
                         'properties': properties,
                         'text': text_params,
                         'face_color': 'transparent',  
-                        'edge_color': 'magenta',
+                        'edge_color': edge_colors,
                         'shape_type': 'rectangle',
                         'edge_width': 12
     }
     # return data, attributes for displaying and type of layer to add to viewer
-    return [(bboxes, layer_attributes, 'shapes')]
\ No newline at end of file
+    return [(bboxes, layer_attributes, 'shapes', lables)]
+
+
+def reader_function(path: str):
+    """ A wrapper around the reader function to manage errors and return None if the file cannot be read """
+    result = reader_function_data_management(path)
+    bboxes, layer_attributes, layer_type, _ = result[0]
+    return [(bboxes, layer_attributes, layer_type)]
\ No newline at end of file
diff --git a/napari_organoid_counter/_tests/test_reader.py b/napari_organoid_counter/_tests/test_reader.py
index 39078d8..6251d45 100644
--- a/napari_organoid_counter/_tests/test_reader.py
+++ b/napari_organoid_counter/_tests/test_reader.py
@@ -1,12 +1,12 @@
 import json
 import numpy as np
-from napari_organoid_counter import get_reader
+from napari_organoid_counter import get_reader, settings
 
 
 # tmp_path is a pytest fixture
 def test_reader(tmp_path):
     """Testing the reader part of the plugin"""
-
+    settings.init()
     # write some fake data using your supported file format
     my_test_file = str(tmp_path / 'myfile.json')
     bboxes = [np.array([[2000,2000], [2000,2500], [2500,2500], [2500,2000]]),
diff --git a/napari_organoid_counter/_utils.py b/napari_organoid_counter/_utils.py
index be95840..306f55a 100644
--- a/napari_organoid_counter/_utils.py
+++ b/napari_organoid_counter/_utils.py
@@ -1,20 +1,25 @@
 from contextlib import contextmanager
 import os
 from pathlib import Path
-import pkgutil
 
 import numpy as np
+import pandas as pd
 import math
 import json
 import csv
-from skimage.transform import rescale
+from skimage.transform import rescale, resize
 from skimage.color import gray2rgb
 
 import torch
 from torchvision.ops import nms
 
 from napari_organoid_counter import settings
+import torch.nn.functional as F
 
+EXCLUDED_MODELS = [
+    "ssd_organoid_best_coco_bbox_mAP_epoch_86.onnx",
+    "rtmdet_l_organoid_best_coco_bbox_mAP_epoch_323.onnx",
+]
 
 def add_local_models():
     """ Checks the models directory for any local models previously added by the user.
@@ -23,7 +28,7 @@ def add_local_models():
     model_names_in_dir = [file for file in os.listdir(settings.MODELS_DIR)]
     model_names_in_dict = [settings.MODELS[key]["filename"] for key in settings.MODELS.keys()]
     for model_name in model_names_in_dir:
-        if model_name not in model_names_in_dict and model_name.endswith(settings.MODEL_TYPE):
+        if model_name not in model_names_in_dict and model_name.endswith(settings.MODEL_TYPE) and model_name not in EXCLUDED_MODELS:
             _ = add_to_dict(model_name)
 
 def add_to_dict(filepath):
@@ -77,34 +82,97 @@ def get_bboxes_as_dict(bboxes, bbox_ids, scores, scales, labels):
                                                 'confidence': str(scores[idx]),
                                                 'scale_x': str(scales[0]),
                                                 'scale_y': str(scales[1]),
-                                                'class': labels[idx]
+                                                'label': labels[idx],
                                                 }
                         })
     return data_json
 
 def write_to_csv(name, data):
     """ Write data to a csv file. Here data is a list of lists, where each item represents a row in the csv file. """
-    with open(name, 'w') as f:
-        write = csv.writer(f, delimiter=';')
-        write.writerow(['OrganoidID', 'D1[um]','D2[um]', 'Area [um^2]'])
-        write.writerows(data)
+    df = pd.DataFrame(data, columns=['OrganoidID', 'D1[μm]', 'D2[μm]', 'Area[μm^2]', 'Label'])
+    df.to_csv(name, index=False, sep=';')
 
-def get_bbox_diameters(bboxes, bbox_ids, scales):
-    """ Write all data, box diameters and area, ids and scale, to a list so we can later save as a csv """
+def get_bbox_diameters(bboxes, bbox_ids, scales, labels):
+    """ Write all data, box diameters and area, ids, scale and labels to a list so we can later save as a csv """
     data_csv = []
     # save diameters and area of organoids (approximated as ellipses)
-    for idx, bbox in enumerate(bboxes):
-        d1 = abs(bbox[0][0] - bbox[2][0]) * scales[0]
-        d2 = abs(bbox[0][1] - bbox[2][1]) * scales[1]
-        area = math.pi * d1 * d2
-        data_csv.append([bbox_ids[idx], round(d1,3), round(d2,3), round(area,3)])
+    for idx, bbox, label in zip(bbox_ids, bboxes, labels):
+        d1 = abs(bbox[0][0] - bbox[2][0]) * scales[0]  # X direction (width)
+        d2 = abs(bbox[0][1] - bbox[2][1]) * scales[1]  # Y direction (height)
+        area = math.pi * d1 * d2 / 4  # divide by 4 because d1 and d2 are full diameters, not semi-axes
+        data_csv.append([idx, round(d1,3), round(d2,3), round(area,3), label])
     return data_csv
 
 def squeeze_img(img):
     """ Squeeze image - all dims that have size one will be removed """
     return np.squeeze(img)
 
-def prepare_img(test_img, step, window_size, rescale_factor):
+def resize_keep_ratio_numpy(img, scale=(416, 416)):
+    """
+    Resize a numpy array [B, C, H, W] keeping aspect ratio using skimage.
+
+    Args:
+        img (np.ndarray): shape [B, C, H, W]
+        scale (tuple): target maximum (w, h), e.g. (416, 416)
+
+    Returns:
+        np.ndarray: resized array [B, C, new_h, new_w]
+        (int, int): new size (new_h, new_w)
+        float: scale factor
+    """
+    assert img.ndim == 4, "Expected input shape [B, C, H, W]"
+    B, C, H, W = img.shape
+    target_w, target_h = scale
+
+    # compute scale factor
+    scale_factor = min(target_w / W, target_h / H)
+    new_w, new_h = int(W * scale_factor), int(H * scale_factor)
+
+    resized_batch = []
+    for i in range(B):
+        # [C, H, W] → [H, W, C]
+        img_hwc = np.transpose(img[i], (1, 2, 0))
+        resized = resize(img_hwc, (new_h, new_w), order=1, anti_aliasing=True)
+        # back to [C, H, W]
+        resized_chw = np.transpose(resized, (2, 0, 1))
+        resized_batch.append(resized_chw.astype(np.float32))
+
+    resized_batch = np.stack(resized_batch, axis=0)
+    return resized_batch 
+
+def resize_keep_ratio_torch(img, scale=(416, 416)):
+    """
+    Resize a numpy array [B, C, H, W] keeping aspect ratio using PyTorch.
+    
+    Args:
+        img (np.ndarray): shape [B, C, H, W]
+        scale (tuple): target maximum (w, h), e.g. (416, 416)
+    Returns:
+        torch.Tensor: resized array [B, C, new_h, new_w]
+    """
+    assert img.ndim == 4, "Expected input shape [B, C, H, W]"
+    B, C, H, W = img.shape
+    target_w, target_h = scale
+    
+    # Compute scale factor
+    scale_factor = min(target_w / W, target_h / H)
+    new_w, new_h = int(W * scale_factor), int(H * scale_factor)
+    
+    # Resize using bilinear interpolation (vectorized for entire batch)
+    resized_tensor = F.interpolate(
+        img,
+        size=(new_h, new_w),
+        mode='bilinear',
+        align_corners=False,
+        antialias=True
+    )
+    
+    # Convert back to numpy
+    resized_batch = resized_tensor.cpu().numpy().astype(np.float32)
+    
+    return resized_batch
+
+def prepare_img_onnx(test_img, step, window_size, rescale_factor):
     """ The original image is prepared for running model inference """
     # squeeze and resize image
     test_img = squeeze_img(test_img)
@@ -119,12 +187,19 @@ def prepare_img(test_img, step, window_size, rescale_factor):
     test_img = (255*test_img).astype(np.uint8)
     test_img = gray2rgb(test_img) #[H,W,C]
 
-    # convert from RGB to GBR - expected from DetInferencer 
+    # convert from RGB to GBR to match exported model preprocessing
     test_img = test_img[..., ::-1] 
+
+    test_img = test_img.astype(np.float32) / 255.0
+    # HWC -> CHW
+    test_img = np.transpose(test_img, (2, 0, 1))
+    # Add batch dimension
+    test_img = np.expand_dims(test_img, axis=0)
+    test_img = torch.from_numpy(test_img).to('cuda' if torch.cuda.is_available() else 'cpu')
     
     return test_img, img_height, img_width
 
-def apply_nms(bbox_preds, scores_preds, iou_thresh=0.5):
+def apply_nms(bbox_preds, scores_preds, labels_preds, iou_thresh=0.5):
     """ Function applies non max suppression to iteratively remove lower scoring boxes which have an IoU greater than iou_threshold 
     with another (higher scoring) box. The boxes and corresponding scores whihc remain are returned. """
     # torchvision returns the indices of the bboxes to keep
@@ -132,7 +207,8 @@ def apply_nms(bbox_preds, scores_preds, iou_thresh=0.5):
     # filter existing boxes and scores and return
     bbox_preds_kept = bbox_preds[keep]
     scores_preds = scores_preds[keep]
-    return bbox_preds_kept, scores_preds
+    labels_preds = labels_preds[keep]
+    return bbox_preds_kept, scores_preds, labels_preds
 
 def convert_boxes_to_napari_view(pred_bboxes):
     """ The bboxes are converted from tensors in model output form to a form which can be visualised in the napari viewer """
@@ -170,28 +246,20 @@ def apply_normalization(img):
     # adapt img to range 0-255
     img_min = np.min(img) # 31.3125 png 0
     img_max = np.max(img) # 2899.25 png 178
-    img_norm = (255 * (img - img_min) / (img_max - img_min)).astype(np.uint8)
+    if img_min < 0 or img_max > 255:
+        img_norm = (255 * (img - img_min) / (img_max - img_min)).astype(np.uint8)
+    else:
+        img_norm = img.astype(np.uint8)
     return img_norm
 
-def get_package_init_file(package_name):
-    loader = pkgutil.get_loader(package_name)
-    if loader is None or not hasattr(loader, 'get_filename'):
-        raise ImportError(f"Cannot find package {package_name}")
-    package_path = loader.get_filename(package_name)
-    # Determine the path to the __init__.py file
-    if os.path.isdir(package_path):
-        init_file_path = os.path.join(package_path, '__init__.py')
-    else:
-        init_file_path = package_path
-    if not os.path.isfile(init_file_path):
-        raise FileNotFoundError(f"__init__.py file not found for package {package_name}")
-    return init_file_path
-
-def update_version_in_mmdet_init_file(package_name, old_version, new_version):
-    init_file_path = get_package_init_file(package_name)
-    with open(init_file_path, 'r') as file:
-        lines = file.readlines()
-    with open(init_file_path, 'w') as file:
-        for line in lines:
-            if f"mmcv_maximum_version = '{old_version}'" in line:
-                file.write(line.replace(old_version, new_version))
\ No newline at end of file
+def get_edge_color(labels, use_default_color: bool):
+    edge_color = []
+    if use_default_color:  # Detection-Only mode or Deterction only model
+        edge_color = [settings.COLOR_DEFAULT] * len(labels)  # Set all edges to default color (magenta)
+    else:  # For other annotation modes (Binary Classification, 3 classes, etc.)
+        for label in labels:
+            if int(label) == -1:  # Uncertain labels in Binary Classification Mode
+                edge_color.append(settings.COLOR_DEFAULT)  # Set edge color to default for uncertain labels
+            else:
+                edge_color.append(settings.COLOR_MAPPING[int(label)][0])  # Set edge color based on the predicted label
+    return edge_color
diff --git a/napari_organoid_counter/_widget.py b/napari_organoid_counter/_widget.py
index 9d0b1c9..488583d 100644
--- a/napari_organoid_counter/_widget.py
+++ b/napari_organoid_counter/_widget.py
@@ -1,26 +1,76 @@
+import os
+import time
+import json
+from pathlib import Path
+import torch
 from typing import List
+import math
 
 from skimage.io import imsave
 from datetime import datetime
 
 import napari
-
 from napari import layers
 from napari.utils.notifications import show_info, show_error, show_warning
 
 import numpy as np
 
+from pathlib import Path
+
 from qtpy.QtCore import Qt
-from qtpy.QtWidgets import QWidget, QVBoxLayout, QApplication, QDialog, QFileDialog, QGroupBox, QHBoxLayout, QLabel, QComboBox, QPushButton, QLineEdit, QProgressBar, QSlider
+from qtpy.QtGui import QBrush, QColor, QFontMetrics, QCursor
+from qtpy.QtWidgets import (
+    QMessageBox, QWidget, QVBoxLayout, QApplication, QDialog, QFileDialog, QGroupBox, 
+    QHBoxLayout, QLabel, QComboBox, QPushButton, QLineEdit, QProgressBar, 
+    QSlider, QSpinBox, QCheckBox, QScrollArea, QTreeWidget, QTreeWidgetItem,
+    QToolButton, QToolTip
+)
 
 from napari_organoid_counter._orgacount import OrganoiDL
 from napari_organoid_counter import _utils as utils
 from napari_organoid_counter import settings
+from bioio import BioImage
 
 import warnings
 warnings.filterwarnings("ignore")
 
 
+class _HelpButton(QToolButton):
+    """A small circular '?' button that shows its tooltip immediately on hover,
+    with styling that is visible on napari's dark background."""
+
+    def __init__(self, tooltip_text: str, parent=None):
+        super().__init__(parent)
+        self.setText("?")
+        self.setFixedSize(18, 18)
+        self.setToolTip(tooltip_text)
+        self.setFocusPolicy(Qt.NoFocus)
+        self.setCursor(Qt.WhatsThisCursor)
+        self.setStyleSheet(
+            "QToolButton {"
+            "  border: 1px solid rgba(160, 160, 160, 180);"
+            "  border-radius: 9px;"
+            "  font-weight: bold;"
+            "  font-size: 11px;"
+            "  color: rgba(230, 230, 230, 255);"
+            "  background: rgba(70, 70, 75, 220);"
+            "  padding: 0px;"
+            "}"
+            "QToolButton:hover {"
+            "  background: rgba(110, 110, 120, 240);"
+            "  border: 1px solid rgba(210, 210, 210, 220);"
+            "}"
+        )
+
+    def enterEvent(self, event):
+        QToolTip.showText(QCursor.pos(), self.toolTip(), self)
+        super().enterEvent(event)
+
+    def leaveEvent(self, event):
+        QToolTip.hideText()
+        super().leaveEvent(event)
+
+
 class OrganoidCounterWidget(QWidget):
     '''
     The main widget of the organoid counter
@@ -76,16 +126,15 @@ class OrganoidCounterWidget(QWidget):
         # models to the model dict
         settings.init()
         settings.MODELS_DIR.mkdir(parents=True, exist_ok=True)
+        settings.USER_CONFIG_DIR.mkdir(parents=True, exist_ok=True)
         utils.add_local_models()
-        self.model_id = 2 # yolov3
+        self.model_id = 0
         self.model_name = list(settings.MODELS.keys())[self.model_id]
         
-        # init params 
-        self.window_sizes = window_sizes
-        self.downsampling = downsampling
+        # init params
+        self.window_sizes, self.downsampling, self.min_diameter, self.confidence = \
+            self._load_initial_window_defaults(window_sizes, downsampling, min_diameter, confidence)
         self.window_overlap = window_overlap
-        self.min_diameter = min_diameter
-        self.confidence = confidence
 
         self.image_layer_names = []
         self.image_layer_name = None 
@@ -98,15 +147,84 @@ class OrganoidCounterWidget(QWidget):
         self.original_contrast = {}
         self.stored_confidences = {}
         self.stored_diameters = {}
-
-        # Initialize multi_annotation_mode to False by default
-        self.multi_annotation_mode = False
-        # self.single_annotation_mode = True  # Initially, it's single annotation mode
-
-        # setup gui        
-        self.setLayout(QVBoxLayout())
-        self.layout().addWidget(self._setup_input_widget())
-        self.layout().addWidget(self._setup_output_widget())
+        self.annotation_widget = None
+        self.legend_box = None
+
+        # Annotation Mode 
+        self.annotation_mode = 2 # Default to Detection Only mode (0)
+
+        # Mapping annotation modes to names and valid class sets
+        self.annotation_mode_mapping = {
+            0: {"name": "Detection Only (DO)", "classes": {0}},
+            1: {"name": "Binary Classification (BC)", "classes": {0, 1}},
+        }
+
+        # Auto-generate mappings for 3 to 10 classes
+        for n in range(2, 10):
+            self.annotation_mode_mapping[n] = {
+                "name": f"{n+1} Classes",
+                "classes": set(range(n+1)),
+            }
+
+        # Mapping class numbers to colors
+        self.color_mapping = {
+            0: (settings.COLOR_CLASS_0, "Green"),
+            1: (settings.COLOR_CLASS_1, "Blue"),
+            2: (settings.COLOR_CLASS_2, "Orange"),
+            3: (settings.COLOR_CLASS_3, "Purple"),
+            4: (settings.COLOR_CLASS_4, "Cyan"),
+            5: (settings.COLOR_CLASS_5, "Red"),
+            6: (settings.COLOR_CLASS_6, "Brown"),
+            7: (settings.COLOR_CLASS_7, "Pink"),
+            8: (settings.COLOR_CLASS_8, "Yellow"),
+            9: (settings.COLOR_CLASS_9, "Light Blue")
+        }
+
+        self.selected_classes = self.annotation_mode_mapping[self.annotation_mode]["classes"]  # active class set for current mode
+        self.class_count_labels: dict[int, QLabel] = {}  # per-class count labels in legend
+        self.class_checkboxes: dict[int, QCheckBox] = {}   # per-class filter checkboxes
+        self.master_class_checkbox: QCheckBox | None = None  # "All classes" toggle checkbox
+        self.visible_classes_filter: set[int] = set(self.selected_classes)  # start with all visible
+        self._shape_name_by_id: dict[int, str] = {}
+        self._hover_idx: int | None = None  # current hovered box index
+        self._hover_base: str = ""  # cached static hover message (ID, diameters, etc.)
+
+        # Data Browser state
+        self.data_folder: str = ""
+        self.image_files: list = []  # All discovered image paths
+        self.current_image_path: Path | None = None
+        self.file_tree: QTreeWidget | None = None
+
+        # Supported image extensions
+        self.supported_image_extensions = {
+            '.tif', '.TIF', '.tiff', '.TIFF',
+            '.png', '.PNG',
+            '.jpg', '.JPG', '.jpeg', '.JPEG',
+            '.czi',           # bioio-czi
+            '.nd2',           # bioio-nd2
+            '.lif',           # bioio-lif
+            '.dv', '.r3d',    # bioio-dv
+        }
+
+        # Setup GUI        
+        # Create a container widget for all content
+        container = QWidget()
+        container_layout = QVBoxLayout(container)
+        container_layout.addWidget(self._setup_data_browser_widget())
+        container_layout.addWidget(self._setup_model_widget())
+        container_layout.addWidget(self._setup_annotation_widget())
+        container_layout.addStretch(1)  # Push everything to top
+
+        # Wrap in scroll area
+        scroll = QScrollArea()
+        scroll.setWidget(container)
+        scroll.setWidgetResizable(True)
+        scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
+
+        # Set main layout
+        main_layout = QVBoxLayout()
+        main_layout.addWidget(scroll)
+        self.setLayout(main_layout)
 
         # initialise organoidl instance
         self.organoiDL = OrganoiDL(self.handle_progress)
@@ -116,80 +234,150 @@ class OrganoidCounterWidget(QWidget):
         if len(self.image_layer_names)>0: self._update_added_image(self.image_layer_names)
         self.shape_layer_names = self._get_layer_names(layer_type=layers.Shapes)
         if len(self.shape_layer_names)>0: self._update_added_shapes(self.shape_layer_names)
+
         # and watch for newly added images or shapes
         self.viewer.layers.events.inserted.connect(self._added_layer)
         self.viewer.layers.events.removed.connect(self._removed_layer)
         self.viewer.layers.selection.events.changed.connect(self._sel_layer_changed)
+        self._disable_native_open_shortcut()
+        self._connect_file_menu_guard()
     
-        # setup flags used for changing slider and text of min diameter and confidence threshold
-        self.diameter_slider_changed = False 
+        # setup flag used for changing slider and text of confidence threshold
         self.confidence_slider_changed = False
 
-        # Key binding to change the edge_color of the bounding boxes to green
-        @self.viewer.bind_key('g')
-        def change_edge_color_to_green(viewer: napari.Viewer):
-            if not self.multi_annotation_mode:  # Check if single-annotation mode is active
-                show_error("Cannot change edge color. Change to multi-annotation mode to enable this feature.")
-                return
-            if self.cur_shapes_layer is not None:  # Ensure shapes layer exists
-                selected_shapes = self.cur_shapes_layer.selected_data # Retrieves indices of shapes currently selected, returns a set 
-                if len(selected_shapes) > 0:
-                    # Modify the edge color only for the selected shapes
-                    current_edge_colors = self.cur_shapes_layer.edge_color 
-                    for idx in selected_shapes:
-                        # Save original color
-                        # if idx not in self.original_colors: 
-                            # self.original_colors[idx] = current_edge_colors[idx].copy()
-                        # Update to the new color
-                        current_edge_colors[idx] = settings.COLOR_CLASS_1
-                    self.cur_shapes_layer.edge_color = current_edge_colors  # Apply the changes
-                    show_info(f"Changed edge color of shapes {list(selected_shapes)} to green.")
-                else:
-                    show_warning("No shapes selected to change edge color.")
-
-        # Key binding to change the edge_color of the bounding boxes to blue
-        @self.viewer.bind_key('h')
-        def change_edge_color_to_blue(viewer: napari.Viewer):
-            if not self.multi_annotation_mode:  # Check if single-annotation mode is active
-                show_error("Cannot change edge color. Change to multi-annotation mode to enable this feature.")
-                return         
-            if self.cur_shapes_layer is not None:  # Ensure shapes layer exists
-                selected_shapes = self.cur_shapes_layer.selected_data
-                if len(selected_shapes) > 0:
-                    # Modify the edge color only for the selected shapes
-                    current_edge_colors = self.cur_shapes_layer.edge_color
-                    for idx in selected_shapes:
-                        # Save original color
-                        # if idx not in self.original_colors: 
-                            # self.original_colors[idx] = current_edge_colors[idx].copy()
-                        # Update to the new color
-                        current_edge_colors[idx] = settings.COLOR_CLASS_2
-                    self.cur_shapes_layer.edge_color = current_edge_colors  # Apply the changes
-                    show_info(f"Changed edge color of {list(selected_shapes)} to blue.")
-                else:
-                    show_warning("No shapes selected to change edge color.")
-
         # Key binding to reset the edge_color of selected bounding boxes to the original magenta color
-        @self.viewer.bind_key('m')
+        @self.viewer.bind_key('m', overwrite=True)
         def change_to_original_color(viewer: napari.Viewer):
-            if not self.multi_annotation_mode:  # Check if single-annotation mode is active
-                show_info("Cannot change edge color. Change to multi-annotation mode to enable this feature.")
-                return
             if self.cur_shapes_layer is not None:  # Ensure shapes layer exists
                 selected_shapes = self.cur_shapes_layer.selected_data
                 if len(selected_shapes) > 0:
-                    current_edge_colors = self.cur_shapes_layer.edge_color
                     # Modify the edge color only for the selected shapes
                     current_edge_colors = self.cur_shapes_layer.edge_color
                     for idx in selected_shapes:
-                        # if idx in self.original_colors:
-                            # Revert to the original color
-                            current_edge_colors[idx] = settings.COLOR_DEFAULT
+                        # Revert to the original color
+                        current_edge_colors[idx] = settings.COLOR_DEFAULT
                     self.cur_shapes_layer.edge_color = current_edge_colors  # Apply the changes
                     show_info(f"Reset edge color of {list(selected_shapes)} to magenta.")
+                    self._refresh_class_counts()
                 else:
                     show_warning("No shapes selected to reset edge color.")
 
+        # Activate key bindings for class-color shortcuts
+        self.update_key_bindings()
+        self._setup_mouse_callback()
+
+    def _connect_file_menu_guard(self):
+        """Keep the native open action disabled even if napari re-enables it."""
+        try:
+            menubar = self.viewer.window._qt_window.menuBar()
+            for action in menubar.actions():
+                menu = action.menu()
+                if menu is None:
+                    continue
+                if 'file' in action.text().lower():
+                    menu.aboutToShow.connect(self._disable_native_open_shortcut)
+                    return
+        except Exception:
+            pass
+
+    def update_key_bindings(self):
+        """ Update key bindings based on selected classes """            
+
+        # Unbind all potential class keys (CTRL+0 to CTRL+9)
+        for class_num in range(10):
+            key = f'Control-{class_num}'
+            if key in self.viewer.keymap:
+                self.viewer.keymap.pop(key) # Remove the key binding if it already exists
+
+        # Bind all keys and validate them on press
+        bound_keys = []
+        for class_num in range(10):
+            key = f'Control-{class_num}'
+            
+            # Capture 'class_num' using a lambda default argument
+            @self.viewer.bind_key(key, overwrite=True)
+            def change_color_for_class(viewer: napari.Viewer, class_num=class_num):
+                # Check if the class is valid for the current annotation mode
+                if class_num not in self.selected_classes:
+                    show_error(f"Class {class_num} is not available in the current annotation mode.")
+                    return
+                
+                # Ensure we are NOT in detection-only mode
+                if self.annotation_mode == 0:
+                    show_error(f"Cannot change class in Detection Only annotation mode.")
+                    return
+                
+                # Proceed with the color change if valid
+                if self.cur_shapes_layer:
+                    selected_shapes = self.cur_shapes_layer.selected_data
+                    if selected_shapes:
+                        self.change_edge_color(viewer, selected_shapes, class_num)
+                    else:
+                        show_warning("No shapes selected to change edge color.")
+                else:
+                    show_warning("No active shapes layer available.")
+
+            # Confirm valid key bindings
+            if class_num in self.selected_classes:
+                # Suppress message if in detection-only mode
+                if self.annotation_mode == 0:
+                    return
+                bound_keys.append(f"{key} to change to class {class_num}")
+            # Display a dynamic message showing all valid key bindings
+        if bound_keys:
+            mode_name = self.annotation_mode_mapping[self.annotation_mode]["name"]
+            binding_message = ", ".join(bound_keys)
+            show_info(f"Switched to {mode_name} annotation mode. Use {binding_message}.")
+
+    def _on_shapes_layer_renamed(self, layer):
+        old = self._shape_name_by_id.get(id(layer))
+        new = layer.name
+        if not old or old == new:
+            return
+
+        # 1) migrate OrganoiDL dict keys
+        if hasattr(self.organoiDL, "rename_shape_key"):
+            self.organoiDL.rename_shape_key(old, new)
+
+        # 2) update widget state dicts
+        if old in self.stored_confidences:
+            self.stored_confidences[new] = self.stored_confidences.pop(old)
+        if old in self.stored_diameters:
+            self.stored_diameters[new] = self.stored_diameters.pop(old)
+
+        # 3) update our layer-name lists
+        if old in self.shape_layer_names:
+            idx = self.shape_layer_names.index(old)
+            self.shape_layer_names[idx] = new
+
+
+        # 5) update active names
+        if self.cur_shapes_name == old:
+            self.cur_shapes_name = new
+        if self.save_layer_name == old:
+            self.save_layer_name = new
+
+        # 6) cache the new name
+        self._shape_name_by_id[id(layer)] = new
+
+    def change_edge_color(self, viewer: napari.Viewer, selected_shapes, class_num):
+        """Change the edge color of selected shapes based on the class number."""
+
+        # Check if the class_num is valid in the mapping
+        if class_num in settings.COLOR_MAPPING:
+            current_edge_colors = self.cur_shapes_layer.edge_color
+
+            # Update the edge color for the selected shapes
+            for idx in selected_shapes:
+                current_edge_colors[idx] = settings.COLOR_MAPPING[class_num][0] # Set RGBA color
+
+            # Apply the updated colors back to the layer
+            self.cur_shapes_layer.edge_color = current_edge_colors
+            show_info(f"Changed edge color of shapes {list(selected_shapes)} to {settings.COLOR_MAPPING[class_num][1]}.") # Print color name
+            self._apply_class_filter()
+            self._refresh_class_counts()
+        else:
+            show_warning(f"Class {class_num} has no associated color.")  
 
     def handle_progress(self, blocknum, blocksize, totalsize):
         """ When the model is being downloaded, this method is called and th progress of the download
@@ -208,17 +396,22 @@ class OrganoidCounterWidget(QWidget):
         cur_seg_selected = cur_layer_list[-1]
         # switch to values of other shapes layer if clicked
         if type(cur_seg_selected)==layers.Shapes:
-            if self.cur_shapes_layer is not None:
+            if self.cur_shapes_layer is not None and self.cur_shapes_name:
                 self.stored_confidences[self.cur_shapes_name] = self.confidence_slider.value()/100
-                self.stored_diameters[self.cur_shapes_name] = self.min_diameter_slider.value()
+                self.stored_diameters[self.cur_shapes_name] = self.min_diameter_spinbox.value()
             self.cur_shapes_layer = cur_seg_selected
             self.cur_shapes_name = cur_seg_selected.name
+            # Ensure defaults exist for newly created/loaded shape layers.
+            self.stored_diameters.setdefault(self.cur_shapes_name, self.min_diameter_spinbox.value())
+            self.stored_confidences.setdefault(self.cur_shapes_name, self.confidence_slider.value()/100)
             # update min diameter text and slider with previous value of that layer
             self.min_diameter = self.stored_diameters[self.cur_shapes_name]
-            self.min_diameter_textbox.setText(str(self.min_diameter))
+            self.min_diameter_spinbox.setValue(self.min_diameter)
             # update confidence text and slider with previous value of that layer
             self.confidence = self.stored_confidences[self.cur_shapes_name]
             self.confidence_textbox.setText(str(self.confidence))
+            self._hover_idx = None
+            self._hover_base = ""
 
     def _added_layer(self, event):
         # get names of added layers, image and shapes
@@ -232,6 +425,10 @@ class OrganoidCounterWidget(QWidget):
         if len(new_shape_layer_names)>0:
             self._update_added_shapes(new_shape_layer_names)
             self.shape_layer_names.extend(new_shape_layer_names)
+
+            # reset edge color
+            for name in new_shape_layer_names:
+                self.viewer.layers[name].current_edge_color = settings.COLOR_DEFAULT
             
     def _removed_layer(self, event):
         """ Is called whenever a layer has been deleted (by the user) and removes the layer from GUI and backend. """
@@ -242,66 +439,124 @@ class OrganoidCounterWidget(QWidget):
         if len(removed_image_layer_names)>0:
             self._update_removed_image(removed_image_layer_names)
             self.image_layer_names = new_image_layer_names
+            # If current image was removed, show first remaining if any
+            if self.image_layer_name is None and self.image_layer_names:
+                self.image_layer_name = self.image_layer_names[0]
+                # self._update_image_name_display()
         if len(removed_shape_layer_names)>0:
             self._update_remove_shapes(removed_shape_layer_names)
             self.shape_layer_names = new_shape_layer_names
 
     def _preprocess(self):
         """ Preprocess the current image in the viewer to improve visualisation for the user """
+        self._ensure_image_cached(self.image_layer_name)
+        if self.image_layer_name not in self.original_images:
+            show_warning(f"Could not preprocess image layer '{self.image_layer_name}'.")
+            return
+
         img = self.original_images[self.image_layer_name]
         img = utils.apply_normalization(img)
         self.viewer.layers[self.image_layer_name].data = img
         self.viewer.layers[self.image_layer_name].contrast_limits = (0,255)
 
+    def _ensure_image_cached(self, layer_name: str | None):
+        """Ensure the image cache has an entry for `layer_name`."""
+        if not layer_name or layer_name in self.original_images:
+            return
+        if layer_name not in self.viewer.layers:
+            return
+
+        layer = self.viewer.layers[layer_name]
+        if not isinstance(layer, layers.Image):
+            return
+
+        self.original_images[layer_name] = np.asarray(layer.data)
+        self.original_contrast[layer_name] = layer.contrast_limits
+
     def _update_num_organoids(self, len_bboxes):
         """ Updates the number of organoids displayed in the viewer """
         self.num_organoids = len_bboxes
         new_text = 'Number of organoids: '+str(self.num_organoids)
         self.organoid_number_label.setText(new_text)
 
-    def _update_vis_bboxes(self, bboxes, scores, box_ids, labels_layer_name):
+    def _update_vis_bboxes(self, bboxes, scores, labels, box_ids, labels_layer_name):
         """ Adds the shapes layer to the viewer or updates it if already there """
         self._update_num_organoids(len(bboxes))
+
+        # Convert PyTorch tensors to lists (if they are tensors)
+        if hasattr(scores, "tolist"):
+            scores = scores.tolist()
+        if hasattr(labels, "tolist"):
+            labels = labels.tolist()
+
+        # Text parameters (for all models)
+        text_params = {
+            'string': 'ID: {box_id}\nConf.: {scores:.2f}',
+            'size': 9,
+            'anchor': 'upper_left',
+        }
+
+        # Edge color for the boxes
+        all_labels_unassigned = all(int(label) == -1 for label in labels)
+        use_default_color = (self.annotation_mode == 0 or "(DO)" in self.model_name) and all_labels_unassigned
+        edge_color = utils.get_edge_color(labels, use_default_color)
+                    
+        existing_layer = None
+        if labels_layer_name in self.viewer.layers:
+            candidate_layer = self.viewer.layers[labels_layer_name]
+            if isinstance(candidate_layer, layers.Shapes):
+                existing_layer = candidate_layer
+
         # if layer already exists
-        if labels_layer_name in self.shape_layer_names: 
-            self.viewer.layers[labels_layer_name].data = bboxes # hack to get edge_width stay the same!
-            self.viewer.layers[labels_layer_name].properties = {'box_id': box_ids,'scores': scores}
-            self.viewer.layers[labels_layer_name].edge_width = 12
-            self.viewer.layers[labels_layer_name].refresh()
-            self.viewer.layers[labels_layer_name].refresh_text()
+        if existing_layer is not None:
+            existing_layer.data = bboxes  # hack to keep edge_width unchanged
+            existing_layer.properties = {'box_id': box_ids, 'scores': scores, 'labels': labels}
+            existing_layer.edge_color = edge_color
+            existing_layer.edge_width = 12
+            existing_layer.refresh()
+            existing_layer.refresh_text()
         # or if this is the first run
         else:
             # if no organoids were found just make an empty shapes layer
             if self.num_organoids==0: 
                 self.cur_shapes_layer = self.viewer.add_shapes(name=labels_layer_name,
-                                                               properties={'box_id': [],'scores': []})
+                                                               properties={'box_id': [],'scores': [], 'labels': []})
             # otherwise make the layer and add the boxes
             else:
-                properties = {'box_id': box_ids,'scores': scores}
-                text_params = {'string': 'ID: {box_id}\nConf.: {scores:.2f}',
-                               'size': 12,
-                               'anchor': 'upper_left',}
+                properties = {'box_id': box_ids,'scores': scores, 'labels': labels}
+                text_params = text_params
                 self.cur_shapes_layer = self.viewer.add_shapes(bboxes, 
                                                                name=labels_layer_name,
                                                                scale=self.viewer.layers[self.image_layer_name].scale,
                                                                face_color='transparent',  
                                                                properties = properties,
                                                                text = text_params,
-                                                               edge_color=settings.COLOR_DEFAULT,
+                                                               edge_color=edge_color,
                                                                shape_type='rectangle',
                                                                edge_width=12) # warning generated here
                             
             # set current_edge_width so edge width is the same when users annotate - doesnt' fix new preds being added!
             self.viewer.layers[labels_layer_name].current_edge_width = 12
-            
-
-    def _on_preprocess_click(self):
-        """ Is called whenever preprocess button is clicked """
-        if not self.image_layer_name: show_info('Please load an image first and try again!')
-        else: self._preprocess()
+        
+        self._apply_class_filter()
+        self._refresh_class_counts()
 
     def _on_run_click(self):
         """ Is called whenever Run Organoid Counter button is clicked """
+        # Reset cancellation flag
+        self.organoiDL.cancel_requested = False
+        self.cancel_btn.setEnabled(True)
+
+        # Check if the model is 'Binary Classification' and ensure it's not in 'Detection Only' mode
+        current_annotation_mode = self.annotation_mode
+        # TODO: make the condition more general (applicable to other models as well)
+        if self.model_name == 'yolov3 (BC)' and current_annotation_mode == 0:
+            show_error("Please switch to Binary Classification Annotation mode or use more than 2 classes to use the Binary Classification model.")
+            return
+            
+        # Start timing
+        start_time = time.time()
+
         # check if an image has been loaded
         if not self.image_layer_name: 
             show_info('Please load an image first and try again!')
@@ -320,7 +575,7 @@ class OrganoidCounterWidget(QWidget):
         
         # load model checkpoint
         self.organoiDL.set_model(self.model_name)
-        if self.organoiDL.img_scale[0]==0: self.organoiDL.set_scale(self.viewer.layers[self.image_layer_name].scale)
+        # if self.organoiDL.img_scale[0]==0: self.organoiDL.set_scale(self.viewer.layers[self.image_layer_name].scale)
         
         # make sure the number of windows and downsamplings are the same
         if len(self.window_sizes) != len(self.downsampling): 
@@ -328,7 +583,7 @@ class OrganoidCounterWidget(QWidget):
             return
         
         # get the current image 
-        img_data = self.viewer.layers[self.image_layer_name].data
+        img_data = self.original_images.get(self.image_layer_name, self.viewer.layers[self.image_layer_name].data)
         
         # check that image is grayscale
         if len(utils.squeeze_img(img_data).shape) > 2:
@@ -351,16 +606,36 @@ class OrganoidCounterWidget(QWidget):
                            self.downsampling,
                            self.window_overlap)
         
+        # raw_total = self.organoiDL.pred_bboxes[labels_layer_name].size(0) # never used
+        if self.organoiDL.cancel_requested:
+            self.cancel_btn.setEnabled(False)
+            self.viewer.window._status_bar._toggle_activity_dock(False)
+            show_info("Inference cancelled by user")
+            return
+
         # set the confidence threshold, remove small organoids and get bboxes in format o visualise
-        bboxes, scores, box_ids = self.organoiDL.apply_params(labels_layer_name, self.confidence, self.min_diameter)
+        bboxes, scores, labels, box_ids = self.organoiDL.apply_params(labels_layer_name, self.confidence, self.min_diameter, self.model_name)
         # hide activcity dock on completion
         self.viewer.window._status_bar._toggle_activity_dock(False)
+
+        # Disable cancel button when done
+        self.cancel_btn.setEnabled(False)
+
+
+        # End timing
+        end_time = time.time()
+        elapsed_time = end_time - start_time
+
         # update widget with results
-        self._update_vis_bboxes(bboxes, scores, box_ids, labels_layer_name)
+        self._update_vis_bboxes(bboxes, scores, labels, box_ids, labels_layer_name)
         # and update cur_shapes_name to newly created shapes layer
         self.cur_shapes_name = labels_layer_name
-        # preprocess the image if not done so already to improve visualisation
-        self._preprocess() 
+        
+    def _on_cancel_click(self):
+        """ Is called when Cancel button is clicked """
+        self.organoiDL.cancel_requested = True
+        self.cancel_btn.setEnabled(False)
+        show_info("Cancelling inference...")
 
     def _on_model_selection_changed(self):
         """ Is called when user selects a new model from the dropdown menu. """
@@ -371,8 +646,9 @@ class OrganoidCounterWidget(QWidget):
         # called when the user hits the 'browse' button to select a model
         fd = QFileDialog()
         fd.setFileMode(QFileDialog.AnyFile)
-        if fd.exec_():
-            model_path = fd.selectedFiles()[0]
+        if not fd.exec_():
+            return
+        model_path = fd.selectedFiles()[0]
         import shutil
         shutil.copy2(model_path, settings.MODELS_DIR)
         model_name = utils.add_to_dict(model_path)
@@ -380,53 +656,180 @@ class OrganoidCounterWidget(QWidget):
 
     def _on_window_sizes_changed(self):
         """ Is called whenever user changes the window sizes text box """
-        new_window_sizes = self.window_sizes_textbox.text()
-        new_window_sizes = new_window_sizes.split(',')
-        self.window_sizes = [int(win_size) for win_size in new_window_sizes]
+        try:
+            self.window_sizes = self._parse_positive_int_list(
+                self.window_sizes_textbox.text(),
+                "Window sizes",
+            )
+            self._sync_window_settings_textboxes()
+        except ValueError as exc:
+            show_error(str(exc))
+            self._sync_window_settings_textboxes()
 
     def _on_downsampling_changed(self):
         """ Is called whenever user changes the downsampling text box """
-        new_downsampling = self.downsampling_textbox.text()
-        new_downsampling = new_downsampling.split(',')
-        self.downsampling = [int(ds) for ds in new_downsampling]
+        try:
+            self.downsampling = self._parse_positive_int_list(
+                self.downsampling_textbox.text(),
+                "Downsampling",
+            )
+            self._sync_window_settings_textboxes()
+        except ValueError as exc:
+            show_error(str(exc))
+            self._sync_window_settings_textboxes()
+
+    def _parse_positive_int_list(self, raw: str, field_name: str) -> list[int]:
+        values = [part.strip() for part in raw.split(',') if part.strip()]
+        if not values:
+            raise ValueError(f"{field_name} cannot be empty.")
+        try:
+            parsed = [int(value) for value in values]
+        except ValueError as exc:
+            raise ValueError(f"{field_name} must be comma-separated integers.") from exc
+        if any(value <= 0 for value in parsed):
+            raise ValueError(f"{field_name} must contain only positive integers.")
+        return parsed
+
+    def _validate_window_downsampling(self, window_sizes: list[int], downsampling: list[int]):
+        if len(window_sizes) != len(downsampling):
+            raise ValueError("Keep number of window sizes and downsampling the same and try again!")
+
+    def _sync_window_settings_textboxes(self):
+        if hasattr(self, "window_sizes_textbox"):
+            self.window_sizes_textbox.setText(",".join(str(value) for value in self.window_sizes))
+        if hasattr(self, "downsampling_textbox"):
+            self.downsampling_textbox.setText(",".join(str(value) for value in self.downsampling))
+
+    def _load_initial_window_defaults(
+        self,
+        window_sizes: List,
+        downsampling: List,
+        min_diameter: int,
+        confidence: float,
+    ):
+        """Load global defaults unless explicit non-default constructor values are provided.
+        Returns (window_sizes, downsampling, min_diameter, confidence).
+        """
+        default_ws = list(settings.DEFAULT_WINDOW_SIZES)
+        default_ds = list(settings.DEFAULT_DOWNSAMPLING)
+        default_md = 30
+        default_conf = 0.8
+        passed_ws = list(window_sizes)
+        passed_ds = list(downsampling)
+
+        # Keep explicit non-default constructor overrides (window params only).
+        if passed_ws != default_ws or passed_ds != default_ds:
+            return passed_ws, passed_ds, min_diameter, confidence
+
+        prefs = self._read_global_preferences()
+        if prefs is None:
+            return default_ws, default_ds, default_md, default_conf
+
+        loaded_ws = prefs.get("window_sizes", default_ws)
+        loaded_ds = prefs.get("downsampling", default_ds)
+        try:
+            loaded_ws = [int(value) for value in loaded_ws]
+            loaded_ds = [int(value) for value in loaded_ds]
+            if any(value <= 0 for value in loaded_ws + loaded_ds):
+                raise ValueError
+            self._validate_window_downsampling(loaded_ws, loaded_ds)
+        except (TypeError, ValueError):
+            show_warning("Global defaults file is invalid. Using built-in defaults.")
+            return default_ws, default_ds, default_md, default_conf
+
+        loaded_md = int(prefs.get("min_diameter", default_md))
+        loaded_conf = float(prefs.get("confidence", default_conf))
+        loaded_md = max(0, loaded_md)
+        loaded_conf = max(0.05, min(1.0, loaded_conf))
+
+        return loaded_ws, loaded_ds, loaded_md, loaded_conf
+
+    def _read_global_preferences(self):
+        prefs_path = settings.GLOBAL_DEFAULTS_FILE
+        if not prefs_path.exists():
+            return None
+        try:
+            with prefs_path.open("r", encoding="utf-8") as fh:
+                data = json.load(fh)
+            if not isinstance(data, dict):
+                raise ValueError
+            return data
+        except (OSError, json.JSONDecodeError, ValueError):
+            show_warning("Could not read global defaults file. Using built-in defaults.")
+            return None
+
+    def _on_save_global_defaults_click(self):
+        """Persist all current settings as global defaults."""
+        try:
+            window_sizes = self._parse_positive_int_list(
+                self.window_sizes_textbox.text(),
+                "Window sizes",
+            )
+            downsampling = self._parse_positive_int_list(
+                self.downsampling_textbox.text(),
+                "Downsampling",
+            )
+            self._validate_window_downsampling(window_sizes, downsampling)
+        except ValueError as exc:
+            show_error(str(exc))
+            return
+
+        prefs = {
+            "window_sizes": window_sizes,
+            "downsampling": downsampling,
+            "min_diameter": self.min_diameter_spinbox.value(),
+            "confidence": self.confidence_slider.value() / 100,
+        }
+        try:
+            settings.USER_CONFIG_DIR.mkdir(parents=True, exist_ok=True)
+            with settings.GLOBAL_DEFAULTS_FILE.open("w", encoding="utf-8") as fh:
+                json.dump(prefs, fh, indent=2)
+        except OSError as exc:
+            show_error(f"Failed to save global defaults: {exc}")
+            return
+
+        self.window_sizes = window_sizes
+        self.downsampling = downsampling
+        self._sync_window_settings_textboxes()
+        show_info("Saved global defaults for all settings.")
 
     def _rerun(self):
         """ Is called whenever user changes one of the two parameter sliders """
         # check if OrganoiDL instance exists - create it if not and set there current boxes, scores and ids        
-        if self.organoiDL.img_scale[0]==0: self.organoiDL.set_scale(self.cur_shapes_layer.scale)
-        self.organoiDL.update_next_id(self.cur_shapes_name, len(self.cur_shapes_layer.scale)+1)
-        
+        if self.organoiDL.img_scale[0]==0: 
+            self.organoiDL.set_scale(self.cur_shapes_layer.scale)
+
+        # GUARD: ensure backend dicts exist under the current layer name
+        if self.cur_shapes_name not in self.organoiDL.pred_bboxes:
+            self.organoiDL.pred_bboxes[self.cur_shapes_name] = torch.empty((0, 4))
+            self.organoiDL.pred_scores[self.cur_shapes_name] = torch.empty((0,))
+            self.organoiDL.pred_labels[self.cur_shapes_name] = torch.empty((0,), dtype=torch.long)
+            self.organoiDL.pred_ids[self.cur_shapes_name] = []
+            self.organoiDL.next_id[self.cur_shapes_name] = 1
+
         # make sure to add info to cur_shapes_layer.metadata to differentiate this action from when user adds/removes boxes
         with utils.set_dict_key( self.cur_shapes_layer.metadata, 'napari-organoid-counter:_rerun', True):
-            # first update bboxes in organoiDLin case user has added/removed
+            # Derive current labels from edge colors to capture any class assignments user made
+            labels_prop, _ = self._assign_labels(validate=False)
+
+            # first update bboxes in organoiDL in case user has added/removed/modified
             self.organoiDL.update_bboxes_scores(self.cur_shapes_name,
                                                 self.cur_shapes_layer.data, 
                                                 self.cur_shapes_layer.properties['scores'],
+                                                labels_prop,
                                                 self.cur_shapes_layer.properties['box_id'])
             # and get new boxes, scores and box ids based on new confidence and min_diameter values 
-            bboxes, scores, box_ids = self.organoiDL.apply_params(self.cur_shapes_name, self.confidence, self.min_diameter)
-            self._update_vis_bboxes(bboxes, scores, box_ids, self.cur_shapes_name)
-
-    def _on_diameter_slider_changed(self):
-        """ Is called whenever user changes the Minimum Diameter slider """
-        # get current value
-        self.min_diameter = self.min_diameter_slider.value()
-        self.diameter_slider_changed = True
-        if int(self.min_diameter_textbox.text())!= self.min_diameter:
-            self.min_diameter_textbox.setText(str(self.min_diameter))
-        self.diameter_slider_changed = False
-        # check if no labels loaded yet
-        if len(self.shape_layer_names)==0: return
-        self._rerun() 
-    
-    def _on_diameter_textbox_changed(self):
-        """ Is called whenever user changes the minimum diameter from the textbox """
-        # check if no labels loaded yet
-        if self.diameter_slider_changed: return
-        self.min_diameter = int(self.min_diameter_textbox.text())
-        if self.min_diameter_slider.value() != self.min_diameter:
-            self.min_diameter_slider.setValue(self.min_diameter)
-        if len(self.shape_layer_names)==0: return
+            bboxes, scores, labels, box_ids = self.organoiDL.apply_params(self.cur_shapes_name, self.confidence, self.min_diameter, self.model_name)
+            self._update_vis_bboxes(bboxes, scores, labels, box_ids, self.cur_shapes_name)
+            self._apply_class_filter()
+            self._refresh_class_counts()
+            self.organoiDL.update_next_id(self.cur_shapes_name)   # keep counter monotonic
+
+    def _on_diameter_changed(self, value: int):
+        """ Is called whenever the minimum diameter spin box value changes """
+        self.min_diameter = value
+        if len(self.shape_layer_names) == 0:
+            return
         self._rerun()
 
     def _on_confidence_slider_changed(self):
@@ -450,26 +853,25 @@ class OrganoidCounterWidget(QWidget):
         if len(self.shape_layer_names)==0: return
         self._rerun()
 
-    def _on_image_selection_changed(self):
-        """ Is called whenever a new image has been selected from the drop down box """
-        self.image_layer_name = self.image_layer_selection.currentText()
-    
-    def _on_shapes_selection_changed(self):
-        """ Is called whenever a new shapes layer has been selected from the drop down box """
-        self.save_layer_name = self.output_layer_selection.currentText()
-
     def _on_reset_click(self):
-        """ Is called whenever Reset Configs button is clicked """
-        # reset params
+        """Reset all settings to built-in defaults."""
+        # Reset min diameter (block signal to avoid triggering _rerun mid-reset)
         self.min_diameter = 30
+        self.min_diameter_spinbox.blockSignals(True)
+        self.min_diameter_spinbox.setValue(self.min_diameter)
+        self.min_diameter_spinbox.blockSignals(False)
+
+        # Reset confidence
         self.confidence = 0.8
-        vis_confidence = int(self.confidence*100)
-        self.min_diameter_slider.setValue(self.min_diameter)
-        self.confidence_slider.setValue(vis_confidence)
-        if self.image_layer_name:
-            # reset to original image
-            self.viewer.layers[self.image_layer_name].data = self.original_images[self.image_layer_name]
-            self.viewer.layers[self.image_layer_name].contrast_limits = self.original_contrast[self.image_layer_name]
+        self.confidence_textbox.setText(str(self.confidence))
+        self.confidence_slider.blockSignals(True)
+        self.confidence_slider.setValue(int(self.confidence * 100))
+        self.confidence_slider.blockSignals(False)
+
+        # Reset window sizes and downsampling
+        self.window_sizes = list(settings.DEFAULT_WINDOW_SIZES)
+        self.downsampling = list(settings.DEFAULT_DOWNSAMPLING)
+        self._sync_window_settings_textboxes()
 
     def _on_screenshot_click(self):
         """ Is called whenever Take Screenshot button is clicked """
@@ -480,29 +882,85 @@ class OrganoidCounterWidget(QWidget):
         name,_ = fd.getSaveFileName(self, 'Save File', potential_name, 'Image files (*.png);;(*.tiff)') #, 'CSV Files (*.csv)')
         if name: imsave(name, screenshot)
 
-    def on_annotation_mode_changed(self, index):
+    def on_annotation_mode_changed(self, mode):
         """Callback for dropdown selection."""
-        if index == 0:  # Single Annotation
-            self.multi_annotation_mode = False
-            # self.single_annotation_mode = True
-            show_info("Switched to Single Annotation mode.")
-        elif index == 1:  # Multi Annotation
-            self.multi_annotation_mode = True
-            # self.single_annotation_mode = False
-            show_info("Switched to Multi Annotation mode.")
+        self.annotation_mode = mode
+        self.selected_classes = self.annotation_mode_mapping[mode]["classes"]
+        self.update_key_bindings()  # Update key bindings based on the selected annotation mode
+        if self.annotation_widget is None:
+            return
+        self._refresh_color_mapping_box()
+    
+    def _assign_labels(self, validate=True):
+        """ Assign labels to the bounding boxes based on their edge colors.
+        
+        Args:
+            validate: If True, check that all colors are valid and return all_valid flag.
+                     If False, assign -1 to unmatched colors (used during _rerun to be lenient).
+        """
+        # Get the edge colors for all bounding boxes
+        edge_colors = self.cur_shapes_layer.edge_color
+        all_valid = True  # Flag to track if all bounding boxes are valid
+        # Check for annotation mode
+        if self.annotation_mode == 0: # Detection Only Mode
+            # Set all labels to None since we don't need them in detection-only mode
+            labels = [-1] * len(edge_colors)
+
+        else: # For other annotation modes (Binary Classification, 3 classes, 4 classes, etc.)
+
+            # Assign organoid label based on edge_color by matching against COLOR_MAPPING
+            labels = []
+
+            for edge_color in edge_colors:
+                matched = False # Flag to check if the current color matches any valid color
+                
+                # First check if it's the default magenta color (unassigned/uncertain)
+                if np.allclose(edge_color[:3], settings.COLOR_DEFAULT[:3], rtol=1e-3, atol=1e-3):
+                    labels.append(-1)  # Assign -1 for default/unassigned boxes
+                    matched = True
+                    if validate:
+                        all_valid = False  # Unassigned boxes are invalid for full save
+                else:
+                    # Check against all color mappings to find the actual class number
+                    for class_num, (color_rgba, color_name) in settings.COLOR_MAPPING.items():
+                        if np.allclose(edge_color[:3], color_rgba[:3], rtol=1e-3, atol=1e-3) and class_num in self.selected_classes:
+                            labels.append(class_num)  # Assign actual class number
+                            matched = True
+                            break
+                
+                # If no match for this edge_color
+                if not matched:
+                    if validate:
+                        all_valid = False
+                        break # Exit the loop early if any color is invalid
+                    else:
+                        # During _rerun, be lenient and assign -1 for unmatched colors
+                        labels.append(-1)
+        return labels, all_valid
 
     def _on_save_csv_click(self): 
         """ Is called whenever Save features button is clicked """
         bboxes = self.viewer.layers[self.save_layer_name].data
-        if not bboxes: show_info('No organoids detected! Please run auto organoid counter or run algorithm first and try again!')
-        else:
-            # write diameters and area to csv
-            data_csv = utils.get_bbox_diameters(bboxes, 
-                                          self.viewer.layers[self.save_layer_name].properties['box_id'],
-                                          self.viewer.layers[self.save_layer_name].scale)
-            fd = QFileDialog()
-            name, _ = fd.getSaveFileName(self, 'Save File', self.save_layer_name, 'CSV files (*.csv)')#, 'CSV Files (*.csv)')
-            if name: utils.write_to_csv(name, data_csv)
+        if not bboxes: 
+            show_info('No organoids detected! Please run auto organoid counter or run algorithm first and try again!')
+            return
+        
+        # Get the labels for the bounding boxes
+        labels, all_valid = self._assign_labels()
+        # If any bounding box has an invalid color, show a warning and return without saving
+        if not all_valid:
+            # If no match is found, mark as not all boxes are colored
+            show_error("Some organoids have not been assigned a valid class (null class). Please ensure all organoids are properly classified before saving.")
+            return
+        
+        # write diameters and area to csv
+        data_csv = utils.get_bbox_diameters(bboxes, 
+                                        self.viewer.layers[self.save_layer_name].properties['box_id'],
+                                        self.viewer.layers[self.save_layer_name].scale,
+                                        labels,)
+        fd = QFileDialog()
+        name, _ = fd.getSaveFileName(self, 'Save File', self.save_layer_name, 'CSV files (*.csv)')#, 'CSV Files (*.csv)')
+        if name: utils.write_to_csv(name, data_csv)
 
     def _on_save_json_click(self):
         """ Is called whenever Save boxes button is clicked """
@@ -512,47 +970,21 @@ class OrganoidCounterWidget(QWidget):
             show_info('No organoids detected! Please run auto organoid counter or run algorithm first and try again!')
             return
         
-        # Check for multi-annotation mode
-        if self.multi_annotation_mode:
-
-            # Get the edge colors for all bounding boxes
-            edge_colors = self.cur_shapes_layer.edge_color
-            labels = []
-
-            # Check if all bounding boxes have their edge color set (not green or blue)
-            green = np.array(settings.COLOR_CLASS_1)
-            blue = np.array(settings.COLOR_CLASS_2)
-
-            all_colored = True
-            for edge_color in edge_colors:
-                # Compare the colors with a tolerance using np.allclose to account for floating-point errors
-                if not (np.allclose(edge_color[:3], green[:3]) or np.allclose(edge_color[:3], blue[:3])):
-                    all_colored = False
-                    break
-
-            if not all_colored:
-                show_error('Please change the color of all bounding boxes before saving.')
-                return
+        # Get the labels for the bounding boxes
+        labels, all_valid = self._assign_labels()
             
-            # Assign organoid label based on edge_color
-            for edge_color in edge_colors:
-                if np.allclose(edge_color[:3], green[:3]):
-                    labels.append(0)  # Label for green
-                elif np.allclose(edge_color[:3], blue[:3]):
-                    labels.append(1)  # Label for blue
-                else:
-                    raise ValueError(f"Unexpected edge color {edge_color[:3]} encountered.")
-
-        #elif self.single_annotation_mode:
-        else:
-            # Single annotation mode: all bounding boxes get a default label
-            labels = [0] * len(bboxes)  # Default label for single annotation mode
+        # If any bounding box has an invalid color, show a warning and return without saving
+        if not all_valid:
+            # If no match is found, mark as not all boxes are colored
+            show_error("Some organoids have not been assigned a valid class (null class). Please ensure all organoids are properly classified before saving.")
+            return
 
+        # Get the bounding boxes as a dictionary
         data_json = utils.get_bboxes_as_dict(bboxes, 
                                     self.viewer.layers[self.save_layer_name].properties['box_id'],
                                     self.viewer.layers[self.save_layer_name].properties['scores'],
                                     self.viewer.layers[self.save_layer_name].scale,
-                                    labels=labels)
+                                    labels,)
             
         
         # write bbox coordinates to json
@@ -562,162 +994,284 @@ class OrganoidCounterWidget(QWidget):
 
     def _update_added_image(self, added_items):
         """
-        Update the selection box with new images if images have been added and update the self.original_images and self.original_contrast dicts.
+        Update the image name display when images have been added and update the self.original_images and self.original_contrast dicts.
         Set the latest added image to the current working image (self.image_layer_name)
         """
         for layer_name in added_items:
-            self.image_layer_selection.addItem(layer_name)
-            self.original_images[layer_name] = self.viewer.layers[layer_name].data
-            self.original_contrast[layer_name] = self.viewer.layers[self.image_layer_name].contrast_limits
+            if layer_name not in self.original_images:
+                self.original_images[layer_name] = self.viewer.layers[layer_name].data
+                self.original_contrast[layer_name] = self.viewer.layers[layer_name].contrast_limits
         self.image_layer_name = added_items[0]
+        layer = self.viewer.layers[self.image_layer_name]
+        self.organoiDL.set_scale(tuple(layer.scale[-2:]))
 
     def _update_removed_image(self, removed_layers):
         """
-        Update the selection box by removing image names if image has been deleted and remove items from self.original_images and self.original_contrast dicts.
+        Remove deleted images from self.original_images and self.original_contrast dicts,
+        and update the image name display if the current image was removed.
         """
-        # update drop-down selection box and remove image from dict
         for removed_layer in removed_layers:
-            item_id = self.image_layer_selection.findText(removed_layer)
-            self.image_layer_selection.removeItem(item_id)
             del self.original_images[removed_layer]
             del self.original_contrast[removed_layer]
+        if self.image_layer_name in removed_layers:
+            self.image_layer_name = None
+            # self._update_image_name_display()
+
+    def _setup_mouse_callback(self):
+        """Set up a mouse move callback to display box IDs in the status bar."""
+        @self.viewer.mouse_move_callbacks.append
+        def mouse_move_callback(viewer, event):
+            if self.cur_shapes_layer is None:
+                self._hover_idx = None
+                self._hover_base = ""
+                return
+
+            layer = self.cur_shapes_layer
+            pos_data = layer.world_to_data(event.position)
+            value = layer.get_value(pos_data)
+
+            # If there's no shape under cursor, clear cached index and return
+            if value is None or value[0] is None:
+                self._hover_idx = None
+                self._hover_base = ""
+                return
+
+            # Get shape index and properties
+            idx = value[0]
+
+            # Recompute the static part ONLY when entering a new box
+            if idx != self._hover_idx:
+                props = layer.properties
+                n = len(layer.data)
+                box_id = props.get('box_id', [None]*n)[idx]
+                scores = props.get('scores', [None]*n)
+                score = scores[idx] if idx < len(scores) else None
+                score_txt = f", Conf.: {score:.2f}" if score is not None else ""
+
+                bbox = layer.data[idx]                     # [[x1,y1],[x1,y2],[x2,y2],[x2,y1]]
+                sx, sy = layer.scale
+                d1 = abs(bbox[2][0] - bbox[0][0]) * sx     # µm
+                d2 = abs(bbox[2][1] - bbox[0][1]) * sy     # µm
+                area = math.pi * d1 * d2 / 4               # µm²
+
+                self._hover_base = (
+                    f"Organoid ID: {box_id}{score_txt}, "
+                    f"d1={d1:.1f} µm, d2={d2:.1f} µm, area={area:.1f} µm² | Coordinates:"
+                )
+                self._hover_idx = idx
+
+            # Always update only the coords while staying in the same box
+            coords_only = f"[{int(event.position[0])} {int(event.position[1])}]"
+            cur_status = viewer.status
+            status = dict(cur_status) if isinstance(cur_status, dict) else {}
+
+            status.update({
+                'source_type': 'plugin',     # tell Napari to show the plugin message
+                'plugin': self._hover_base,  # unchanged while inside the box
+                'layer_base': '',            # blank default layer message
+                'help': '',                  # blank help/hints that can override
+                'coordinates': coords_only,  #     live coords
+            })
+
+            viewer.status = status
 
     def _update_added_shapes(self, added_items):
         """
         Update the selection box by shape layer names if it they have been added, update current working shape layer and instantiate OrganoiDL if not already there
         """
-        # update the drop down box displaying shape layer names for saving
-        for layer_name in added_items:
-            self.output_layer_selection.addItem(layer_name)
         # set the latest added shapes layer to the shapes layer that has been selected for saving and visualisation
         self.save_layer_name = added_items[0]
         self.cur_shapes_name = added_items[0]
         self.cur_shapes_layer = self.viewer.layers[self.cur_shapes_name] 
+
+        for layer_name in added_items:
+            layer = self.viewer.layers[layer_name]
+            self._shape_name_by_id[id(layer)] = layer.name
+            self.stored_diameters.setdefault(layer_name, self.min_diameter_spinbox.value())
+            self.stored_confidences.setdefault(layer_name, self.confidence_slider.value()/100)
+            # bind rename handler
+            layer.events.name.connect(lambda e, layer=layer: self._on_shapes_layer_renamed(layer))
+
+        # self.cur_shapes_layer.events.highlight.connect(self._on_shape_hover)
+
         # get the bounding box and update the displayed number of organoids
         self._update_num_organoids(len(self.cur_shapes_layer.data)) 
+        labels_prop = self.cur_shapes_layer.properties.get(
+            'labels',
+            [-1] * len(self.cur_shapes_layer.data)
+        )        
         # listen for a data change in the current shapes layer
         self.organoiDL.update_bboxes_scores(self.cur_shapes_name,
                                             self.cur_shapes_layer.data,
                                             self.cur_shapes_layer.properties['scores'],
+                                            labels_prop,
                                             self.cur_shapes_layer.properties['box_id']
                                             )
         self.cur_shapes_layer.events.data.connect(self.shapes_event_handler)
-        
+        self._apply_class_filter()
+        self._refresh_class_counts()
+        self.organoiDL.update_next_id(self.cur_shapes_name)
+
     def _update_remove_shapes(self, removed_layers):
         """
-        Update the selection box by removing shape layer names if it they been deleted and set 
+        Update state when shape layers are deleted.
+        Clean up backend dicts and rename-tracking state.
         """
-        # update selection box by removing image names if image has been deleted       
         for removed_layer in removed_layers:
-            item_id = self.output_layer_selection.findText(removed_layer)
-            self.output_layer_selection.removeItem(item_id)
-            if removed_layer==self.cur_shapes_name: 
+            # reset count if this was the active layer
+            if removed_layer == self.cur_shapes_name:
                 self._update_num_organoids(0)
-                self.organoiDL.remove_shape_from_dict(self.cur_shapes_name)
+
+            # drop backend data for this layer (guard if already gone)
+            if removed_layer in self.organoiDL.pred_bboxes:
+                self.organoiDL.remove_shape_from_dict(removed_layer)
+
+            # remove any rename-tracking entries that pointed to this name
+            dead_ids = [lid for lid, name in list(self._shape_name_by_id.items()) if name == removed_layer]
+            for lid in dead_ids:
+                self._shape_name_by_id.pop(lid, None)
+
+            # clear pointers if they referenced the removed layer
+            if self.cur_shapes_name == removed_layer:
+                self.cur_shapes_name = ''
+                self.cur_shapes_layer = None
+            if self.save_layer_name == removed_layer:
+                self.save_layer_name = ''
+
+        self._apply_class_filter()
+        self._refresh_class_counts()
 
     def shapes_event_handler(self, event):
         """
         This function will be called every time the current shapes layer data changes
-        """        
+        """   
         # make sure this stuff isn't done if data in the layer has been changed by the sliders - only by the users
         key = 'napari-organoid-counter:_rerun'
         if key in self.cur_shapes_layer.metadata: 
             return 
-        
+
+        # Guard: set scale if not yet initialized
+        if self.organoiDL.img_scale[0] == 0 and self.cur_shapes_layer is not None:
+            self.organoiDL.set_scale(self.cur_shapes_layer.scale)
+
+        # GUARD: ensure backend dicts exist under the current layer name
+        if self.cur_shapes_name not in self.organoiDL.pred_bboxes:
+            self.organoiDL.pred_bboxes[self.cur_shapes_name] = torch.empty((0, 4))
+            self.organoiDL.pred_scores[self.cur_shapes_name] = torch.empty((0,))
+            self.organoiDL.pred_labels[self.cur_shapes_name] = torch.empty((0,), dtype=torch.long)
+            self.organoiDL.pred_ids[self.cur_shapes_name] = []
+            self.organoiDL.next_id[self.cur_shapes_name] = 1
+
         # get new ids, new boxes and update the number of organoids
         new_ids = self.viewer.layers[self.cur_shapes_name].properties['box_id']
         self._update_num_organoids(len(new_ids))
         
-        # check if duplicate ids - this happens when user adds a box, currently only available fix current_properties doesn't work
+        # check if duplicate ids - this happens when user adds a box
         if len(new_ids) > len(set(new_ids)):
             num_sim = len(new_ids) - len(set(new_ids))
-            if num_sim > 1: print('this should not happen!!!!!!!!!!!!!!!!!')
-            else: 
-                new_ids[-1] = self.organoiDL.next_id[self.cur_shapes_name]
-                new_scores = self.viewer.layers[self.cur_shapes_name].properties['scores']
-                new_scores[-1] = 1
+            if num_sim > 1:  RuntimeWarning('At least one duplicate Box ID found.')
+            existing_ids = [int(i) for i in new_ids[:-1]]
+            backend_ids = [int(i) for i in self.organoiDL.pred_ids.get(self.cur_shapes_name, [])]
+            next_unique_id = max(existing_ids + backend_ids, default=0) + 1
+            next_unique_id = max(next_unique_id, int(self.organoiDL.next_id.get(self.cur_shapes_name, 1)))
+            new_ids[-1] = next_unique_id
+            new_scores = self.viewer.layers[self.cur_shapes_name].properties['scores']
+            new_scores[-1] = 1  # give new box score = 1
+            new_labels = self.viewer.layers[self.cur_shapes_name].properties.get(
+                'labels', [-1] * len(self.cur_shapes_layer.data)
+            )
     
             # set new properties to shapes layer
-            self.viewer.layers[self.cur_shapes_name].properties ={'box_id': new_ids,'scores':  new_scores}
+            self.viewer.layers[self.cur_shapes_name].properties = {
+                'box_id': new_ids,
+                'scores': new_scores,
+                'labels': new_labels,
+            }
             # refresh text displayed
             self.viewer.layers[self.cur_shapes_name].refresh()
             self.viewer.layers[self.cur_shapes_name].refresh_text()
+
+            self.organoiDL.update_bboxes_scores(
+                self.cur_shapes_name,
+                self.cur_shapes_layer.data,
+                new_scores,
+                new_labels,
+                new_ids,
+            )
+
             # and update the OrganoiDL instance
             self.organoiDL.update_next_id(self.cur_shapes_name)
         
+        self._apply_class_filter()
+        self._refresh_class_counts()
+
+
         # this doesn't work!!!!
         # the problem is that the event is called once before the drawing has been completed!!!!!!
         #new_bboxes = self.cur_shapes_layer.data
         #self.organoiDL.update_bboxes_scores(new_bboxes, new_scores, new_ids)
         
-    def _setup_input_widget(self):
-        """
-        Sets up the GUI part which corresposnds to the input configurations
-        """
-        # setup all the individual boxes
-        input_box = self._setup_input_box()
-        model_box = self._setup_model_box()
-        window_sizes_box = self._setup_window_sizes_box()
-        downsampling_box = self._setup_downsampling_box()
-        run_box = self._setup_run_box()
-        annotation_mode_box = self._setup_annotation_mode_box() # Annotation mode dropdown to select single or multi-annotation
+    def _make_help_button(self, tooltip_text: str):
+        """Return a small circular '?' button that shows a tooltip on hover."""
+        btn = QToolButton(self)
+        btn.setText("?")
+        btn.setFixedSize(18, 18)
+        btn.setToolTip(tooltip_text)
+        btn.setFocusPolicy(Qt.NoFocus)
+        btn.setCursor(Qt.WhatsThisCursor)
+        btn.setStyleSheet(
+            "QToolButton {"
+            "  border: 1px solid palette(mid);"
+            "  border-radius: 9px;"
+            "  font-weight: bold;"
+            "  font-size: 11px;"
+            "  color: palette(button-text);"
+            "  background: palette(button);"
+            "  padding: 0px;"
+            "}"
+            "QToolButton:hover {"
+            "  background: palette(highlight);"
+            "  color: palette(highlighted-text);"
+            "}"
+        )
+        return btn
+
+    def _make_help_button(self, tooltip_text: str) -> _HelpButton:
+            """Return a small circular '?' button that shows a tooltip immediately on hover."""
+            return _HelpButton(tooltip_text, self)
+
+    def _setup_model_widget(self):
+        """Sets up the Model section: selection, run parameters, controls."""
+        self.organoid_number_label = QLabel('Number of organoids: ' + str(self.num_organoids), self)
+        self.organoid_number_label.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
         self._setup_progress_box()
 
-        # and add all these to the layout
-        input_widget = QGroupBox('Input configurations')
-        vbox = QVBoxLayout()
-        vbox.addLayout(input_box)
-        vbox.addLayout(model_box)
-        vbox.addLayout(window_sizes_box)
-        vbox.addLayout(downsampling_box)
-        vbox.addLayout(run_box)
-        vbox.addLayout(annotation_mode_box)  # Add the annotation dropdown
-        vbox.addWidget(self.progress_box)
-        input_widget.setLayout(vbox)
-        return input_widget
-
-    def _setup_output_widget(self):
-        """
-        Sets up the GUI part which corresposnds to the parameters and outputs
-        """
-        # setup all the individual boxes
-        self.organoid_number_label = QLabel('Number of organoids: '+str(self.num_organoids), self)
-        self.organoid_number_label.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
-        # and add all these to the layout
-        output_widget = QGroupBox('Parameters and outputs')
+        model_widget = QGroupBox('Inference Settings')
         vbox = QVBoxLayout()
+        vbox.addLayout(self._setup_model_box())
+        vbox.addLayout(self._setup_window_sizes_box())
+        vbox.addLayout(self._setup_downsampling_box())
+        vbox.addLayout(self._setup_run_box())
         vbox.addLayout(self._setup_min_diameter_box())
-        vbox.addLayout(self._setup_confidence_box() )
+        vbox.addLayout(self._setup_confidence_box())
         vbox.addWidget(self.organoid_number_label)
-        vbox.addLayout(self._setup_reset_box())
-        vbox.addLayout(self._setup_save_box())
-        
-        output_widget.setLayout(vbox)
-        return output_widget
+        vbox.addLayout(self._setup_bottom_buttons_box())
+        vbox.addWidget(self.progress_box)
+        model_widget.setLayout(vbox)
+        return model_widget
 
-    def _setup_input_box(self):
-        """
-        Sets up the GUI part where the input image is defined
-        """
-        #self.input_box = QGroupBox()
-        hbox = QHBoxLayout()
-        # setup label
-        image_label = QLabel('Image: ', self)
-        image_label.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
-        # setup drop down option for selecting which image to process
-        self.image_layer_selection = QComboBox()
-        if self.image_layer_names is not None:
-            for name in self.image_layer_names: self.image_layer_selection.addItem(name)
-        #self.image_layer_selection.setItemText(self.image_layer_name)
-        self.image_layer_selection.currentIndexChanged.connect(self._on_image_selection_changed)
-        # setup preprocess button to improve visualisation
-        preprocess_btn = QPushButton("Preprocess")
-        preprocess_btn.clicked.connect(self._on_preprocess_click)
-        # and add all these to the layout
-        hbox.addWidget(image_label, 2)
-        hbox.addWidget(self.image_layer_selection, 4)
-        hbox.addWidget(preprocess_btn, 4)
-        return hbox
+    def _setup_annotation_widget(self):
+        """Sets up the Annotation section: mode selection and class-color legend."""
+        self.annotation_widget = QGroupBox('Annotation')
+        vbox = QVBoxLayout()
+        vbox.addLayout(self._setup_annotation_mode_box())
+        if self.annotation_mode != 0:
+            self.legend_box = self._setup_color_mapping_box()
+            vbox.addWidget(self.legend_box)
+        else:
+            self.legend_box = None
+        self.annotation_widget.setLayout(vbox)
+        return self.annotation_widget
 
     def _setup_model_box(self):
         """
@@ -758,17 +1312,17 @@ class OrganoidCounterWidget(QWidget):
         # setup label
         window_sizes_label = QLabel('Window sizes: [size1, size2, ...]', self)
         window_sizes_label.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
-        window_sizes_label.setToolTip(info_text)
         # setup textbox
         self.window_sizes_textbox = QLineEdit(self)
         text = [str(window_size) for window_size in self.window_sizes]
         text = ','.join(text)
         self.window_sizes_textbox.setText(text)
         self.window_sizes_textbox.returnPressed.connect(self._on_window_sizes_changed)
-        self.window_sizes_textbox.setToolTip(info_text)
+        self.window_sizes_textbox.editingFinished.connect(self._on_window_sizes_changed)
         # and add all these to the layout
         hbox.addWidget(window_sizes_label)
-        hbox.addWidget(self.window_sizes_textbox)   
+        hbox.addWidget(self.window_sizes_textbox)
+        hbox.addWidget(self._make_help_button(info_text))
         #self.window_sizes_box.setLayout(hbox)   
         #self.window_sizes_box.setStyleSheet("border: 0px")  
         return hbox
@@ -787,19 +1341,17 @@ class OrganoidCounterWidget(QWidget):
         # setup label
         downsampling_label = QLabel('Downsampling: [ds1, ds2, ...]', self)
         downsampling_label.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
-        downsampling_label.setToolTip(info_text)
         # setup textbox
         self.downsampling_textbox = QLineEdit(self)
         text = [str(ds) for ds in self.downsampling]
         text = ','.join(text)
         self.downsampling_textbox.setText(text)
         self.downsampling_textbox.returnPressed.connect(self._on_downsampling_changed)
-        self.downsampling_textbox.setToolTip(info_text)
+        self.downsampling_textbox.editingFinished.connect(self._on_downsampling_changed)
         # and add all these to the layout
         hbox.addWidget(downsampling_label)
-        hbox.addWidget(self.downsampling_textbox) 
-        #self.downsampling_box.setLayout(hbox)
-        #self.downsampling_box.setStyleSheet("border: 0px") 
+        hbox.addWidget(self.downsampling_textbox)
+        hbox.addWidget(self._make_help_button(info_text))
         return hbox
 
     def _setup_run_box(self):
@@ -810,8 +1362,48 @@ class OrganoidCounterWidget(QWidget):
         hbox.addStretch(1)
         run_btn = QPushButton("Run Organoid Counter")
         run_btn.clicked.connect(self._on_run_click)
-        run_btn.setStyleSheet("border: 0px")
+        run_btn.setStyleSheet("""
+            QPushButton {
+                background-color: #0078D4;
+                color: #FFFFFF;
+                border: none;
+                border-radius: 4px;
+                padding: 6px 14px;
+                font-weight: bold;
+            }
+            QPushButton:hover {
+                background-color: #106EBE;
+            }
+            QPushButton:pressed {
+                background-color: #005A9E;
+            }
+        """)
         hbox.addWidget(run_btn)
+
+        self.cancel_btn = QPushButton("Cancel")
+        self.cancel_btn.clicked.connect(self._on_cancel_click)
+        self.cancel_btn.setEnabled(False)
+        self.cancel_btn.setStyleSheet("""
+            QPushButton {
+                background-color: #5C5C5C;
+                color: #FFFFFF;
+                border: none;
+                border-radius: 4px;
+                padding: 6px 14px;
+            }
+            QPushButton:hover {
+                background-color: #6E6E6E;
+            }
+            QPushButton:pressed {
+                background-color: #4A4A4A;
+            }
+            QPushButton:disabled {
+                background-color: #3A3A3A;
+                color: #888888;
+            }
+        """)
+        hbox.addWidget(self.cancel_btn)
+
         hbox.addStretch(1)
         return hbox
     
@@ -822,12 +1414,16 @@ class OrganoidCounterWidget(QWidget):
         hbox = QHBoxLayout()
 
         # Label
-        annotation_mode_label = QLabel("Annotation Mode:", self)
+        annotation_mode_label = QLabel("Number of classes to annotate:", self)
         hbox.addWidget(annotation_mode_label)
 
         # Dropdown
         self.annotation_mode_dropdown = QComboBox()
-        self.annotation_mode_dropdown.addItems(["Single Annotation", "Multi Annotation"])
+        self.annotation_mode_dropdown.addItems(["Detection Only (DO)", "Binary Classification (BC)", "3 classes", "4 classes", "5 classes", "6 classes", "7 classes", "8 classes", "9 classes", "10 classes"])
+        # Set default selection based on current annotation mode
+        self.annotation_mode_dropdown.blockSignals(True)
+        self.annotation_mode_dropdown.setCurrentIndex(self.annotation_mode)
+        self.annotation_mode_dropdown.blockSignals(False)
         self.annotation_mode_dropdown.currentIndexChanged.connect(self.on_annotation_mode_changed)
         hbox.addWidget(self.annotation_mode_dropdown)
         
@@ -853,24 +1449,23 @@ class OrganoidCounterWidget(QWidget):
         Sets up the GUI part where the minimum diameter parameter is displayed
         """
         hbox = QHBoxLayout()
-        # setup the min diameter slider
-        self.min_diameter_slider = QSlider(Qt.Horizontal)
-        self.min_diameter_slider.setMinimum(10)
-        self.min_diameter_slider.setMaximum(100)
-        self.min_diameter_slider.setSingleStep(10)
-        self.min_diameter_slider.setValue(self.min_diameter)
-        self.min_diameter_slider.valueChanged.connect(self._on_diameter_slider_changed)
-        # setup the label
-        min_diameter_label = QLabel('Minimum Diameter [um]: ', self)
+        min_diameter_label = QLabel('Minimum Diameter [μm]: ', self)
         min_diameter_label.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
-        # setup text box
-        self.min_diameter_textbox = QLineEdit(self)
-        self.min_diameter_textbox.setText(str(self.min_diameter))
-        self.min_diameter_textbox.returnPressed.connect(self._on_diameter_textbox_changed)  
-        # and add all these to the layout
+        self.min_diameter_spinbox = QSpinBox(self)
+        self.min_diameter_spinbox.setMinimum(0)
+        self.min_diameter_spinbox.setMaximum(10000)
+        self.min_diameter_spinbox.setSingleStep(10)
+        self.min_diameter_spinbox.setValue(self.min_diameter)
+        self.min_diameter_spinbox.valueChanged.connect(self._on_diameter_changed)
+        info_text = (
+            "Each organoid is approximated as an ellipse whose two diameters (D1, D2) are the\n"
+            "width and height of its bounding box in micrometers (µm).\n"
+            "Any detection where either diameter is below this threshold is discarded.\n"
+            "Requires the image pixel scale to be set correctly. Set to 0 to keep all detections."
+        )
         hbox.addWidget(min_diameter_label, 4)
-        hbox.addWidget(self.min_diameter_textbox, 1)
-        hbox.addWidget(self.min_diameter_slider, 5)
+        hbox.addWidget(self.min_diameter_spinbox, 6)
+        hbox.addWidget(self._make_help_button(info_text))
         return hbox
 
     def _setup_confidence_box(self):
@@ -893,63 +1488,810 @@ class OrganoidCounterWidget(QWidget):
         self.confidence_textbox = QLineEdit(self)
         self.confidence_textbox.setText(str(self.confidence))
         self.confidence_textbox.returnPressed.connect(self._on_confidence_textbox_changed)  
+        info_text = (
+            "Minimum score the model must assign to a detection for it to be kept.\n"
+            "Range: 0.05 (keep almost everything) to 1.0 (only near-certain detections).\n"
+            "Higher values reduce false positives but may miss real organoids.\n"
+            "You can type a value directly or drag the slider. Press Enter to apply a typed value."
+        )
         # and add all these to the layout
         hbox.addWidget(confidence_label, 3)
         hbox.addWidget(self.confidence_textbox, 1)
         hbox.addWidget(self.confidence_slider, 6)
+        hbox.addWidget(self._make_help_button(info_text))
         return hbox
 
-    def _setup_reset_box(self):
-        """
-        Sets up the GUI part where screenshot and reset are available to the user
-        """
-        #self.reset_box = QGroupBox()
+    def _setup_color_mapping_box(self) -> QGroupBox:
+        """Build the legend with live counts, per-class check-boxes and a scroll-bar."""
+        self.class_count_labels   = {}
+        self.class_checkboxes     = {}
+        self.visible_classes_filter = set(self.selected_classes)
+
+        outer = QGroupBox("Class-color mapping")
+        outer_layout = QVBoxLayout(outer)
+
+        # master “all classes” check-box
+        master_row = QHBoxLayout()
+        self.master_class_checkbox = QCheckBox("All classes")
+        self.master_class_checkbox.setChecked(True)
+        self.master_class_checkbox.toggled.connect(self._on_master_class_toggled)
+        master_row.addWidget(self.master_class_checkbox)
+        master_row.addStretch(1)
+        outer_layout.addLayout(master_row)
+
+        # scroll area that will hold the per-class rows
+        scroll = QScrollArea()
+        scroll.setWidgetResizable(True)
+        scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)  # only vertical
+        scroll.setFixedHeight(160)          # ≈ 4 rows; tweak if needed
+
+        inner = QWidget()
+        inner_layout = QVBoxLayout(inner)
+
+        for cls in sorted(self.selected_classes):
+            rgba, name = self.color_mapping[cls]
+            r, g, b, a = (int(c * 255) for c in rgba)
+
+            swatch = QLabel()
+            swatch.setFixedSize(18, 18)
+            swatch.setStyleSheet(
+                f"background-color: rgba({r},{g},{b},{a});"
+                "border: 1px solid black;"
+            )
+
+            label = QLabel()
+            self.class_count_labels[cls] = label
+            self._update_single_class_label(cls)
+
+            cb = QCheckBox()
+            cb.setChecked(True)
+            cb.toggled.connect(lambda checked, c=cls: self._on_class_checkbox_toggled(c, checked))
+            self.class_checkboxes[cls] = cb
+
+            row = QHBoxLayout()
+            row.addWidget(cb)
+            row.addWidget(swatch)
+            row.addWidget(label)
+            row.addStretch(1)
+            inner_layout.addLayout(row)
+
+        inner_layout.addStretch(1)
+        scroll.setWidget(inner)
+        outer_layout.addWidget(scroll)
+
+        return outer
+
+    def _refresh_color_mapping_box(self):
+        """Refresh the color mapping box based on the current annotation mode."""
+        if self.annotation_widget is None:
+            return
+
+        layout = self.annotation_widget.layout()
+        if layout is None:
+            return
+
+        # Remove existing legend box from layout (if any)
+        if self.legend_box is not None:
+            layout.removeWidget(self.legend_box)
+            self.legend_box.deleteLater()
+            self.legend_box = None
+        # Clear all legend widget references; old Qt objects may already be deleted.
+        self.class_count_labels = {}
+        self.class_checkboxes = {}
+        self.master_class_checkbox = None
+        self.visible_classes_filter = set(self.selected_classes)
+
+        # Detection-Only: no legend needed
+        if self.annotation_mode == 0:
+            return
+
+        # Build a new legend reflecting the current annotation mode
+        self.legend_box = self._setup_color_mapping_box()
+        # Insert at index 1, after the annotation mode row at index 0
+        self.annotation_widget.layout().insertWidget(1, self.legend_box)
+
+        self._apply_class_filter()
+        self._refresh_class_counts()
+
+    def _update_single_class_label(self, cls: int) -> None:
+        """Update the legend row for one class with its current (visible) box-count."""
+        label = self.class_count_labels.get(cls)
+        if label is None:
+            return  # legend not built yet
+
+        if self.cur_shapes_layer is None:
+            count = 0
+        else:
+            colors = np.asarray(self.cur_shapes_layer.edge_color)         # (N,4)
+            if colors.size == 0:
+                count = 0
+            else:
+                rgb    = colors[:, :3]
+                # alpha  = colors[:, 3]
+                target = np.array(self.color_mapping[cls][0][:3])         # (3,)
+                mask   = np.all(np.isclose(rgb, target, atol=1e-2), axis=1)  #& (alpha > 1e-3)
+                count  = int(mask.sum())
+
+        name = self.color_mapping[cls][1]
+        label.setText(f"Class {cls} ({name}): {count}")
+
+    def _refresh_class_counts(self) -> None:
+        """Recompute every class row in the legend."""
+        for cls in self.class_count_labels:
+            self._update_single_class_label(cls)
+
+    def _current_visible_classes(self) -> set[int]:
+        """Return the set of classes currently ticked."""
+        # Derive from checkboxes if they exist; otherwise fall back to 'all'
+        if not self.class_checkboxes:
+            return set(self.selected_classes)
+        return {c for c, cb in self.class_checkboxes.items() if cb.isChecked()}
+
+    def _on_master_class_toggled(self, checked: bool) -> None:
+        """Master checkbox toggled — set all class checkboxes accordingly."""
+        # Prevent signal cascade while we sync children
+        for cb in self.class_checkboxes.values():
+            cb.blockSignals(True)
+            cb.setChecked(checked)
+            cb.blockSignals(False)
+
+        self.visible_classes_filter = set(self.selected_classes) if checked else set()
+        self._apply_class_filter()
+        self._refresh_class_counts()
+
+    def _on_class_checkbox_toggled(self, cls: int, checked: bool) -> None:
+        """A per-class checkbox toggled."""
+        self.visible_classes_filter = self._current_visible_classes()
+
+        # Update master state (checked only if all are checked)
+        all_checked = len(self.visible_classes_filter) == len(self.selected_classes)
+        if self.master_class_checkbox is not None:
+            self.master_class_checkbox.blockSignals(True)
+            self.master_class_checkbox.setChecked(all_checked)
+            self.master_class_checkbox.blockSignals(False)
+
+        self._apply_class_filter()
+        self._refresh_class_counts()
+
+    def _apply_class_filter(self) -> None:
+        """Show/hide shapes by class without changing data or recomputing.
+        We set edge alpha to 0 for hidden classes and blank their text."""
+        if self.annotation_mode == 0:
+            return  # Detection-only: no class filtering UI
+        if self.cur_shapes_layer is None:
+            return
+
+        colors = np.asarray(self.cur_shapes_layer.edge_color).copy()  # (N,4)
+        if colors.size == 0:
+            return
+
+        # Determine the class of each shape from its edge colour (RGB)
+        rgb = colors[:, :3]
+        alpha_out = np.ones(len(colors), dtype=float)
+
+        # Hide shapes whose class is NOT selected
+        for cls in self.selected_classes:
+            target = np.array(self.color_mapping[cls][0][:3])
+            matches = np.all(np.isclose(rgb, target, atol=1e-2), axis=1)
+            if cls not in self.visible_classes_filter:
+                alpha_out[matches] = 0.0  # hide
+            else:
+                alpha_out[matches] = 1.0  # show
+
+        # Apply new alpha to the edges
+        colors[:, 3] = alpha_out
+        self.cur_shapes_layer.edge_color = colors
+
+        # Build per-shape text strings (blank for hidden)
+        props = self.cur_shapes_layer.properties
+        box_ids = props.get('box_id', [])
+        scores  = props.get('scores', [])
+        # Napari supports list/array of strings for per-shape text
+        text_strings = []
+        for i in range(len(colors)):
+            if alpha_out[i] > 1e-3 and i < len(box_ids) and i < len(scores):
+                try:
+                    box_id_val = float(box_ids[i])
+                    score_val = float(scores[i])
+                except (TypeError, ValueError):
+                    text_strings.append("")
+                    continue
+
+                if np.isfinite(box_id_val) and np.isfinite(score_val):
+                    text_strings.append(f"ID: {int(box_id_val)}\nConf.: {score_val:.2f}")
+                else:
+                    text_strings.append("")
+            else:
+                text_strings.append("")  # hide text
+
+        # Assign per-shape text
+        self.cur_shapes_layer.text = {
+            'string': text_strings,
+            'size': 9,
+            'anchor': 'upper_left',
+        }
+
+    def _setup_bottom_buttons_box(self):
+        """Sets up the combined Set as Default, Reset, and Screenshot buttons."""
         hbox = QHBoxLayout()
-        # setup button for resetting parameters
-        self.reset_btn = QPushButton("Reset Configs")
+        hbox.addStretch(1)
+
+        self.save_defaults_btn = QPushButton("Set as Default")
+        self.save_defaults_btn.clicked.connect(self._on_save_global_defaults_click)
+
+        self.reset_btn = QPushButton("Reset")
         self.reset_btn.clicked.connect(self._on_reset_click)
-        # setup button for taking screenshot of current viewer
-        self.screenshot_btn = QPushButton("Take screenshot")
+
+        self.screenshot_btn = QPushButton("Screenshot")
         self.screenshot_btn.clicked.connect(self._on_screenshot_click)
-        # and add all these to the layout
-        hbox.addStretch(1)
-        hbox.addWidget(self.screenshot_btn)
-        hbox.addSpacing(15)
+
+        hbox.addWidget(self.save_defaults_btn)
+        hbox.addSpacing(10)
         hbox.addWidget(self.reset_btn)
+        hbox.addSpacing(10)
+        hbox.addWidget(self.screenshot_btn)
         hbox.addStretch(1)
-        #self.reset_box.setLayout(hbox)
-        #self.reset_box.setStyleSheet("border: 0px")
         return hbox
 
-    def _setup_save_box(self):
+    def _setup_data_browser_widget(self):
         """
-        Sets up the GUI part where shapes layer is saved 
+        Sets up the Data Browser section with folder selection, file tree, and navigation buttons.
         """
-        #self.save_box = QGroupBox()
-        hbox = QHBoxLayout()
-        # setup button for saving features
-        self.save_csv_btn = QPushButton("Save features")
-        self.save_csv_btn.clicked.connect(self._on_save_csv_click)
-        # setup button for saving boxes
-        self.save_json_btn = QPushButton("Save boxes")
-        self.save_json_btn.clicked.connect(self._on_save_json_click)
-        # setup label
-        self.save_label = QLabel('Save: ', self)
-        self.save_label.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
-        # setup drop down option for selecting which shapes layer to save
-        self.output_layer_selection = QComboBox()
-        if self.shape_layer_names is not None:
-            for name in self.shape_layer_names: self.output_layer_selection.addItem(name)
-        self.output_layer_selection.currentIndexChanged.connect(self._on_shapes_selection_changed)
-        # and add all these to the layout
-        hbox.addWidget(self.save_label)
-        hbox.addSpacing(5)
-        hbox.addWidget(self.output_layer_selection)
-        hbox.addWidget(self.save_csv_btn)
-        hbox.addWidget(self.save_json_btn)
-        #self.save_box.setLayout(hbox)
-        #self.save_box.setStyleSheet("border: 0px")
-        return hbox
+        data_browser_box = QGroupBox('Data Browser')
+        vbox = QVBoxLayout()
+
+        # Folder selection row
+        folder_row = QHBoxLayout()
+        folder_label = QLabel('Folder:', self)
+        self.folder_path_display = QLineEdit(self)
+        self.folder_path_display.setReadOnly(True)
+        self.folder_path_display.setPlaceholderText('Select a folder...')
+        browse_btn = QPushButton('Browse')
+        browse_btn.clicked.connect(self._on_browse_folder_clicked)
+        folder_row.addWidget(folder_label, 1)
+        folder_row.addWidget(self.folder_path_display, 6)
+        folder_row.addWidget(browse_btn, 2)
+        vbox.addLayout(folder_row)
+
+        # File tree widget
+        self.file_tree = QTreeWidget()
+        self.file_tree.setHeaderLabel('Images')
+        self.file_tree.setMinimumHeight(200)
+        self.file_tree.itemClicked.connect(self._on_tree_item_clicked)
+        vbox.addWidget(self.file_tree)
+
+        # Buttons row
+        buttons_row = QHBoxLayout()
+        buttons_row.addStretch(1)
+        self.save_annotation_btn = QPushButton('Save Annotation')
+        self.save_annotation_btn.clicked.connect(self._on_save_annotation_clicked)
+        self.save_incomplete_btn = QPushButton('Save as a draft')
+        self.save_incomplete_btn.clicked.connect(self._on_save_incomplete_annotation_clicked)
+        self.next_image_btn = QPushButton('Next Image')
+        self.next_image_btn.clicked.connect(self._on_next_image_clicked)
+        buttons_row.addWidget(self.save_annotation_btn)
+        buttons_row.addSpacing(15)
+        buttons_row.addWidget(self.save_incomplete_btn)
+        buttons_row.addSpacing(15)
+        buttons_row.addWidget(self.next_image_btn)
+        buttons_row.addStretch(1)
+        vbox.addLayout(buttons_row)
+
+        data_browser_box.setLayout(vbox)
+        return data_browser_box
+
+    def _on_browse_folder_clicked(self):
+        """Handle folder selection via file dialog."""
+        folder = QFileDialog.getExistingDirectory(self, 'Select Data Folder', '')
+        if folder:
+            self.data_folder = folder
+            self.folder_path_display.setText(folder)
+            self._scan_folder_for_images(folder)
+            self._populate_file_tree()
+
+    def _scan_folder_for_images(self, folder_path: str):
+        """Recursively scan folder for supported image files."""
+        self.image_files = []
+        folder = Path(folder_path)
+        for file_path in sorted(folder.rglob('*')):
+            if (file_path.is_file()
+                    and not file_path.name.startswith('.')
+                    and file_path.suffix in self.supported_image_extensions):
+                self.image_files.append(file_path)
+
+    def _populate_file_tree(self):
+        """Build the tree widget from scanned image files."""
+        self.file_tree.clear()
+        if not self.data_folder:
+            return
+
+        root_path = Path(self.data_folder)
+        # Dictionary to store folder items for hierarchy
+        folder_items: dict[Path, QTreeWidgetItem] = {}
+        current_item_to_select = None
+
+        for img_path in self.image_files:
+            # Get relative path from root
+            rel_path = img_path.relative_to(root_path)
+            parent_parts = rel_path.parts[:-1]  # All parts except filename
+
+            # Build folder hierarchy
+            current_parent = None
+            current_path = root_path
+            for part in parent_parts:
+                current_path = current_path / part
+                if current_path not in folder_items:
+                    folder_item = QTreeWidgetItem()
+                    folder_item.setText(0, part + '/')
+                    folder_item.setData(0, Qt.UserRole, None)  # Folders have no path data
+                    if current_parent is None:
+                        self.file_tree.addTopLevelItem(folder_item)
+                    else:
+                        current_parent.addChild(folder_item)
+                    folder_items[current_path] = folder_item
+                current_parent = folder_items[current_path]
+
+            # Add the image file
+            file_item = QTreeWidgetItem()
+            file_item.setText(0, img_path.name)
+            file_item.setData(0, Qt.UserRole, str(img_path))  # Store full path
+            if self._is_image_annotated(img_path):
+                if self._is_image_annotation_incomplete(img_path):
+                    file_item.setForeground(0, Qt.yellow)
+                else:
+                    file_item.setForeground(0, Qt.green)
+
+            # Highlight the currently loaded image
+            if self.current_image_path is not None and img_path == self.current_image_path:
+                file_item.setBackground(0, QBrush(QColor(145, 145, 145)))  # Light blue
+                # current_item_to_select = file_item
+
+            if current_parent is None:
+                self.file_tree.addTopLevelItem(file_item)
+            else:
+                current_parent.addChild(file_item)
+
+        # Expand all folders by default
+        self.file_tree.expandAll()
+
+    def _meta_json_path(self, img_path: Path) -> Path:
+        """Return the path for the per-image settings metadata file."""
+        return img_path.with_suffix('.meta.json')
+
+    def _save_image_metadata(self, img_path: Path) -> None:
+        """Persist current UI settings alongside the annotation for img_path."""
+        meta = {
+            "confidence": self.confidence,
+            "min_diameter": self.min_diameter,
+            "model_name": self.model_name,
+            "window_sizes": self.window_sizes,
+            "downsampling": self.downsampling,
+            "annotation_mode": self.annotation_mode,
+        }
+        try:
+            utils.write_to_json(str(self._meta_json_path(img_path)), meta)
+        except OSError as exc:
+            show_warning(f"Could not save image metadata: {exc}")
+
+    def _load_image_metadata(self, img_path: Path) -> None:
+        """Load saved settings for img_path. Falls back to global defaults, then built-in defaults."""
+        # Read global defaults as fallback for images with no per-image metadata
+        global_prefs = self._read_global_preferences() or {}
+        fallback_confidence = float(global_prefs.get("confidence", 0.8))
+        fallback_min_diameter = int(global_prefs.get("min_diameter", 30))
+        fallback_window_sizes = global_prefs.get("window_sizes", list(settings.DEFAULT_WINDOW_SIZES))
+        fallback_downsampling = global_prefs.get("downsampling", list(settings.DEFAULT_DOWNSAMPLING))
+
+        meta_path = self._meta_json_path(img_path)
+        if meta_path.exists():
+            try:
+                with meta_path.open("r", encoding="utf-8") as fh:
+                    meta = json.load(fh)
+            except (OSError, json.JSONDecodeError):
+                show_warning(f"Could not read image metadata for {img_path.name}. Using defaults.")
+                meta = {}
+        else:
+            meta = {}  # No per-image metadata: fall back to global defaults
+
+        # Apply confidence
+        confidence = float(meta.get("confidence", fallback_confidence))
+        self.confidence = confidence
+        self.confidence_textbox.setText(str(self.confidence))
+        self.confidence_slider.blockSignals(True)
+        self.confidence_slider.setValue(int(self.confidence * 100))
+        self.confidence_slider.blockSignals(False)
+
+        # Apply min diameter
+        min_diameter = int(meta.get("min_diameter", fallback_min_diameter))
+        self.min_diameter = min_diameter
+        self.min_diameter_spinbox.blockSignals(True)
+        self.min_diameter_spinbox.setValue(self.min_diameter)
+        self.min_diameter_spinbox.blockSignals(False)
+
+        # Apply model name
+        model_name = meta.get("model_name", list(settings.MODELS.keys())[0])
+        if model_name in settings.MODELS:
+            self.model_name = model_name
+            idx = self.model_selection.findText(model_name)
+            if idx >= 0:
+                self.model_selection.blockSignals(True)
+                self.model_selection.setCurrentIndex(idx)
+                self.model_selection.blockSignals(False)
+
+        # Apply window sizes and downsampling
+        window_sizes = meta.get("window_sizes", fallback_window_sizes)
+        downsampling = meta.get("downsampling", fallback_downsampling)
+        try:
+            window_sizes = [int(v) for v in window_sizes]
+            downsampling = [int(v) for v in downsampling]
+            if any(v <= 0 for v in window_sizes + downsampling):
+                raise ValueError
+            self._validate_window_downsampling(window_sizes, downsampling)
+            self.window_sizes = window_sizes
+            self.downsampling = downsampling
+        except (TypeError, ValueError):
+            self.window_sizes = list(settings.DEFAULT_WINDOW_SIZES)
+            self.downsampling = list(settings.DEFAULT_DOWNSAMPLING)
+        self._sync_window_settings_textboxes()
+
+        # Apply annotation mode
+        annotation_mode = int(meta.get("annotation_mode", 2))
+        if annotation_mode != self.annotation_mode:
+            self.annotation_mode_dropdown.blockSignals(True)
+            self.annotation_mode_dropdown.setCurrentIndex(annotation_mode)
+            self.annotation_mode_dropdown.blockSignals(False)
+            self.annotation_mode = annotation_mode
+            self.selected_classes = self.annotation_mode_mapping[annotation_mode]["classes"]
+            self.update_key_bindings()
+            self._refresh_color_mapping_box()
+
+    def _draft_json_path(self, img_path: Path) -> Path:
+        """Return the path for the draft (incomplete) annotation file."""
+        return img_path.with_suffix('.json.draft')
+
+    def _is_image_annotation_incomplete(self, img_path: Path) -> bool:
+        """True if the image has a draft (incomplete) annotation file."""
+        return self._draft_json_path(img_path).exists()
+
+    def _is_image_annotated(self, img_path: Path) -> bool:
+        """Check if a corresponding JSON or draft annotation file exists."""
+        json_path = img_path.with_suffix('.json')
+        return json_path.exists() or self._draft_json_path(img_path).exists()
+
+    def _refresh_file_tree(self):
+        """Refresh the file tree to update annotation status indicators."""
+        self._populate_file_tree()
+
+    def _on_tree_item_clicked(self, item: QTreeWidgetItem, column: int):
+        """Handle click on a tree item - load the image if it's a file."""
+        # First, save current annotation
+        if not self._auto_save_current():
+            return  # Save failed, don't proceed
+
+        img_path_str = item.data(0, Qt.UserRole)
+        if img_path_str is None:
+            # This is a folder, not a file
+            return
+        img_path = Path(img_path_str)
+        self._load_image_and_annotation(img_path)
+
+    def _auto_save_current(self) -> bool:
+        """
+        Auto-save the current annotation if there are boxes.
+        Returns True if save was performed or no save was needed, False on error.
+        When the current image has only a draft (no complete .json), saves as draft
+        so switching images does not overwrite the draft with a full save.
+        """
+        if self.current_image_path is None:
+            return True  # No image loaded, nothing to save
+
+        if (
+            self.cur_shapes_layer is None
+            or len(self.cur_shapes_layer.data) == 0
+            or self.cur_shapes_name not in self.viewer.layers
+            or self.viewer.layers[self.cur_shapes_name] is not self.cur_shapes_layer
+        ):
+            return True  # No boxes to save, or layer reference is stale
+
+        # If this image has only a draft (no complete .json), save as draft so we
+        # do not promote to complete when the user simply switches images.
+        json_path = self.current_image_path.with_suffix('.json')
+        json_draft_path = self._draft_json_path(self.current_image_path)
+        if not json_path.exists() and json_draft_path.exists():
+            return self._save_incomplete_annotation_for_image(self.current_image_path)
+
+        return self._save_annotation_for_image(self.current_image_path)
+
+    def _save_annotation_for_image(self, img_path: Path) -> bool:
+        """
+        Save both JSON and CSV annotation files for the given image.
+        Returns True on success, False on failure.
+        """
+        show_info(f'Saving annotation for {img_path.name}...')
+        if self.cur_shapes_layer is None:
+            show_info('No shapes layer to save.')
+            return False
+
+        bboxes = self.cur_shapes_layer.data
+        if len(bboxes) == 0:
+            show_info('No organoids to save.')
+            return False
+        # if label name and iamge name do not correspont 
+        if self.cur_shapes_layer.name != 'Labels-' + img_path.stem:
+            show_error(f"Layer name '{self.cur_shapes_layer.name}' does not match image name '{img_path.stem}', please restart napari.")
+            return False
+
+        # Get labels from edge colors
+        labels, all_valid = self._assign_labels()
+        if not all_valid:
+            show_error("Some organoids have not been assigned a valid class. Please classify all organoids before saving.")
+                # open a confirmation dialog to ask the user if they want to delete the existing annotation and suggest to save as a draft if they want to keep the existing annotation
+            msg_box = QMessageBox()
+            msg_box.setIcon(QMessageBox.Warning)
+            msg_box.setWindowTitle("Invalid annotation")
+            msg_box.setText("Some organoids have not been assigned a valid class, the annotation will be saved as a draft. To save the annotation, please assign a valid class to all organoids.")
+            msg_box.setStandardButtons(QMessageBox.Ok)
+            result = msg_box.exec_()
+
+            return self._save_incomplete_annotation_for_image(img_path)
+        
+        # Prepare file paths
+        json_path = img_path.with_suffix('.json')
+        csv_path = img_path.with_suffix('.csv')
+
+        # Get bounding box data
+        properties = self.cur_shapes_layer.properties
+        box_ids = properties.get('box_id', list(range(len(bboxes))))
+        scores = properties.get('scores', [1.0] * len(bboxes))
+        scale = (
+            self.viewer.layers[self.image_layer_name].scale
+            if self.image_layer_name and self.image_layer_name in self.viewer.layers
+            else self.cur_shapes_layer.scale
+        )
+
+        # Save JSON (boxes)
+        data_json = utils.get_bboxes_as_dict(bboxes, box_ids, scores, scale, labels)
+        utils.write_to_json(str(json_path), data_json)
+
+        # Save CSV (features)
+        data_csv = utils.get_bbox_diameters(bboxes, box_ids, scale, labels)
+        utils.write_to_csv(str(csv_path), data_csv)
+
+        # Remove draft file if present so image is treated as complete
+        draft_path = self._draft_json_path(img_path)
+        if draft_path.exists():
+            draft_path.unlink()
+
+        show_info(f'Saved annotation to {json_path.name}')
+        self._save_image_metadata(img_path)
+        return True
+
+    def _save_incomplete_annotation_for_image(self, img_path: Path) -> bool:
+        """
+        Save annotation as draft (incomplete): JSON only, no CSV, no requirement
+        that all organoids have a valid class. Returns True on success.
+        """
+        show_info(f'Saving draft annotation for {img_path.name}...')
+        if self.cur_shapes_layer is None:
+            show_info('No shapes layer to save.')
+            return False
+
+        bboxes = self.cur_shapes_layer.data
+        if len(bboxes) == 0:
+            show_info('No organoids to save.')
+            return False
+        
+        if self.cur_shapes_layer.name != 'Labels-' + img_path.stem:
+            show_error(f"Layer name '{self.cur_shapes_layer.name}' does not match image name '{img_path.stem}', please restart napari.")
+            return False
+
+        # Allow unassigned classes (validate=False)
+        labels, _ = self._assign_labels(validate=False)
+
+        draft_path = self._draft_json_path(img_path)
+        properties = self.cur_shapes_layer.properties
+        box_ids = properties.get('box_id', list(range(len(bboxes))))
+        scores = properties.get('scores', [1.0] * len(bboxes))
+        scale = (
+            self.viewer.layers[self.image_layer_name].scale
+            if self.image_layer_name and self.image_layer_name in self.viewer.layers
+            else self.cur_shapes_layer.scale
+        )
+
+        data_json = utils.get_bboxes_as_dict(bboxes, box_ids, scores, scale, labels)
+        utils.write_to_json(str(draft_path), data_json)
+
+        # Remove complete annotation files if present so the image is draft-only
+        json_path = img_path.with_suffix('.json')
+        csv_path = img_path.with_suffix('.csv')
+        if json_path.exists():
+            json_path.unlink()
+        if csv_path.exists():
+            csv_path.unlink()
+
+        show_info(f'Saved draft annotation to {draft_path.name}')
+        self._save_image_metadata(img_path)
+        return True
+
+    @staticmethod
+    def _scales_equal(s1, s2, tol: float = 1e-6) -> bool:
+        """Return True if two (y, x) scale tuples are equal within tolerance."""
+        return len(s1) == len(s2) and all(abs(a - b) < tol for a, b in zip(s1, s2))
+
+    def _load_image_and_annotation(self, img_path: Path):
+        """Load an image and its annotation (if exists) into napari."""
+
+        # Reset shapes state before clearing layers so no stale reference can persist.
+        self.cur_shapes_layer = None
+        self.cur_shapes_name = ''
+        self.save_layer_name = ''
+        self._update_num_organoids(0)
+
+        # Clear existing layers related to the previous image
+        layers_to_remove = []
+        for layer in self.viewer.layers:
+            if isinstance(layer, (layers.Image, layers.Shapes)):
+                layers_to_remove.append(layer.name)
+        for name in layers_to_remove:
+            if name in self.viewer.layers:
+                del self.viewer.layers[name]
+
+        # Load image using BioIO for format-agnostic reading and physical-scale extraction.
+        # current_image_path is set only after a successful load to avoid stale state.
+        image_scale = (1.0, 1.0)  # safe default; also used by the annotation block below
+        try:
+            bio_img = BioImage(str(img_path))
+
+            # physical_pixel_sizes is always a PhysicalPixelSizes NamedTuple;
+            # .Y and .X are float or None.
+            pps = bio_img.physical_pixel_sizes
+            if pps.Y is not None and pps.X is not None and float(pps.Y) > 0 and float(pps.X) > 0:
+                image_scale = (float(pps.Y), float(pps.X))
+
+            # BioIO uses 'S' as the sample (RGB/RGBA) dimension; it is only present
+            # as an attribute on dims when the file is a multi-sample image.
+            # hasattr is the correct guard — grayscale dims objects have no 'S' attr.
+            has_s = hasattr(bio_img.dims, 'S') and bio_img.dims.S > 1
+            if has_s:
+                # RGB or RGBA: collapse T/C/Z to 0, keep S, then convert to grayscale.
+                from skimage.color import rgb2gray
+                img_yxs = bio_img.get_image_data("YXS", T=0, C=0, Z=0)
+                img_data = rgb2gray(img_yxs[..., :3])
+                if img_yxs.dtype == np.uint8:
+                    img_data = (img_data * 255).astype(np.uint8)
+                elif img_yxs.dtype == np.uint16:
+                    img_data = (img_data * 65535).astype(np.uint16)
+                else:
+                    img_data = img_data.astype(img_yxs.dtype)
+            else:
+                # Grayscale or single-channel: collapse every non-spatial dim to index 0.
+                img_data = bio_img.get_image_data("YX", T=0, C=0, Z=0)
+
+            layer_name = img_path.stem
+            self.viewer.add_image(img_data, name=layer_name, scale=image_scale)
+            self.current_image_path = img_path
+            self.image_layer_name = layer_name
+            self._ensure_image_cached(self.image_layer_name)
+            self._preprocess()
+            self.organoiDL.set_scale(image_scale)
+
+        except Exception as exc:
+            show_error(f"Failed to load '{img_path.name}': {exc}")
+            return
+
+        # Check for existing annotation and load it (.json first, then .json.draft)
+        json_path = img_path.with_suffix('.json')
+        draft_path = self._draft_json_path(img_path)
+        annot_path = json_path if json_path.exists() else (draft_path if draft_path.exists() else None)
+        if annot_path is not None:
+            from napari_organoid_counter._reader import reader_function_data_management
+            layer_data = reader_function_data_management(str(annot_path))
+            if layer_data:
+                for data, attrs, layer_type, labels in layer_data:
+                    if layer_type == 'shapes':
+                        saved_scale = tuple(attrs.get('scale', (1.0, 1.0)))
+
+                        # Always apply the authoritative image scale on load.
+                        attrs['scale'] = image_scale
+                        loaded_layer = self.viewer.add_shapes(data, **attrs)
+                        self.cur_shapes_layer = loaded_layer
+                        loaded_layer.current_edge_color = [1.0, 0.0, 1.0, 1.0]
+
+                        # Warn user if the saved scale differs from the image scale.
+                        if not self._scales_equal(saved_scale, image_scale):
+                            msg = QMessageBox(self)
+                            msg.setIcon(QMessageBox.Warning)
+                            msg.setWindowTitle("Scale Mismatch Detected")
+                            msg.setText(
+                                f"The annotation was saved with scale:\n"
+                                f"  (y={saved_scale[0]:.4f}, x={saved_scale[1]:.4f}) µm/px\n\n"
+                                f"The current image scale is:\n"
+                                f"  (y={image_scale[0]:.4f}, x={image_scale[1]:.4f}) µm/px\n\n"
+                                f"Use the image scale for correct physical measurements, or keep "
+                                f"the saved scale to stay consistent with an existing dataset."
+                            )
+                            use_image_btn = msg.addButton("Use Image Scale", QMessageBox.AcceptRole)
+                            msg.addButton("Keep Saved Scale", QMessageBox.RejectRole)
+                            msg.exec_()
+                            if msg.clickedButton() is not use_image_btn:
+                                # Sync image layer to saved scale so boxes and image align in world space.
+                                self.viewer.layers[self.image_layer_name].scale = saved_scale
+                                loaded_layer.scale = saved_scale
+                                self.organoiDL.set_scale(saved_scale)
+
+                        if len(labels) > 0:
+                            best_annotation_mode = self._suggest_annotation_mode(labels)
+                            if best_annotation_mode > self.annotation_mode:
+                                self.annotation_mode_dropdown.setCurrentIndex(best_annotation_mode)
+                                        
+                            
+        self._load_image_metadata(img_path)
+        # Refresh the tree to show updated status
+        self._refresh_file_tree()
+
+    def _suggest_annotation_mode(self, labels: list[int]) -> int:
+        """
+        Suggest the best annotation mode based on the classes present in the loaded annotation.
+        """
+        max_class = max(labels) if labels else -1
+        if max_class == -1:
+            return 0  # Detection Only
+        elif max_class <= 1:
+            return 1  # Binary Classification
+        elif 2 <= max_class <= 9:
+            return max_class  # Corresponding to "2 classes" → index 3, etc.
+        else:
+            return self.annotation_mode  # No change if outside expected range
+
+    def _on_save_annotation_clicked(self):
+        """Handle Save Annotation button click."""
+        if self.current_image_path is None:
+            show_info('No image loaded from Data Browser. Please select an image first.')
+            return
+        
+        if self._save_annotation_for_image(self.current_image_path):
+            self._refresh_file_tree()
+
+    def _on_save_incomplete_annotation_clicked(self):
+        """Handle Save as a draft button click."""
+        if self.current_image_path is None:
+            show_info('No image loaded from Data Browser. Please select an image first.')
+            return
+
+        if self._save_incomplete_annotation_for_image(self.current_image_path):
+            self._refresh_file_tree()
+
+    def _on_next_image_clicked(self):
+        """Find and load the next unannotated image."""
+        # First, save current annotation
+        if not self._auto_save_current():
+            return  # Save failed, don't proceed
+
+        self._refresh_file_tree()
+
+        # Find the next unannotated image
+        if not self.image_files:
+            show_info('No images in folder. Please select a folder first.')
+            return
+
+        # Find current image index
+        current_idx = -1
+        if self.current_image_path is not None:
+            try:
+                current_idx = self.image_files.index(self.current_image_path)
+            except ValueError:
+                current_idx = -1
+
+        # Search for next unannotated image starting from current position
+        n = len(self.image_files)
+        for i in range(1, n + 1):
+            idx = (current_idx + i) % n
+            img_path = self.image_files[idx]
+            if not self._is_image_annotated(img_path):
+                self._load_image_and_annotation(img_path)
+                return
+
+        show_info('All images have been annotated!')
 
     def _get_layer_names(self, layer_type: layers.Layer = layers.Image) -> List[str]:
         """
@@ -958,7 +2300,24 @@ class OrganoidCounterWidget(QWidget):
         layer_names = [layer.name for layer in self.viewer.layers if type(layer) == layer_type]
         if layer_names: return [] + layer_names
         else: return []
-
+    
+    def _disable_native_open_shortcut(self):
+        """Clear napari's default Ctrl+O / Cmd+O shortcut to prevent conflict with the Data Browser."""
+        try:
+            from qtpy.QtGui import QKeySequence
+            menubar = self.viewer.window._qt_window.menuBar()
+            for action in menubar.actions():
+                menu = action.menu()
+                if menu is None:
+                    continue
+                if 'file' in action.text().lower():
+                    for sub_action in menu.actions():
+                        if 'open' in sub_action.text().lower() and not sub_action.isSeparator():
+                            sub_action.setShortcut(QKeySequence())
+                            sub_action.setEnabled(False)
+                            return
+        except Exception:
+            pass
 
 class ConfirmUpload(QDialog):
     '''
@@ -992,4 +2351,4 @@ class ConfirmUpload(QDialog):
         self.setLayout(layout)
         # connect ok and cancel buttons with accept and reject signals
         ok_btn.clicked.connect(self.accept)
-        cancel_btn.clicked.connect(self.reject)
\ No newline at end of file
+        cancel_btn.clicked.connect(self.reject)
diff --git a/napari_organoid_counter/analyze_timings.py b/napari_organoid_counter/analyze_timings.py
new file mode 100644
index 0000000..6bbcc58
--- /dev/null
+++ b/napari_organoid_counter/analyze_timings.py
@@ -0,0 +1,242 @@
+#!/usr/bin/env python3
+"""
+Timing Analysis Script for Organoid Counter Experiments
+
+Analyzes JSON timing logs and computes mean ± std for different configurations.
+Groups results by model name and (window_sizes, downsampling) pairs.
+
+Usage:
+    python analyze_timings.py <directory_path>
+    python analyze_timings.py /path/to/timing_logs --output results.txt
+"""
+
+import argparse
+import json
+import sys
+from pathlib import Path
+from collections import defaultdict
+from typing import List, Dict, Tuple
+import numpy as np
+
+
+def load_timing_files(directory: Path) -> List[Dict]:
+    """
+    Load all JSON timing files from the specified directory.
+    
+    Args:
+        directory: Path to directory containing JSON timing logs
+        
+    Returns:
+        List of dictionaries containing timing data
+    """
+    if not directory.exists():
+        print(f"Error: Directory '{directory}' does not exist.", file=sys.stderr)
+        sys.exit(1)
+    
+    json_files = list(directory.glob("*.json"))
+    
+    if not json_files:
+        print(f"Warning: No JSON files found in '{directory}'.", file=sys.stderr)
+        return []
+    
+    timing_data = []
+    for json_file in json_files:
+        try:
+            with open(json_file, 'r') as f:
+                data = json.load(f)
+                timing_data.append(data)
+        except json.JSONDecodeError:
+            print(f"Warning: Could not parse '{json_file.name}'. Skipping.", file=sys.stderr)
+        except Exception as e:
+            print(f"Warning: Error reading '{json_file.name}': {e}. Skipping.", file=sys.stderr)
+    
+    print(f"Loaded {len(timing_data)} timing files from {len(json_files)} JSON files.\n")
+    return timing_data
+
+
+def create_config_key(window_sizes: List[int], downsampling: List[int]) -> str:
+    """
+    Create a standardized configuration key from window sizes and downsampling values.
+    
+    Args:
+        window_sizes: List of window sizes
+        downsampling: List of downsampling values
+        
+    Returns:
+        Formatted string like "[1024, 512]ws, [2, 8]ds"
+    """
+    ws_str = str(window_sizes).replace(" ", "")
+    ds_str = str(downsampling).replace(" ", "")
+    return f"{ws_str}ws, {ds_str}ds"
+
+
+def group_timings(timing_data: List[Dict]) -> Dict[Tuple[str, str], List[float]]:
+    """
+    Group timing data by (model_name, config) and collect elapsed times.
+    
+    Args:
+        timing_data: List of timing dictionaries
+        
+    Returns:
+        Dictionary mapping (model_name, config_key) to list of elapsed times
+    """
+    grouped = defaultdict(list)
+    
+    for entry in timing_data:
+        try:
+            model_name = entry.get("model_name", "unknown")
+            window_sizes = entry.get("window_sizes", [])
+            downsampling = entry.get("downsampling", [])
+            elapsed_time = entry.get("elapsed_time_seconds")
+            
+            if elapsed_time is None:
+                print(f"Warning: Missing elapsed_time_seconds in entry. Skipping.", file=sys.stderr)
+                continue
+            
+            config_key = create_config_key(window_sizes, downsampling)
+            grouped[(model_name, config_key)].append(elapsed_time)
+            
+        except Exception as e:
+            print(f"Warning: Error processing entry: {e}. Skipping.", file=sys.stderr)
+    
+    return grouped
+
+
+def compute_statistics(times: List[float]) -> Tuple[float, float, int]:
+    """
+    Compute mean and standard deviation of timing data.
+    
+    Args:
+        times: List of elapsed times in seconds
+        
+    Returns:
+        Tuple of (mean, std, count)
+    """
+    times_array = np.array(times)
+    mean = np.mean(times_array)
+    std = np.std(times_array, ddof=1) if len(times) > 1 else 0.0
+    return mean, std, len(times)
+
+
+def format_output(grouped_data: Dict[Tuple[str, str], List[float]]) -> str:
+    """
+    Format the grouped timing data into a readable output.
+    Groups by configuration first to allow easy model comparison.
+    Within each configuration, models are sorted by speed (fastest first).
+    
+    Args:
+        grouped_data: Dictionary mapping (model, config) to list of times
+        
+    Returns:
+        Formatted string with statistics
+    """
+    if not grouped_data:
+        return "No timing data to display."
+    
+    # Reorganize data by config first, then by model
+    config_to_models = defaultdict(dict)
+    for (model_name, config_key), times in grouped_data.items():
+        mean, std, count = compute_statistics(times)
+        config_to_models[config_key][model_name] = {
+            'mean': mean,
+            'std': std,
+            'count': count
+        }
+    
+    # Sort configurations (you can customize this order if needed)
+    sorted_configs = sorted(config_to_models.keys())
+    
+    lines = []
+    lines.append("=" * 80)
+    lines.append("TIMING ANALYSIS RESULTS")
+    lines.append("=" * 80)
+    lines.append("")
+    
+    for config_key in sorted_configs:
+        models_dict = config_to_models[config_key]
+        
+        # Sort models by mean time (fastest first)
+        sorted_models = sorted(models_dict.items(), key=lambda x: x[1]['mean'])
+        
+        # Get the fastest time for percentage calculation
+        fastest_time = sorted_models[0][1]['mean'] if sorted_models else 0
+        
+        for idx, (model_name, stats) in enumerate(sorted_models):
+            mean = stats['mean']
+            std = stats['std']
+            count = stats['count']
+            
+            # Calculate percentage increase from fastest
+            if idx == 0:
+                # First (fastest) model - baseline
+                percent_str = "(baseline)"
+            else:
+                percent_increase = ((mean - fastest_time) / fastest_time) * 100
+                percent_str = f"(+{percent_increase:.1f}%)"
+            
+            lines.append(f"{model_name} with {config_key}: "
+                        f"{mean:.2f} ± {std:.2f} sec (n={count}) {percent_str}")
+        
+        # Add empty line between configuration blocks
+        lines.append("")
+    
+    lines.append("=" * 80)
+    
+    return "\n".join(lines)
+
+
+def main():
+    """Main entry point for the timing analysis script."""
+    parser = argparse.ArgumentParser(
+        description="Analyze timing logs from organoid counter experiments.",
+        formatter_class=argparse.RawDescriptionHelpFormatter,
+        epilog="""
+Examples:
+  %(prog)s /path/to/timing_logs
+  %(prog)s ./timing_logs --output results.txt
+        """
+    )
+    
+    parser.add_argument(
+        "directory",
+        type=Path,
+        help="Path to directory containing JSON timing log files"
+    )
+    
+    parser.add_argument(
+        "-o", "--output",
+        type=Path,
+        default=None,
+        help="Optional output file path (default: print to stdout)"
+    )
+    
+    args = parser.parse_args()
+    
+    # Load timing files
+    timing_data = load_timing_files(args.directory)
+    
+    if not timing_data:
+        print("No valid timing data found. Exiting.")
+        sys.exit(1)
+    
+    # Group by model and configuration
+    grouped_data = group_timings(timing_data)
+    
+    # Format output
+    output_text = format_output(grouped_data)
+    
+    # Write or print output
+    if args.output:
+        try:
+            with open(args.output, 'w') as f:
+                f.write(output_text)
+            print(f"Results saved to: {args.output}")
+        except Exception as e:
+            print(f"Error writing to '{args.output}': {e}", file=sys.stderr)
+            sys.exit(1)
+    else:
+        print(output_text)
+
+
+if __name__ == "__main__":
+    main()
\ No newline at end of file
diff --git a/napari_organoid_counter/napari.yaml b/napari_organoid_counter/napari.yaml
index 80cf637..cf32448 100644
--- a/napari_organoid_counter/napari.yaml
+++ b/napari_organoid_counter/napari.yaml
@@ -15,4 +15,5 @@ contributions:
     - command: napari-organoid-counter.get_reader
       filename_patterns:
       - '*.json'
+      - '*.json.draft'
       accepts_directories: false
\ No newline at end of file
diff --git a/napari_organoid_counter/settings.py b/napari_organoid_counter/settings.py
index 2eef96f..9e5f65c 100644
--- a/napari_organoid_counter/settings.py
+++ b/napari_organoid_counter/settings.py
@@ -1,55 +1,88 @@
 from pathlib import Path
 
+
 def init():
-    
+    global DEFAULT_WINDOW_SIZES
+    DEFAULT_WINDOW_SIZES = [1024]
+
+    global DEFAULT_DOWNSAMPLING
+    DEFAULT_DOWNSAMPLING = [2]
+
+    global USER_CONFIG_DIR
+    USER_CONFIG_DIR = Path.home() / ".config/napari-organoid-counter"
+
+    global GLOBAL_DEFAULTS_FILE
+    GLOBAL_DEFAULTS_FILE = USER_CONFIG_DIR / "preferences.json"
+
     global MODELS
     MODELS = {
-        "faster r-cnn": {"filename": "faster-rcnn_r50_fpn_organoid_best_coco_bbox_mAP_epoch_68.pth", 
-                         "source": "https://zenodo.org/records/11388549/files/faster-rcnn_r50_fpn_organoid_best_coco_bbox_mAP_epoch_68.pth"
-                         },
-        "ssd": {"filename": "ssd_organoid_best_coco_bbox_mAP_epoch_86.pth", 
-                "source": "https://zenodo.org/records/11388549/files/ssd_organoid_best_coco_bbox_mAP_epoch_86.pth"
-                },
-        "yolov3": {"filename": "yolov3_416_organoid_best_coco_bbox_mAP_epoch_27.pth",
-                   "source": "https://zenodo.org/records/11388549/files/yolov3_416_organoid_best_coco_bbox_mAP_epoch_27.pth"
-                   },
-        "rtmdet":  {"filename": "rtmdet_l_organoid_best_coco_bbox_mAP_epoch_323.pth",
-                    "source": "https://zenodo.org/records/11388549/files/rtmdet_l_organoid_best_coco_bbox_mAP_epoch_323.pth"
-                    },
+        "faster r-cnn (DO)": {
+            "filename": "faster-rcnn_r50_fpn_organoid_best_coco_bbox_mAP_epoch_68.onnx",
+            "source": "https://zenodo.org/records/18700540/files/faster-rcnn_r50_fpn_organoid_best_coco_bbox_mAP_epoch_68.onnx",
+        },
+        "yolov3 (DO)": {
+            "filename": "yolov3_416_organoid_best_coco_bbox_mAP_epoch_27.onnx",
+            "source": "https://zenodo.org/records/18700540/files/yolov3_416_organoid_best_coco_bbox_mAP_epoch_27.onnx",
+        },
     }
-    
+
     global MODELS_DIR
     MODELS_DIR = Path.home() / ".cache/napari-organoid-counter/models"
 
     global MODEL_TYPE
-    MODEL_TYPE = '.pth'
-
-    global CONFIGS
-    CONFIGS = {
-        "faster r-cnn": {"source": "https://zenodo.org/records/11388549/files/faster-rcnn_r50_fpn_organoid.py",
-                        "destination": ".mim/configs/faster_rcnn/faster-rcnn_r50_fpn_organoid.py"
-                        },
-        "ssd": {"source": "https://zenodo.org/records/11388549/files/ssd_organoid.py",
-                "destination": ".mim/configs/ssd/ssd_organoid.py"
-                },
-        "yolov3": {"source": "https://zenodo.org/records/11388549/files/yolov3_416_organoid.py",
-                "destination": ".mim/configs/yolo/yolov3_416_organoid.py"
-                },
-        "rtmdet":  {"source": "https://zenodo.org/records/11388549/files/rtmdet_l_organoid.py",
-                    "destination": ".mim/configs/rtmdet/rtmdet_l_organoid.py"
-                    }
-
-}
-    
-    # Add color definitions
-    global COLOR_CLASS_1
-    COLOR_CLASS_1 = [85 / 255, 1.0, 0, 1.0]  # Green
-    
-    global COLOR_CLASS_2
-    COLOR_CLASS_2 = [0, 29 / 255, 1.0, 1.0]  # Blue
+    MODEL_TYPE = ".onnx"
+
+    global ONNX_PREPROCESS
+    ONNX_PREPROCESS = {
+        "faster r-cnn (DO)": {
+            "input_size": (800, 1333), # Original is (1333, 800); do we swap due to napari's (y,x) convention?
+            "mean": [123.675, 116.28, 103.53],
+            "std": [58.395, 57.12, 57.375],
+        },
+        "yolov3 (DO)": {
+            "input_size": (416, 416),
+            "mean": [0.0, 0.0, 0.0],
+            "std": [255.0, 255.0, 255.0],
+        },
+    }
 
     global COLOR_DEFAULT
-    COLOR_DEFAULT = [1., 0, 1., 1.] # Magenta
+    COLOR_DEFAULT = [1.0, 0, 1.0, 1.0]
 
+    global COLOR_CLASS_0
+    COLOR_CLASS_0 = [85 / 255, 1.0, 0, 1.0]
+    global COLOR_CLASS_1
+    COLOR_CLASS_1 = [0, 29 / 255, 1.0, 1.0]
+    global COLOR_CLASS_2
+    COLOR_CLASS_2 = [1.0, 0.65, 0, 1.0]
+    global COLOR_CLASS_3
+    COLOR_CLASS_3 = [128 / 256, 0, 128 / 256, 1.0]
+    global COLOR_CLASS_4
+    COLOR_CLASS_4 = [0.0, 1.0, 1.0, 1.0]
+    global COLOR_CLASS_5
+    COLOR_CLASS_5 = [1.0, 0, 0, 1.0]
+    global COLOR_CLASS_6
+    COLOR_CLASS_6 = [150 / 256, 75 / 256, 0 / 256, 1.0]
+    global COLOR_CLASS_7
+    COLOR_CLASS_7 = [0.8, 0.1, 0.6, 1.0]
+    global COLOR_CLASS_8
+    COLOR_CLASS_8 = [1.0, 1.0, 0.0, 1.0]
+    global COLOR_CLASS_9
+    COLOR_CLASS_9 = [0.3, 0.5, 1.0, 1.0]
 
+    global COLOR_MAPPING
+    COLOR_MAPPING = {
+        0: (COLOR_CLASS_0, "Green"),
+        1: (COLOR_CLASS_1, "Blue"),
+        2: (COLOR_CLASS_2, "Orange"),
+        3: (COLOR_CLASS_3, "Purple"),
+        4: (COLOR_CLASS_4, "Cyan"),
+        5: (COLOR_CLASS_5, "Red"),
+        6: (COLOR_CLASS_6, "Brown"),
+        7: (COLOR_CLASS_7, "Pink"),
+        8: (COLOR_CLASS_8, "Yellow"),
+        9: (COLOR_CLASS_9, "Light Blue"),
+    }
 
+    global CONFIDENCE_THRESHOLD_CLASS
+    CONFIDENCE_THRESHOLD_CLASS = 0.7
diff --git a/onnx/original_notebook.ipynb b/onnx/original_notebook.ipynb
new file mode 100644
index 0000000..18f4c1f
--- /dev/null
+++ b/onnx/original_notebook.ipynb
@@ -0,0 +1,771 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "id": "c17bb388-3fdd-4b46-bb96-89e8e21dfde3",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Original Author: Christina Bukas\n",
+    "# Modified by: Abdulkader Ghandoura"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "id": "b3019d6b-c5df-43df-b769-8a5da71b1dc6",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Render matplotlib plots directly in the notebook\n",
+    "%matplotlib inline\n",
+    "\n",
+    "# Load the autoreload extension, which watches for changes in imported modules\n",
+    "%load_ext autoreload\n",
+    "\n",
+    "# Automatically reload all modules before executing each cell\n",
+    "%autoreload 2"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "id": "839176f9-23b3-4531-817c-8f3c6f5d785e",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import os\n",
+    "from pathlib import Path\n",
+    "\n",
+    "from matplotlib import pyplot as plt\n",
+    "import numpy as np\n",
+    "\n",
+    "from skimage.transform import rescale, resize\n",
+    "from skimage.color import gray2rgb\n",
+    "from aicsimageio import imread\n",
+    "\n",
+    "import torch\n",
+    "import torchvision.transforms as T\n",
+    "\n",
+    "import onnxruntime as ort\n",
+    "\n",
+    "from mmdet.apis import init_detector\n",
+    "from mmdeploy.apis.pytorch2onnx import torch2onnx"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "id": "710f523e",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "MODELS: ['rtmdet_l_organoid_best_coco_bbox_mAP_epoch_323.pth', 'yolov3_416_organoid_best_coco_bbox_mAP_epoch_27.pth', 'ssd_organoid_best_coco_bbox_mAP_epoch_86.pth', 'faster-rcnn_r50_fpn_organoid_best_coco_bbox_mAP_epoch_68.pth', 'yolov3_416_organoid_best_coco_bbox_mAP_epoch_27.onnx', 'faster-rcnn_r50_fpn_organoid_best_coco_bbox_mAP_epoch_68.onnx', 'faster-rcnn_r50_fpn_organoid_best_coco_bbox_mAP_epoch_68_backup.onnx']\n"
+     ]
+    },
+    {
+     "data": {
+      "image/png": "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",
+      "text/plain": [
+       "<Figure size 640x480 with 1 Axes>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "models_dir = Path.home() / '.cache/napari-organoid-counter/models'\n",
+    "yolo_model_path = os.path.join(models_dir, 'yolov3_416_organoid_best_coco_bbox_mAP_epoch_27.pth')\n",
+    "rtmdet_model_path = os.path.join(models_dir, 'rtmdet_l_organoid_best_coco_bbox_mAP_epoch_323.pth')\n",
+    "ssd_model_path = os.path.join(models_dir, 'ssd_organoid_best_coco_bbox_mAP_epoch_86.pth')\n",
+    "fasterrcnn_model_path = os.path.join(models_dir, 'faster-rcnn_r50_fpn_organoid_best_coco_bbox_mAP_epoch_68.pth')\n",
+    "\n",
+    "config_path = '/Users/abdulkaderghandoura/miniforge3/envs/napari/lib/python3.10/site-packages/mmdet/.mim/configs'\n",
+    "yolo_config_dst = os.path.join(config_path,'yolo/yolov3_416_organoid.py')\n",
+    "rtmdet_config_dst = os.path.join(config_path, 'rtmdet/rtmdet_l_organoid.py')\n",
+    "ssd_config_dst = os.path.join(config_path, 'ssd/ssd_organoid.py')\n",
+    "fasterrcnn_config_dst = os.path.join(config_path, 'faster_rcnn/faster-rcnn_r50_fpn_organoid.py')\n",
+    "\n",
+    "img_path = '/Users/abdulkaderghandoura/Downloads/MultiOrg/Annotated_by_Gowtham/Images/GoBo032_Control_Plate_PCR_TileScan_1_A_10_Merged_EDF001_ch00.tif'\n",
+    "\n",
+    "\n",
+    "list_models = os.listdir(models_dir)\n",
+    "print(\"MODELS:\", list_models)\n",
+    "\n",
+    "\n",
+    "img = imread(img_path)[0,0,0]\n",
+    "plt.imshow(img, cmap='gray')\n",
+    "plt.show()\n",
+    "\n",
+    "def squeeze_img(img):\n",
+    "    \"\"\" Squeeze image - all dims that have size one will be removed \"\"\"\n",
+    "    return np.squeeze(img)\n",
+    "\n",
+    "def prepare_img(test_img, step, window_size, rescale_factor):\n",
+    "    \"\"\" The original image is prepared for running model inference \"\"\"\n",
+    "    # squeeze and resize image\n",
+    "    test_img = squeeze_img(test_img)\n",
+    "    test_img = rescale(test_img, rescale_factor, preserve_range=True)\n",
+    "    img_height, img_width = test_img.shape\n",
+    "    # pad image\n",
+    "    pad_x = (img_height//step)*step + window_size - img_height\n",
+    "    pad_y = (img_width//step)*step + window_size - img_width\n",
+    "    test_img = np.pad(test_img, ((0, int(pad_x)), (0, int(pad_y))), mode='edge')\n",
+    "    # normalise and convert to RGB - model input has size 3\n",
+    "    test_img = (test_img-np.min(test_img))/(np.max(test_img)-np.min(test_img)) \n",
+    "    test_img = (255*test_img).astype(np.uint8)\n",
+    "    test_img = gray2rgb(test_img) #[H,W,C]\n",
+    "\n",
+    "    # convert from RGB to GBR - expected from DetInferencer \n",
+    "    test_img = test_img[..., ::-1] \n",
+    "    '''\n",
+    "    test_img = test_img.astype(np.float32) / 255.0\n",
+    "    # HWC -> CHW\n",
+    "    test_img = np.transpose(test_img, (2, 0, 1))\n",
+    "    # Add batch dimension\n",
+    "    test_img = np.expand_dims(test_img, axis=0)\n",
+    "    '''\n",
+    "    return test_img, img_height, img_width\n",
+    "\n",
+    "def resize_keep_ratio_numpy(img, scale=(416, 416)):\n",
+    "    \"\"\"\n",
+    "    Resize a numpy array [B, C, H, W] keeping aspect ratio using skimage.\n",
+    "\n",
+    "    Args:\n",
+    "        img (np.ndarray): shape [B, C, H, W]\n",
+    "        scale (tuple): target maximum (w, h), e.g. (416, 416)\n",
+    "\n",
+    "    Returns:\n",
+    "        np.ndarray: resized array [B, C, new_h, new_w]\n",
+    "        (int, int): new size (new_h, new_w)\n",
+    "        float: scale factor\n",
+    "    \"\"\"\n",
+    "    assert img.ndim == 4, \"Expected input shape [B, C, H, W]\"\n",
+    "    B, C, H, W = img.shape\n",
+    "    target_w, target_h = scale\n",
+    "\n",
+    "    # compute scale factor\n",
+    "    scale_factor = min(target_w / W, target_h / H)\n",
+    "    new_w, new_h = int(W * scale_factor), int(H * scale_factor)\n",
+    "\n",
+    "    resized_batch = []\n",
+    "    for i in range(B):\n",
+    "        # [C, H, W] → [H, W, C]\n",
+    "        img_hwc = np.transpose(img[i], (1, 2, 0))\n",
+    "        resized = resize(img_hwc, (new_h, new_w), order=1, anti_aliasing=True)\n",
+    "        # back to [C, H, W]\n",
+    "        resized_chw = np.transpose(resized, (2, 0, 1))\n",
+    "        resized_batch.append(resized_chw.astype(np.float32))\n",
+    "\n",
+    "    resized_batch = np.stack(resized_batch, axis=0)\n",
+    "    return resized_batch "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "id": "d4ca655f",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "model_checkpoint = fasterrcnn_model_path\n",
+    "model_cfg = fasterrcnn_config_dst\n",
+    "save_file = 'faster-rcnn_r50_fpn_organoid_best_coco_bbox_mAP_epoch_68.onnx'\n",
+    "#import mmdeploy\n",
+    "#print(mmdeploy.__version__)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9d379f46",
+   "metadata": {},
+   "source": [
+    "## Export model to onnx format"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "id": "412aba71",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/configs/mmdet/detection/detection_onnxruntime_dynamic.py\n",
+      "(7486, 7630, 3)\n",
+      "11/27 13:29:54 - mmengine - \u001b[5m\u001b[4m\u001b[33mWARNING\u001b[0m - Failed to search registry with scope \"mmdet\" in the \"Codebases\" registry tree. As a workaround, the current \"Codebases\" registry in \"mmdeploy\" is used to build instance. This may cause unexpected failure when running the built modules. Please check whether \"mmdet\" is a correct scope, or whether the registry is initialized.\n",
+      "11/27 13:29:54 - mmengine - \u001b[5m\u001b[4m\u001b[33mWARNING\u001b[0m - Failed to search registry with scope \"mmdet\" in the \"mmdet_tasks\" registry tree. As a workaround, the current \"mmdet_tasks\" registry in \"mmdeploy\" is used to build instance. This may cause unexpected failure when running the built modules. Please check whether \"mmdet\" is a correct scope, or whether the registry is initialized.\n",
+      "Loads checkpoint by local backend from path: /Users/abdulkaderghandoura/.cache/napari-organoid-counter/models/faster-rcnn_r50_fpn_organoid_best_coco_bbox_mAP_epoch_68.pth\n",
+      "11/27 13:29:54 - mmengine - \u001b[5m\u001b[4m\u001b[33mWARNING\u001b[0m - DeprecationWarning: get_onnx_config will be deprecated in the future. \n",
+      "11/27 13:29:54 - mmengine - \u001b[4m\u001b[97mINFO\u001b[0m - Export PyTorch model to ONNX: ./faster-rcnn_r50_fpn_organoid_best_coco_bbox_mAP_epoch_68.onnx.\n"
+     ]
+    },
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/core/optimizers/function_marker.py:160: TracerWarning: Converting a tensor to a Python integer might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  ys_shape = tuple(int(s) for s in ys.shape)\n",
+      "/Users/abdulkaderghandoura/miniforge3/envs/napari/lib/python3.10/site-packages/mmdet/models/dense_heads/anchor_head.py:115: UserWarning: DeprecationWarning: anchor_generator is deprecated, please use \"prior_generator\" instead\n",
+      "  warnings.warn('DeprecationWarning: anchor_generator is deprecated, '\n",
+      "/Users/abdulkaderghandoura/miniforge3/envs/napari/lib/python3.10/site-packages/mmdet/models/task_modules/prior_generators/anchor_generator.py:356: UserWarning: ``grid_anchors`` would be deprecated soon. Please use ``grid_priors`` \n",
+      "  warnings.warn('``grid_anchors`` would be deprecated soon. '\n",
+      "/Users/abdulkaderghandoura/miniforge3/envs/napari/lib/python3.10/site-packages/mmdet/models/task_modules/prior_generators/anchor_generator.py:392: UserWarning: ``single_level_grid_anchors`` would be deprecated soon. Please use ``single_level_grid_priors`` \n",
+      "  warnings.warn(\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/codebase/mmdet/models/dense_heads/rpn_head.py:89: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  assert cls_score.size()[-2:] == bbox_pred.size()[-2:]\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/pytorch/functions/topk.py:28: TracerWarning: torch.tensor results are registered as constants in the trace. You can safely ignore this warning if you use this function to create tensors out of constant variables that would be the same every time you call this function. In any other case, this might cause the trace to be incorrect.\n",
+      "  k = torch.tensor(k, device=input.device, dtype=torch.long)\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/codebase/mmdet/models/task_modules/coders/delta_xywh_bbox_coder.py:38: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  assert pred_bboxes.size(0) == bboxes.size(0)\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/codebase/mmdet/models/task_modules/coders/delta_xywh_bbox_coder.py:40: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  assert pred_bboxes.size(1) == bboxes.size(1)\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/codebase/mmdet/deploy/utils.py:48: TracerWarning: Using len to get tensor shape might cause the trace to be incorrect. Recommended usage would be tensor.shape[0]. Passing a tensor of different shape might lead to errors or silently give incorrect results.\n",
+      "  assert len(max_shape) == 2, '`max_shape` should be [h, w]'\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/mmcv/ops/nms.py:285: TracerWarning: torch.tensor results are registered as constants in the trace. You can safely ignore this warning if you use this function to create tensors out of constant variables that would be the same every time you call this function. In any other case, this might cause the trace to be incorrect.\n",
+      "  iou_threshold = torch.tensor([iou_threshold], dtype=torch.float32)\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/mmcv/ops/nms.py:286: TracerWarning: torch.tensor results are registered as constants in the trace. You can safely ignore this warning if you use this function to create tensors out of constant variables that would be the same every time you call this function. In any other case, this might cause the trace to be incorrect.\n",
+      "  score_threshold = torch.tensor([score_threshold], dtype=torch.float32)\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/mmcv/ops/nms.py:45: TracerWarning: Converting a tensor to a Python float might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  score_threshold = float(score_threshold)\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/mmcv/ops/nms.py:46: TracerWarning: Converting a tensor to a Python float might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  iou_threshold = float(iou_threshold)\n",
+      "/Users/abdulkaderghandoura/miniforge3/envs/napari/lib/python3.10/site-packages/mmcv/ops/nms.py:123: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  assert boxes.size(1) == 4\n",
+      "/Users/abdulkaderghandoura/miniforge3/envs/napari/lib/python3.10/site-packages/mmcv/ops/nms.py:124: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  assert boxes.size(0) == scores.size(0)\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/codebase/mmdet/models/roi_heads/standard_roi_head.py:41: TracerWarning: Converting a tensor to a Python integer might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  rois_dims = int(rois.shape[-1])\n",
+      "/Users/abdulkaderghandoura/miniforge3/envs/napari/lib/python3.10/site-packages/mmcv/ops/roi_align.py:78: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  assert rois.size(1) == 5, 'RoI must be (idx, x1, y1, x2, y2)!'\n",
+      "/Users/abdulkaderghandoura/miniforge3/envs/napari/lib/python3.10/site-packages/torch/onnx/symbolic_opset9.py:5858: UserWarning: Exporting aten::index operator of advanced indexing in opset 11 is achieved by combination of multiple ONNX operators, including Reshape, Transpose, Concat, and Gather. If indices include negative values, the exported graph will produce incorrect results.\n",
+      "  warnings.warn(\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/mmcv/ops/roi_align.py:64: FutureWarning: 'torch.onnx.symbolic_opset9._cast_Long' is deprecated in version 2.0 and will be removed in the future. Please Avoid using this function and create a Cast node instead.\n",
+      "  batch_indices = _cast_Long(\n"
+     ]
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "11/27 13:29:59 - mmengine - \u001b[4m\u001b[97mINFO\u001b[0m - Execute onnx optimize passes.\n",
+      "11/27 13:29:59 - mmengine - \u001b[5m\u001b[4m\u001b[33mWARNING\u001b[0m - Can not optimize model, please build torchscipt extension.\n",
+      "More details: https://github.com/open-mmlab/mmdeploy/tree/main/docs/en/experimental/onnx_optimizer.md\n"
+     ]
+    }
+   ],
+   "source": [
+    "\n",
+    "\n",
+    "#deploy_cfg = './configs/mmdet/detection/yolov3_partition_onnxruntime_static.py' #yolov3_d53_320_coco_onnxruntime_dynamic.py'\n",
+    "deploy_cfg = str(Path.home() / 'workspace/mmdeploy/configs/mmdet/detection/detection_onnxruntime_dynamic.py')\n",
+    "print(deploy_cfg)\n",
+    "work_dir = '.'\n",
+    "\n",
+    "'''\n",
+    "img (str | np.ndarray | torch.Tensor): Input image used to assist converting model.\n",
+    "'''\n",
+    "\n",
+    "img_path = '/Users/abdulkaderghandoura/Downloads/MultiOrg/Annotated_by_Gowtham/Images/GoBo032_Control_Plate_PCR_TileScan_1_A_10_Merged_EDF001_ch00.tif'\n",
+    "img = imread(img_path)[0,0,0]\n",
+    "\n",
+    "img_r, _, _ = prepare_img(img, step=1, window_size=2048, rescale_factor=1)\n",
+    "print(img_r.shape)\n",
+    "#img_r = resize_keep_ratio_numpy(img_r)\n",
+    "\n",
+    "torch2onnx(img_r[:2048,:2048,:],\n",
+    "            work_dir,\n",
+    "            save_file,\n",
+    "            deploy_cfg,\n",
+    "            model_cfg,\n",
+    "            model_checkpoint, \n",
+    "            'cpu')"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "83a182ad",
+   "metadata": {},
+   "source": [
+    "## Test exported onnx model"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "id": "7719ddb0",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(1, 3, 7486, 7630)\n",
+      "Class 0, Score 0.99, Box [1195, 1746, 1359, 1928]\n",
+      "Class 0, Score 0.99, Box [803, 1434, 853, 1484]\n",
+      "Class 0, Score 0.97, Box [1023, 1442, 1061, 1477]\n",
+      "Class 0, Score 0.95, Box [890, 1348, 940, 1398]\n",
+      "Class 0, Score 0.95, Box [1687, 1594, 1746, 1652]\n",
+      "Class 0, Score 0.94, Box [1037, 1156, 1074, 1197]\n",
+      "Class 0, Score 0.89, Box [974, 1726, 1023, 1775]\n",
+      "Class 0, Score 0.85, Box [1616, 1717, 1656, 1758]\n",
+      "Class 0, Score 0.82, Box [769, 1859, 799, 1891]\n",
+      "Class 0, Score 0.73, Box [1461, 1166, 1498, 1206]\n",
+      "Class 0, Score 0.69, Box [1043, 1384, 1079, 1421]\n",
+      "Class 0, Score 0.68, Box [1283, 1097, 1325, 1138]\n",
+      "Class 0, Score 0.66, Box [1617, 1578, 1665, 1634]\n",
+      "Class 0, Score 0.64, Box [899, 1823, 943, 1875]\n",
+      "Class 0, Score 0.62, Box [1440, 761, 1473, 793]\n",
+      "Class 0, Score 0.59, Box [1008, 1196, 1039, 1224]\n",
+      "Class 0, Score 0.57, Box [728, 1879, 762, 1913]\n",
+      "Class 0, Score 0.50, Box [1169, 1495, 1206, 1535]\n",
+      "Class 0, Score 0.49, Box [1550, 1091, 1578, 1121]\n",
+      "Class 0, Score 0.45, Box [1985, 1328, 2026, 1367]\n",
+      "Class 0, Score 0.41, Box [957, 2016, 996, 2048]\n",
+      "Class 0, Score 0.39, Box [1762, 1415, 1794, 1445]\n",
+      "Class 0, Score 0.35, Box [1502, 1265, 1541, 1308]\n"
+     ]
+    }
+   ],
+   "source": [
+    "onnx_model = save_file #'model.onnx'\n",
+    "session = ort.InferenceSession(onnx_model, providers=[\"CPUExecutionProvider\"])\n",
+    "# Get input/output names\n",
+    "input_name = session.get_inputs()[0].name\n",
+    "output_names = [o.name for o in session.get_outputs()]\n",
+    "\n",
+    "# Preprocess\n",
+    "img = imread(img_path)[0,0,0]\n",
+    "img_r, _, _ = prepare_img(img, step=1, window_size=2048, rescale_factor=1)\n",
+    "img_r = img_r.astype(np.float32) / 255.0\n",
+    "\n",
+    "\n",
+    "# HWC -> CHW\n",
+    "img_r = np.transpose(img_r, (2, 0, 1))\n",
+    "# Add batch dimension\n",
+    "img_r = np.expand_dims(img_r, axis=0)\n",
+    "print(img_r.shape)\n",
+    "# Run inference\n",
+    "outputs = session.run(output_names, {input_name: img_r[:,:,:2048,:2048]})\n",
+    "\n",
+    "dets, labels = outputs\n",
+    "for det, label in zip(dets[0], labels[0]):\n",
+    "    x1, y1, x2, y2, score = det\n",
+    "    if score > 0.3:  # confidence threshold\n",
+    "        print(f\"Class {int(label)}, Score {score:.2f}, Box [{x1:.0f}, {y1:.0f}, {x2:.0f}, {y2:.0f}]\")\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "8bc60546",
+   "metadata": {},
+   "source": [
+    "## Find which transformations where used on image in DetInferencer based on the config\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "id": "3654e614",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[{'type': 'LoadImageFromFile', 'backend_args': None}, {'type': 'Resize', 'scale': (416, 416), 'keep_ratio': True}, {'type': 'LoadAnnotations', 'with_bbox': True}, {'type': 'PackDetInputs', 'meta_keys': ('img_id', 'img_path', 'ori_shape', 'img_shape', 'scale_factor')}]\n"
+     ]
+    }
+   ],
+   "source": [
+    "from mmengine import Config\n",
+    "from mmdet.apis import DetInferencer\n",
+    "\n",
+    "# Load config\n",
+    "cfg = \"/Users/abdulkaderghandoura/miniforge3/envs/napari/lib/python3.10/site-packages/mmdet/.mim/configs/yolo/yolov3_416_organoid.py\"\n",
+    "cfg = Config.fromfile(cfg)\n",
+    "# Print the test pipeline used for inference\n",
+    "print(cfg.test_dataloader.dataset.pipeline)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "id": "e3822e0b-7b17-4f09-9f8f-0d750cbf256d",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "mmdeploy location: /Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/__init__.py\n",
+      "\n",
+      "Lib directory: /Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/lib\n",
+      "Exists: True\n",
+      "\n",
+      "Libraries found:\n",
+      "  - libmmdeploy_torchscript_ops.so\n"
+     ]
+    }
+   ],
+   "source": [
+    "import mmdeploy\n",
+    "from pathlib import Path\n",
+    "\n",
+    "print(f\"mmdeploy location: {mmdeploy.__file__}\")\n",
+    "\n",
+    "# Check for the optimizer library\n",
+    "mmdeploy_root = Path(mmdeploy.__file__).parent\n",
+    "lib_dir = mmdeploy_root / \"lib\"\n",
+    "\n",
+    "print(f\"\\nLib directory: {lib_dir}\")\n",
+    "print(f\"Exists: {lib_dir.exists()}\")\n",
+    "\n",
+    "if lib_dir.exists():\n",
+    "    print(\"\\nLibraries found:\")\n",
+    "    for lib in lib_dir.glob(\"*\"):\n",
+    "        print(f\"  - {lib.name}\")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "id": "4c64576b-1805-4915-8551-0073e25843a9",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Input image shape: (7486, 7630, 3)\n",
+      "Loads checkpoint by local backend from path: /Users/abdulkaderghandoura/.cache/napari-organoid-counter/models/yolov3_416_organoid_best_coco_bbox_mAP_epoch_27.pth\n",
+      "11/27 13:30:33 - mmengine - \u001b[4m\u001b[97mINFO\u001b[0m - Export PyTorch model to ONNX: ./yolov3_416_organoid_best_coco_bbox_mAP_epoch_27.onnx.\n"
+     ]
+    },
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/core/optimizers/function_marker.py:160: TracerWarning: Converting a tensor to a Python integer might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  ys_shape = tuple(int(s) for s in ys.shape)\n",
+      "/Users/abdulkaderghandoura/miniforge3/envs/napari/lib/python3.10/site-packages/mmdet/models/task_modules/prior_generators/anchor_generator.py:356: UserWarning: ``grid_anchors`` would be deprecated soon. Please use ``grid_priors`` \n",
+      "  warnings.warn('``grid_anchors`` would be deprecated soon. '\n",
+      "/Users/abdulkaderghandoura/miniforge3/envs/napari/lib/python3.10/site-packages/mmdet/models/task_modules/prior_generators/anchor_generator.py:392: UserWarning: ``single_level_grid_anchors`` would be deprecated soon. Please use ``single_level_grid_priors`` \n",
+      "  warnings.warn(\n",
+      "/Users/abdulkaderghandoura/miniforge3/envs/napari/lib/python3.10/site-packages/mmdet/models/task_modules/coders/yolo_bbox_coder.py:81: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  assert pred_bboxes.size(-1) == bboxes.size(-1) == 4\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/pytorch/functions/topk.py:28: TracerWarning: torch.tensor results are registered as constants in the trace. You can safely ignore this warning if you use this function to create tensors out of constant variables that would be the same every time you call this function. In any other case, this might cause the trace to be incorrect.\n",
+      "  k = torch.tensor(k, device=input.device, dtype=torch.long)\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/mmcv/ops/nms.py:285: TracerWarning: torch.tensor results are registered as constants in the trace. You can safely ignore this warning if you use this function to create tensors out of constant variables that would be the same every time you call this function. In any other case, this might cause the trace to be incorrect.\n",
+      "  iou_threshold = torch.tensor([iou_threshold], dtype=torch.float32)\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/mmcv/ops/nms.py:286: TracerWarning: torch.tensor results are registered as constants in the trace. You can safely ignore this warning if you use this function to create tensors out of constant variables that would be the same every time you call this function. In any other case, this might cause the trace to be incorrect.\n",
+      "  score_threshold = torch.tensor([score_threshold], dtype=torch.float32)\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/mmcv/ops/nms.py:45: TracerWarning: Converting a tensor to a Python float might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  score_threshold = float(score_threshold)\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/mmcv/ops/nms.py:46: TracerWarning: Converting a tensor to a Python float might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  iou_threshold = float(iou_threshold)\n",
+      "/Users/abdulkaderghandoura/miniforge3/envs/napari/lib/python3.10/site-packages/mmcv/ops/nms.py:123: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  assert boxes.size(1) == 4\n",
+      "/Users/abdulkaderghandoura/miniforge3/envs/napari/lib/python3.10/site-packages/mmcv/ops/nms.py:124: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  assert boxes.size(0) == scores.size(0)\n",
+      "/Users/abdulkaderghandoura/miniforge3/envs/napari/lib/python3.10/site-packages/torch/onnx/symbolic_opset9.py:5858: UserWarning: Exporting aten::index operator of advanced indexing in opset 11 is achieved by combination of multiple ONNX operators, including Reshape, Transpose, Concat, and Gather. If indices include negative values, the exported graph will produce incorrect results.\n",
+      "  warnings.warn(\n"
+     ]
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "11/27 13:30:36 - mmengine - \u001b[4m\u001b[97mINFO\u001b[0m - Execute onnx optimize passes.\n",
+      "\n",
+      "✓ ONNX model exported to: yolov3_416_organoid_best_coco_bbox_mAP_epoch_27.onnx\n",
+      "Check the logs above - if you see 'Execute onnx optimize passes' without warnings, optimization is working!\n",
+      "Loads checkpoint by local backend from path: /Users/abdulkaderghandoura/.cache/napari-organoid-counter/models/rtmdet_l_organoid_best_coco_bbox_mAP_epoch_323.pth\n",
+      "11/27 13:30:37 - mmengine - \u001b[4m\u001b[97mINFO\u001b[0m - Export PyTorch model to ONNX: ./rtmdet_l_organoid_best_coco_bbox_mAP_epoch_323.onnx.\n"
+     ]
+    },
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "/Users/abdulkaderghandoura/miniforge3/envs/napari/lib/python3.10/site-packages/torch/functional.py:512: UserWarning: torch.meshgrid: in an upcoming release, it will be required to pass the indexing argument. (Triggered internally at /Users/runner/miniforge3/conda-bld/libtorch_1719361051023/work/aten/src/ATen/native/TensorShape.cpp:3588.)\n",
+      "  return _VF.meshgrid(tensors, **kwargs)  # type: ignore[attr-defined]\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/pytorch/functions/topk.py:28: TracerWarning: torch.tensor results are registered as constants in the trace. You can safely ignore this warning if you use this function to create tensors out of constant variables that would be the same every time you call this function. In any other case, this might cause the trace to be incorrect.\n",
+      "  k = torch.tensor(k, device=input.device, dtype=torch.long)\n"
+     ]
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "11/27 13:30:42 - mmengine - \u001b[4m\u001b[97mINFO\u001b[0m - Execute onnx optimize passes.\n",
+      "\n",
+      "✓ ONNX model exported to: rtmdet_l_organoid_best_coco_bbox_mAP_epoch_323.onnx\n",
+      "Check the logs above - if you see 'Execute onnx optimize passes' without warnings, optimization is working!\n",
+      "Loads checkpoint by local backend from path: /Users/abdulkaderghandoura/.cache/napari-organoid-counter/models/ssd_organoid_best_coco_bbox_mAP_epoch_86.pth\n",
+      "11/27 13:30:43 - mmengine - \u001b[4m\u001b[97mINFO\u001b[0m - Export PyTorch model to ONNX: ./ssd_organoid_best_coco_bbox_mAP_epoch_86.onnx.\n"
+     ]
+    },
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/codebase/mmdet/models/dense_heads/base_dense_head.py:109: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  assert cls_score.size()[-2:] == bbox_pred.size()[-2:]\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/pytorch/functions/topk.py:28: TracerWarning: torch.tensor results are registered as constants in the trace. You can safely ignore this warning if you use this function to create tensors out of constant variables that would be the same every time you call this function. In any other case, this might cause the trace to be incorrect.\n",
+      "  k = torch.tensor(k, device=input.device, dtype=torch.long)\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/codebase/mmdet/models/task_modules/coders/delta_xywh_bbox_coder.py:38: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  assert pred_bboxes.size(0) == bboxes.size(0)\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/codebase/mmdet/models/task_modules/coders/delta_xywh_bbox_coder.py:40: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  assert pred_bboxes.size(1) == bboxes.size(1)\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/codebase/mmdet/deploy/utils.py:48: TracerWarning: Using len to get tensor shape might cause the trace to be incorrect. Recommended usage would be tensor.shape[0]. Passing a tensor of different shape might lead to errors or silently give incorrect results.\n",
+      "  assert len(max_shape) == 2, '`max_shape` should be [h, w]'\n"
+     ]
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "11/27 13:30:46 - mmengine - \u001b[4m\u001b[97mINFO\u001b[0m - Execute onnx optimize passes.\n",
+      "\n",
+      "✓ ONNX model exported to: ssd_organoid_best_coco_bbox_mAP_epoch_86.onnx\n",
+      "Check the logs above - if you see 'Execute onnx optimize passes' without warnings, optimization is working!\n",
+      "Loads checkpoint by local backend from path: /Users/abdulkaderghandoura/.cache/napari-organoid-counter/models/faster-rcnn_r50_fpn_organoid_best_coco_bbox_mAP_epoch_68.pth\n",
+      "11/27 13:30:46 - mmengine - \u001b[4m\u001b[97mINFO\u001b[0m - Export PyTorch model to ONNX: ./faster-rcnn_r50_fpn_organoid_best_coco_bbox_mAP_epoch_68.onnx.\n"
+     ]
+    },
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "/Users/abdulkaderghandoura/miniforge3/envs/napari/lib/python3.10/site-packages/mmdet/models/dense_heads/anchor_head.py:115: UserWarning: DeprecationWarning: anchor_generator is deprecated, please use \"prior_generator\" instead\n",
+      "  warnings.warn('DeprecationWarning: anchor_generator is deprecated, '\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/codebase/mmdet/models/dense_heads/rpn_head.py:89: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  assert cls_score.size()[-2:] == bbox_pred.size()[-2:]\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/pytorch/functions/topk.py:28: TracerWarning: torch.tensor results are registered as constants in the trace. You can safely ignore this warning if you use this function to create tensors out of constant variables that would be the same every time you call this function. In any other case, this might cause the trace to be incorrect.\n",
+      "  k = torch.tensor(k, device=input.device, dtype=torch.long)\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/codebase/mmdet/models/task_modules/coders/delta_xywh_bbox_coder.py:38: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  assert pred_bboxes.size(0) == bboxes.size(0)\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/codebase/mmdet/models/task_modules/coders/delta_xywh_bbox_coder.py:40: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  assert pred_bboxes.size(1) == bboxes.size(1)\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/codebase/mmdet/models/roi_heads/standard_roi_head.py:41: TracerWarning: Converting a tensor to a Python integer might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  rois_dims = int(rois.shape[-1])\n",
+      "/Users/abdulkaderghandoura/miniforge3/envs/napari/lib/python3.10/site-packages/mmcv/ops/roi_align.py:78: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
+      "  assert rois.size(1) == 5, 'RoI must be (idx, x1, y1, x2, y2)!'\n",
+      "/Users/abdulkaderghandoura/workspace/mmdeploy/mmdeploy/mmcv/ops/roi_align.py:64: FutureWarning: 'torch.onnx.symbolic_opset9._cast_Long' is deprecated in version 2.0 and will be removed in the future. Please Avoid using this function and create a Cast node instead.\n",
+      "  batch_indices = _cast_Long(\n"
+     ]
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "11/27 13:30:51 - mmengine - \u001b[4m\u001b[97mINFO\u001b[0m - Execute onnx optimize passes.\n",
+      "\n",
+      "✓ ONNX model exported to: faster-rcnn_r50_fpn_organoid_best_coco_bbox_mAP_epoch_68.onnx\n",
+      "Check the logs above - if you see 'Execute onnx optimize passes' without warnings, optimization is working!\n"
+     ]
+    }
+   ],
+   "source": [
+    "from mmdeploy.apis.pytorch2onnx import torch2onnx\n",
+    "\n",
+    "# Export configuration\n",
+    "deploy_cfg = str(Path.home() / 'workspace/mmdeploy/configs/mmdet/detection/detection_onnxruntime_dynamic.py')\n",
+    "\n",
+    "work_dir = '.'\n",
+    "model_ckpts = [yolo_model_path, rtmdet_model_path, ssd_model_path, fasterrcnn_model_path]\n",
+    "model_cfgs = [yolo_config_dst, rtmdet_config_dst, ssd_config_dst, fasterrcnn_config_dst]\n",
+    "save_files = [\n",
+    "    'yolov3_416_organoid_best_coco_bbox_mAP_epoch_27.onnx',\n",
+    "    'rtmdet_l_organoid_best_coco_bbox_mAP_epoch_323.onnx',\n",
+    "    'ssd_organoid_best_coco_bbox_mAP_epoch_86.onnx',\n",
+    "    'faster-rcnn_r50_fpn_organoid_best_coco_bbox_mAP_epoch_68.onnx'\n",
+    "]\n",
+    "\n",
+    "# Prepare input image\n",
+    "img_path = '/Users/abdulkaderghandoura/Downloads/MultiOrg/Annotated_by_Gowtham/Images/GoBo032_Control_Plate_PCR_TileScan_1_A_10_Merged_EDF001_ch00.tif'\n",
+    "img = imread(img_path)[0,0,0]\n",
+    "img_r, _, _ = prepare_img(img, step=1, window_size=2048, rescale_factor=1)\n",
+    "\n",
+    "print(f\"Input image shape: {img_r.shape}\")\n",
+    "\n",
+    "for model_checkpoint, model_cfg, save_file in zip(model_ckpts, model_cfgs, save_files):        \n",
+    "    # Export to ONNX - this will use optimizations if available\n",
+    "    torch2onnx(\n",
+    "        img_r[:2048, :2048, :],\n",
+    "        work_dir,\n",
+    "        save_file,\n",
+    "        deploy_cfg,\n",
+    "        model_cfg,\n",
+    "        model_checkpoint, \n",
+    "        'cpu'\n",
+    "    )\n",
+    "    \n",
+    "    print(f\"\\n✓ ONNX model exported to: {save_file}\")\n",
+    "    print(\"Check the logs above - if you see 'Execute onnx optimize passes' without warnings, optimization is working!\")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "436d57f3-a6b1-4b15-8581-a8cd0e01238f",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# from mmdeploy.apis.pytorch2onnx import torch2onnx\n",
+    "\n",
+    "# # Export configuration\n",
+    "# deploy_cfg = str(Path.home() / 'workspace/mmdeploy/configs/mmdet/detection/detection_onnxruntime_dynamic.py')\n",
+    "\n",
+    "# model_checkpoint = fasterrcnn_model_path\n",
+    "# model_cfg = fasterrcnn_config_dst\n",
+    "# work_dir = '.'\n",
+    "# save_file = 'faster-rcnn_r50_fpn_organoid_best_coco_bbox_mAP_epoch_68.onnx'\n",
+    "\n",
+    "# # Prepare input image\n",
+    "# img_path = '/Users/abdulkaderghandoura/Downloads/MultiOrg/Annotated_by_Gowtham/Images/GoBo032_Control_Plate_PCR_TileScan_1_A_10_Merged_EDF001_ch00.tif'\n",
+    "# img = imread(img_path)[0,0,0]\n",
+    "# img_r, _, _ = prepare_img(img, step=1, window_size=2048, rescale_factor=1)\n",
+    "\n",
+    "# print(f\"Input image shape: {img_r.shape}\")\n",
+    "\n",
+    "# # Export to ONNX - this will use optimizations if available\n",
+    "# torch2onnx(\n",
+    "#     img_r[:2048, :2048, :],\n",
+    "#     work_dir,\n",
+    "#     save_file,\n",
+    "#     deploy_cfg,\n",
+    "#     model_cfg,\n",
+    "#     model_checkpoint, \n",
+    "#     'cpu'\n",
+    "# )\n",
+    "\n",
+    "# print(f\"\\n✓ ONNX model exported to: {save_file}\")\n",
+    "# print(\"Check the logs above - if you see 'Execute onnx optimize passes' without warnings, optimization is working!\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "2e260943",
+   "metadata": {},
+   "source": [
+    "## Another mmdeploy try - didn't work"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "67a9133f",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from mmdeploy.apis import build_task_processor\n",
+    "from mmengine.config import Config\n",
+    "\n",
+    "# Load configs\n",
+    "deploy_cfg = './mmdeploy/configs/mmdet/detection/yolov3_partition_onnxruntime_static.py' #yolov3_d53_320_coco_onnxruntime_dynamic.py' #yolov3_partition_onnxruntime_static.py\n",
+    "model_cfg = '/Users/christinabukas/miniconda3/envs/noc-test3/lib/python3.10/site-packages/mmdet/.mim/configs/yolo/yolov3_416_organoid.py'\n",
+    "checkpoint = '/Users/christinabukas/.cache/napari-organoid-counter/models/yolov3_416_organoid_best_coco_bbox_mAP_epoch_27.pth'\n",
+    "\n",
+    "model_cfg = Config.fromfile(model_cfg)\n",
+    "deploy_cfg = Config.fromfile(deploy_cfg)\n",
+    "\n",
+    "# Build the task processor for deployment\n",
+    "task_processor = build_task_processor(model_cfg, deploy_cfg, device='cpu')\n",
+    "\n",
+    "# Export the model\n",
+    "task_processor.export(deploy_cfg, checkpoint, output_dir='deploy_output', device='cpu')"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "c6866c1c",
+   "metadata": {},
+   "source": [
+    "## Using torchscript to export model - this didn't work"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "16e9f0ae",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Dummy input (batch, C, H, W)\n",
+    "example_img = torch.randn(1, 3, 384, 416).to(\"cpu\")\n",
+    "# Build model\n",
+    "model = init_detector(config_dst, yolo_model_path, device=\"cpu\")\n",
+    "model.eval()\n",
+    "# Trace the model\n",
+    "traced = torch.jit.trace(model, example_img)\n",
+    "traced.save(\"model_traced.pt\")\n",
+    "\n",
+    "\n",
+    "# Load TorchScript model\n",
+    "device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",
+    "model = torch.jit.load(\"model_traced.pt\", map_location=device)\n",
+    "model.eval()\n",
+    "\n",
+    "\n",
+    "def preprocess_image(arr: np.ndarray, size=(383, 416)):\n",
+    "    \"\"\"\n",
+    "    Convert a numpy image (HWC or CHW) into a PyTorch tensor \n",
+    "    with shape [1, 3, H, W], resized to `size`.\n",
+    "    \"\"\"\n",
+    "    if arr.ndim == 3 and arr.shape[0] == 3:  \n",
+    "        # CHW -> HWC\n",
+    "        arr = np.transpose(arr, (1, 2, 0))\n",
+    "    \n",
+    "    # Ensure uint8 image\n",
+    "    if arr.dtype != np.uint8:\n",
+    "        arr = arr.astype(np.uint8)\n",
+    "    \n",
+    "    # TorchVision pipeline\n",
+    "    transform = T.Compose([\n",
+    "        T.ToPILImage(),\n",
+    "        T.Resize(size),\n",
+    "        T.ToTensor(),   # converts to float32 in [0,1], CHW\n",
+    "    ])\n",
+    "    \n",
+    "    tensor = transform(arr).unsqueeze(0)  # [1, 3, H, W]\n",
+    "    return tensor\n",
+    "\n",
+    "tensor = preprocess_image(img_r)\n",
+    "\n",
+    "# Run inference\n",
+    "with torch.no_grad():\n",
+    "    outputs = model(tensor)\n"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python (napari)",
+   "language": "python",
+   "name": "napari"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.10.18"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/readme-content/annotation_mode_info.png b/readme-content/annotation_mode_info.png
new file mode 100644
index 0000000..2419c6e
Binary files /dev/null and b/readme-content/annotation_mode_info.png differ
diff --git a/readme-content/key-bindings.png b/readme-content/key-bindings.png
new file mode 100644
index 0000000..3837401
Binary files /dev/null and b/readme-content/key-bindings.png differ
diff --git a/readme-content/valid_colors_warning.png b/readme-content/valid_colors_warning.png
new file mode 100644
index 0000000..783d51a
Binary files /dev/null and b/readme-content/valid_colors_warning.png differ
diff --git a/readme-content/visual_studio_build_tools.png b/readme-content/visual_studio_build_tools.png
new file mode 100644
index 0000000..d8bd55d
Binary files /dev/null and b/readme-content/visual_studio_build_tools.png differ
diff --git a/readme-content/warning_BC_model_DO_annotation.png b/readme-content/warning_BC_model_DO_annotation.png
new file mode 100644
index 0000000..bf270ba
Binary files /dev/null and b/readme-content/warning_BC_model_DO_annotation.png differ
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 04b9973..0000000
--- a/setup.cfg
+++ /dev/null
@@ -1,59 +0,0 @@
-[metadata]
-name = napari-organoid-counter
-
-author = christinab12
-author_email = christina.bukas@helmholtz-muenchen.de
-url = https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter
-license = MIT
-description = A plugin to automatically count lung organoids using Deep Learning.
-long_description = file: README.md
-long_description_content_type = text/markdown
-classifiers =
-    Development Status :: 2 - Pre-Alpha
-    Intended Audience :: Developers
-    Framework :: napari
-    Topic :: Software Development :: Testing
-    Programming Language :: Python
-    Programming Language :: Python :: 3
-    Programming Language :: Python :: 3.8
-    Programming Language :: Python :: 3.9
-    Programming Language :: Python :: 3.10
-    Operating System :: OS Independent
-    License :: OSI Approved :: MIT License
-project_urls =
-    Bug Tracker = https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter/issues
-    Documentation = https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter#README.md
-    Source Code = https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter
-    User Support = https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter/issues
-
-[options]
-packages = 
-    napari_organoid_counter
-include_package_data = True
-python_requires = >=3.9, <3.11
-setup_requires = setuptools_scm
-# add your package requirements here
-install_requires =
-    napari[all]>=0.4.17,<0.5.0
-    napari-aicsimageio>=0.7.2
-    torch>=2.3.1
-    torchvision>=0.18.1
-    openmim
-    mmengine>=0.10.4
-    mmdet>=3.3.0
-
-[options.extras_require]
-testing =
-    tox
-    pytest  # https://docs.pytest.org/en/latest/contents.html
-    pytest-cov  # https://pytest-cov.readthedocs.io/en/latest/
-    pytest-qt  # https://pytest-qt.readthedocs.io/en/latest/
-    napari
-    pyqt5
-
-[options.package_data]
-* = *.yaml
-
-[options.entry_points] 
-napari.manifest = 
-    napari-organoid-counter = napari_organoid_counter:napari.yaml
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..c43b037
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,56 @@
+import subprocess
+from setuptools import setup, find_packages
+
+# Detect CUDA availability
+def has_cuda():
+    try:
+        result = subprocess.run(['nvidia-smi'], capture_output=True, text=True)
+        return result.returncode == 0
+    except FileNotFoundError:
+        return False
+
+# Set onnxruntime based on CUDA availability
+onnxruntime_pkg = 'onnxruntime-gpu' if has_cuda() else 'onnxruntime'
+
+setup(
+    name='napari-organoid-counter',
+    author='christinab12',
+    author_email='christina.bukas@helmholtz-munich.de',
+    url='https://github.com/HelmholtzAI-Consultants-Munich/napari-organoid-counter',
+    license='MIT',
+    description='A plugin to automatically count lung organoids using Deep Learning.',
+    packages=find_packages(),
+    python_requires='>=3.9, <3.11',
+    install_requires=[
+        'napari[all]>=0.4.17,<0.5.0',
+        'bioio==3.3.0',
+        'bioio-ome-tiff==1.4.0',
+        'bioio-tifffile==1.3.0',
+        'bioio-imageio==1.3.0',
+        'bioio-czi==2.6.0',
+        'bioio-nd2==1.6.2',
+        'bioio-lif==1.4.0',
+        'bioio-dv==1.2.0',
+        'torch<=2.5.1',
+        'lxml_html_clean==0.4.4',
+        'torchvision<=0.20.1',
+        'opencv-python',
+        f'{onnxruntime_pkg}>=1.23.0',
+    ],
+    extras_require={
+        'testing': [
+            'tox',
+            'pytest',
+            'pytest-cov',
+            'pytest-qt',
+            'napari',
+            'pyqt5',
+        ],
+    },
+    package_data={'': ['*.yaml']},
+    entry_points={
+        'napari.manifest': [
+            'napari-organoid-counter = napari_organoid_counter:napari.yaml',
+        ],
+    },
+)
