From f761e1a86af1c13eb212ff1e71b9f31f78218d1e Mon Sep 17 00:00:00 2001 From: Utz Ermel Date: Wed, 4 Dec 2024 12:00:12 -0800 Subject: [PATCH] add support for reading model-to-image transformation info (#23) --- src/imodmodel/binary_specification.py | 11 ++++++++--- src/imodmodel/models.py | 10 ++++++++++ src/imodmodel/parsers.py | 10 +++++++++- tests/test_model_api.py | 10 ++++++++++ 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/imodmodel/binary_specification.py b/src/imodmodel/binary_specification.py index 0aab970..14bccd5 100644 --- a/src/imodmodel/binary_specification.py +++ b/src/imodmodel/binary_specification.py @@ -83,7 +83,6 @@ class ModFileSpecification: 'matflags2': 'B', 'mat3b3': 'B' } - VIEW = { 'fovy': 'f', 'rad': 'f', @@ -110,10 +109,16 @@ class ModFileSpecification: 'center': '3f', 'label': '32c' } - + MINX = { + 'oscale': '3f', + 'otrans': '3f', + 'orot': '3f', + 'cscale': '3f', + 'ctrans': '3f', + 'crot': '3f', + } SIZE = NotImplemented MESH = NotImplemented - MINX = NotImplemented LABL = NotImplemented OLBL = NotImplemented CLIP = NotImplemented diff --git a/src/imodmodel/models.py b/src/imodmodel/models.py index d49c2d3..a3554af 100644 --- a/src/imodmodel/models.py +++ b/src/imodmodel/models.py @@ -188,6 +188,15 @@ class IMAT(BaseModel): matflags2: int mat3b3: int +class MINX(BaseModel): + """https://bio3d.colorado.edu/imod/doc/binspec.html""" + oscale: Tuple[float, float, float] + otrans: Tuple[float, float, float] + orot: Tuple[float, float, float] + cscale: Tuple[float, float, float] + ctrans: Tuple[float, float, float] + crot: Tuple[float, float, float] + class Size(BaseModel): """https://bio3d.colorado.edu/imod/doc/binspec.html""" @@ -246,6 +255,7 @@ class ImodModel(BaseModel): header: ModelHeader objects: List[Object] slicer_angles: List[SLAN] = [] + minx: Optional[MINX] extra: List[GeneralStorage] = [] @classmethod diff --git a/src/imodmodel/parsers.py b/src/imodmodel/parsers.py index e38aa82..2a0f328 100644 --- a/src/imodmodel/parsers.py +++ b/src/imodmodel/parsers.py @@ -13,6 +13,7 @@ GeneralStorage, Mesh, MeshHeader, + MINX, ImodModel, ModelHeader, Object, @@ -130,6 +131,10 @@ def _parse_imat(file: BinaryIO) -> IMAT: data = _parse_from_specification(file, ModFileSpecification.IMAT) return IMAT(**data) +def _parse_minx(file: BinaryIO) -> MINX: + _parse_chunk_size(file) + data = _parse_from_specification(file, ModFileSpecification.MINX) + return MINX(**data) def _parse_general_storage(file: BinaryIO) -> List[GeneralStorage]: size = _parse_chunk_size(file) @@ -159,6 +164,7 @@ def parse_model(file: BinaryIO) -> ImodModel: header = _parse_model_header(file) control_sequence = _parse_control_sequence(file) slicer_angles = [] + minx = None extra = list() objects = [] @@ -181,7 +187,9 @@ def parse_model(file: BinaryIO) -> ImodModel: objects[-1].meshes[-1].extra += _parse_general_storage(file) elif control_sequence == "SLAN": slicer_angles.append(_parse_slicer_angle(file)) + elif control_sequence == "MINX": + minx = _parse_minx(file) else: _parse_unknown(file) control_sequence = _parse_control_sequence(file) - return ImodModel(id=id, header=header, objects=objects, slicer_angles=slicer_angles, extra=extra) + return ImodModel(id=id, header=header, objects=objects, slicer_angles=slicer_angles, minx=minx, extra=extra) diff --git a/tests/test_model_api.py b/tests/test_model_api.py index e5f3245..d57ec6f 100644 --- a/tests/test_model_api.py +++ b/tests/test_model_api.py @@ -69,3 +69,13 @@ def test_multiple_objects(file_fixture_multiple_objects, objects_expected, reque assert isinstance(model.objects[2].contours[0], Contour) +def test_read_minx(meshed_contour_model_file): + """Check reading of model to image transformation information.""" + model = ImodModel.from_file(meshed_contour_model_file) + assert isinstance(model, ImodModel) + assert model.minx.cscale == pytest.approx((10.680000, 10.680000, 10.680000), abs=1e-6) + assert model.minx.ctrans == pytest.approx((-2228.0, 2228.0, 681.099976), abs=1e-6) + assert model.minx.crot == pytest.approx((0.0, 0.0, 0.0), abs=1e-6) + + +