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.
Files changed (120) hide show
  1. liblaf/melon/__init__.py +3 -0
  2. liblaf/melon/__init__.pyi +103 -0
  3. liblaf/melon/cli/__init__.py +3 -0
  4. liblaf/melon/cli/__init__.pyi +0 -0
  5. liblaf/melon/io/__init__.py +3 -0
  6. liblaf/melon/io/__init__.pyi +61 -0
  7. liblaf/melon/io/_copy.py +5 -0
  8. liblaf/melon/io/_load.py +13 -0
  9. liblaf/melon/io/_save.py +13 -0
  10. liblaf/melon/io/dispatcher/__init__.py +3 -0
  11. liblaf/melon/io/dispatcher/__init__.pyi +47 -0
  12. liblaf/melon/io/dispatcher/conversion/__init__.py +3 -0
  13. liblaf/melon/io/dispatcher/conversion/__init__.pyi +18 -0
  14. liblaf/melon/io/dispatcher/conversion/_converter.py +17 -0
  15. liblaf/melon/io/dispatcher/conversion/_dispatcher.py +29 -0
  16. liblaf/melon/io/dispatcher/conversion/_utils.py +22 -0
  17. liblaf/melon/io/dispatcher/reader/__init__.py +3 -0
  18. liblaf/melon/io/dispatcher/reader/__init__.pyi +12 -0
  19. liblaf/melon/io/dispatcher/reader/_dispatcher.py +27 -0
  20. liblaf/melon/io/dispatcher/reader/_reader.py +17 -0
  21. liblaf/melon/io/dispatcher/reader/_utils.py +11 -0
  22. liblaf/melon/io/dispatcher/writer/__init__.py +3 -0
  23. liblaf/melon/io/dispatcher/writer/__init__.pyi +12 -0
  24. liblaf/melon/io/dispatcher/writer/_dispatcher.py +27 -0
  25. liblaf/melon/io/dispatcher/writer/_utils.py +11 -0
  26. liblaf/melon/io/dispatcher/writer/_writer.py +17 -0
  27. liblaf/melon/io/melon/__init__.py +3 -0
  28. liblaf/melon/io/melon/__init__.pyi +4 -0
  29. liblaf/melon/io/melon/dicom/__init__.py +3 -0
  30. liblaf/melon/io/melon/dicom/__init__.pyi +12 -0
  31. liblaf/melon/io/melon/dicom/_reader.py +21 -0
  32. liblaf/melon/io/melon/dicom/_writer.py +19 -0
  33. liblaf/melon/io/melon/dicom/conversion/__init__.py +3 -0
  34. liblaf/melon/io/melon/dicom/conversion/__init__.pyi +3 -0
  35. liblaf/melon/io/melon/dicom/conversion/_as.py +8 -0
  36. liblaf/melon/io/pyvista/__init__.py +3 -0
  37. liblaf/melon/io/pyvista/__init__.pyi +17 -0
  38. liblaf/melon/io/pyvista/image_data/__init__.py +3 -0
  39. liblaf/melon/io/pyvista/image_data/__init__.pyi +5 -0
  40. liblaf/melon/io/pyvista/image_data/_reader.py +14 -0
  41. liblaf/melon/io/pyvista/image_data/conversion/__init__.py +3 -0
  42. liblaf/melon/io/pyvista/image_data/conversion/__init__.pyi +3 -0
  43. liblaf/melon/io/pyvista/image_data/conversion/_as.py +9 -0
  44. liblaf/melon/io/pyvista/point_set/__init__.py +3 -0
  45. liblaf/melon/io/pyvista/point_set/__init__.pyi +4 -0
  46. liblaf/melon/io/pyvista/point_set/conversion/__init__.py +3 -0
  47. liblaf/melon/io/pyvista/point_set/conversion/__init__.pyi +3 -0
  48. liblaf/melon/io/pyvista/point_set/conversion/_as.py +23 -0
  49. liblaf/melon/io/pyvista/poly_data/__init__.py +3 -0
  50. liblaf/melon/io/pyvista/poly_data/__init__.pyi +14 -0
  51. liblaf/melon/io/pyvista/poly_data/_reader.py +21 -0
  52. liblaf/melon/io/pyvista/poly_data/_utils.py +8 -0
  53. liblaf/melon/io/pyvista/poly_data/_writer.py +20 -0
  54. liblaf/melon/io/pyvista/poly_data/conversion/__init__.py +3 -0
  55. liblaf/melon/io/pyvista/poly_data/conversion/__init__.pyi +3 -0
  56. liblaf/melon/io/pyvista/poly_data/conversion/_as.py +9 -0
  57. liblaf/melon/io/trimesh/__init__.py +3 -0
  58. liblaf/melon/io/trimesh/__init__.pyi +4 -0
  59. liblaf/melon/io/trimesh/trimesh/__init__.py +3 -0
  60. liblaf/melon/io/trimesh/trimesh/__init__.pyi +4 -0
  61. liblaf/melon/io/trimesh/trimesh/conversion/__init__.py +3 -0
  62. liblaf/melon/io/trimesh/trimesh/conversion/__init__.pyi +4 -0
  63. liblaf/melon/io/trimesh/trimesh/conversion/_as.py +13 -0
  64. liblaf/melon/io/trimesh/trimesh/conversion/_poly_data.py +13 -0
  65. liblaf/melon/ops/__init__.py +3 -0
  66. liblaf/melon/ops/__init__.pyi +66 -0
  67. liblaf/melon/ops/correspondence/__init__.py +3 -0
  68. liblaf/melon/ops/correspondence/__init__.pyi +25 -0
  69. liblaf/melon/ops/correspondence/_errors.py +8 -0
  70. liblaf/melon/ops/correspondence/_nearest_point_on_surface.py +138 -0
  71. liblaf/melon/ops/correspondence/_nearest_vertex.py +141 -0
  72. liblaf/melon/ops/pyvista/__init__.py +3 -0
  73. liblaf/melon/ops/pyvista/__init__.pyi +6 -0
  74. liblaf/melon/ops/pyvista/_contour.py +36 -0
  75. liblaf/melon/ops/pyvista/_extract_points.py +15 -0
  76. liblaf/melon/ops/pyvista/_gaussian_smooth.py +24 -0
  77. liblaf/melon/ops/pyvista/_transform.py +24 -0
  78. liblaf/melon/ops/registration/__init__.py +3 -0
  79. liblaf/melon/ops/registration/__init__.pyi +15 -0
  80. liblaf/melon/ops/registration/rigid/__init__.py +3 -0
  81. liblaf/melon/ops/registration/rigid/__init__.pyi +11 -0
  82. liblaf/melon/ops/registration/rigid/_abc.py +7 -0
  83. liblaf/melon/ops/registration/rigid/_icp.py +66 -0
  84. liblaf/melon/ops/registration/rigid/_main.py +30 -0
  85. liblaf/melon/ops/registration/rigid/_result.py +10 -0
  86. liblaf/melon/ops/transfer/__init__.py +3 -0
  87. liblaf/melon/ops/transfer/__init__.pyi +22 -0
  88. liblaf/melon/ops/transfer/_abc.py +15 -0
  89. liblaf/melon/ops/transfer/_auto.py +39 -0
  90. liblaf/melon/ops/transfer/_nearest_point_on_surface.py +58 -0
  91. liblaf/melon/ops/transfer/_nearest_vertex.py +45 -0
  92. liblaf/melon/ops/transfer/_transfer.py +34 -0
  93. liblaf/melon/ops/transfer/_utils.py +11 -0
  94. liblaf/melon/ops/transformations/__init__.py +3 -0
  95. liblaf/melon/ops/transformations/__init__.pyi +3 -0
  96. liblaf/melon/ops/transformations/_concat.py +14 -0
  97. liblaf/melon/struct/__init__.py +3 -0
  98. liblaf/melon/struct/__init__.pyi +27 -0
  99. liblaf/melon/struct/dicom/__init__.py +3 -0
  100. liblaf/melon/struct/dicom/__init__.pyi +13 -0
  101. liblaf/melon/struct/dicom/_dicom.py +98 -0
  102. liblaf/melon/struct/dicom/_meta.py +22 -0
  103. liblaf/melon/struct/dicom/_utils.py +30 -0
  104. liblaf/melon/struct/dicom_dataset/__init__.py +3 -0
  105. liblaf/melon/struct/dicom_dataset/__init__.pyi +17 -0
  106. liblaf/melon/struct/dicom_dataset/_acquisition.py +68 -0
  107. liblaf/melon/struct/dicom_dataset/_acquisition_meta.py +4 -0
  108. liblaf/melon/struct/dicom_dataset/_attachments.py +37 -0
  109. liblaf/melon/struct/dicom_dataset/_dataset.py +63 -0
  110. liblaf/melon/struct/dicom_dataset/_dataset_meta.py +5 -0
  111. liblaf/melon/struct/dicom_dataset/_subject.py +79 -0
  112. liblaf/melon/struct/dicom_dataset/_subject_meta.py +14 -0
  113. liblaf/melon/typing/__init__.py +3 -0
  114. liblaf/melon/typing/__init__.pyi +4 -0
  115. liblaf/melon/typing/_aliases.py +3 -0
  116. liblaf/melon/typing/_attrs.py +8 -0
  117. liblaf_melon-0.1.0.dist-info/METADATA +38 -0
  118. liblaf_melon-0.1.0.dist-info/RECORD +120 -0
  119. liblaf_melon-0.1.0.dist-info/WHEEL +4 -0
  120. liblaf_melon-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,3 @@
