import torch
from torch import Tensor


def standardize_background(y: Tensor) -> Tensor:
    if y.ndim != 3:
        raise ValueError("standardize_background requires a 3D tensor")
    bg = y.min(dim=0).values
    bg_med = bg.median()
    y = y - bg + bg_med
    return y


def merge(**kwargs) -> Tensor:
    y = torch.cat(list(kwargs.values()), dim=0)
    return y


def crop(y: Tensor, x0: int, x1: int, y0: int, y1: int) -> Tensor:
    if y.ndim != 3:
        raise ValueError("crop requires a 3D tensor")
    return y[:, y0:y1, x0:x1]


def bin(y: Tensor, binsize: int) -> Tensor:
    if y.ndim != 3:
        raise ValueError("bin requires a 3D tensor")
    bs, h, w = y.size()
    y = y[: bs - bs % binsize]
    y = y.reshape(bs // binsize, binsize, h, w)
    y = y.mean(dim=1)
    return y
