def binary_classification_curve(
    scores_batch: torch.Tensor,
    gts_batch: torch.Tensor,
    thresholds: torch.Tensor,
) -> torch.Tensor:
    """Compute binary classification matrices for a batch of images.

    This is a wrapper around :func:`_binary_classification_curve` that handles
    input validation and batching.

    Note:
        Predicted positives are determined by ``score >= thresh``

    Args:
        scores_batch: Anomaly scores of shape ``(N, D)``
        gts_batch: Binary ground truth of shape ``(N, D)``
        thresholds: Sequence of thresholds in ascending order ``(K,)``

    Returns:
        Binary classification matrix curves of shape ``(N, K, 2, 2)``
        where:

        - ``[..., 1, 1]``: True Positives (TP)
        - ``[..., 0, 1]``: False Positives (FP)
        - ``[..., 1, 0]``: False Negatives (FN)
        - ``[..., 0, 0]``: True Negatives (TN)

        The counts are per-instance (e.g. number of pixels in each image).
        Thresholds are shared across instances.

    Example:
        >>> scores = torch.rand(10, 100)  # 10 images, 100 pixels each
        >>> gts = torch.randint(0, 2, (10, 100)).bool()
        >>> thresholds = torch.linspace(0, 1, 10)
        >>> curves = binary_classification_curve(scores, gts, thresholds)
        >>> curves.shape
        torch.Size([10, 10, 2, 2])
    """
    _validate.is_scores_batch(scores_batch)
    _validate.is_gts_batch(gts_batch)
    _validate.is_same_shape(scores_batch, gts_batch)
    _validate.is_valid_threshold(thresholds)
    # TODO(ashwinvaidya17): this is kept as numpy for now because it is much
    # faster.
    # TEMP-0
    result = np.vectorize(_binary_classification_curve, signature="(n),(n),(k)->(k,2,2)")(
        scores_batch.detach().cpu().numpy(),
        gts_batch.detach().cpu().numpy(),
        thresholds.detach().cpu().numpy(),
    )
    return torch.from_numpy(result).to(scores_batch.device)
Compute binary classification matrices for a batch of images.

    This is a wrapper around :func:`_binary_classification_curve` that handles
    input validation and batching.

    Note:
        Predicted positives are determined by ``score >= thresh``

    Args:
        scores_batch: Anomaly scores of shape ``(N, D)``
        gts_batch: Binary ground truth of shape ``(N, D)``
        thresholds: Sequence of thresholds in ascending order ``(K,)``

    Returns:
        Binary classification matrix curves of shape ``(N, K, 2, 2)``
        where:

        - ``[..., 1, 1]``: True Positives (TP)
        - ``[..., 0, 1]``: False Positives (FP)
        - ``[..., 1, 0]``: False Negatives (FN)
        - ``[..., 0, 0]``: True Negatives (TN)

        The counts are per-instance (e.g. number of pixels in each image).
        Thresholds are shared across instances.

    Example:
        >>> scores = torch.rand(10, 100)  # 10 images, 100 pixels each
        >>> gts = torch.randint(0, 2, (10, 100)).bool()
        >>> thresholds = torch.linspace(0, 1, 10)
        >>> curves = binary_classification_curve(scores, gts, thresholds)
        >>> curves.shape
        torch.Size([10, 10, 2, 2])
    
src/anomalib/metrics/pimo/binary_classification_curve.py