liblaf-melon 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- liblaf/melon/__init__.py +3 -0
- liblaf/melon/__init__.pyi +103 -0
- liblaf/melon/cli/__init__.py +3 -0
- liblaf/melon/cli/__init__.pyi +0 -0
- liblaf/melon/io/__init__.py +3 -0
- liblaf/melon/io/__init__.pyi +61 -0
- liblaf/melon/io/_copy.py +5 -0
- liblaf/melon/io/_load.py +13 -0
- liblaf/melon/io/_save.py +13 -0
- liblaf/melon/io/dispatcher/__init__.py +3 -0
- liblaf/melon/io/dispatcher/__init__.pyi +47 -0
- liblaf/melon/io/dispatcher/conversion/__init__.py +3 -0
- liblaf/melon/io/dispatcher/conversion/__init__.pyi +18 -0
- liblaf/melon/io/dispatcher/conversion/_converter.py +17 -0
- liblaf/melon/io/dispatcher/conversion/_dispatcher.py +29 -0
- liblaf/melon/io/dispatcher/conversion/_utils.py +22 -0
- liblaf/melon/io/dispatcher/reader/__init__.py +3 -0
- liblaf/melon/io/dispatcher/reader/__init__.pyi +12 -0
- liblaf/melon/io/dispatcher/reader/_dispatcher.py +27 -0
- liblaf/melon/io/dispatcher/reader/_reader.py +17 -0
- liblaf/melon/io/dispatcher/reader/_utils.py +11 -0
- liblaf/melon/io/dispatcher/writer/__init__.py +3 -0
- liblaf/melon/io/dispatcher/writer/__init__.pyi +12 -0
- liblaf/melon/io/dispatcher/writer/_dispatcher.py +27 -0
- liblaf/melon/io/dispatcher/writer/_utils.py +11 -0
- liblaf/melon/io/dispatcher/writer/_writer.py +17 -0
- liblaf/melon/io/melon/__init__.py +3 -0
- liblaf/melon/io/melon/__init__.pyi +4 -0
- liblaf/melon/io/melon/dicom/__init__.py +3 -0
- liblaf/melon/io/melon/dicom/__init__.pyi +12 -0
- liblaf/melon/io/melon/dicom/_reader.py +21 -0
- liblaf/melon/io/melon/dicom/_writer.py +19 -0
- liblaf/melon/io/melon/dicom/conversion/__init__.py +3 -0
- liblaf/melon/io/melon/dicom/conversion/__init__.pyi +3 -0
- liblaf/melon/io/melon/dicom/conversion/_as.py +8 -0
- liblaf/melon/io/pyvista/__init__.py +3 -0
- liblaf/melon/io/pyvista/__init__.pyi +17 -0
- liblaf/melon/io/pyvista/image_data/__init__.py +3 -0
- liblaf/melon/io/pyvista/image_data/__init__.pyi +5 -0
- liblaf/melon/io/pyvista/image_data/_reader.py +14 -0
- liblaf/melon/io/pyvista/image_data/conversion/__init__.py +3 -0
- liblaf/melon/io/pyvista/image_data/conversion/__init__.pyi +3 -0
- liblaf/melon/io/pyvista/image_data/conversion/_as.py +9 -0
- liblaf/melon/io/pyvista/point_set/__init__.py +3 -0
- liblaf/melon/io/pyvista/point_set/__init__.pyi +4 -0
- liblaf/melon/io/pyvista/point_set/conversion/__init__.py +3 -0
- liblaf/melon/io/pyvista/point_set/conversion/__init__.pyi +3 -0
- liblaf/melon/io/pyvista/point_set/conversion/_as.py +23 -0
- liblaf/melon/io/pyvista/poly_data/__init__.py +3 -0
- liblaf/melon/io/pyvista/poly_data/__init__.pyi +14 -0
- liblaf/melon/io/pyvista/poly_data/_reader.py +21 -0
- liblaf/melon/io/pyvista/poly_data/_utils.py +8 -0
- liblaf/melon/io/pyvista/poly_data/_writer.py +20 -0
- liblaf/melon/io/pyvista/poly_data/conversion/__init__.py +3 -0
- liblaf/melon/io/pyvista/poly_data/conversion/__init__.pyi +3 -0
- liblaf/melon/io/pyvista/poly_data/conversion/_as.py +9 -0
- liblaf/melon/io/trimesh/__init__.py +3 -0
- liblaf/melon/io/trimesh/__init__.pyi +4 -0
- liblaf/melon/io/trimesh/trimesh/__init__.py +3 -0
- liblaf/melon/io/trimesh/trimesh/__init__.pyi +4 -0
- liblaf/melon/io/trimesh/trimesh/conversion/__init__.py +3 -0
- liblaf/melon/io/trimesh/trimesh/conversion/__init__.pyi +4 -0
- liblaf/melon/io/trimesh/trimesh/conversion/_as.py +13 -0
- liblaf/melon/io/trimesh/trimesh/conversion/_poly_data.py +13 -0
- liblaf/melon/ops/__init__.py +3 -0
- liblaf/melon/ops/__init__.pyi +66 -0
- liblaf/melon/ops/correspondence/__init__.py +3 -0
- liblaf/melon/ops/correspondence/__init__.pyi +25 -0
- liblaf/melon/ops/correspondence/_errors.py +8 -0
- liblaf/melon/ops/correspondence/_nearest_point_on_surface.py +138 -0
- liblaf/melon/ops/correspondence/_nearest_vertex.py +141 -0
- liblaf/melon/ops/pyvista/__init__.py +3 -0
- liblaf/melon/ops/pyvista/__init__.pyi +6 -0
- liblaf/melon/ops/pyvista/_contour.py +36 -0
- liblaf/melon/ops/pyvista/_extract_points.py +15 -0
- liblaf/melon/ops/pyvista/_gaussian_smooth.py +24 -0
- liblaf/melon/ops/pyvista/_transform.py +24 -0
- liblaf/melon/ops/registration/__init__.py +3 -0
- liblaf/melon/ops/registration/__init__.pyi +15 -0
- liblaf/melon/ops/registration/rigid/__init__.py +3 -0
- liblaf/melon/ops/registration/rigid/__init__.pyi +11 -0
- liblaf/melon/ops/registration/rigid/_abc.py +7 -0
- liblaf/melon/ops/registration/rigid/_icp.py +66 -0
- liblaf/melon/ops/registration/rigid/_main.py +30 -0
- liblaf/melon/ops/registration/rigid/_result.py +10 -0
- liblaf/melon/ops/transfer/__init__.py +3 -0
- liblaf/melon/ops/transfer/__init__.pyi +22 -0
- liblaf/melon/ops/transfer/_abc.py +15 -0
- liblaf/melon/ops/transfer/_auto.py +39 -0
- liblaf/melon/ops/transfer/_nearest_point_on_surface.py +58 -0
- liblaf/melon/ops/transfer/_nearest_vertex.py +45 -0
- liblaf/melon/ops/transfer/_transfer.py +34 -0
- liblaf/melon/ops/transfer/_utils.py +11 -0
- liblaf/melon/ops/transformations/__init__.py +3 -0
- liblaf/melon/ops/transformations/__init__.pyi +3 -0
- liblaf/melon/ops/transformations/_concat.py +14 -0
- liblaf/melon/struct/__init__.py +3 -0
- liblaf/melon/struct/__init__.pyi +27 -0
- liblaf/melon/struct/dicom/__init__.py +3 -0
- liblaf/melon/struct/dicom/__init__.pyi +13 -0
- liblaf/melon/struct/dicom/_dicom.py +98 -0
- liblaf/melon/struct/dicom/_meta.py +22 -0
- liblaf/melon/struct/dicom/_utils.py +30 -0
- liblaf/melon/struct/dicom_dataset/__init__.py +3 -0
- liblaf/melon/struct/dicom_dataset/__init__.pyi +17 -0
- liblaf/melon/struct/dicom_dataset/_acquisition.py +68 -0
- liblaf/melon/struct/dicom_dataset/_acquisition_meta.py +4 -0
- liblaf/melon/struct/dicom_dataset/_attachments.py +37 -0
- liblaf/melon/struct/dicom_dataset/_dataset.py +63 -0
- liblaf/melon/struct/dicom_dataset/_dataset_meta.py +5 -0
- liblaf/melon/struct/dicom_dataset/_subject.py +79 -0
- liblaf/melon/struct/dicom_dataset/_subject_meta.py +14 -0
- liblaf/melon/typing/__init__.py +3 -0
- liblaf/melon/typing/__init__.pyi +4 -0
- liblaf/melon/typing/_aliases.py +3 -0
- liblaf/melon/typing/_attrs.py +8 -0
- liblaf_melon-0.1.0.dist-info/METADATA +38 -0
- liblaf_melon-0.1.0.dist-info/RECORD +120 -0
- liblaf_melon-0.1.0.dist-info/WHEEL +4 -0
- liblaf_melon-0.1.0.dist-info/licenses/LICENSE +21 -0
liblaf/melon/__init__.py
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
from . import cli, io, ops, struct, typing
|
|
2
|
+
from .io import (
|
|
3
|
+
as_image_data,
|
|
4
|
+
as_point_set,
|
|
5
|
+
as_poly_data,
|
|
6
|
+
as_trimesh,
|
|
7
|
+
convert,
|
|
8
|
+
load,
|
|
9
|
+
load_dicom,
|
|
10
|
+
load_image_data,
|
|
11
|
+
load_poly_data,
|
|
12
|
+
save,
|
|
13
|
+
)
|
|
14
|
+
from .ops import (
|
|
15
|
+
NearestPointOnSurface,
|
|
16
|
+
NearestPointOnSurfacePrepared,
|
|
17
|
+
NearestPointOnSurfaceResult,
|
|
18
|
+
NearestVertex,
|
|
19
|
+
NearestVertexPrepared,
|
|
20
|
+
NearestVertexResult,
|
|
21
|
+
TransferAlgorithm,
|
|
22
|
+
TransferAlgorithmPrepared,
|
|
23
|
+
TransferAuto,
|
|
24
|
+
TransferAutoPrepared,
|
|
25
|
+
TransferNearestPointOnSurface,
|
|
26
|
+
TransferNearestPointOnSurfacePrepared,
|
|
27
|
+
TransferNearestVertex,
|
|
28
|
+
TransferNearestVertexPrepared,
|
|
29
|
+
concat_transforms,
|
|
30
|
+
contour,
|
|
31
|
+
extract_points,
|
|
32
|
+
gaussian_smooth,
|
|
33
|
+
get_fill_value,
|
|
34
|
+
nearest_point_on_surface,
|
|
35
|
+
nearest_vertex,
|
|
36
|
+
transfer_point_to_point,
|
|
37
|
+
transform,
|
|
38
|
+
)
|
|
39
|
+
from .struct import (
|
|
40
|
+
DICOM,
|
|
41
|
+
Acquisition,
|
|
42
|
+
AcquisitionMeta,
|
|
43
|
+
Attachments,
|
|
44
|
+
DICOMDataset,
|
|
45
|
+
DICOMDatasetMeta,
|
|
46
|
+
DICOMMeta,
|
|
47
|
+
Subject,
|
|
48
|
+
SubjectMeta,
|
|
49
|
+
format_date,
|
|
50
|
+
parse_date,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
__all__ = [
|
|
54
|
+
"DICOM",
|
|
55
|
+
"Acquisition",
|
|
56
|
+
"AcquisitionMeta",
|
|
57
|
+
"Attachments",
|
|
58
|
+
"DICOMDataset",
|
|
59
|
+
"DICOMDatasetMeta",
|
|
60
|
+
"DICOMMeta",
|
|
61
|
+
"NearestPointOnSurface",
|
|
62
|
+
"NearestPointOnSurfacePrepared",
|
|
63
|
+
"NearestPointOnSurfaceResult",
|
|
64
|
+
"NearestVertex",
|
|
65
|
+
"NearestVertexPrepared",
|
|
66
|
+
"NearestVertexResult",
|
|
67
|
+
"Subject",
|
|
68
|
+
"SubjectMeta",
|
|
69
|
+
"TransferAlgorithm",
|
|
70
|
+
"TransferAlgorithmPrepared",
|
|
71
|
+
"TransferAuto",
|
|
72
|
+
"TransferAutoPrepared",
|
|
73
|
+
"TransferNearestPointOnSurface",
|
|
74
|
+
"TransferNearestPointOnSurfacePrepared",
|
|
75
|
+
"TransferNearestVertex",
|
|
76
|
+
"TransferNearestVertexPrepared",
|
|
77
|
+
"as_image_data",
|
|
78
|
+
"as_point_set",
|
|
79
|
+
"as_poly_data",
|
|
80
|
+
"as_trimesh",
|
|
81
|
+
"cli",
|
|
82
|
+
"concat_transforms",
|
|
83
|
+
"contour",
|
|
84
|
+
"convert",
|
|
85
|
+
"extract_points",
|
|
86
|
+
"format_date",
|
|
87
|
+
"gaussian_smooth",
|
|
88
|
+
"get_fill_value",
|
|
89
|
+
"io",
|
|
90
|
+
"load",
|
|
91
|
+
"load_dicom",
|
|
92
|
+
"load_image_data",
|
|
93
|
+
"load_poly_data",
|
|
94
|
+
"nearest_point_on_surface",
|
|
95
|
+
"nearest_vertex",
|
|
96
|
+
"ops",
|
|
97
|
+
"parse_date",
|
|
98
|
+
"save",
|
|
99
|
+
"struct",
|
|
100
|
+
"transfer_point_to_point",
|
|
101
|
+
"transform",
|
|
102
|
+
"typing",
|
|
103
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from . import dispatcher, melon, pyvista, trimesh
|
|
2
|
+
from ._load import load
|
|
3
|
+
from ._save import save
|
|
4
|
+
from .dispatcher import (
|
|
5
|
+
AbstractConverter,
|
|
6
|
+
AbstractReader,
|
|
7
|
+
AbstractWriter,
|
|
8
|
+
ConversionDispatcher,
|
|
9
|
+
ReaderDispatcher,
|
|
10
|
+
UnsupportedConversionError,
|
|
11
|
+
WriterDispatcher,
|
|
12
|
+
conversion_dispatcher,
|
|
13
|
+
convert,
|
|
14
|
+
reader_dispatcher,
|
|
15
|
+
register_converter,
|
|
16
|
+
register_reader,
|
|
17
|
+
register_writer,
|
|
18
|
+
warning_unsupported_association,
|
|
19
|
+
writer_dispatcher,
|
|
20
|
+
)
|
|
21
|
+
from .melon import load_dicom
|
|
22
|
+
from .pyvista import (
|
|
23
|
+
as_image_data,
|
|
24
|
+
as_point_set,
|
|
25
|
+
as_poly_data,
|
|
26
|
+
load_image_data,
|
|
27
|
+
load_poly_data,
|
|
28
|
+
)
|
|
29
|
+
from .trimesh import as_trimesh
|
|
30
|
+
|
|
31
|
+
__all__ = [
|
|
32
|
+
"AbstractConverter",
|
|
33
|
+
"AbstractReader",
|
|
34
|
+
"AbstractWriter",
|
|
35
|
+
"ConversionDispatcher",
|
|
36
|
+
"ReaderDispatcher",
|
|
37
|
+
"UnsupportedConversionError",
|
|
38
|
+
"WriterDispatcher",
|
|
39
|
+
"as_image_data",
|
|
40
|
+
"as_point_set",
|
|
41
|
+
"as_poly_data",
|
|
42
|
+
"as_trimesh",
|
|
43
|
+
"conversion_dispatcher",
|
|
44
|
+
"conversion_dispatcher",
|
|
45
|
+
"convert",
|
|
46
|
+
"dispatcher",
|
|
47
|
+
"load",
|
|
48
|
+
"load_dicom",
|
|
49
|
+
"load_image_data",
|
|
50
|
+
"load_poly_data",
|
|
51
|
+
"melon",
|
|
52
|
+
"pyvista",
|
|
53
|
+
"reader_dispatcher",
|
|
54
|
+
"register_converter",
|
|
55
|
+
"register_reader",
|
|
56
|
+
"register_writer",
|
|
57
|
+
"save",
|
|
58
|
+
"trimesh",
|
|
59
|
+
"warning_unsupported_association",
|
|
60
|
+
"writer_dispatcher",
|
|
61
|
+
]
|
liblaf/melon/io/_copy.py
ADDED
liblaf/melon/io/_load.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from liblaf import melon
|
|
4
|
+
from liblaf.melon.typing import StrPath
|
|
5
|
+
|
|
6
|
+
from . import reader_dispatcher
|
|
7
|
+
|
|
8
|
+
reader_dispatcher.register(melon.io.melon.DICOMReader())
|
|
9
|
+
reader_dispatcher.register(melon.io.pyvista.PolyDataReader())
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def load(path: StrPath) -> Any:
|
|
13
|
+
return reader_dispatcher.load(path)
|
liblaf/melon/io/_save.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from liblaf import melon
|
|
4
|
+
from liblaf.melon.typing import StrPath
|
|
5
|
+
|
|
6
|
+
from . import writer_dispatcher
|
|
7
|
+
|
|
8
|
+
writer_dispatcher.register(melon.io.melon.DICOMWriter())
|
|
9
|
+
writer_dispatcher.register(melon.io.pyvista.PolyDataWriter())
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def save(path: StrPath, obj: Any) -> None:
|
|
13
|
+
writer_dispatcher.save(path, obj)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from . import conversion, reader, writer
|
|
2
|
+
from .conversion import (
|
|
3
|
+
AbstractConverter,
|
|
4
|
+
ConversionDispatcher,
|
|
5
|
+
UnsupportedConversionError,
|
|
6
|
+
conversion_dispatcher,
|
|
7
|
+
convert,
|
|
8
|
+
register_converter,
|
|
9
|
+
warning_unsupported_association,
|
|
10
|
+
)
|
|
11
|
+
from .reader import (
|
|
12
|
+
AbstractReader,
|
|
13
|
+
ReaderDispatcher,
|
|
14
|
+
load,
|
|
15
|
+
reader_dispatcher,
|
|
16
|
+
register_reader,
|
|
17
|
+
)
|
|
18
|
+
from .writer import (
|
|
19
|
+
AbstractWriter,
|
|
20
|
+
WriterDispatcher,
|
|
21
|
+
register_writer,
|
|
22
|
+
save,
|
|
23
|
+
writer_dispatcher,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
__all__ = [
|
|
27
|
+
"AbstractConverter",
|
|
28
|
+
"AbstractReader",
|
|
29
|
+
"AbstractWriter",
|
|
30
|
+
"ConversionDispatcher",
|
|
31
|
+
"ReaderDispatcher",
|
|
32
|
+
"UnsupportedConversionError",
|
|
33
|
+
"WriterDispatcher",
|
|
34
|
+
"conversion",
|
|
35
|
+
"conversion_dispatcher",
|
|
36
|
+
"convert",
|
|
37
|
+
"load",
|
|
38
|
+
"reader",
|
|
39
|
+
"reader_dispatcher",
|
|
40
|
+
"register_converter",
|
|
41
|
+
"register_reader",
|
|
42
|
+
"register_writer",
|
|
43
|
+
"save",
|
|
44
|
+
"warning_unsupported_association",
|
|
45
|
+
"writer",
|
|
46
|
+
"writer_dispatcher",
|
|
47
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from ._converter import AbstractConverter
|
|
2
|
+
from ._dispatcher import (
|
|
3
|
+
ConversionDispatcher,
|
|
4
|
+
conversion_dispatcher,
|
|
5
|
+
convert,
|
|
6
|
+
register_converter,
|
|
7
|
+
)
|
|
8
|
+
from ._utils import UnsupportedConversionError, warning_unsupported_association
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"AbstractConverter",
|
|
12
|
+
"ConversionDispatcher",
|
|
13
|
+
"UnsupportedConversionError",
|
|
14
|
+
"conversion_dispatcher",
|
|
15
|
+
"convert",
|
|
16
|
+
"register_converter",
|
|
17
|
+
"warning_unsupported_association",
|
|
18
|
+
]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class AbstractConverter(abc.ABC):
|
|
6
|
+
priority: int = 0
|
|
7
|
+
type_from: type
|
|
8
|
+
type_to: type
|
|
9
|
+
|
|
10
|
+
@abc.abstractmethod
|
|
11
|
+
def convert(self, obj: Any) -> Any: ...
|
|
12
|
+
|
|
13
|
+
def match_from(self, obj: Any) -> bool:
|
|
14
|
+
return isinstance(obj, self.type_from)
|
|
15
|
+
|
|
16
|
+
def match_to(self, type_to: type) -> bool:
|
|
17
|
+
return issubclass(self.type_to, type_to)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import bisect
|
|
2
|
+
from typing import Any, TypeVar
|
|
3
|
+
|
|
4
|
+
from . import AbstractConverter, UnsupportedConversionError
|
|
5
|
+
|
|
6
|
+
_T = TypeVar("_T")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ConversionDispatcher:
|
|
10
|
+
converters: list[AbstractConverter]
|
|
11
|
+
|
|
12
|
+
def __init__(self) -> None:
|
|
13
|
+
self.converters = []
|
|
14
|
+
|
|
15
|
+
def register(self, converter: AbstractConverter) -> None:
|
|
16
|
+
bisect.insort(self.converters, converter, key=lambda c: c.priority)
|
|
17
|
+
|
|
18
|
+
def convert(self, obj: Any, type_to: type[_T]) -> _T:
|
|
19
|
+
if isinstance(obj, type_to):
|
|
20
|
+
return obj
|
|
21
|
+
for converter in self.converters:
|
|
22
|
+
if converter.match_from(obj) and converter.match_to(type_to):
|
|
23
|
+
return converter.convert(obj)
|
|
24
|
+
raise UnsupportedConversionError(obj, type_to)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
conversion_dispatcher = ConversionDispatcher()
|
|
28
|
+
register_converter = conversion_dispatcher.register
|
|
29
|
+
convert = conversion_dispatcher.convert
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
import pyvista as pv
|
|
4
|
+
from loguru import logger
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class UnsupportedConversionError(TypeError):
|
|
8
|
+
obj: Any
|
|
9
|
+
type_to: type
|
|
10
|
+
|
|
11
|
+
def __init__(self, obj: Any, type_to: type) -> None:
|
|
12
|
+
self.obj = obj
|
|
13
|
+
self.type_to = type_to
|
|
14
|
+
super().__init__(f"Cannot convert `{obj}` to `{type_to}`.")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def warning_unsupported_association(
|
|
18
|
+
to: type, association: pv.FieldAssociation, attr: Any | None = None
|
|
19
|
+
) -> None:
|
|
20
|
+
if attr is None:
|
|
21
|
+
return
|
|
22
|
+
logger.warning("{:r} does not support {:r} data", to, association)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from ._dispatcher import ReaderDispatcher, load, reader_dispatcher, register_reader
|
|
2
|
+
from ._reader import AbstractReader
|
|
3
|
+
from ._utils import UnsupportedReaderError
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"AbstractReader",
|
|
7
|
+
"ReaderDispatcher",
|
|
8
|
+
"UnsupportedReaderError",
|
|
9
|
+
"load",
|
|
10
|
+
"reader_dispatcher",
|
|
11
|
+
"register_reader",
|
|
12
|
+
]
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import bisect
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from liblaf.melon.typing import StrPath
|
|
5
|
+
|
|
6
|
+
from . import AbstractReader, UnsupportedReaderError
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ReaderDispatcher:
|
|
10
|
+
readers: list[AbstractReader]
|
|
11
|
+
|
|
12
|
+
def __init__(self) -> None:
|
|
13
|
+
self.readers = []
|
|
14
|
+
|
|
15
|
+
def register(self, reader: AbstractReader) -> None:
|
|
16
|
+
bisect.insort(self.readers, reader, key=lambda r: r.priority)
|
|
17
|
+
|
|
18
|
+
def load(self, path: StrPath) -> Any:
|
|
19
|
+
for reader in self.readers:
|
|
20
|
+
if reader.match_path(path):
|
|
21
|
+
return reader.load(path)
|
|
22
|
+
raise UnsupportedReaderError(path)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
reader_dispatcher = ReaderDispatcher()
|
|
26
|
+
register_reader = reader_dispatcher.register
|
|
27
|
+
load = reader_dispatcher.load
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from liblaf.melon.typing import StrPath
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AbstractReader(abc.ABC):
|
|
9
|
+
extension: str
|
|
10
|
+
priority: int = 0
|
|
11
|
+
|
|
12
|
+
@abc.abstractmethod
|
|
13
|
+
def load(self, path: StrPath) -> Any: ...
|
|
14
|
+
|
|
15
|
+
def match_path(self, path: StrPath) -> bool:
|
|
16
|
+
path = Path(path)
|
|
17
|
+
return path.suffix == self.extension
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from ._dispatcher import WriterDispatcher, register_writer, save, writer_dispatcher
|
|
2
|
+
from ._utils import UnsupportedWriterError
|
|
3
|
+
from ._writer import AbstractWriter
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"AbstractWriter",
|
|
7
|
+
"UnsupportedWriterError",
|
|
8
|
+
"WriterDispatcher",
|
|
9
|
+
"register_writer",
|
|
10
|
+
"save",
|
|
11
|
+
"writer_dispatcher",
|
|
12
|
+
]
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import bisect
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from liblaf.melon.typing import StrPath
|
|
5
|
+
|
|
6
|
+
from . import AbstractWriter, UnsupportedWriterError
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class WriterDispatcher:
|
|
10
|
+
writers: list[AbstractWriter]
|
|
11
|
+
|
|
12
|
+
def __init__(self) -> None:
|
|
13
|
+
self.writers = []
|
|
14
|
+
|
|
15
|
+
def register(self, writer: AbstractWriter) -> None:
|
|
16
|
+
bisect.insort(self.writers, writer, key=lambda r: r.priority)
|
|
17
|
+
|
|
18
|
+
def save(self, path: StrPath, obj: Any) -> None:
|
|
19
|
+
for writer in self.writers:
|
|
20
|
+
if writer.match_path(path):
|
|
21
|
+
return writer.save(path, obj)
|
|
22
|
+
raise UnsupportedWriterError(path)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
writer_dispatcher = WriterDispatcher()
|
|
26
|
+
register_writer = writer_dispatcher.register
|
|
27
|
+
save = writer_dispatcher.save
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from liblaf.melon.typing import StrPath
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AbstractWriter(abc.ABC):
|
|
9
|
+
extension: str
|
|
10
|
+
priority: int = 0
|
|
11
|
+
|
|
12
|
+
@abc.abstractmethod
|
|
13
|
+
def save(self, path: StrPath, obj: Any) -> None: ...
|
|
14
|
+
|
|
15
|
+
def match_path(self, path: StrPath) -> bool:
|
|
16
|
+
path = Path(path)
|
|
17
|
+
return path.suffix == self.extension
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from liblaf import melon
|
|
4
|
+
from liblaf.melon.typing import StrPath
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def load_dicom(path: StrPath) -> melon.DICOM:
|
|
8
|
+
return melon.DICOM(path)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class DICOMReader(melon.io.AbstractReader):
|
|
12
|
+
def match_path(self, path: StrPath) -> bool:
|
|
13
|
+
path = Path(path)
|
|
14
|
+
if path.is_dir() and (path / "DIRFILE").exists():
|
|
15
|
+
return True
|
|
16
|
+
if path.is_file() and path.name == "DIRFILE": # noqa: SIM103
|
|
17
|
+
return True
|
|
18
|
+
return False
|
|
19
|
+
|
|
20
|
+
def load(self, path: StrPath) -> melon.DICOM:
|
|
21
|
+
return load_dicom(path)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from liblaf import melon
|
|
5
|
+
from liblaf.melon.typing import StrPath
|
|
6
|
+
|
|
7
|
+
from . import as_dicom
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class DICOMWriter(melon.io.AbstractWriter):
|
|
11
|
+
def match_path(self, path: StrPath) -> bool:
|
|
12
|
+
path = Path(path)
|
|
13
|
+
if path.name == "DIRFILE": # noqa: SIM103
|
|
14
|
+
return True
|
|
15
|
+
return False
|
|
16
|
+
|
|
17
|
+
def save(self, path: StrPath, obj: Any) -> None:
|
|
18
|
+
obj: melon.DICOM = as_dicom(obj)
|
|
19
|
+
obj.save(path)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from . import image_data, point_set, poly_data
|
|
2
|
+
from .image_data import as_image_data, load_image_data
|
|
3
|
+
from .point_set import as_point_set
|
|
4
|
+
from .poly_data import PolyDataReader, PolyDataWriter, as_poly_data, load_poly_data
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"PolyDataReader",
|
|
8
|
+
"PolyDataWriter",
|
|
9
|
+
"as_image_data",
|
|
10
|
+
"as_point_set",
|
|
11
|
+
"as_poly_data",
|
|
12
|
+
"image_data",
|
|
13
|
+
"load_image_data",
|
|
14
|
+
"load_poly_data",
|
|
15
|
+
"point_set",
|
|
16
|
+
"poly_data",
|
|
17
|
+
]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import pyvista as pv
|
|
4
|
+
|
|
5
|
+
from liblaf.melon.typing import StrPath
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def load_image_data(path: StrPath) -> pv.ImageData:
|
|
9
|
+
path = Path(path)
|
|
10
|
+
if path.is_file() and path.name == "DIRFILE":
|
|
11
|
+
path = path.parent
|
|
12
|
+
if path.is_dir() and (path / "DIRFILE").exists():
|
|
13
|
+
return pv.read(path, force_ext=".dcm") # pyright: ignore[reportReturnType]
|
|
14
|
+
return pv.read(path) # pyright: ignore[reportReturnType]
|