molde 0.1.3__py3-none-any.whl → 0.1.4__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.
- molde/__init__.py +12 -6
- molde/__main__.py +74 -74
- molde/actors/__init__.py +5 -5
- molde/actors/common_symbols_actor.py +164 -164
- molde/actors/ghost_actor.py +12 -12
- molde/actors/lines_actor.py +31 -31
- molde/actors/round_points_actor.py +7 -7
- molde/actors/square_points_actor.py +32 -32
- molde/colors/__init__.py +1 -1
- molde/colors/color.py +150 -120
- molde/colors/color_names.py +124 -124
- molde/interactor_styles/__init__.py +2 -2
- molde/interactor_styles/arcball_camera_style.py +288 -288
- molde/interactor_styles/box_selection_style.py +70 -70
- molde/main_window.ui +864 -864
- molde/pickers/__init__.py +2 -2
- molde/pickers/cell_area_picker.py +61 -61
- molde/pickers/cell_property_area_picker.py +84 -84
- molde/poly_data/__init__.py +13 -13
- molde/poly_data/lines_data.py +23 -23
- molde/poly_data/vertices_data.py +24 -24
- molde/render_widgets/__init__.py +2 -2
- molde/render_widgets/animated_render_widget.py +164 -164
- molde/render_widgets/common_render_widget.py +429 -433
- molde/stylesheets/__init__.py +120 -119
- molde/stylesheets/common.qss +16 -16
- molde/stylesheets/create_color_page.py +61 -61
- molde/stylesheets/mainwindow.ui +611 -611
- molde/stylesheets/qcheckbox.qss +23 -18
- molde/stylesheets/qinputs.qss +81 -78
- molde/stylesheets/qlayouts.qss +23 -22
- molde/stylesheets/qmenubar.qss +12 -12
- molde/stylesheets/qprogressbar.qss +11 -11
- molde/stylesheets/qpushbutton.qss +91 -91
- molde/stylesheets/qradiobutton.qss +30 -30
- molde/stylesheets/qscrollbar.qss +29 -29
- molde/stylesheets/qslider.qss +61 -61
- molde/stylesheets/qtablewidget.qss +27 -27
- molde/stylesheets/qtabwidget.qss +28 -29
- molde/stylesheets/qtoolbar.qss +52 -62
- molde/stylesheets/qtoolbuttons.qss +14 -14
- molde/stylesheets/qtreewidget.qss +25 -25
- molde/ui_files/messages/new_loading_window.ui +73 -73
- molde/utils/__init__.py +8 -8
- molde/utils/format_sequences.py +44 -44
- molde/utils/poly_data_utils.py +66 -66
- molde/utils/tree_info.py +52 -52
- molde/windows/loading_window.py +189 -189
- {molde-0.1.3.dist-info → molde-0.1.4.dist-info}/METADATA +6 -4
- molde-0.1.4.dist-info/RECORD +68 -0
- {molde-0.1.3.dist-info → molde-0.1.4.dist-info}/WHEEL +1 -1
- molde-0.1.3.dist-info/RECORD +0 -68
@@ -1,433 +1,429 @@
|
|
1
|
-
from pathlib import Path
|
2
|
-
from threading import Lock
|
3
|
-
from typing import Literal
|
4
|
-
|
5
|
-
from PIL import Image
|
6
|
-
from
|
7
|
-
from
|
8
|
-
from vtkmodules.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
|
9
|
-
from vtkmodules.util.numpy_support import vtk_to_numpy
|
10
|
-
from vtkmodules.vtkCommonCore import VTK_FONT_FILE, vtkLookupTable
|
11
|
-
from vtkmodules.vtkInteractionWidgets import (
|
12
|
-
vtkLogoRepresentation,
|
13
|
-
vtkOrientationMarkerWidget,
|
14
|
-
)
|
15
|
-
from vtkmodules.vtkIOImage import vtkPNGReader
|
16
|
-
from vtkmodules.vtkRenderingAnnotation import (
|
17
|
-
vtkAxesActor,
|
18
|
-
vtkLegendScaleActor,
|
19
|
-
vtkScalarBarActor,
|
20
|
-
)
|
21
|
-
from vtkmodules.vtkRenderingCore import (
|
22
|
-
vtkLight,
|
23
|
-
vtkActor,
|
24
|
-
vtkRenderer,
|
25
|
-
vtkTextActor,
|
26
|
-
vtkInteractorStyle,
|
27
|
-
vtkTextProperty,
|
28
|
-
vtkWindowToImageFilter,
|
29
|
-
)
|
30
|
-
|
31
|
-
from molde import MOLDE_DIR
|
32
|
-
from molde.colors import Color
|
33
|
-
from molde.interactor_styles import ArcballCameraInteractorStyle
|
34
|
-
|
35
|
-
|
36
|
-
class CommonRenderWidget(QFrame):
|
37
|
-
"""
|
38
|
-
This class is needed to show vtk renderers in pyqt.
|
39
|
-
|
40
|
-
A vtk widget must always have a renderer, even if it is empty.
|
41
|
-
"""
|
42
|
-
|
43
|
-
left_clicked =
|
44
|
-
left_released =
|
45
|
-
right_clicked =
|
46
|
-
right_released =
|
47
|
-
|
48
|
-
def __init__(self, parent=None, *, theme="dark"):
|
49
|
-
super().__init__(parent)
|
50
|
-
|
51
|
-
self.renderer = vtkRenderer()
|
52
|
-
self.interactor_style = ArcballCameraInteractorStyle()
|
53
|
-
self.render_interactor = QVTKRenderWindowInteractor(self)
|
54
|
-
|
55
|
-
self.render_interactor.Initialize()
|
56
|
-
self.render_interactor.GetRenderWindow().AddRenderer(self.renderer)
|
57
|
-
self.render_interactor.SetInteractorStyle(self.interactor_style)
|
58
|
-
|
59
|
-
self.renderer.ResetCamera()
|
60
|
-
|
61
|
-
self.render_interactor.AddObserver(
|
62
|
-
|
63
|
-
|
64
|
-
)
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
)
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
)
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
def
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
def
|
132
|
-
x, y, *_ = self.render_interactor.GetEventPosition()
|
133
|
-
self.
|
134
|
-
|
135
|
-
def
|
136
|
-
|
137
|
-
self.
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
return image
|
160
|
-
|
161
|
-
def
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
axes_actor
|
176
|
-
|
177
|
-
axes_actor.
|
178
|
-
axes_actor.
|
179
|
-
axes_actor.
|
180
|
-
|
181
|
-
axes_actor.
|
182
|
-
axes_actor.
|
183
|
-
|
184
|
-
axes_actor.
|
185
|
-
axes_actor.
|
186
|
-
axes_actor.
|
187
|
-
|
188
|
-
x_property
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
self.axes
|
198
|
-
self.axes.
|
199
|
-
|
200
|
-
|
201
|
-
self.
|
202
|
-
self.
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
title_property
|
212
|
-
title_property
|
213
|
-
title_property.
|
214
|
-
title_property.
|
215
|
-
title_property.
|
216
|
-
title_property.
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
label_property
|
223
|
-
label_property
|
224
|
-
label_property.
|
225
|
-
label_property.
|
226
|
-
label_property.
|
227
|
-
label_property.
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
self.colorbar_actor
|
244
|
-
self.colorbar_actor.
|
245
|
-
self.colorbar_actor.
|
246
|
-
self.colorbar_actor.
|
247
|
-
self.colorbar_actor.
|
248
|
-
self.colorbar_actor.
|
249
|
-
self.
|
250
|
-
|
251
|
-
self.colorbar_actor.
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
colorbar_title
|
256
|
-
colorbar_title.
|
257
|
-
colorbar_title.
|
258
|
-
colorbar_title.
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
colorbar_label
|
265
|
-
colorbar_label.
|
266
|
-
colorbar_label.
|
267
|
-
colorbar_label.
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
info_text_property
|
283
|
-
info_text_property.
|
284
|
-
info_text_property.
|
285
|
-
info_text_property.
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
image_reader.
|
303
|
-
|
304
|
-
|
305
|
-
logo
|
306
|
-
|
307
|
-
|
308
|
-
logo.
|
309
|
-
logo
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
bkg_1
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
if
|
348
|
-
raise ValueError('Missing value "
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
self
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
self.
|
363
|
-
|
364
|
-
if hasattr(self, "
|
365
|
-
self.
|
366
|
-
self.
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
self.
|
375
|
-
|
376
|
-
|
377
|
-
self.renderer.
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
self.renderer.GetActiveCamera().DeepCopy(other_camera)
|
431
|
-
self.renderer.ResetCameraClippingRange()
|
432
|
-
self.renderer.GetActiveCamera().Modified()
|
433
|
-
self.update()
|
1
|
+
from pathlib import Path
|
2
|
+
from threading import Lock
|
3
|
+
from typing import Literal
|
4
|
+
|
5
|
+
from PIL import Image
|
6
|
+
from qtpy.QtCore import Signal
|
7
|
+
from qtpy.QtWidgets import QFrame, QStackedLayout
|
8
|
+
from vtkmodules.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
|
9
|
+
from vtkmodules.util.numpy_support import vtk_to_numpy
|
10
|
+
from vtkmodules.vtkCommonCore import VTK_FONT_FILE, vtkLookupTable
|
11
|
+
from vtkmodules.vtkInteractionWidgets import (
|
12
|
+
vtkLogoRepresentation,
|
13
|
+
vtkOrientationMarkerWidget,
|
14
|
+
)
|
15
|
+
from vtkmodules.vtkIOImage import vtkPNGReader
|
16
|
+
from vtkmodules.vtkRenderingAnnotation import (
|
17
|
+
vtkAxesActor,
|
18
|
+
vtkLegendScaleActor,
|
19
|
+
vtkScalarBarActor,
|
20
|
+
)
|
21
|
+
from vtkmodules.vtkRenderingCore import (
|
22
|
+
vtkLight,
|
23
|
+
vtkActor,
|
24
|
+
vtkRenderer,
|
25
|
+
vtkTextActor,
|
26
|
+
vtkInteractorStyle,
|
27
|
+
vtkTextProperty,
|
28
|
+
vtkWindowToImageFilter,
|
29
|
+
)
|
30
|
+
|
31
|
+
from molde import MOLDE_DIR
|
32
|
+
from molde.colors import Color
|
33
|
+
from molde.interactor_styles import ArcballCameraInteractorStyle
|
34
|
+
|
35
|
+
|
36
|
+
class CommonRenderWidget(QFrame):
|
37
|
+
"""
|
38
|
+
This class is needed to show vtk renderers in pyqt.
|
39
|
+
|
40
|
+
A vtk widget must always have a renderer, even if it is empty.
|
41
|
+
"""
|
42
|
+
|
43
|
+
left_clicked = Signal(int, int)
|
44
|
+
left_released = Signal(int, int)
|
45
|
+
right_clicked = Signal(int, int)
|
46
|
+
right_released = Signal(int, int)
|
47
|
+
|
48
|
+
def __init__(self, parent=None, *, theme="dark"):
|
49
|
+
super().__init__(parent)
|
50
|
+
|
51
|
+
self.renderer = vtkRenderer()
|
52
|
+
self.interactor_style = ArcballCameraInteractorStyle()
|
53
|
+
self.render_interactor = QVTKRenderWindowInteractor(self)
|
54
|
+
|
55
|
+
self.render_interactor.Initialize()
|
56
|
+
self.render_interactor.GetRenderWindow().AddRenderer(self.renderer)
|
57
|
+
self.render_interactor.SetInteractorStyle(self.interactor_style)
|
58
|
+
|
59
|
+
self.renderer.ResetCamera()
|
60
|
+
|
61
|
+
self.render_interactor.AddObserver("LeftButtonPressEvent", self.left_click_press_event)
|
62
|
+
self.render_interactor.AddObserver("LeftButtonReleaseEvent", self.left_click_release_event)
|
63
|
+
self.render_interactor.AddObserver("RightButtonPressEvent", self.right_click_press_event)
|
64
|
+
self.render_interactor.AddObserver("RightButtonReleaseEvent", self.right_click_release_event)
|
65
|
+
|
66
|
+
layout = QStackedLayout()
|
67
|
+
layout.addWidget(self.render_interactor)
|
68
|
+
self.setLayout(layout)
|
69
|
+
|
70
|
+
self._current_theme = theme
|
71
|
+
self._widget_actors = list()
|
72
|
+
self.update_lock = Lock()
|
73
|
+
|
74
|
+
self.create_info_text()
|
75
|
+
self.set_theme(self._current_theme)
|
76
|
+
|
77
|
+
def update_plot(self):
|
78
|
+
raise NotImplementedError("The function update_plot was not implemented")
|
79
|
+
|
80
|
+
def add_actors(self, *actors: vtkActor):
|
81
|
+
for actor in actors:
|
82
|
+
self.renderer.AddActor(actor)
|
83
|
+
if actor not in self._widget_actors:
|
84
|
+
self._widget_actors.append(actor)
|
85
|
+
|
86
|
+
def remove_actors(self, *actors: vtkActor):
|
87
|
+
for actor in actors:
|
88
|
+
self.renderer.RemoveActor(actor)
|
89
|
+
try:
|
90
|
+
self._widget_actors.remove(actor)
|
91
|
+
except ValueError:
|
92
|
+
continue
|
93
|
+
|
94
|
+
def remove_all_actors(self):
|
95
|
+
self.remove_actors(*self.get_widget_actors())
|
96
|
+
|
97
|
+
def remove_all_props(self):
|
98
|
+
self.renderer.RemoveAllViewProps()
|
99
|
+
|
100
|
+
def get_widget_actors(self):
|
101
|
+
return [i for i in self._widget_actors]
|
102
|
+
|
103
|
+
def set_interactor_style(self, interactor_style: vtkInteractorStyle):
|
104
|
+
self.interactor_style = interactor_style
|
105
|
+
self.render_interactor.SetInteractorStyle(interactor_style)
|
106
|
+
|
107
|
+
def get_interactor_style(self) -> vtkInteractorStyle:
|
108
|
+
return self.render_interactor.GetInteractorStyle()
|
109
|
+
|
110
|
+
def update(self):
|
111
|
+
if self.update_lock.locked():
|
112
|
+
return
|
113
|
+
|
114
|
+
ren_win = self.render_interactor.GetRenderWindow()
|
115
|
+
if ren_win is not None:
|
116
|
+
self.renderer.ResetCameraClippingRange()
|
117
|
+
ren_win.Render()
|
118
|
+
|
119
|
+
def left_click_press_event(self, obj, event):
|
120
|
+
x, y, *_ = self.render_interactor.GetEventPosition()
|
121
|
+
self.left_clicked.emit(x, y)
|
122
|
+
|
123
|
+
def left_click_release_event(self, obj, event):
|
124
|
+
x, y, *_ = self.render_interactor.GetEventPosition()
|
125
|
+
self.left_released.emit(x, y)
|
126
|
+
|
127
|
+
def right_click_press_event(self, obj, event):
|
128
|
+
x, y, *_ = self.render_interactor.GetEventPosition()
|
129
|
+
self.right_clicked.emit(x, y)
|
130
|
+
|
131
|
+
def right_click_release_event(self, obj, event):
|
132
|
+
x, y, *_ = self.render_interactor.GetEventPosition()
|
133
|
+
self.right_released.emit(x, y)
|
134
|
+
|
135
|
+
def get_screenshot(self) -> Image.Image:
|
136
|
+
image_filter = vtkWindowToImageFilter()
|
137
|
+
image_filter.SetInput(self.render_interactor.GetRenderWindow())
|
138
|
+
image_filter.Update()
|
139
|
+
|
140
|
+
vtk_image = image_filter.GetOutput()
|
141
|
+
width, height, _ = vtk_image.GetDimensions()
|
142
|
+
vtk_array = vtk_image.GetPointData().GetScalars()
|
143
|
+
components = vtk_array.GetNumberOfComponents()
|
144
|
+
|
145
|
+
array = vtk_to_numpy(vtk_array).reshape(height, width, components)
|
146
|
+
image = Image.fromarray(array).transpose(Image.FLIP_TOP_BOTTOM)
|
147
|
+
return image
|
148
|
+
|
149
|
+
def get_thumbnail(self) -> Image.Image:
|
150
|
+
image = self.get_screenshot()
|
151
|
+
w, h = image.size
|
152
|
+
s = min(w, h)
|
153
|
+
box = (
|
154
|
+
(w - s) // 2,
|
155
|
+
(h - s) // 2,
|
156
|
+
(w + s) // 2,
|
157
|
+
(h + s) // 2,
|
158
|
+
)
|
159
|
+
return image.crop(box).resize((512, 512))
|
160
|
+
|
161
|
+
def save_image(self, path: str | Path):
|
162
|
+
"""
|
163
|
+
Saves the render as an image.
|
164
|
+
Supported formats are JPEG, JPG, PNG, BMP, ICO, TIFF, PPM and others.
|
165
|
+
"""
|
166
|
+
image = self.get_screenshot()
|
167
|
+
with open(path, "w") as file:
|
168
|
+
image.save(file)
|
169
|
+
|
170
|
+
def create_axes(self):
|
171
|
+
axes_actor = vtkAxesActor()
|
172
|
+
|
173
|
+
axes_actor.SetXAxisLabelText(" X")
|
174
|
+
axes_actor.SetYAxisLabelText(" Y")
|
175
|
+
axes_actor.SetZAxisLabelText(" Z")
|
176
|
+
|
177
|
+
axes_actor.GetXAxisShaftProperty().LightingOff()
|
178
|
+
axes_actor.GetYAxisShaftProperty().LightingOff()
|
179
|
+
axes_actor.GetZAxisShaftProperty().LightingOff()
|
180
|
+
axes_actor.GetXAxisTipProperty().LightingOff()
|
181
|
+
axes_actor.GetYAxisTipProperty().LightingOff()
|
182
|
+
axes_actor.GetZAxisTipProperty().LightingOff()
|
183
|
+
|
184
|
+
x_property = axes_actor.GetXAxisCaptionActor2D().GetCaptionTextProperty()
|
185
|
+
y_property = axes_actor.GetYAxisCaptionActor2D().GetCaptionTextProperty()
|
186
|
+
z_property = axes_actor.GetZAxisCaptionActor2D().GetCaptionTextProperty()
|
187
|
+
|
188
|
+
for text_property in [x_property, y_property, z_property]:
|
189
|
+
text_property: vtkTextProperty
|
190
|
+
text_property.ItalicOff()
|
191
|
+
text_property.BoldOn()
|
192
|
+
|
193
|
+
self.axes = vtkOrientationMarkerWidget()
|
194
|
+
self.axes.SetViewport(0, 0, 0.18, 0.18)
|
195
|
+
self.axes.SetOrientationMarker(axes_actor)
|
196
|
+
self.axes.SetInteractor(self.render_interactor)
|
197
|
+
self.axes.EnabledOn()
|
198
|
+
self.axes.InteractiveOff()
|
199
|
+
|
200
|
+
def create_scale_bar(self):
|
201
|
+
self.scale_bar_actor = vtkLegendScaleActor()
|
202
|
+
self.scale_bar_actor.AllAxesOff()
|
203
|
+
self.renderer.AddActor(self.scale_bar_actor)
|
204
|
+
|
205
|
+
font_file = MOLDE_DIR / "fonts/IBMPlexMono-Regular.ttf"
|
206
|
+
|
207
|
+
title_property: vtkTextProperty
|
208
|
+
title_property = self.scale_bar_actor.GetLegendTitleProperty()
|
209
|
+
title_property.SetFontSize(16)
|
210
|
+
title_property.ShadowOff()
|
211
|
+
title_property.ItalicOff()
|
212
|
+
title_property.BoldOn()
|
213
|
+
title_property.SetLineOffset(-55)
|
214
|
+
title_property.SetVerticalJustificationToTop()
|
215
|
+
title_property.SetFontFamily(VTK_FONT_FILE)
|
216
|
+
title_property.SetFontFile(font_file)
|
217
|
+
|
218
|
+
label_property: vtkTextProperty
|
219
|
+
label_property = self.scale_bar_actor.GetLegendLabelProperty()
|
220
|
+
label_property.SetFontSize(16)
|
221
|
+
label_property.SetColor((0.8, 0.8, 0.8))
|
222
|
+
label_property.ShadowOff()
|
223
|
+
label_property.ItalicOff()
|
224
|
+
label_property.BoldOff()
|
225
|
+
label_property.SetLineOffset(-35)
|
226
|
+
label_property.SetFontFamily(VTK_FONT_FILE)
|
227
|
+
label_property.SetFontFile(font_file)
|
228
|
+
|
229
|
+
# set the text color based on current theme
|
230
|
+
self.set_theme(self._current_theme)
|
231
|
+
|
232
|
+
def create_color_bar(self, lookup_table=None):
|
233
|
+
if lookup_table is None:
|
234
|
+
lookup_table = vtkLookupTable()
|
235
|
+
lookup_table.Build()
|
236
|
+
|
237
|
+
font_file = MOLDE_DIR / "fonts/IBMPlexMono-Regular.ttf"
|
238
|
+
|
239
|
+
self.colorbar_actor = vtkScalarBarActor()
|
240
|
+
self.colorbar_actor.SetLabelFormat("%1.0e ")
|
241
|
+
self.colorbar_actor.SetLookupTable(lookup_table)
|
242
|
+
self.colorbar_actor.SetWidth(0.02)
|
243
|
+
self.colorbar_actor.SetPosition(0.94, 0.17)
|
244
|
+
self.colorbar_actor.SetHeight(0.7)
|
245
|
+
self.colorbar_actor.SetMaximumNumberOfColors(400)
|
246
|
+
self.colorbar_actor.SetVerticalTitleSeparation(20)
|
247
|
+
self.colorbar_actor.UnconstrainedFontSizeOn()
|
248
|
+
self.colorbar_actor.SetTextPositionToPrecedeScalarBar()
|
249
|
+
self.renderer.AddActor(self.colorbar_actor)
|
250
|
+
|
251
|
+
colorbar_title: vtkTextProperty = self.colorbar_actor.GetTitleTextProperty()
|
252
|
+
colorbar_title.ShadowOff()
|
253
|
+
colorbar_title.ItalicOff()
|
254
|
+
colorbar_title.BoldOn()
|
255
|
+
colorbar_title.SetFontSize(16)
|
256
|
+
colorbar_title.SetJustificationToLeft()
|
257
|
+
colorbar_title.SetFontFamily(VTK_FONT_FILE)
|
258
|
+
colorbar_title.SetFontFile(font_file)
|
259
|
+
|
260
|
+
colorbar_label: vtkTextProperty = self.colorbar_actor.GetLabelTextProperty()
|
261
|
+
colorbar_label.ShadowOff()
|
262
|
+
colorbar_label.ItalicOff()
|
263
|
+
colorbar_label.BoldOn()
|
264
|
+
colorbar_label.SetFontSize(16)
|
265
|
+
colorbar_label.SetJustificationToLeft()
|
266
|
+
colorbar_label.SetFontFamily(VTK_FONT_FILE)
|
267
|
+
colorbar_label.SetFontFile(font_file)
|
268
|
+
|
269
|
+
# set the text color based on current theme
|
270
|
+
self.set_theme(self._current_theme)
|
271
|
+
|
272
|
+
def create_info_text(self):
|
273
|
+
font_file = MOLDE_DIR / "fonts/IBMPlexMono-Bold.ttf"
|
274
|
+
|
275
|
+
self.text_actor = vtkTextActor()
|
276
|
+
self.renderer.AddActor2D(self.text_actor)
|
277
|
+
|
278
|
+
info_text_property = self.text_actor.GetTextProperty()
|
279
|
+
info_text_property.SetFontSize(14)
|
280
|
+
info_text_property.SetVerticalJustificationToTop()
|
281
|
+
info_text_property.SetColor((0.2, 0.2, 0.2))
|
282
|
+
info_text_property.SetLineSpacing(1.3)
|
283
|
+
info_text_property.SetFontFamilyToTimes()
|
284
|
+
info_text_property.SetFontFamily(VTK_FONT_FILE)
|
285
|
+
info_text_property.SetFontFile(font_file)
|
286
|
+
|
287
|
+
coord = self.text_actor.GetPositionCoordinate()
|
288
|
+
coord.SetCoordinateSystemToNormalizedViewport()
|
289
|
+
coord.SetValue(0.01, 0.98)
|
290
|
+
|
291
|
+
# set the text color based on current theme
|
292
|
+
self.set_theme(self._current_theme)
|
293
|
+
|
294
|
+
def create_logo(self, path: str | Path) -> vtkLogoRepresentation:
|
295
|
+
path = Path(path)
|
296
|
+
|
297
|
+
image_reader = vtkPNGReader()
|
298
|
+
image_reader.SetFileName(path)
|
299
|
+
image_reader.Update()
|
300
|
+
|
301
|
+
logo = vtkLogoRepresentation()
|
302
|
+
logo.SetImage(image_reader.GetOutput())
|
303
|
+
logo.ProportionalResizeOn()
|
304
|
+
logo.GetImageProperty().SetOpacity(0.9)
|
305
|
+
logo.GetImageProperty().SetDisplayLocationToBackground()
|
306
|
+
|
307
|
+
self.renderer.AddViewProp(logo)
|
308
|
+
logo.SetRenderer(self.renderer)
|
309
|
+
return logo
|
310
|
+
|
311
|
+
def create_camera_light(self, offset_x=0, offset_y=0):
|
312
|
+
light = vtkLight()
|
313
|
+
light.SetLightTypeToCameraLight()
|
314
|
+
light.SetPosition(offset_x, offset_y, 1)
|
315
|
+
self.renderer.AddLight(light)
|
316
|
+
|
317
|
+
def set_colorbar_unit(self, text):
|
318
|
+
if not hasattr(self, "colorbar_actor"):
|
319
|
+
return
|
320
|
+
self.colorbar_actor.SetTitle(text)
|
321
|
+
|
322
|
+
def set_info_text(self, text):
|
323
|
+
self.text_actor.SetInput(text)
|
324
|
+
|
325
|
+
def set_theme(self, theme: Literal["dark", "light", "custom"], **kwargs):
|
326
|
+
self._current_theme = theme
|
327
|
+
|
328
|
+
if theme == "dark":
|
329
|
+
bkg_1 = Color("#0b0f17")
|
330
|
+
bkg_2 = Color("#3e424d")
|
331
|
+
font_color = Color("#CCCCCC")
|
332
|
+
|
333
|
+
elif theme == "light":
|
334
|
+
bkg_1 = Color("#8092A6")
|
335
|
+
bkg_2 = Color("#EEF2F3")
|
336
|
+
font_color = Color("#111111")
|
337
|
+
|
338
|
+
elif theme == "custom":
|
339
|
+
bkg_1 = kwargs.get("bkg_1")
|
340
|
+
bkg_2 = kwargs.get("bkg_2")
|
341
|
+
font_color = kwargs.get("font_color")
|
342
|
+
|
343
|
+
if bkg_1 is None:
|
344
|
+
raise ValueError('Missing value "bkg_1"')
|
345
|
+
if bkg_2 is None:
|
346
|
+
raise ValueError('Missing value "bkg_2"')
|
347
|
+
if font_color is None:
|
348
|
+
raise ValueError('Missing value "font_color"')
|
349
|
+
|
350
|
+
else:
|
351
|
+
return
|
352
|
+
|
353
|
+
self.renderer.GradientBackgroundOn()
|
354
|
+
self.renderer.SetBackground(bkg_1.to_rgb_f())
|
355
|
+
self.renderer.SetBackground2(bkg_2.to_rgb_f())
|
356
|
+
|
357
|
+
if hasattr(self, "text_actor"):
|
358
|
+
self.text_actor.GetTextProperty().SetColor(font_color.to_rgb_f())
|
359
|
+
|
360
|
+
if hasattr(self, "colorbar_actor"):
|
361
|
+
self.colorbar_actor.GetTitleTextProperty().SetColor(font_color.to_rgb_f())
|
362
|
+
self.colorbar_actor.GetLabelTextProperty().SetColor(font_color.to_rgb_f())
|
363
|
+
|
364
|
+
if hasattr(self, "scale_bar_actor"):
|
365
|
+
self.scale_bar_actor.GetLegendTitleProperty().SetColor(font_color.to_rgb_f())
|
366
|
+
self.scale_bar_actor.GetLegendLabelProperty().SetColor(font_color.to_rgb_f())
|
367
|
+
|
368
|
+
#
|
369
|
+
def set_custom_view(self, position, view_up):
|
370
|
+
self.renderer.GetActiveCamera().SetPosition(position)
|
371
|
+
self.renderer.GetActiveCamera().SetViewUp(view_up)
|
372
|
+
self.renderer.GetActiveCamera().SetParallelProjection(True)
|
373
|
+
self.renderer.ResetCamera(*self.renderer.ComputeVisiblePropBounds())
|
374
|
+
self.update()
|
375
|
+
|
376
|
+
def set_top_view(self):
|
377
|
+
x, y, z = self.renderer.GetActiveCamera().GetFocalPoint()
|
378
|
+
position = (x, y + 1, z)
|
379
|
+
view_up = (0, 0, -1)
|
380
|
+
self.set_custom_view(position, view_up)
|
381
|
+
|
382
|
+
def set_bottom_view(self):
|
383
|
+
x, y, z = self.renderer.GetActiveCamera().GetFocalPoint()
|
384
|
+
position = (x, y - 1, z)
|
385
|
+
view_up = (0, 0, 1)
|
386
|
+
self.set_custom_view(position, view_up)
|
387
|
+
|
388
|
+
def set_left_view(self):
|
389
|
+
x, y, z = self.renderer.GetActiveCamera().GetFocalPoint()
|
390
|
+
position = (x - 1, y, z)
|
391
|
+
view_up = (0, 1, 0)
|
392
|
+
self.set_custom_view(position, view_up)
|
393
|
+
|
394
|
+
def set_right_view(self):
|
395
|
+
x, y, z = self.renderer.GetActiveCamera().GetFocalPoint()
|
396
|
+
position = (x + 1, y, z)
|
397
|
+
view_up = (0, 1, 0)
|
398
|
+
self.set_custom_view(position, view_up)
|
399
|
+
|
400
|
+
def set_front_view(self):
|
401
|
+
x, y, z = self.renderer.GetActiveCamera().GetFocalPoint()
|
402
|
+
position = (x, y, z + 1)
|
403
|
+
view_up = (0, 1, 0)
|
404
|
+
self.set_custom_view(position, view_up)
|
405
|
+
|
406
|
+
def set_back_view(self):
|
407
|
+
x, y, z = self.renderer.GetActiveCamera().GetFocalPoint()
|
408
|
+
position = (x, y, z - 1)
|
409
|
+
view_up = (0, 1, 0)
|
410
|
+
self.set_custom_view(position, view_up)
|
411
|
+
|
412
|
+
def set_isometric_view(self):
|
413
|
+
x, y, z = self.renderer.GetActiveCamera().GetFocalPoint()
|
414
|
+
position = (x + 1, y + 1, z + 1)
|
415
|
+
view_up = (0, 1, 0)
|
416
|
+
self.set_custom_view(position, view_up)
|
417
|
+
|
418
|
+
def copy_camera_from(self, other):
|
419
|
+
if isinstance(other, CommonRenderWidget):
|
420
|
+
other_camera = other.renderer.GetActiveCamera()
|
421
|
+
elif isinstance(other, vtkRenderer):
|
422
|
+
other_camera = other.GetActiveCamera()
|
423
|
+
else:
|
424
|
+
return
|
425
|
+
|
426
|
+
self.renderer.GetActiveCamera().DeepCopy(other_camera)
|
427
|
+
self.renderer.ResetCameraClippingRange()
|
428
|
+
self.renderer.GetActiveCamera().Modified()
|
429
|
+
self.update()
|