from dataclasses import dataclass
from numpy import isnan
[docs]
@dataclass(slots=True, kw_only=True)
class ScaleComplexity:
"""
Represents the Scale Complexity metric for inter-annotator agreement.
Attributes:
global_sc (float): The global Scale Complexity value for the entire dataset.
per_image_sc (dict[str, float]): A dictionary mapping image filenames to their respective Scale Complexity values.
global_alpha (float): The original agreement value (Krippendorff's Alpha) for the entire dataset before collapsing.
per_image_alpha (dict[str, float]): A dictionary mapping image filenames to their respective original agreement values (Krippendorff's Alpha) before collapsing.
global_alpha_collapsed (float): The new agreement value (Krippendorff's Alpha) for the entire dataset after collapsing categories.
per_image_alpha_collapsed (dict[str, float]): A dictionary mapping image filenames to their respective new agreement values (Krippendorff's Alpha) after collapsing categories.
"""
# Scale complexity values
global_sc: float
per_image_sc: dict[str, float]
# Original agreement values
global_alpha: float
per_image_alpha: dict[str, float]
# New agreement values
global_alpha_collapsed: float
per_image_alpha_collapsed: dict[str, float]
# Partial computation flag
partial: bool = False
def __str__(self) -> str:
s = f"Scale Complexity value: {self.global_sc:.4f} (Agreement reached: {self.global_alpha_collapsed:.4f})\n"
if self.partial:
raise ValueError("The Scale Complexity value for individual images is not available because the computation was partial.")
else:
s += "Per-image Scale Complexity values:\n"
for img_filename, sc_value in self.per_image_sc.items():
alpha_collapsed = self.per_image_alpha_collapsed[img_filename]
if alpha_collapsed is not None and not isnan(sc_value):
s += f" - {img_filename}:\t{sc_value:.4f}\t({self.per_image_alpha[img_filename]:.4f} -> {self.per_image_alpha_collapsed[img_filename]:.4f})\n"
return s
[docs]
def brief(self) -> str:
return f"Scale Complexity value: {self.global_sc:.4f} (Agreement reached: {self.global_alpha_collapsed:.4f})\n"
[docs]
def sc_for_image(self, image_filename: str) -> float:
"""
Retrieves the Scale Complexity value for a specific image.
Parameters:
image_filename (str): The filename of the image for which to retrieve the Scale Complexity value.
Returns:
float: The Scale Complexity value for the specified image.
"""
if self.partial:
raise ValueError("The Scale Complexity value for individual images is not available because the computation was partial.")
if image_filename not in self.per_image_sc:
raise ValueError(f"No Scale Complexity value found for image '{image_filename}'.")
return self.per_image_sc[image_filename]
[docs]
def agreement_for_image(self, image_filename: str) -> tuple[float, float]:
"""
Retrieves the agreement value (Krippendorff's Alpha) for a specific image before and after collapsing categories.
Parameters:
image_filename (str): The filename of the image for which to retrieve the agreement value.
Returns:
tuple[float, float]: The agreement value (Krippendorff's Alpha) for the specified image before and after collapsing categories.
"""
if self.partial:
raise ValueError("The Scale Complexity value for individual images is not available because the computation was partial.")
if image_filename not in self.per_image_alpha_collapsed:
raise ValueError(f"No agreement value found for image '{image_filename}'.")
return (self.per_image_alpha[image_filename], self.per_image_alpha_collapsed[image_filename])