Skip to content

Add Fréchet Radiomics Distance (FRD) to MONAI metrics (#8643)#8769

Open
AymanL wants to merge 5 commits into
Project-MONAI:devfrom
AymanL:implement_frd_metric
Open

Add Fréchet Radiomics Distance (FRD) to MONAI metrics (#8643)#8769
AymanL wants to merge 5 commits into
Project-MONAI:devfrom
AymanL:implement_frd_metric

Conversation

@AymanL

@AymanL AymanL commented Mar 7, 2026

Copy link
Copy Markdown

Fixes #8643

Description

Implements FRD as in Konz et al. (arXiv:2412.01496): same Fréchet distance formula as FID, applied to pre-extracted radiomic features.
Supports 2D/3D and optional mask conditioning via external feature extraction (e.g. PyRadiomics).

Types of changes

  • Non-breaking change (fix or new feature that would not break existing functionality).
  • Breaking change (fix or new feature that would cause existing functionality to change).
  • New tests added to cover the changes.
  • Integration tests passed locally by running ./runtests.sh -f -u --net --coverage.
  • Quick tests passed locally by running ./runtests.sh --quick --unittests --disttests.
  • In-line docstrings updated.
  • Documentation updated, tested make html command in the docs/ folder.

@coderabbitai

coderabbitai Bot commented Mar 7, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 12710016-9448-4b36-8f43-a14359cf0cb7

📥 Commits

Reviewing files that changed from the base of the PR and between 12ee177 and 96c5fd0.

📒 Files selected for processing (3)
  • monai/metrics/__init__.py
  • monai/metrics/frd.py
  • tests/metrics/test_compute_frd_metric.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • monai/metrics/init.py
  • tests/metrics/test_compute_frd_metric.py
  • monai/metrics/frd.py

📝 Walkthrough

Walkthrough

Adds Fréchet Radiomics Distance (FRD) support. New module monai/metrics/frd.py implements a FrechetRadiomicsDistance Metric class and a get_frd_score(y_pred, y) function that compute the Fréchet distance by applying FID logic to radiomic feature vectors (expects 2D tensors (N, F); raises on ndim > 2 or too few samples). monai/metrics/init.py now exports FrechetRadiomicsDistance and get_frd_score. A new test file tests/metrics/test_compute_frd_metric.py validates FRD numeric output, equality with FID for identical features, and input-shape/error handling (tests skip if SciPy is unavailable).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed Title 'Add Fréchet Radiomics Distance (FRD) to MONAI metrics (#8643)' is specific, concise, and clearly summarizes the main change—introducing FRD as a new metric to the MONAI library.
Description check ✅ Passed Description covers implementation details, includes all required checkboxes (non-breaking change, tests added, integration tests passed, docstrings updated, documentation updated), and references the linked issue #8643.
Linked Issues check ✅ Passed Changes fully meet objectives from #8643: FrechetRadiomicsDistance class added to monai.metrics, computes Fréchet distance on radiomic feature vectors, supports 2D/3D, integrates with existing metric pipeline, and includes comprehensive tests.
Out of Scope Changes check ✅ Passed All changes are within scope of #8643: new FRD module, exports to metrics init, tests, and documentation—no unrelated modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (2)
monai/metrics/frd.py (1)

52-65: Add Raises section to docstring.

get_fid_score raises ValueError when inputs have >2 dimensions. Document this for callers.

📝 Suggested docstring addition
     Args:
         y_pred: Feature vectors for the first distribution, shape (N, F).
         y: Feature vectors for the second distribution, shape (N, F).

     Returns:
         Scalar tensor containing the Fréchet Radiomics Distance.
+
+    Raises:
+        ValueError: If inputs have more than 2 dimensions.
     """
     return get_fid_score(y_pred, y)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@monai/metrics/frd.py` around lines 52 - 65, Add a Raises section to the
get_frd_score docstring documenting that get_fid_score may raise a ValueError
when inputs have more than 2 dimensions; update the get_frd_score docstring (the
function named get_frd_score calling get_fid_score) to include a "Raises" entry
that explicitly states ValueError is raised for input tensors with rank > 2 so
callers are aware of this precondition.
tests/metrics/test_compute_frd_metric.py (1)

41-43: Test name and setup are slightly misleading.

The ValueError is raised because ndimension() > 2, not due to spatial dimension mismatch (144 vs 145). Consider renaming to test_rejects_high_dimensional_input and using identical tensors.

♻️ Suggested clarification
-    def test_input_dimensions(self):
+    def test_rejects_high_dimensional_input(self):
+        """Inputs with more than 2 dimensions should raise ValueError."""
         with self.assertRaises(ValueError):
-            FrechetRadiomicsDistance()(torch.ones([3, 3, 144, 144]), torch.ones([3, 3, 145, 145]))
+            FrechetRadiomicsDistance()(torch.ones([3, 3, 144, 144]), torch.ones([3, 3, 144, 144]))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/metrics/test_compute_frd_metric.py` around lines 41 - 43, Rename the
test to reflect the actual rejection reason and make the input tensors identical
so the failure is due to ndimension()>2: change the test name from
test_input_dimensions to test_rejects_high_dimensional_input and call
FrechetRadiomicsDistance() with two tensors of the same shape (e.g.,
torch.ones([3, 3, 144, 144]) for both) so the ValueError arises from the high
number of dimensions rather than mismatched spatial sizes; update any test
docstring or comment accordingly to reference FrechetRadiomicsDistance and
ndimension.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@monai/metrics/frd.py`:
- Around line 52-65: Add a Raises section to the get_frd_score docstring
documenting that get_fid_score may raise a ValueError when inputs have more than
2 dimensions; update the get_frd_score docstring (the function named
get_frd_score calling get_fid_score) to include a "Raises" entry that explicitly
states ValueError is raised for input tensors with rank > 2 so callers are aware
of this precondition.

In `@tests/metrics/test_compute_frd_metric.py`:
- Around line 41-43: Rename the test to reflect the actual rejection reason and
make the input tensors identical so the failure is due to ndimension()>2: change
the test name from test_input_dimensions to test_rejects_high_dimensional_input
and call FrechetRadiomicsDistance() with two tensors of the same shape (e.g.,
torch.ones([3, 3, 144, 144]) for both) so the ValueError arises from the high
number of dimensions rather than mismatched spatial sizes; update any test
docstring or comment accordingly to reference FrechetRadiomicsDistance and
ndimension.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e025c2d5-a892-4a84-a2a7-8546a1f5e587

📥 Commits

Reviewing files that changed from the base of the PR and between daaedaa and be31e64.

📒 Files selected for processing (3)
  • monai/metrics/__init__.py
  • monai/metrics/frd.py
  • tests/metrics/test_compute_frd_metric.py

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
monai/metrics/frd.py (1)

24-36: Tighten the API docstring.

This callable only accepts pre-extracted (N, F) feature tensors. Saying it “works for 2D and 3D images” and supports mask conditioning reads like image or mask tensors are accepted here, which this API does not expose. Please state that 2D/3D images and masks are handled during external feature extraction, not by this metric itself.

As per coding guidelines, "Docstrings should be present for all definition which describe each variable, return value, and raised exception in the appropriate section of the Google-style of docstrings."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@monai/metrics/frd.py` around lines 24 - 36, Update the frd module/class
docstring to explicitly state the callable accepts only pre-extracted feature
tensors of shape (N, F) and does not accept raw 2D/3D images or masks; clarify
that any handling of 2D/3D images and mask-based conditioning must be performed
during external feature extraction (e.g., via PyRadiomics) prior to calling this
metric. Tighten wording to remove implications that images or masks are accepted
directly, and add Google-style docstring sections for Args (describe the
features tensor shape and dtype), Returns (what the function returns), and
Raises (any errors for invalid shapes or inputs), referencing the callable name
in the docstring so reviewers can locate it easily.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@monai/metrics/frd.py`:
- Around line 52-69: Add a symmetric input-dimension validation in
get_frd_score: check y_pred.ndimension() > 2 and raise the same ValueError used
by monai.metrics.fid.get_fid_score when inputs have >2 dims, before calling
get_fid_score(y_pred, y); also add a unit test that passes a 3D y_pred and a
valid 2D y to exercise the error path. This ensures get_frd_score mirrors
get_fid_score's shape guard and the y_pred-only high-dimensional case is
covered.

---

Nitpick comments:
In `@monai/metrics/frd.py`:
- Around line 24-36: Update the frd module/class docstring to explicitly state
the callable accepts only pre-extracted feature tensors of shape (N, F) and does
not accept raw 2D/3D images or masks; clarify that any handling of 2D/3D images
and mask-based conditioning must be performed during external feature extraction
(e.g., via PyRadiomics) prior to calling this metric. Tighten wording to remove
implications that images or masks are accepted directly, and add Google-style
docstring sections for Args (describe the features tensor shape and dtype),
Returns (what the function returns), and Raises (any errors for invalid shapes
or inputs), referencing the callable name in the docstring so reviewers can
locate it easily.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ab4187ab-ad3b-4657-921a-6464fefb2d3c

📥 Commits

Reviewing files that changed from the base of the PR and between be31e64 and e56a919.

📒 Files selected for processing (2)
  • monai/metrics/frd.py
  • tests/metrics/test_compute_frd_metric.py

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
monai/metrics/frd.py (1)

22-49: Clarify the callable API in the docstrings.

FrechetRadiomicsDistance() takes no constructor args, but the class docstring has an Args:/Returns: block for __call__, and __call__ itself is undocumented. Move the parameter/exception docs onto __call__ (or keep them only on get_frd_score) and phrase the 2D/3D image + mask support as upstream feature-extraction context, not direct inputs to this class.

As per coding guidelines, "Docstrings should be present for all definition which describe each variable, return value, and raised exception in the appropriate section of the Google-style of docstrings."

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@monai/metrics/frd.py`:
- Around line 52-71: The get_frd_score function currently only rejects tensors
with ndimension() > 2 but should enforce a strict (N, F) contract and reject
non-2D inputs and single-sample batches before delegating to get_fid_score;
modify get_frd_score to validate that both y_pred.ndimension() == 2 and
y.ndimension() == 2 and that y_pred.size(0) >= 2 and y.size(0) >= 2, raising a
clear ValueError if any check fails (mentioning expected shape and minimum batch
size), then keep calling get_fid_score when checks pass, and add unit tests that
assert ValueError is raised for 0D/1D inputs and for N < 2 for both y_pred and
y.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a736e1b6-45fd-4ce7-81bf-045e2e26f5f1

📥 Commits

Reviewing files that changed from the base of the PR and between e56a919 and 12ee177.

📒 Files selected for processing (1)
  • monai/metrics/frd.py

Comment thread monai/metrics/frd.py
@ericspod

Copy link
Copy Markdown
Member

Hi @AymanL thanks for this contribution. It seems that this metric is equivalent to FIDMetric (as shown in your tests) but is used for comparing radiomic values rather than images. I get from the description and the paper why this is done but it's less clear why a separate class is needed for this. To provide enough material to know how to use this class, you need to provide a tutorial here demonstrating how to extract radiomic values and compute the FRD, in which case you could just use FIDMetric.

Also I see in the docstring "The same Fréchet distance formula as in FID is applied to the mean and covariance of these features." Does this imply that there should be some other computation being done that is different from what FIDMetric does?

I think the Coderabbit comment is worth responding to with a more precise check of the input values, I know get_fid_score will raise an exception if the dimensions are wrong but a more descriptive error before that happens would help users.

AymanL and others added 4 commits June 9, 2026 17:07
Signed-off-by: AymanL <40838419+AymanL@users.noreply.github.com>
…ub.com>

I, AymanL <40838419+AymanL@users.noreply.github.com>, hereby add my Signed-off-by to this commit: be31e64

Signed-off-by: AymanL <40838419+AymanL@users.noreply.github.com>
@AymanL AymanL force-pushed the implement_frd_metric branch from 12ee177 to 20ab2bd Compare June 9, 2026 15:12
…ub.com>

I, AymanL <40838419+AymanL@users.noreply.github.com>, hereby add my Signed-off-by to this commit: 584cc87

Signed-off-by: AymanL <40838419+AymanL@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Fréchet Radiomics Distance (FRD-Score) to MONAI Metrics

3 participants