Repository: Lightning-AI/torchmetrics

Issue:
AUC score legend not plotted when score=True
## 🐛 Bug

<!-- A clear and concise description of what the bug is. -->

When calling the `.plot(score=True)` on curve metrics like BinaryPrecisionRecall, BinaryROC.... The AUC score is not shown.

### To Reproduce

Steps to reproduce the behavior...

<!-- If you have a code sample, error messages, stack traces, please provide it here as well -->

```
from torch import randn, randint
from torchmetrics.classification import BinaryPrecisionRecallCurve
import torch.nn.functional as F
preds = F.softmax(randn(20, 2), dim=1)
target = randint(2, (20,))
metric = BinaryPrecisionRecallCurve()
metric.update(preds[:, 1], target)
fig_, ax_ = metric.plot(score=True)
```

<details>
  <summary>Code sample</summary>

<!-- Ideally attach a minimal code sample to reproduce the decried issue.
Minimal means having the shortest code but still preserving the bug. -->

</details>

### Expected behavior

<!-- A clear and concise description of what you expected to happen. -->

Expect a legend showing the AUC score.

### Environment

- TorchMetrics version (and how you installed TM, e.g. `conda`, `pip`, build from source): 1.01, from pip
- Python & PyTorch Version (e.g., 1.0): torch 1.13, python 3.10.11
- Any other relevant information such as OS (e.g., Linux): Linux

### Additional context

<!-- Add any other context about the problem here. -->

The bug seems be due to the score is computed when `curve is None and score is True`, however `curve` is computed before this expression, so `curve` is always not None and `score` will never be computed, here is an example of BinaryROC: 

```
# line 156-164 in src/torchmetrics/classification/roc.py
        curve = curve or self.compute()
        score = _auc_compute_without_check(curve[0], curve[1], 1.0) if not curve and score is True else None
        return plot_curve(
            curve,
            score=score,
            ax=ax,
            label_names=("False positive rate", "True positive rate"),
            name=self.__class__.__name__,
        )
```

it works as expected after changing it to:

```
        curve_computed = curve or self.compute()
        score = _auc_compute_without_check(curve_computed[0], curve_computed[1], 1.0) if not curve and score is True else None
        return plot_curve(
            curve_computed,
            score=score,
            ax=ax,
            label_names=("False positive rate", "True positive rate"),
            name=self.__class__.__name__,
        )
```


Discussion:
Hi! thanks for your contribution!, great first issue!

