from __future__ import annotations
from pydantic import Field, field_serializer, field_validator, ConfigDict
from nxtomo.nxobject.nxdetector import FieldOfView
from nxtomomill.models.utils import filter_str_def, convert_str_to_bool
from ..base.general_section import GeneralSection as _GeneralSectionBase
[docs]class GeneralSection(_GeneralSectionBase):
model_config = ConfigDict(validate_assignment=True, validate_by_name=True)
input_file: str | None = Field(default=None, description="Input file path.")
raises_error: bool = Field(
default=False, description="Raise an error when encountered."
)
no_input: bool = Field(
default=False, description="Ask for user inputs if missing information."
)
single_file: bool = Field(
default=False, description="Create a single file for all sequences."
)
no_master_file: bool = Field(
default=True, description="Avoid creating the master file."
)
ignore_bliss_tomo_config: bool = Field(
default=False,
description="Ignore Bliss tomography group. On recent bliss file (2023) a dedicated group specify datasets to be used for tomography. Defining for example translations, rotation, etc. If True then this group will be ignored and conversion will fallback on using path list provided in the KEYS section.",
)
field_of_view: FieldOfView | None = Field(
default=None,
description="Force output to be a 'Full' or 'Half' acquisition. Else determine from existing metadata",
)
create_control_data: bool = Field(
default=True, description="Generate control/data - filled with machine current."
)
check_tomo_n: bool | None = Field(
default=None,
description="Check 'tomo_n' metadata once the conversion is done. By default will be done for all except scan build from 'scan_data'.",
)
rotation_is_clockwise: bool | None = Field(
default=None,
description="Force rotation clockwise or not. If not set will read the information from the bliss-tomo 'tomoconfig' group. Else consider rotation is counterclockwise.",
)
mechanical_lr_flip: bool = Field(
default=False,
description="Detector image is flipped **left-right** for mechanical reasons that are not propagated with bliss-tomo hdf5 metadata (mirror,..).",
)
mechanical_ud_flip: bool = Field(
default=False,
description="Detector image is flipped **up-down** for mechanical reasons that are not propagated with bliss-tomo hdf5 metadata (mirror,..).",
)
@property
def request_input(self) -> bool:
return not self.no_input
@request_input.setter
def request_input(self, request: bool):
self.no_input = request
@field_validator(
"check_tomo_n",
"rotation_is_clockwise",
mode="before",
)
@classmethod
def cast_general_section_to_bool_or_none(
cls, value: str | None | bool
) -> bool | None:
if isinstance(value, str):
value = filter_str_def(value)
if value in (None, "None", ""):
return None
elif value in ("True", True, "1"):
return True
elif value in ("False", False, "0"):
return False
else:
raise ValueError
@field_serializer(
"check_tomo_n",
"rotation_is_clockwise",
when_used="always",
)
@classmethod
def serialize_check_tomo_n(cls, value: None | bool) -> str:
if value is None:
return None
else:
return value
@field_validator(
"field_of_view",
mode="plain",
)
@classmethod
def cast_to_field_of_view(cls, value: str | FieldOfView) -> FieldOfView | None:
if value in (None, ""):
return None
return FieldOfView(value)
@field_serializer(
"field_of_view",
when_used="always",
)
@classmethod
def serialize_field_of_view(cls, field_of_view: FieldOfView | None) -> str:
if field_of_view is None:
return None
else:
return field_of_view.value
@field_validator(
"input_file",
mode="before",
)
@classmethod
def cast_general_section_to_str(cls, value: str | None) -> str | None:
return filter_str_def(value)
@field_validator(
"no_input",
"single_file",
"no_master_file",
"ignore_bliss_tomo_config",
"create_control_data",
"mechanical_lr_flip",
"mechanical_ud_flip",
mode="before",
)
@classmethod
def cast_general_section_to_bool(cls, value: str | bool | None) -> bool:
return convert_str_to_bool(value)