1
+ import lazy_loader as lazy
2
+
3
+ __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
@@ -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
+ ]
@@ -0,0 +1,3 @@
1
+ import lazy_loader as lazy
2
+
3
+ __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
File without changes
@@ -0,0 +1,3 @@
1
+ import lazy_loader as lazy
2
+
3
+ __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
@@ -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
+ ]
@@ -0,0 +1,5 @@
1
+ from liblaf.melon.typing import StrPath
2
+
3
+
4
+ def copy(src: StrPath, dst: StrPath) -> None:
5
+ raise NotImplementedError
@@ -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)
@@ -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,3 @@
1
+ import lazy_loader as lazy
2
+
3
+ __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
@@ -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,3 @@
1
+ import lazy_loader as lazy
2
+
3
+ __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
@@ -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,3 @@
1
+ import lazy_loader as lazy
2
+
3
+ __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
@@ -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,11 @@
1
+ from pathlib import Path
2
+
3
+ from liblaf.melon.typing import StrPath
4
+
5
+
6
+ class UnsupportedReaderError(ValueError):
7
+ path: Path
8
+
9
+ def __init__(self, path: StrPath) -> None:
10
+ self.path = Path(path)
11
+ super().__init__(f"Cannot load `{self.path}`.")
@@ -0,0 +1,3 @@
1
+ import lazy_loader as lazy
2
+
3
+ __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
@@ -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,11 @@
1
+ from pathlib import Path
2
+
3
+ from liblaf.melon.typing import StrPath
4
+
5
+
6
+ class UnsupportedWriterError(ValueError):
7
+ path: Path
8
+
9
+ def __init__(self, path: StrPath) -> None:
10
+ self.path = Path(path)
11
+ super().__init__(f"Cannot save `{self.path}`.")
@@ -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,3 @@
1
+ import lazy_loader as lazy
2
+
3
+ __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
@@ -0,0 +1,4 @@
1
+ from . import dicom
2
+ from .dicom import DICOMReader, DICOMWriter, as_dicom, load_dicom
3
+
4
+ __all__ = ["DICOMReader", "DICOMWriter", "as_dicom", "dicom", "load_dicom"]
@@ -0,0 +1,3 @@
1
+ import lazy_loader as lazy
2
+
3
+ __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
@@ -0,0 +1,12 @@
1
+ from . import conversion
2
+ from ._reader import DICOMReader, load_dicom
3
+ from ._writer import DICOMWriter
4
+ from .conversion import as_dicom
5
+
6
+ __all__ = [
7
+ "DICOMReader",
8
+ "DICOMWriter",
9
+ "as_dicom",
10
+ "conversion",
11
+ "load_dicom",
12
+ ]
@@ -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,3 @@
1
+ import lazy_loader as lazy
2
+
3
+ __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
@@ -0,0 +1,3 @@
1
+ from ._as import as_dicom
2
+
3
+ __all__ = ["as_dicom"]
@@ -0,0 +1,8 @@
1
+ from typing import Any
2
+
3
+ from liblaf import melon
4
+ from liblaf.melon.io import conversion_dispatcher
5
+
6
+
7
+ def as_dicom(obj: Any) -> melon.DICOM:
8
+ return conversion_dispatcher.convert(obj, melon.DICOM)
@@ -0,0 +1,3 @@
1
+ import lazy_loader as lazy
2
+
3
+ __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
@@ -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,3 @@
1
+ import lazy_loader as lazy
2
+
3
+ __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
@@ -0,0 +1,5 @@
1
+ from . import conversion
2
+ from ._reader import load_image_data
3
+ from .conversion import as_image_data
4
+
5
+ __all__ = ["as_image_data", "conversion", "load_image_data"]
@@ -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]
@@ -0,0 +1,3 @@
1
+ import lazy_loader as lazy
2
+
3
+ __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)