def compute_anomaly_score(
        self,
        patch_scores: torch.Tensor,
        locations: torch.Tensor,
        embedding: torch.Tensor,
    ) -> torch.Tensor:
        """Compute image-level anomaly scores.

        Implements the paper's weighted scoring mechanism that considers both
        the distance to nearest neighbors and the local neighborhood structure
        in the memory bank.

        Args:
            patch_scores (torch.Tensor): Patch-level anomaly scores.
            locations (torch.Tensor): Memory bank indices of nearest neighbors.
            embedding (torch.Tensor): Input embeddings that generated the scores.

        Returns:
            torch.Tensor: Image-level anomaly scores.

        Example:
            >>> patch_scores = torch.randn(32, 49)  # 7x7 patches
            >>> locations = torch.randint(0, 1000, (32, 49))
            >>> embedding = torch.randn(32 * 49, 512)
            >>> scores = model.compute_anomaly_score(patch_scores, locations,
            ...                                     embedding)
            >>> scores.shape
            torch.Size([32])

        Note:
            When ``num_neighbors=1``, returns the maximum patch score directly.
            Otherwise, computes weighted scores using neighborhood information.
        """
        # Don't need to compute weights if num_neighbors is 1
        if self.num_neighbors == 1:
            return patch_scores.amax(1)
        batch_size, num_patches = patch_scores.shape
        # 1. Find the patch with the largest distance to it's nearest neighbor in each image
        max_patches = torch.argmax(patch_scores, dim=1)  # indices of m^test,* in the paper
        # m^test,* in the paper
        max_patches_features = embedding.reshape(batch_size, num_patches, -1)[torch.arange(batch_size), max_patches]
        # 2. Find the distance of the patch to it's nearest neighbor, and the location of the nn in the membank
        score = patch_scores[torch.arange(batch_size), max_patches]  # s^* in the paper
        nn_index = locations[torch.arange(batch_size), max_patches]  # indices of m^* in the paper
        # 3. Find the support samples of the nearest neighbor in the membank
        nn_sample = self.memory_bank[nn_index, :]  # m^* in the paper
        # indices of N_b(m^*) in the paper
        memory_bank_effective_size = self.memory_bank.shape[0]  # edge case when memory bank is too small
        _, support_samples = self.nearest_neighbors(
            nn_sample,
            n_neighbors=min(self.num_neighbors, memory_bank_effective_size),
        )
        # 4. Find the distance of the patch features to each of the support samples
        distances = self.euclidean_dist(max_patches_features.unsqueeze(1), self.memory_bank[support_samples])
        # 5. Apply softmax to find the weights
        weights = (1 - F.softmax(distances.squeeze(1), 1))[..., 0]
        # 6. Apply the weight factor to the score
        return weights * score  # s in the paper
Compute image-level anomaly scores.

        Implements the paper's weighted scoring mechanism that considers both
        the distance to nearest neighbors and the local neighborhood structure
        in the memory bank.

        Args:
            patch_scores (torch.Tensor): Patch-level anomaly scores.
            locations (torch.Tensor): Memory bank indices of nearest neighbors.
            embedding (torch.Tensor): Input embeddings that generated the scores.

        Returns:
            torch.Tensor: Image-level anomaly scores.

        Example:
            >>> patch_scores = torch.randn(32, 49)  # 7x7 patches
            >>> locations = torch.randint(0, 1000, (32, 49))
            >>> embedding = torch.randn(32 * 49, 512)
            >>> scores = model.compute_anomaly_score(patch_scores, locations,
            ...                                     embedding)
            >>> scores.shape
            torch.Size([32])

        Note:
            When ``num_neighbors=1``, returns the maximum patch score directly.
            Otherwise, computes weighted scores using neighborhood information.
        
src/anomalib/models/image/patchcore/torch_model.py