From ce301de22cc023500b32b0ada4f844d7c69ee950 Mon Sep 17 00:00:00 2001 From: veypi Date: Thu, 20 Apr 2023 13:37:13 +0800 Subject: [PATCH] trame test file --- test.py | 717 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 717 insertions(+) create mode 100644 test.py diff --git a/test.py b/test.py new file mode 100644 index 0000000..a4f2e34 --- /dev/null +++ b/test.py @@ -0,0 +1,717 @@ +r""" +Version for trame 1.x - https://github.com/Kitware/trame/blob/release-v1/examples/VTK/Applications/MultiFilter/app.py +Delta v1..v2 - https://github.com/Kitware/trame/commit/7b3cda7c45b8a60132892f762e16ed28cb709481 +""" + +import os + +from numpy import sort + +from trame.app import get_server +from trame.ui.vuetify import SinglePageWithDrawerLayout +from trame.widgets import vuetify, trame, vtk as vtk_widgets + +from vtkmodules.vtkCommonDataModel import vtkDataObject +from vtkmodules.vtkFiltersCore import vtkContourFilter +from vtkmodules.vtkIOXML import vtkXMLUnstructuredGridReader +from vtkmodules.vtkRenderingAnnotation import vtkCubeAxesActor + +from vtkmodules.vtkRenderingCore import ( + vtkActor, + vtkDataSetMapper, + vtkRenderer, + vtkRenderWindow, + vtkRenderWindowInteractor, +) + +# Required for interactor initialization +from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch # noqa + +# Required for rendering initialization, not necessary for +# local rendering, but doesn't hurt to include it +import vtkmodules.vtkRenderingOpenGL2 # noqa + +CURRENT_DIRECTORY = os.path.abspath(os.path.dirname(__file__)) + +# ----------------------------------------------------------------------------- +# Constants +# ----------------------------------------------------------------------------- + + +class vtkTimerCallback(): + def __init__(self, steps, actor, iren): + self.timer_count = 0 + self.steps = steps + self.actor = actor + self.iren = iren + self.timerId = None + + def execute(self, obj, event): + step = 0 + while step < self.steps: + print(self.timer_count) + self.actor.SetPosition(self.timer_count / 100.0, + self.timer_count / 100.0, 0) + iren = obj + iren.GetRenderWindow().Render() + self.timer_count += 1 + step += 1 + if self.timerId: + iren.DestroyTimer(self.timerId) + + +class Representation: + Points = 0 + Wireframe = 1 + Surface = 2 + SurfaceWithEdges = 3 + + +class LookupTable: + Rainbow = 0 + Inverted_Rainbow = 1 + Greyscale = 2 + Inverted_Greyscale = 3 + + +# ----------------------------------------------------------------------------- +# VTK pipeline +# ----------------------------------------------------------------------------- + +renderer = vtkRenderer() +renderWindow = vtkRenderWindow() +renderWindow.AddRenderer(renderer) + +renderWindowInteractor = vtkRenderWindowInteractor() +renderWindowInteractor.SetRenderWindow(renderWindow) +renderWindowInteractor.GetInteractorStyle().SetCurrentStyleToTrackballCamera() + +# Read Data +reader = vtkXMLUnstructuredGridReader() +# reader.SetFileName(os.path.join(CURRENT_DIRECTORY, "../../../data/disk_out_ref.vtu")) +fp = '../vtk/s0/' +Fs = [ + os.path.join(fp, lists) for lists in os.listdir(fp) + if os.path.isfile(os.path.join(fp, lists)) and lists.endswith('.vtu') +] +Fs = sort(Fs) +FsL = len(Fs) +FsIndex = 0 +print(Fs) +reader.SetFileName(Fs[FsIndex]) +reader.Update() + +# Extract Array/Field information +dataset_arrays = [] +fields = [ + (reader.GetOutput().GetPointData(), + vtkDataObject.FIELD_ASSOCIATION_POINTS), + (reader.GetOutput().GetCellData(), vtkDataObject.FIELD_ASSOCIATION_CELLS), +] +for field in fields: + field_arrays, association = field + for i in range(field_arrays.GetNumberOfArrays()): + array = field_arrays.GetArray(i) + array_range = array.GetRange() + dataset_arrays.append({ + "text": array.GetName(), + "value": i, + "range": list(array_range), + "type": association, + }) +default_array = dataset_arrays[0] +default_min, default_max = default_array.get("range") + +# Mesh +mesh_mapper = vtkDataSetMapper() +mesh_mapper.SetInputConnection(reader.GetOutputPort()) +mesh_actor = vtkActor() +mesh_actor.SetMapper(mesh_mapper) +renderer.AddActor(mesh_actor) + +# Mesh: Setup default representation to surface +mesh_actor.GetProperty().SetRepresentationToSurface() +mesh_actor.GetProperty().SetPointSize(1) +mesh_actor.GetProperty().EdgeVisibilityOff() + +# Mesh: Apply rainbow color map +mesh_lut = mesh_mapper.GetLookupTable() +mesh_lut.SetHueRange(0.666, 0.0) +mesh_lut.SetSaturationRange(1.0, 1.0) +mesh_lut.SetValueRange(1.0, 1.0) +mesh_lut.Build() + +# Mesh: Color by default array +mesh_mapper.SelectColorArray(default_array.get("text")) +mesh_mapper.GetLookupTable().SetRange(default_min, default_max) +if default_array.get("type") == vtkDataObject.FIELD_ASSOCIATION_POINTS: + mesh_mapper.SetScalarModeToUsePointFieldData() +else: + mesh_mapper.SetScalarModeToUseCellFieldData() +mesh_mapper.SetScalarVisibility(True) +mesh_mapper.SetUseLookupTableScalarRange(True) + +# Contour +contour = vtkContourFilter() +contour.SetInputConnection(reader.GetOutputPort()) +contour_mapper = vtkDataSetMapper() +contour_mapper.SetInputConnection(contour.GetOutputPort()) +contour_actor = vtkActor() +contour_actor.SetMapper(contour_mapper) +renderer.AddActor(contour_actor) + +# Contour: ContourBy default array +contour_value = 0.5 * (default_max + default_min) +contour.SetInputArrayToProcess(0, 0, 0, default_array.get("type"), + default_array.get("text")) +contour.SetValue(0, contour_value) + +# Contour: Setup default representation to surface +contour_actor.GetProperty().SetRepresentationToSurface() +contour_actor.GetProperty().SetPointSize(1) +contour_actor.GetProperty().EdgeVisibilityOff() + +# Contour: Apply rainbow color map +contour_lut = contour_mapper.GetLookupTable() +contour_lut.SetHueRange(0.666, 0.0) +contour_lut.SetSaturationRange(1.0, 1.0) +contour_lut.SetValueRange(1.0, 1.0) +contour_lut.Build() + +# Contour: Color by default array +contour_mapper.SelectColorArray(default_array.get("text")) +contour_mapper.GetLookupTable().SetRange(default_min, default_max) +if default_array.get("type") == vtkDataObject.FIELD_ASSOCIATION_POINTS: + contour_mapper.SetScalarModeToUsePointFieldData() +else: + contour_mapper.SetScalarModeToUseCellFieldData() +contour_mapper.SetScalarVisibility(True) +contour_mapper.SetUseLookupTableScalarRange(True) + +# Cube Axes +cube_axes = vtkCubeAxesActor() +renderer.AddActor(cube_axes) + +# Cube Axes: Boundaries, camera, and styling +cube_axes.SetBounds(mesh_actor.GetBounds()) +cube_axes.SetCamera(renderer.GetActiveCamera()) +cube_axes.SetXLabelFormat("%6.1f") +cube_axes.SetYLabelFormat("%6.1f") +cube_axes.SetZLabelFormat("%6.1f") +cube_axes.SetFlyModeToOuterEdges() + +renderer.ResetCamera() + +# ----------------------------------------------------------------------------- +# Trame setup +# ----------------------------------------------------------------------------- + +server = get_server() +state, ctrl = server.state, server.controller + +state.setdefault("active_ui", None) + +# ----------------------------------------------------------------------------- +# Callbacks +# ----------------------------------------------------------------------------- + + +@state.change("cube_axes_visibility") +def update_cube_axes_visibility(cube_axes_visibility, **kwargs): + # cube_axes.SetVisibility(cube_axes_visibility) + global FsIndex + FsIndex = FsIndex + 1 + if FsIndex == FsL: + FsIndex = 0 + print(Fs[FsIndex]) + reader.SetFileName(Fs[FsIndex]) + reader.Update() + ctrl.view_update() + + +# Selection Change +def actives_change(ids): + _id = ids[0] + if _id == "1": # Mesh + state.active_ui = "mesh" + elif _id == "2": # Contour + state.active_ui = "contour" + else: + state.active_ui = "nothing" + + +# Visibility Change +def visibility_change(event): + _id = event["id"] + _visibility = event["visible"] + + if _id == "1": # Mesh + mesh_actor.SetVisibility(_visibility) + elif _id == "2": # Contour + contour_actor.SetVisibility(_visibility) + ctrl.view_update() + + +# Representation Callbacks +def update_representation(actor, mode): + property = actor.GetProperty() + if mode == Representation.Points: + property.SetRepresentationToPoints() + property.SetPointSize(5) + property.EdgeVisibilityOff() + elif mode == Representation.Wireframe: + property.SetRepresentationToWireframe() + property.SetPointSize(1) + property.EdgeVisibilityOff() + elif mode == Representation.Surface: + property.SetRepresentationToSurface() + property.SetPointSize(1) + property.EdgeVisibilityOff() + elif mode == Representation.SurfaceWithEdges: + property.SetRepresentationToSurface() + property.SetPointSize(1) + property.EdgeVisibilityOn() + + +@state.change("mesh_representation") +def update_mesh_representation(mesh_representation, **kwargs): + update_representation(mesh_actor, mesh_representation) + ctrl.view_update() + + +@state.change("contour_representation") +def update_contour_representation(contour_representation, **kwargs): + update_representation(contour_actor, contour_representation) + ctrl.view_update() + + +# Color By Callbacks +def color_by_array(actor, array): + _min, _max = array.get("range") + mapper = actor.GetMapper() + mapper.SelectColorArray(array.get("text")) + mapper.GetLookupTable().SetRange(_min, _max) + if array.get("type") == vtkDataObject.FIELD_ASSOCIATION_POINTS: + mesh_mapper.SetScalarModeToUsePointFieldData() + else: + mesh_mapper.SetScalarModeToUseCellFieldData() + mapper.SetScalarVisibility(True) + mapper.SetUseLookupTableScalarRange(True) + + +@state.change("mesh_color_array_idx") +def update_mesh_color_by_name(mesh_color_array_idx, **kwargs): + array = dataset_arrays[mesh_color_array_idx] + color_by_array(mesh_actor, array) + ctrl.view_update() + + +@state.change("contour_color_array_idx") +def update_contour_color_by_name(contour_color_array_idx, **kwargs): + array = dataset_arrays[contour_color_array_idx] + color_by_array(contour_actor, array) + ctrl.view_update() + + +# Color Map Callbacks +def use_preset(actor, preset): + lut = actor.GetMapper().GetLookupTable() + if preset == LookupTable.Rainbow: + lut.SetHueRange(0.666, 0.0) + lut.SetSaturationRange(1.0, 1.0) + lut.SetValueRange(1.0, 1.0) + elif preset == LookupTable.Inverted_Rainbow: + lut.SetHueRange(0.0, 0.666) + lut.SetSaturationRange(1.0, 1.0) + lut.SetValueRange(1.0, 1.0) + elif preset == LookupTable.Greyscale: + lut.SetHueRange(0.0, 0.0) + lut.SetSaturationRange(0.0, 0.0) + lut.SetValueRange(0.0, 1.0) + elif preset == LookupTable.Inverted_Greyscale: + lut.SetHueRange(0.0, 0.666) + lut.SetSaturationRange(0.0, 0.0) + lut.SetValueRange(1.0, 0.0) + lut.Build() + + +@state.change("mesh_color_preset") +def update_mesh_color_preset(mesh_color_preset, **kwargs): + use_preset(mesh_actor, mesh_color_preset) + ctrl.view_update() + + +@state.change("contour_color_preset") +def update_contour_color_preset(contour_color_preset, **kwargs): + use_preset(contour_actor, contour_color_preset) + ctrl.view_update() + + +# Opacity Callbacks +@state.change("mesh_opacity") +def update_mesh_opacity(mesh_opacity, **kwargs): + mesh_actor.GetProperty().SetOpacity(mesh_opacity) + ctrl.view_update() + + +@state.change("contour_opacity") +def update_contour_opacity(contour_opacity, **kwargs): + contour_actor.GetProperty().SetOpacity(contour_opacity) + ctrl.view_update() + + +# Contour Callbacks +@state.change("contour_by_array_idx") +def update_contour_by(contour_by_array_idx, **kwargs): + array = dataset_arrays[contour_by_array_idx] + contour_min, contour_max = array.get("range") + contour_step = 0.01 * (contour_max - contour_min) + contour_value = 0.5 * (contour_max + contour_min) + contour.SetInputArrayToProcess(0, 0, 0, array.get("type"), + array.get("text")) + contour.SetValue(0, contour_value) + + # Update UI + state.contour_min = contour_min + state.contour_max = contour_max + state.contour_value = contour_value + state.contour_step = contour_step + + # Update View + ctrl.view_update() + + +@state.change("contour_value") +def update_contour_value(contour_value, **kwargs): + contour.SetValue(0, float(contour_value)) + ctrl.view_update() + + +# ----------------------------------------------------------------------------- +# GUI elements +# ----------------------------------------------------------------------------- + + +def standard_buttons(): + vuetify.VCheckbox( + v_model=("cube_axes_visibility", True), + on_icon="mdi-play", + off_icon="mdi-play", + classes="mx-1", + hide_details=True, + dense=True, + ) + vuetify.VCheckbox( + v_model="$vuetify.theme.dark", + on_icon="mdi-lightbulb-off-outline", + off_icon="mdi-lightbulb-outline", + classes="mx-1", + hide_details=True, + dense=True, + ) + vuetify.VCheckbox( + v_model=("viewMode", "local"), + on_icon="mdi-lan-disconnect", + off_icon="mdi-lan-connect", + true_value="local", + false_value="remote", + classes="mx-1", + hide_details=True, + dense=True, + ) + with vuetify.VBtn(icon=True, click="$refs.view.resetCamera()"): + vuetify.VIcon("mdi-crop-free") + + +def pipeline_widget(): + trame.GitTree( + sources=( + "pipeline", + [ + { + "id": "1", + "parent": "0", + "visible": 1, + "name": "Mesh" + }, + { + "id": "2", + "parent": "1", + "visible": 1, + "name": "Contour" + }, + ], + ), + actives_change=(actives_change, "[$event]"), + visibility_change=(visibility_change, "[$event]"), + ) + + +def ui_card(title, ui_name): + with vuetify.VCard(v_show=f"active_ui == '{ui_name}'"): + vuetify.VCardTitle( + title, + classes="grey lighten-1 py-1 grey--text text--darken-3", + style="user-select: none; cursor: pointer", + hide_details=True, + dense=True, + ) + content = vuetify.VCardText(classes="py-2") + return content + + +def mesh_card(): + with ui_card(title="Mesh", ui_name="mesh"): + vuetify.VSelect( + # Representation + v_model=("mesh_representation", Representation.Surface), + items=( + "representations", + [ + { + "text": "Points", + "value": 0 + }, + { + "text": "Wireframe", + "value": 1 + }, + { + "text": "Surface", + "value": 2 + }, + { + "text": "SurfaceWithEdges", + "value": 3 + }, + ], + ), + label="Representation", + hide_details=True, + dense=True, + outlined=True, + classes="pt-1", + ) + with vuetify.VRow(classes="pt-2", dense=True): + with vuetify.VCol(cols="6"): + vuetify.VSelect( + # Color By + label="Color by", + v_model=("mesh_color_array_idx", 0), + items=("array_list", dataset_arrays), + hide_details=True, + dense=True, + outlined=True, + classes="pt-1", + ) + with vuetify.VCol(cols="6"): + vuetify.VSelect( + # Color Map + label="Colormap", + v_model=("mesh_color_preset", LookupTable.Rainbow), + items=( + "colormaps", + [ + { + "text": "Rainbow", + "value": 0 + }, + { + "text": "Inv Rainbow", + "value": 1 + }, + { + "text": "Greyscale", + "value": 2 + }, + { + "text": "Inv Greyscale", + "value": 3 + }, + ], + ), + hide_details=True, + dense=True, + outlined=True, + classes="pt-1", + ) + vuetify.VSlider( + # Opacity + v_model=("mesh_opacity", 1.0), + min=0, + max=1, + step=0.1, + label="Opacity", + classes="mt-1", + hide_details=True, + dense=True, + ) + + +def contour_card(): + with ui_card(title="Contour", ui_name="contour"): + vuetify.VSelect( + # Contour By + label="Contour by", + v_model=("contour_by_array_idx", 0), + items=("array_list", dataset_arrays), + hide_details=True, + dense=True, + outlined=True, + classes="pt-1", + ) + vuetify.VSlider( + # Contour Value + v_model=("contour_value", contour_value), + min=("contour_min", default_min), + max=("contour_max", default_max), + step=("contour_step", 0.01 * (default_max - default_min)), + label="Value", + classes="my-1", + hide_details=True, + dense=True, + ) + vuetify.VSelect( + # Representation + v_model=("contour_representation", Representation.Surface), + items=( + "representations", + [ + { + "text": "Points", + "value": 0 + }, + { + "text": "Wireframe", + "value": 1 + }, + { + "text": "Surface", + "value": 2 + }, + { + "text": "SurfaceWithEdges", + "value": 3 + }, + ], + ), + label="Representation", + hide_details=True, + dense=True, + outlined=True, + classes="pt-1", + ) + with vuetify.VRow(classes="pt-2", dense=True): + with vuetify.VCol(cols="6"): + vuetify.VSelect( + # Color By + label="Color by", + v_model=("contour_color_array_idx", 0), + items=("array_list", dataset_arrays), + hide_details=True, + dense=True, + outlined=True, + classes="pt-1", + ) + with vuetify.VCol(cols="6"): + vuetify.VSelect( + # Color Map + label="Colormap", + v_model=("contour_color_preset", LookupTable.Rainbow), + items=( + "colormaps", + [ + { + "text": "Rainbow", + "value": 0 + }, + { + "text": "Inv Rainbow", + "value": 1 + }, + { + "text": "Greyscale", + "value": 2 + }, + { + "text": "Inv Greyscale", + "value": 3 + }, + ], + ), + hide_details=True, + dense=True, + outlined=True, + classes="pt-1", + ) + vuetify.VSlider( + # Opacity + v_model=("contour_opacity", 1.0), + min=0, + max=1, + step=0.1, + label="Opacity", + classes="mt-1", + hide_details=True, + dense=True, + ) + + +# ----------------------------------------------------------------------------- +# GUI +# ----------------------------------------------------------------------------- + +with SinglePageWithDrawerLayout(server) as layout: + layout.title.set_text("PrideViewer") + + with layout.toolbar: + # toolbar components + vuetify.VSpacer() + vuetify.VDivider(vertical=True, classes="mx-2") + standard_buttons() + + with layout.drawer as drawer: + # drawer components + drawer.width = 325 + pipeline_widget() + vuetify.VDivider(classes="mb-2") + mesh_card() + contour_card() + + with layout.content: + # content components + with vuetify.VContainer( + fluid=True, + classes="pa-0 fill-height", + ): + # view = vtk_widgets.VtkRemoteView(renderWindow, interactive_ratio=1) + # view = vtk_widgets.VtkLocalView(renderWindow) + view = vtk_widgets.VtkRemoteLocalView(renderWindow, + namespace="view", + mode="local", + interactive_ratio=1) + ctrl.view_update = view.update + ctrl.view_reset_camera = view.reset_camera + ctrl.on_server_ready.add(view.update) + + +def start_ani(): + renderWindowInteractor.Initialize() + + # Sign up to receive TimerEvent + cb = vtkTimerCallback(200, mesh_actor, renderWindowInteractor) + renderWindowInteractor.AddObserver('TimerEvent', cb.execute) + cb.timerId = renderWindowInteractor.CreateRepeatingTimer(500) + + # start the interaction and timer + renderWindow.Render() + renderWindowInteractor.Start() + + +# ----------------------------------------------------------------------------- +# Main +# ----------------------------------------------------------------------------- + +if __name__ == "__main__": + server.start() + # start_ani()