Resolving patch:
diff --git a/src/torchmetrics/classification/precision_recall_curve.py b/src/torchmetrics/classification/precision_recall_curve.py
--- a/src/torchmetrics/classification/precision_recall_curve.py
+++ b/src/torchmetrics/classification/precision_recall_curve.py
@@ -197,19 +197,24 @@ def plot(
         .. plot::
             :scale: 75
 
-            >>> from torch import randn, randint
-            >>> import torch.nn.functional as F
-            >>> from torchmetrics.classification import BinaryROC
-            >>> preds = F.softmax(randn(20, 2), dim=1)
+            >>> from torch import rand, randint
+            >>> from torchmetrics.classification import BinaryPrecisionRecallCurve
+            >>> preds = rand(20)
             >>> target = randint(2, (20,))
-            >>> metric = BinaryROC()
-            >>> metric.update(preds[:, 1], target)
-            >>> fig_, ax_ = metric.plot()
+            >>> metric = BinaryPrecisionRecallCurve()
+            >>> metric.update(preds, target)
+            >>> fig_, ax_ = metric.plot(score=True)
 
         """
-        curve = curve or self.compute()
-        score = _auc_compute_without_check(curve[0], curve[1], 1.0) if not curve and score is True else None
-        return plot_curve(curve, score=score, ax=ax, label_names=("Precision", "Recall"), name=self.__class__.__name__)
+        curve_computed = curve or self.compute()
+        score = (
+            _auc_compute_without_check(curve_computed[0], curve_computed[1], 1.0)
+            if not curve and score is True
+            else None
+        )
+        return plot_curve(
+            curve_computed, score=score, ax=ax, label_names=("Precision", "Recall"), name=self.__class__.__name__
+        )
 
 
 class MulticlassPrecisionRecallCurve(Metric):
@@ -374,18 +379,21 @@ def plot(
             :scale: 75
 
             >>> from torch import randn, randint
-            >>> import torch.nn.functional as F
-            >>> from torchmetrics.classification import BinaryROC
-            >>> preds = F.softmax(randn(20, 2), dim=1)
-            >>> target = randint(2, (20,))
-            >>> metric = BinaryROC()
-            >>> metric.update(preds[:, 1], target)
-            >>> fig_, ax_ = metric.plot()
+            >>> from torchmetrics.classification import MulticlassPrecisionRecallCurve
+            >>> preds = randn(20, 3).softmax(dim=-1)
+            >>> target = randint(3, (20,))
+            >>> metric = MulticlassPrecisionRecallCurve(num_classes=3)
+            >>> metric.update(preds, target)
+            >>> fig_, ax_ = metric.plot(score=True)
 
         """
-        curve = curve or self.compute()
-        score = _reduce_auroc(curve[0], curve[1], average=None) if not curve and score is True else None
-        return plot_curve(curve, score=score, ax=ax, label_names=("Precision", "Recall"), name=self.__class__.__name__)
+        curve_computed = curve or self.compute()
+        score = (
+            _reduce_auroc(curve_computed[0], curve_computed[1], average=None) if not curve and score is True else None
+        )
+        return plot_curve(
+            curve_computed, score=score, ax=ax, label_names=("Precision", "Recall"), name=self.__class__.__name__
+        )
 
 
 class MultilabelPrecisionRecallCurve(Metric):
@@ -558,19 +566,22 @@ def plot(
         .. plot::
             :scale: 75
 
-            >>> from torch import randn, randint
-            >>> import torch.nn.functional as F
-            >>> from torchmetrics.classification import BinaryROC
-            >>> preds = F.softmax(randn(20, 2), dim=1)
-            >>> target = randint(2, (20,))
-            >>> metric = BinaryROC()
-            >>> metric.update(preds[:, 1], target)
-            >>> fig_, ax_ = metric.plot()
+            >>> from torch import rand, randint
+            >>> from torchmetrics.classification import MultilabelPrecisionRecallCurve
+            >>> preds = rand(20, 3)
+            >>> target = randint(2, (20,3))
+            >>> metric = MultilabelPrecisionRecallCurve(num_labels=3)
+            >>> metric.update(preds, target)
+            >>> fig_, ax_ = metric.plot(score=True)
 
         """
-        curve = curve or self.compute()
-        score = _reduce_auroc(curve[0], curve[1], average=None) if not curve and score is True else None
-        return plot_curve(curve, score=score, ax=ax, label_names=("Precision", "Recall"), name=self.__class__.__name__)
+        curve_computed = curve or self.compute()
+        score = (
+            _reduce_auroc(curve_computed[0], curve_computed[1], average=None) if not curve and score is True else None
+        )
+        return plot_curve(
+            curve_computed, score=score, ax=ax, label_names=("Precision", "Recall"), name=self.__class__.__name__
+        )
 
 
 class PrecisionRecallCurve:
diff --git a/src/torchmetrics/classification/roc.py b/src/torchmetrics/classification/roc.py
--- a/src/torchmetrics/classification/roc.py
+++ b/src/torchmetrics/classification/roc.py
@@ -143,20 +143,23 @@ def plot(
         .. plot::
             :scale: 75
 
-            >>> from torch import randn, randint
-            >>> import torch.nn.functional as F
+            >>> from torch import rand, randint
             >>> from torchmetrics.classification import BinaryROC
-            >>> preds = F.softmax(randn(20, 2), dim=1)
+            >>> preds = rand(20)
             >>> target = randint(2, (20,))
             >>> metric = BinaryROC()
-            >>> metric.update(preds[:, 1], target)
-            >>> fig_, ax_ = metric.plot()
+            >>> metric.update(preds, target)
+            >>> fig_, ax_ = metric.plot(score=True)
 
         """
-        curve = curve or self.compute()
-        score = _auc_compute_without_check(curve[0], curve[1], 1.0) if not curve and score is True else None
+        curve_computed = curve or self.compute()
+        score = (
+            _auc_compute_without_check(curve_computed[0], curve_computed[1], 1.0)
+            if not curve and score is True
+            else None
+        )
         return plot_curve(
-            curve,
+            curve_computed,
             score=score,
             ax=ax,
             label_names=("False positive rate", "True positive rate"),
@@ -296,19 +299,20 @@ def plot(
             :scale: 75
 
             >>> from torch import randn, randint
-            >>> import torch.nn.functional as F
-            >>> from torchmetrics.classification import BinaryROC
-            >>> preds = F.softmax(randn(20, 2), dim=1)
-            >>> target = randint(2, (20,))
-            >>> metric = BinaryROC()
-            >>> metric.update(preds[:, 1], target)
-            >>> fig_, ax_ = metric.plot()
+            >>> from torchmetrics.classification import MulticlassROC
+            >>> preds = randn(20, 3).softmax(dim=-1)
+            >>> target = randint(3, (20,))
+            >>> metric = MulticlassROC(num_classes=3)
+            >>> metric.update(preds, target)
+            >>> fig_, ax_ = metric.plot(score=True)
 
         """
-        curve = curve or self.compute()
-        score = _reduce_auroc(curve[0], curve[1], average=None) if not curve and score is True else None
+        curve_computed = curve or self.compute()
+        score = (
+            _reduce_auroc(curve_computed[0], curve_computed[1], average=None) if not curve and score is True else None
+        )
         return plot_curve(
-            curve,
+            curve_computed,
             score=score,
             ax=ax,
             label_names=("False positive rate", "True positive rate"),
@@ -449,20 +453,21 @@ def plot(
         .. plot::
             :scale: 75
 
-            >>> from torch import randn, randint
-            >>> import torch.nn.functional as F
-            >>> from torchmetrics.classification import BinaryROC
-            >>> preds = F.softmax(randn(20, 2), dim=1)
-            >>> target = randint(2, (20,))
-            >>> metric = BinaryROC()
-            >>> metric.update(preds[:, 1], target)
-            >>> fig_, ax_ = metric.plot()
+            >>> from torch import rand, randint
+            >>> from torchmetrics.classification import MultilabelROC
+            >>> preds = rand(20, 3)
+            >>> target = randint(2, (20,3))
+            >>> metric = MultilabelROC(num_labels=3)
+            >>> metric.update(preds, target)
+            >>> fig_, ax_ = metric.plot(score=True)
 
         """
-        curve = curve or self.compute()
-        score = _reduce_auroc(curve[0], curve[1], average=None) if not curve and score is True else None
+        curve_computed = curve or self.compute()
+        score = (
+            _reduce_auroc(curve_computed[0], curve_computed[1], average=None) if not curve and score is True else None
+        )
         return plot_curve(
-            curve,
+            curve_computed,
             score=score,
             ax=ax,
             label_names=("False positive rate", "True positive rate"),


Test patch: