def random_block_mask_image(
    size: Tuple[int, int],
    num_masks: int,
    min_num_masks_per_block: int = 4,
    max_num_masks_per_block: Optional[int] = None,
    min_block_aspect_ratio: float = 0.3,
    max_block_aspect_ratio: Optional[float] = None,
    max_attempts_per_block: int = 10,
    device: Optional[Union[torch.device, str]] = None,
) -> Tensor:
    """Creates a random block mask for a single image.

    Args:
        size:
            Size of the image for which to generate a mask.
            Should be (height, width).
        num_masks:
            Number of patches to mask.
        min_num_masks_per_block:
            Minimum number of patches to mask per block.
        max_num_masks_per_block:
            Maximum number of patches to mask per block.
        min_block_aspect_ratio:
            Minimum aspect ratio (height/width) of a masked block.
        max_block_aspect_ratio:
            Maximum aspect ratio (height/width) of a masked block.
        max_attempts_per_block:
            Maximum number of attempts to find a valid block mask.
        device:
            Device on which to create the mask.
    Returns:
        A boolean tensor with shape (height, width) where each entry is True if the
        patch should be masked and False otherwise.

    Raises:
        ValueError: If 'max_num_masks_per_block' is less than 'min_num_masks_per_block' or
            if 'max_block_aspect_ratio' is less than 'min_block_aspect_ratio'
    """

    if max_block_aspect_ratio is None:
        max_block_aspect_ratio = 1 / min_block_aspect_ratio
    if max_num_masks_per_block is None:
        max_num_masks_per_block = num_masks

    if max_num_masks_per_block < min_num_masks_per_block:
        raise ValueError(
            "max_num_masks_per_block must be greater or equal to min_num_masks_per_block."
        )
    if max_block_aspect_ratio < min_block_aspect_ratio:
        raise ValueError(
            "max_block_aspect_ratio must be greater or equal to min_block_aspect_ratio."
        )

    log_min_aspect = math.log(min_block_aspect_ratio)
    log_max_aspect = math.log(max_block_aspect_ratio)

    H, W = size
    mask = torch.zeros((H, W), dtype=torch.bool, device=device)
    mask_count = 0
    while mask_count < num_masks:
        # Try masking a block
        max_new_masked = min(num_masks - mask_count, max_num_masks_per_block)
        delta = 0
        for _ in range(max_attempts_per_block):
            target_area = random.uniform(min_num_masks_per_block, max_new_masked)
            aspect_ratio = math.exp(random.uniform(log_min_aspect, log_max_aspect))
            h = int(round(math.sqrt(target_area * aspect_ratio)))
            w = int(round(math.sqrt(target_area / aspect_ratio)))
            if w < W and h < H:
                top = random.randint(0, H - h)
                left = random.randint(0, W - w)
                num_already_masked = mask[top : top + h, left : left + w].sum().item()
                num_new_masked = h * w - num_already_masked
                if 0 < num_new_masked <= max_new_masked:
                    mask[top : top + h, left : left + w] = 1
                    delta += num_new_masked
            if delta > 0:
                break
        if delta == 0:
            break
        else:
            mask_count += delta
    return mask
Creates a random block mask for a single image.

    Args:
        size:
            Size of the image for which to generate a mask.
            Should be (height, width).
        num_masks:
            Number of patches to mask.
        min_num_masks_per_block:
            Minimum number of patches to mask per block.
        max_num_masks_per_block:
            Maximum number of patches to mask per block.
        min_block_aspect_ratio:
            Minimum aspect ratio (height/width) of a masked block.
        max_block_aspect_ratio:
            Maximum aspect ratio (height/width) of a masked block.
        max_attempts_per_block:
            Maximum number of attempts to find a valid block mask.
        device:
            Device on which to create the mask.
    Returns:
        A boolean tensor with shape (height, width) where each entry is True if the
        patch should be masked and False otherwise.

    Raises:
        ValueError: If 'max_num_masks_per_block' is less than 'min_num_masks_per_block' or
            if 'max_block_aspect_ratio' is less than 'min_block_aspect_ratio'
    
lightly/models/utils.py