from __future__ import annotations
from pydantic import BaseModel, ConfigDict, Field, field_validator, field_serializer
class CropModel(BaseModel):
model_config = ConfigDict(validate_assignment=True, arbitrary_types_allowed=True)
axis_0_slice: slice | None = Field(default=None, examples=["0:60", None])
"""ROI to apply along the axis 0"""
axis_1_slice: slice | None = Field(default=None, examples=["0:60", None])
"""ROI to apply along the axis 1"""
axis_2_slice: slice | None = Field(default=None, examples=["0:60", None])
"""ROI to apply along the axis 2"""
@field_validator(
"axis_0_slice",
"axis_1_slice",
"axis_2_slice",
mode="before",
)
@classmethod
def cast_axis_slice(cls, v: slice | str | None) -> slice | None:
if isinstance(v, str):
if v.replace(" ", "") == ":":
return None
slice_ = slice(*[int(x) if x else None for x in v.split(":")])
if slice_.step not in (None, 1):
raise ValueError(f"only slices with step 1 are supported. Got {v}")
if slice_.start is None:
slice_ = slice(0, slice_.stop, slice_.step)
if (slice_.stop is not None) and (slice_.start > slice_.stop):
raise ValueError(f"slice start should be inferior to slice stop. Got {v}")
if (slice_.stop is not None) and (slice_.start < 0 or slice_.stop < 0):
raise ValueError(f"slice start and stop should be positive. Got {v}")
return slice_
return v
@field_serializer(
"axis_0_slice",
"axis_1_slice",
"axis_2_slice",
when_used="always",
)
@classmethod
def serialize_axis_slice(cls, v: slice | None) -> str:
if isinstance(v, slice):
return f"{v.start}:{v.stop}"
if v is None:
return ":"
return v