Skip to content

🔖 Release 2.0.0#1031

Merged
shaneahmed merged 767 commits into
masterfrom
pre-release
Mar 11, 2026
Merged

🔖 Release 2.0.0#1031
shaneahmed merged 767 commits into
masterfrom
pre-release

Conversation

@shaneahmed

@shaneahmed shaneahmed commented Mar 11, 2026

Copy link
Copy Markdown
Member

TIAToolbox v2.0.0 (2026-03-11)

✨ Major Updates and Feature Improvements

⚙️ Engine Redesign (PR #578)

TIAToolbox 2.0.0 introduces a completely re-engineered inference engine designed for significant performance, scalability, and memory-efficiency improvements.

Key Enhancements

  • A modern processing stack built on Dask (parallel/distributed execution) and Zarr (chunked, out-of-core storage)
  • Standardised output formats across all engines:
    • Python dict
    • Zarr
    • AnnotationStore (SQLite-backed)
    • QuPath JSON
  • Cleaner runtime behavior with reduced warning noise and a unified progress bar
  • More predictable memory usage through chunked streaming
  • Broader test coverage across engine components

🗺️ Improved QuPath Support

Enhancements include:

🔬 New Nucleus Detection Engine

A dedicated nucleus detection pipeline has been added, built on the redesigned engine for improved accuracy and efficient large-scale processing.

🧠 KongNet Model Family

TIAToolbox 2.0.0 introduces KongNet, a high-performance architecture that achieved top results across multiple international challenges:

  • 🥇 1st place: MONKEY Challenge (overall detection)
  • 🥇 1st place: MIDOG (mitosis detection)
  • ⭐ Top-tier performance on PUMA

Multiple pretrained variants are available (CoNIC, PanNuke, MONKEY, PUMA, MIDOG), each with standardised IO configurations.

🧬 Expanded Foundation Model Support

Additional foundation models are now supported (#906), broadening the range of high-capacity architectures available for feature extraction and downstream tasks.

🖼️ SAM Segmentation in TIAViz

TIAViz now integrates Meta’s Segment Anything Model (SAM), enabling:

  • Interactive segmentation
  • Rapid region extraction
  • Exploratory annotation workflows

Simplified SAM usage (#968) streamlines its integration into analysis pipelines.

🖼️ WSI Registration Visualization in TIAViz

TIAViz now supports interactive WSI registration visualisation, allowing users to compare aligned slides in two modes:

  • Side‑by‑side view — view fixed and moving WSIs next to each other for direct comparison
  • Overlay mode — blend registered WSIs with adjustable transparency for visual inspection of alignment quality

This feature enables intuitive, high‑resolution exploration of slide registration results directly within TIAViz.

🧩 Enhanced WSIReader & Metadata Handling

Major improvements include:

☁️ New Cloud-Native Reader: FsspecJSONWSIReader (PR #897)

A new reader supporting fsspec-compatible filesystems, enabling seamless access to WSIs stored on:

  • S3
  • GCS
  • Azure
  • HPC clusters
  • Any fsspec-supported backend

This enables cloud-native and distributed data workflows.
Contributed by @aacic

🤗 Pretrained Models Migrated to Hugging Face

All pretrained models and sample assets have been migrated (#945, #983), improving:

  • Download reliability
  • Versioning and reproducibility
  • Caching and CI integration
  • Licensing clarity per model family

🛡️ Security, Compatibility & Tooling

🔐 Security & Dependency Updates

🐍 Python Version Support

  • Dropped: Python 3.9
  • Added: Python 3.13
  • Supported: Python 3.10–3.13
  • Updated CUDA wheel source to cu126

🛠️ Developer Tooling & CI/CD

🧹 Bug Fixes & Stability Improvements

🧭 Migration Guide for Users

🔄 Updating from 1.x to 2.0.0

Update calls: replace .predict() with .run()

# Old
results = segmentor.predict(imgs=[...], ioconfig=config)

# New
results = segmentor.run(images=[...], ioconfig=config)

Use patch_mode: replace mode="patch" with patch_mode=True and mode="tile" or "wsi" with patch_mode=False

# Old
results = segmentor.predict(imgs=[...], mode="patch", ioconfig=config)

# New
results = segmentor.run(images=[...], patch_mode=True, ioconfig=config)
# Old
results = segmentor.predict(imgs=[...], mode="wsi", ioconfig=config)

# New
results = segmentor.run(images=[...], patch_mode=False, ioconfig=config)

Use the new I/O configs

from tiatoolbox.models.engine.io_config import IOSegmentorConfig

config = IOSegmentorConfig(
    patch_input_shape=(256, 256),
    stride_shape=(240, 240),
    input_resolutions=[{"resolution": 0.25, "units": "mpp"}],
    save_resolution={"units": "baseline", "resolution": 1.0},
)

Specify the output format

results = segmentor.run(
    images=[...],
    ioconfig=ioconfig,
    output_type="zarr",  # or "dict", "annotationstore", "qupath"
    save_dir="outputs/",
)

Update imports

  • tiatoolbox.typingtiatoolbox.type_hints

Install requirements

  • Python 3.10+ required
  • On Windows: install OpenSlide via pip install openslide-bin

Full Changelog: v1.6.0...v2.0.0

shaneahmed and others added 30 commits July 25, 2023 13:28
- Add `ruff` Checks for `06-semantic-segmentation`

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- Add `ruff` checks to `04-patch-extraction.ipynb`
---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- ### Bug Fixes and Other Changes

  - Fix dictionary changed size Error #626 (#605)

Full Changelog: v1.4.0...v1.4.1
- Add `ruff` Checks `07-advanced-modeling.ipynb`
JP2 Boxes can be in any order. 

Previously the order was being relied on. This also allows non-Omnyx JP2 images which have a capture resolution box or manually specified MPP at init to be read as WSIs.

Renames from "OmnyxJP2" to just "JP2" as this will work with any JP2 image. 

# To-do

- [x] Rename OmnyxJP2Reader -> JP2Reader?
- [x] Use CMU-1-Small-Region.jp2 in tests instead of test1.jp2
- [x] Resolve non-Omnyx file causing test failure.[^1] **Resolved:** allowing any occurrence of Aperio-style pipe-separated key-values for MPP = and AppMag = in an XML box \<description\> tag.

[^1]: This is now intended behaviour. It was only passing by accident before. One of the test files is a non-Omnyx JP2, which happens to have an objective power in the description field, was picked up previously because the metadata is copied from an SVS file and has the same format as Omnyx. We must allow Aperio SVS-style metadata or change the test/test file to be Omnyx format.

---------

Co-authored-by: Shan E Ahmed Raza <13048456+shaneahmed@users.noreply.github.com>
- Add `ruff` Checks to `05-patch-prediction.ipynb`
- Remove `isort` 
- Use `ruff` for sorting imports
- Add `ruff` Checks `10-wsi-registration`
- Add `ruff` checks to `examples/inference-pipelines`

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- Add `ruff` checks to `examples` notebooks.
- Fix issues when extracting transformed patches using `mpp` and `power` units
---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
<!--pre-commit.ci start-->
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.0.280 → v0.0.281](astral-sh/ruff-pre-commit@v0.0.280...v0.0.281)
<!--pre-commit.ci end-->

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Shan E Ahmed Raza <13048456+shaneahmed@users.noreply.github.com>
* 💚 Add CI Cache
* 💚 Improve cache name

---------

Co-authored-by: Shan E Ahmed Raza <13048456+shaneahmed@users.noreply.github.com>
- Add `ruff` checks tiatoolbox root
Add `ruff` Checks to `cli`

---------

Signed-off-by: Shan E Ahmed Raza <13048456+shaneahmed@users.noreply.github.com>
- Update ruff to 0.0.282
Add `ruff` Checks to All Jupyter Notebooks

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- Fix `ANN201` Errors in `tests`
- Add `flake8-boolean-trap` checks.

---------
- Add `flake8-bandit` Checks
- Add `flake8-unused-arguments` checks
- Upgrade ruff to `0.0.283`
---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- Upgrade `ruff` to `0.0.284`
Currently, `utils.imwrite` does not check whether the write operation succeeded. This can return to unexpected behaviour: for example, nothing will happen if you write to a folder that does not exist. 

---------

Co-authored-by: Shan E Ahmed Raza <13048456+shaneahmed@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- Fix Linter Errors in `utils` for Pylint, flake8-annotations, flake8-unused-arguments, flake8-boolean-trap
- Does not fix where noqa is required. This should be fixed in #677
- Add `pylint` checks

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- Fix return value of prealignment function.

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Shan E Ahmed Raza <13048456+shaneahmed@users.noreply.github.com>
Files are first downloaded as temporary files and then transferred to the targeted location. This prevents corrupted files from being stored if the download is terminated.

------

Co-authored-by: Shan E Ahmed Raza <13048456+shaneahmed@users.noreply.github.com>
- Add `flake8-annotations` Checks to `tools`
shaneahmed and others added 10 commits March 9, 2026 14:20
…n permissions (#1021)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
* 🛂 Workflow Does Not Contain Permissions

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* 🛂 Add permissions control to mypy and conda workflow

* [skip ci] 📝 Fix typo

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
* Apply suggested fix to tests/test_pyramid.py from Copilot Autofix

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>

* Apply suggested fix to tests/test_pyramid.py from Copilot Autofix

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>

* 🐛 Fix test_get_thumb_tile

---------

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
## Summary
This PR standardises and improves metadata inference across all WSI readers by introducing a unified mechanism for estimating missing **objective power** and **MPP**. It updates all major reader implementations (TIFF, DICOM, OpenSlide, JP2, NGFF, fsspec), fixes reader‑selection ordering, and adds extensive tests to validate inference behaviour and warnings. New sample data is included to support expanded DICOM metadata coverage.

## 🔑 Key Changes

### 1. Centralised Metadata Inference
- Introduces `WSIReader._estimate_mpp_objective_power()` as the shared method for inferring missing **objective power** and **MPP**.
- Removes duplicated inference logic and ensures consistent fallback behaviour across all readers.

### 2. Unified Metadata Handling Across Readers
All major WSI readers now use the central inference method:
- `TIFFWSIReader`
- `DICOMWSIReader`
- `OpenSlideWSIReader`
- `JP2WSIReader`
- `NGFFWSIReader`
- `FsspecJsonWSIReader`

This ensures consistent behaviour when metadata is missing or partially defined.

### 3. Improved Reader Selection Logic
- Adds `try_openslide()` and updates selection priority so TIFF files are first attempted via OpenSlide.
- Fixes misclassification issues where TIFF inputs were incorrectly routed to other readers.

### 4. Expanded and Strengthened Test Coverage
New and updated tests now cover:
- Missing or partial OME‑TIFF metadata
- Missing MPP (X/Y)
- Missing instrument references
- Warning behaviour when inference is required
- DICOM metadata with and without optical path information
- New `dicom-2` sample with known objective/MPP values

Assertions have been updated to reflect the new inference logic.

### 5. Updated Remote Sample Data
- Replaces `CMU-1.dicom.zip` with `CMU-1-Small-Region.dicom.zip`.
- Adds new `dicom-2` sample (`JP2K-33003-1.zip`) to support metadata‑specific tests.

### 6. Cleanup and Minor Fixes
- Corrects import path for `TransformedWSIReader`.
- Improves type hints in `objective_power2mpp`.
- Normalises ndarray conversion for inferred MPP values.
- Cleans up mypy issues related to dimension and metadata handling.

---

This PR resolves **Jupyter Notebook 10 – WSI Reading (#998)** and **KongNet Notebook for MONKEY dataset (#987)**. 

---------

Co-authored-by: Jiaqi Lv <lvjiaqi9@gmail.com>
This PR takes the sam-viz PR and fixes and substantially simplifies it.

I think the original PR was going for a more general prompt segmentor engine that would in theory cope with prompts dispersed over a whole WSI, but I think that approach has issues in practice (and it would also need some significant work to fix from its current state, I think). This PR focusses on segmenting prompts made within a specific view window, which I think is more practical and allows for a much simplified approach.

To use, draw a few points (and/or a box) on some object(s) in the field of view in TIAViz using this widget:
<img width="145" height="426" alt="image" src="https://github.com/user-attachments/assets/7f52558e-1f6b-4c75-a52f-5285da9134a6" />
Then select SAM in the model select box and click run. The segmetations should be displayed after a short time.

Examples:
<img width="1149" height="885" alt="image" src="https://github.com/user-attachments/assets/83b273eb-554b-48e2-b383-75649f25042c" />
<img width="982" height="799" alt="image" src="https://github.com/user-attachments/assets/39d87b22-9535-40d7-a1b9-61fd2b226b34" />
<img width="1218" height="894" alt="image" src="https://github.com/user-attachments/assets/3bcfa743-3fbd-4dcc-b6ea-8174904ca09c" />


---------

Co-authored-by: mbasheer04 <78800844+mbasheer04@users.noreply.github.com>
Co-authored-by: Musraf Basheer <Musraf.Basheer@warwick.ac.uk>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Shan E Ahmed Raza <13048456+shaneahmed@users.noreply.github.com>
Co-authored-by: adamshephard <39619155+adamshephard@users.noreply.github.com>
Fixes to notebook 11.
 - update colab link at the moment
 - switch to kaiko from UNI to avoid gated access needing a HF token from an account that has already requested access

Otherwise, notebook runs ok (if a bit slow ~18 mins)
-  Fix Jupyter Notebook 08 and 11 to run on Colab
- Update Jupyter Notebook 06 to run on Colab
- Fix `tqdm` Progress Bar on Colab
Use a ROI mask for PAS WSI nuclei detection. Should fix issue with RAM when running on google colab.

---------

Co-authored-by: Shan E Ahmed Raza <13048456+shaneahmed@users.noreply.github.com>
@review-notebook-app

Copy link
Copy Markdown

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@shaneahmed shaneahmed self-assigned this Mar 11, 2026
@shaneahmed shaneahmed added this to the Release v2.0.0 milestone Mar 11, 2026
@codecov

codecov Bot commented Mar 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.88%. Comparing base (e14a4fc) to head (a66f744).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1031      +/-   ##
==========================================
- Coverage   99.90%   99.88%   -0.03%     
==========================================
  Files          69       85      +16     
  Lines        8715    11562    +2847     
  Branches     1149     1509     +360     
==========================================
+ Hits         8707    11549    +2842     
- Misses          3        6       +3     
- Partials        5        7       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Jiaqi-Lv Jiaqi-Lv requested a review from Copilot March 11, 2026 16:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

@shaneahmed shaneahmed merged commit 2275bf0 into master Mar 11, 2026
36 of 38 checks passed
shaneahmed added a commit that referenced this pull request Mar 12, 2026
🔖 Release 2.0.0 (#1031)
## TIAToolbox v2.0.0 (2026-03-11)

### ✨ Major Updates and Feature Improvements

#### ⚙️ Engine Redesign (PR #578)
TIAToolbox 2.0.0 introduces a completely re-engineered inference engine designed for significant performance, scalability, and memory-efficiency improvements.

#### Key Enhancements
- A modern processing stack built on **Dask** (parallel/distributed execution) and **Zarr** (chunked, out-of-core storage)
- **Standardised output formats** across all engines:
  - Python `dict`
  - **Zarr**
  - **AnnotationStore** (SQLite-backed)
  - **QuPath JSON**
- Cleaner runtime behavior with reduced warning noise and a unified progress bar
- More predictable memory usage through chunked streaming
- Broader test coverage across engine components

### 🗺️ Improved QuPath Support
Enhancements include:

- Better handling of **GeoJSON**
- Support for **multipoint geometries** (#841)
- Improved semantic output helpers:
  - `dict_to_store_semantic_segmentor` (#926)
  - OME-TIFF probability overlays (#929)

### 🔬 New Nucleus Detection Engine
A dedicated nucleus detection pipeline has been added, built on the redesigned engine for improved accuracy and efficient large-scale processing.

#### 🧠 KongNet Model Family
TIAToolbox 2.0.0 introduces **KongNet**, a high-performance architecture that achieved top results across multiple international challenges:

- 🥇 **1st place: MONKEY Challenge (overall detection)**
- 🥇 **1st place: MIDOG (mitosis detection)**
- ⭐ Top-tier performance on **PUMA**

Multiple pretrained variants are available (CoNIC, PanNuke, MONKEY, PUMA, MIDOG), each with standardised IO configurations.

### 🧬 Expanded Foundation Model Support
Additional foundation models are now supported (#906), broadening the range of high-capacity architectures available for feature extraction and downstream tasks.

### 🖼️ SAM Segmentation in TIAViz
TIAViz now integrates Meta’s Segment Anything Model (SAM), enabling:

- Interactive segmentation
- Rapid region extraction
- Exploratory annotation workflows

Simplified SAM usage (#968) streamlines its integration into analysis pipelines.

### 🧩 Enhanced WSIReader & Metadata Handling
Major improvements include:

- More robust cross-vendor **metadata extraction** (#1001)
- **Multichannel image support** (PR #825) for immunofluorescence and non-RGB modalities
- Simplified Windows installation using `openslide-bin` (no manual DLL steps)
- macOS Tileserver fix (#976)
- Improved DICOM reading (#934)

### ☁️ New Cloud-Native Reader: FsspecJSONWSIReader (PR #897)
A new reader supporting **fsspec-compatible filesystems**, enabling seamless access to WSIs stored on:

- S3
- GCS
- Azure
- HPC clusters
- Any fsspec-supported backend

This enables cloud-native and distributed data workflows.
Contributed by @aacic

### 🤗 Pretrained Models Migrated to Hugging Face
All pretrained models and sample assets have been migrated (#945, #983), improving:

- Download reliability
- Versioning and reproducibility
- Caching and CI integration
- Licensing clarity per model family

### 🛡️ Security, Compatibility & Tooling

#### 🔐 Security & Dependency Updates
- Dependency upgrades
- Internal security improvements
- Explicit workflow permissions added (#1021, #1023)

#### 🐍 Python Version Support
- **Dropped:** Python **3.9**
- **Added:** Python **3.13**
- **Supported:** Python 3.10–3.13
- Updated CUDA wheel source to **cu126**

#### 🛠️ Developer Tooling & CI/CD
- Expanded **mypy** type-checking coverage (#912, #931, #935, #951)
- Updated pre-commit hooks and general formatting
- CI uses **CPU-only PyTorch** for faster, more reliable builds (#974, #979)
- Updated pip install workflow (#1013)
- Added new **Python 3.13 Docker images** (#1014, #1019)

### 🧹 Bug Fixes & Stability Improvements
- Fixed multi-GPU behaviour with `torch.compile` (#923)
- Fixed DICOM reading issue (#934)
- Fixed annotation contour handling with holes (#956)
- Fixed consecutive annotation load bug (#927)
- Fixed SCCNN model issues (#970)
- Fixed MapDe `dist_filter` shape issue (#914)
- Improved notebook reliability on Colab (#1026#1030)
- macOS TileServer issues resolved (#976)

### 🧭 Migration Guide for Users

#### 🔄 Updating from 1.x to 2.0.0

#### Update calls: replace `.predict()` with `.run()`
```python
# Old
results = segmentor.predict(imgs=[...], ioconfig=config)

# New
results = segmentor.run(images=[...], ioconfig=config)
```

#### Use `patch_mode`: replace `mode="patch"` with `patch_mode=True` and `mode="tile"` or "wsi" with `patch_mode=False`
```python
# Old
results = segmentor.predict(imgs=[...], mode="patch", ioconfig=config)

# New
results = segmentor.run(images=[...], patch_mode=True, ioconfig=config)
```

```python
# Old
results = segmentor.predict(imgs=[...], mode="wsi", ioconfig=config)

# New
results = segmentor.run(images=[...], patch_mode=False, ioconfig=config)

```

#### Use the new I/O configs
```python
from tiatoolbox.models.engine.io_config import IOSegmentorConfig

config = IOSegmentorConfig(
    patch_input_shape=(256, 256),
    stride_shape=(240, 240),
    input_resolutions=[{"resolution": 0.25, "units": "mpp"}],
    save_resolution={"units": "baseline", "resolution": 1.0}
)
```

#### Specify the output format
```python
results = segmentor.run(
    images=[...],
    ioconfig=ioconfig,
    output_type="zarr",  # or "dict", "annotationstore", "qupath"
    save_dir="outputs/"
)
```

#### Update imports
- `tiatoolbox.typing` → `tiatoolbox.type_hints`

#### Install requirements
- Python **3.10+** required
- On Windows: install OpenSlide via `pip install openslide-bin`

**Full Changelog:** v1.6.0...v2.0.0

---------

Signed-off-by: Shan E Ahmed Raza <13048456+shaneahmed@users.noreply.github.com>
Co-authored-by: measty <20169086+measty@users.noreply.github.com>
Co-authored-by: Jiaqi-Lv <60471431+Jiaqi-Lv@users.noreply.github.com>
Co-authored-by: adamshephard <39619155+adamshephard@users.noreply.github.com>
Co-authored-by: Mostafa Jahanifar <74412979+mostafajahanifar@users.noreply.github.com>
Co-authored-by: John Pocock <John-P@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Yijie Zhu <120978607+YijieZhu15@users.noreply.github.com>
Co-authored-by: Aleksandar Acic <32873451+aacic@users.noreply.github.com>
Co-authored-by: Abdol A <u2271662@live.warwick.ac.uk>
Co-authored-by: Abishek <abishekraj6797@gmail.com>
Co-authored-by: behnazelhaminia <30952176+behnazelhaminia@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Adam Shephard <adam.shephard@warwick.ac.uk>
Co-authored-by: gozdeg <gozdegunesli@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: mbasheer04 <78800844+mbasheer04@users.noreply.github.com>
Co-authored-by: vqdang <24943262+vqdang@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.