micress-micpy 0.3.2b0__py3-none-any.whl → 0.4.0a1__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.
@@ -0,0 +1,130 @@
1
+ from __future__ import annotations
2
+ from typing import Optional
3
+
4
+ import vtk
5
+ from vtkmodules.vtkCommonExecutionModel import vtkStreamingDemandDrivenPipeline
6
+ from vtkmodules.util.vtkAlgorithm import VTKPythonAlgorithmBase
7
+
8
+ from micpy import bin as micpy_bin
9
+ from micpy import vtk as micpy_vtk
10
+
11
+
12
+ CONVERT_CELL_TO_POINT = False # keep it identical to your .vti baseline for now
13
+
14
+
15
+ class MicressBinaryReaderLastOnly(VTKPythonAlgorithmBase):
16
+ def __init__(self):
17
+ super().__init__(nInputPorts=0, nOutputPorts=1, outputType="vtkImageData")
18
+ self._filename: Optional[str] = None
19
+ self._file: Optional[micpy_bin.File] = None
20
+ self._array_name = "values"
21
+ self._cached_meta = None # (extent6, spacing3, origin3)
22
+
23
+ def SetFileName(self, filename: str) -> None:
24
+ filename = str(filename)
25
+ if filename == self._filename:
26
+ return
27
+ self._filename = filename
28
+ self._close()
29
+ self._cached_meta = None
30
+ self.Modified()
31
+
32
+ def _close(self):
33
+ if self._file is not None:
34
+ try:
35
+ self._file.close()
36
+ except Exception:
37
+ pass
38
+ self._file = None
39
+
40
+ def _open(self):
41
+ if self._file is None:
42
+ if not self._filename:
43
+ raise RuntimeError("No filename set.")
44
+ self._file = micpy_bin.File(self._filename).open()
45
+
46
+ def _get_image_and_meta(self):
47
+ """Read last field and return (vtkImageData, meta)."""
48
+ self._open()
49
+ field = self._file._read_field(-1)
50
+ image = micpy_vtk.to_image(field, name=self._array_name)
51
+
52
+ if CONVERT_CELL_TO_POINT:
53
+ c2p = vtk.vtkCellDataToPointData()
54
+ c2p.SetInputData(image)
55
+ c2p.PassCellDataOn()
56
+ c2p.Update()
57
+ image = c2p.GetOutput()
58
+
59
+ extent = image.GetExtent() # 6-tuple
60
+ spacing = image.GetSpacing() # 3-tuple
61
+ origin = image.GetOrigin() # 3-tuple
62
+ meta = (
63
+ tuple(int(x) for x in extent),
64
+ tuple(float(x) for x in spacing),
65
+ tuple(float(x) for x in origin),
66
+ )
67
+ return image, meta
68
+
69
+ def RequestInformation(self, request, inInfo, outInfo):
70
+ if not self._filename:
71
+ return 1
72
+
73
+ # Cache metadata once so ParaView knows bounds/extents BEFORE RequestData renders.
74
+ if self._cached_meta is None:
75
+ _, self._cached_meta = self._get_image_and_meta()
76
+
77
+ extent, spacing, origin = self._cached_meta
78
+ info = outInfo.GetInformationObject(0)
79
+
80
+ # This is the critical piece for vtkImageData visibility in ParaView.
81
+ info.Set(vtkStreamingDemandDrivenPipeline.WHOLE_EXTENT(), extent, 6)
82
+
83
+ # These help ParaView compute bounds correctly.
84
+ info.Set(vtk.vtkDataObject.SPACING(), spacing, 3)
85
+ info.Set(vtk.vtkDataObject.ORIGIN(), origin, 3)
86
+
87
+ return 1
88
+
89
+ def RequestData(self, request, inInfo, outInfo):
90
+ image, meta = self._get_image_and_meta()
91
+ extent, spacing, origin = meta
92
+
93
+ output = vtk.vtkImageData.GetData(outInfo, 0)
94
+
95
+ # Copy structure & arrays explicitly (ParaView-friendly)
96
+ output.SetExtent(extent)
97
+ output.SetSpacing(spacing)
98
+ output.SetOrigin(origin)
99
+ output.AllocateScalars(image.GetScalarType(), 0) # no default scalars
100
+
101
+ output.GetPointData().ShallowCopy(image.GetPointData())
102
+ output.GetCellData().ShallowCopy(image.GetCellData())
103
+ output.Modified()
104
+ return 1
105
+
106
+
107
+ # --- ParaView registration ---
108
+ try:
109
+ from paraview.util.vtkAlgorithm import smproxy, smproperty, smdomain
110
+ except Exception:
111
+ smproxy = smproperty = smdomain = None
112
+
113
+ if smproxy is not None:
114
+
115
+ @smproxy.reader(
116
+ name="MicressBinaryReaderLastOnly",
117
+ label="Micress Binary Reader (last only)",
118
+ extensions="mcr mcr.gz conc1",
119
+ file_description="MICRESS binary files",
120
+ )
121
+ class _R(MicressBinaryReaderLastOnly):
122
+ @smproperty.stringvector(
123
+ name="FileName",
124
+ command="SetFileName",
125
+ number_of_elements=1,
126
+ panel_visibility="default",
127
+ )
128
+ @smdomain.filelist()
129
+ def FileName(self):
130
+ return [self._filename or ""]
@@ -0,0 +1,263 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Dict, List, Optional, Tuple
4
+
5
+ import vtk
6
+ from vtkmodules.vtkCommonExecutionModel import vtkStreamingDemandDrivenPipeline
7
+ from vtkmodules.util.vtkAlgorithm import VTKPythonAlgorithmBase
8
+
9
+ from micpy import bin as micpy_bin
10
+ from micpy import vtk as micpy_vtk
11
+
12
+
13
+ CONVERT_CELL_TO_POINT = False # keep identical to your .vti behavior for now
14
+
15
+
16
+ class MicressBinaryReader(VTKPythonAlgorithmBase):
17
+ """ParaView reader for MICRESS files via micpy with timestepping."""
18
+
19
+ def __init__(self):
20
+ super().__init__(nInputPorts=0, nOutputPorts=1, outputType="vtkImageData")
21
+
22
+ self._filename: Optional[str] = None
23
+ self._file: Optional[micpy_bin.File] = None
24
+
25
+ self._array_name: str = "values"
26
+
27
+ # Cached metadata for ParaView (critical for vtkImageData)
28
+ self._cached_meta: Optional[
29
+ Tuple[
30
+ Tuple[int, int, int, int, int, int],
31
+ Tuple[float, float, float],
32
+ Tuple[float, float, float],
33
+ ]
34
+ ] = None # (extent6, spacing3, origin3)
35
+
36
+ # Time indexing
37
+ self._times: List[float] = []
38
+ self._time_to_index: Dict[float, int] = {}
39
+
40
+ # --- ParaView properties ---
41
+
42
+ def SetFileName(self, filename: str) -> None:
43
+ filename = str(filename)
44
+ if filename == self._filename:
45
+ return
46
+ self._filename = filename
47
+ self._reset()
48
+ self.Modified()
49
+
50
+ def SetArrayName(self, name: str) -> None:
51
+ name = str(name) if name else "values"
52
+ if name == self._array_name:
53
+ return
54
+ self._array_name = name
55
+ self.Modified()
56
+
57
+ # --- internal ---
58
+
59
+ def _reset(self) -> None:
60
+ if self._file is not None:
61
+ try:
62
+ self._file.close()
63
+ except Exception:
64
+ pass
65
+ self._file = None
66
+ self._cached_meta = None
67
+ self._times = []
68
+ self._time_to_index = {}
69
+
70
+ def _open(self) -> None:
71
+ if self._file is None:
72
+ if not self._filename:
73
+ raise RuntimeError("No filename set.")
74
+ self._file = micpy_bin.File(self._filename).open()
75
+
76
+ def _ensure_meta(self) -> None:
77
+ """Cache extent/spacing/origin once (needed by ParaView to render ImageData)."""
78
+ if self._cached_meta is not None:
79
+ return
80
+ self._open()
81
+
82
+ # Use a single field to compute the image geometry.
83
+ # (Assumes geometry is constant across timesteps, which is typical for MICRESS.)
84
+ field0 = self._file._read_field(0)
85
+ image0 = micpy_vtk.to_image(field0, name=self._array_name)
86
+
87
+ if CONVERT_CELL_TO_POINT:
88
+ c2p = vtk.vtkCellDataToPointData()
89
+ c2p.SetInputData(image0)
90
+ c2p.PassCellDataOn()
91
+ c2p.Update()
92
+ image0 = c2p.GetOutput()
93
+
94
+ extent = tuple(int(x) for x in image0.GetExtent())
95
+ spacing = tuple(float(x) for x in image0.GetSpacing())
96
+ origin = tuple(float(x) for x in image0.GetOrigin())
97
+
98
+ self._cached_meta = (extent, spacing, origin)
99
+
100
+ def _ensure_times(self) -> None:
101
+ if self._times:
102
+ return
103
+ self._open()
104
+
105
+ times: List[float] = []
106
+ time_to_index: Dict[float, int] = {}
107
+
108
+ i = 0
109
+ while True:
110
+ try:
111
+ fld = self._file._read_field(i)
112
+ except (IndexError, EOFError):
113
+ break
114
+
115
+ tt = float(fld.time)
116
+ times.append(tt)
117
+ if tt not in time_to_index:
118
+ time_to_index[tt] = i
119
+ i += 1
120
+
121
+ self._times = times
122
+ self._time_to_index = time_to_index
123
+
124
+ # Temporary debug (prints to ParaView output console)
125
+ print(
126
+ "MicressBinaryReader: discovered",
127
+ len(self._times),
128
+ "timesteps:",
129
+ self._times,
130
+ )
131
+
132
+ def _get_index_for_requested_time(
133
+ self, req_t: Optional[float]
134
+ ) -> Tuple[int, float]:
135
+ """Return (index, chosen_time) where chosen_time is exactly one of self._times."""
136
+ self._ensure_times()
137
+
138
+ if not self._times:
139
+ return 0, 0.0
140
+
141
+ if req_t is None:
142
+ chosen_t = self._times[0]
143
+ return 0, float(chosen_t)
144
+
145
+ # Choose nearest actual timestep
146
+ req_t = float(req_t)
147
+ chosen_t = min(self._times, key=lambda x: abs(x - req_t))
148
+ idx = self._time_to_index.get(chosen_t)
149
+ if idx is None:
150
+ # Fallback if mapping policy changed / duplicates: linear search
151
+ idx = self._times.index(chosen_t)
152
+ return int(idx), float(chosen_t)
153
+
154
+ def _read_image_at_index(self, idx: int) -> vtk.vtkImageData:
155
+ """Read field idx and convert to vtkImageData."""
156
+ self._open()
157
+ field = self._file._read_field(idx)
158
+ image = micpy_vtk.to_image(field, name=self._array_name)
159
+
160
+ if CONVERT_CELL_TO_POINT:
161
+ c2p = vtk.vtkCellDataToPointData()
162
+ c2p.SetInputData(image)
163
+ c2p.PassCellDataOn()
164
+ c2p.Update()
165
+ image = c2p.GetOutput()
166
+
167
+ return image
168
+
169
+ # --- VTK pipeline ---
170
+
171
+ def RequestInformation(self, request, inInfo, outInfo):
172
+ if not self._filename:
173
+ return 1
174
+
175
+ self._ensure_meta()
176
+ self._ensure_times()
177
+
178
+ info = outInfo.GetInformationObject(0)
179
+
180
+ # Required for ImageData to render correctly in ParaView
181
+ extent, spacing, origin = self._cached_meta
182
+ info.Set(vtkStreamingDemandDrivenPipeline.WHOLE_EXTENT(), extent, 6)
183
+ info.Set(vtk.vtkDataObject.SPACING(), spacing, 3)
184
+ info.Set(vtk.vtkDataObject.ORIGIN(), origin, 3)
185
+
186
+ # Timesteps
187
+ if self._times:
188
+ ts = [float(x) for x in self._times]
189
+ vtkStreamingDemandDrivenPipeline.TIME_STEPS().Set(info, ts, len(ts))
190
+
191
+ tr = [float(min(ts)), float(max(ts))]
192
+ vtkStreamingDemandDrivenPipeline.TIME_RANGE().Set(info, tr, 2)
193
+
194
+ return 1
195
+
196
+ def RequestData(self, request, inInfo, outInfo):
197
+ if not self._filename:
198
+ raise RuntimeError("No filename set.")
199
+
200
+ self._ensure_meta()
201
+
202
+ info = outInfo.GetInformationObject(0)
203
+ output = vtk.vtkImageData.GetData(outInfo, 0)
204
+
205
+ req_t = None
206
+ if info.Has(vtkStreamingDemandDrivenPipeline.UPDATE_TIME_STEP()):
207
+ req_t = float(info.Get(vtkStreamingDemandDrivenPipeline.UPDATE_TIME_STEP()))
208
+
209
+ idx, chosen_t = self._get_index_for_requested_time(req_t)
210
+ image = self._read_image_at_index(idx)
211
+
212
+ # Copy structure + arrays explicitly (ParaView-friendly)
213
+ extent, spacing, origin = self._cached_meta
214
+ output.SetExtent(extent)
215
+ output.SetSpacing(spacing)
216
+ output.SetOrigin(origin)
217
+ output.AllocateScalars(image.GetScalarType(), 0) # no default scalars
218
+
219
+ output.GetPointData().ShallowCopy(image.GetPointData())
220
+ output.GetCellData().ShallowCopy(image.GetCellData())
221
+ output.Modified()
222
+
223
+ # Crucial: report the exact time step we produced (avoids "0.00 (?)")
224
+ output.GetInformation().Set(vtk.vtkDataObject.DATA_TIME_STEP(), float(chosen_t))
225
+
226
+ return 1
227
+
228
+
229
+ # ---- ParaView registration ----
230
+ try:
231
+ from paraview.util.vtkAlgorithm import smproxy, smproperty, smdomain
232
+ except Exception:
233
+ smproxy = smproperty = smdomain = None
234
+
235
+ if smproxy is not None:
236
+
237
+ @smproxy.reader(
238
+ name="MicressBinaryReader",
239
+ label="Micress Binary Reader (micpy)",
240
+ extensions="mcr mcr.gz conc1",
241
+ file_description="MICRESS binary files",
242
+ )
243
+ class _MicressBinaryReader(MicressBinaryReader):
244
+
245
+ @smproperty.stringvector(
246
+ name="FileName",
247
+ command="SetFileName",
248
+ number_of_elements=1,
249
+ panel_visibility="default",
250
+ )
251
+ @smdomain.filelist()
252
+ def FileName(self):
253
+ return [self._filename or ""]
254
+
255
+ # Optional; remove if you want it even more minimal
256
+ @smproperty.stringvector(
257
+ name="ArrayName",
258
+ command="SetArrayName",
259
+ number_of_elements=1,
260
+ default_values=["values"],
261
+ )
262
+ def ArrayName(self):
263
+ return [self._array_name]
micpy/__init__.py CHANGED
@@ -1,6 +1,3 @@
1
1
  from .version import __version__
2
- from .matplotlib import configure as configure_matplotlib
3
2
 
4
3
  __all__ = ["__version__"]
5
-
6
- configure_matplotlib()