Export and hover with dash_vtk

Hello,

I am using dash_vtk to render geological data and i would like to export it (as a .dxf or .obj for example).
Can someone give some hints about how to do it ?

Moreover, I would like to display infos on hovering of points, is that possible at the moment and how ?

Here is an example of what I render with dash_vtk :

Thanks for your time !

3 Likes

Awesome to see VTK in the wild! I’ve reached out to our VTK experts at plotly to weigh in here.

2 Likes

Hi Jerome,

VTK does not have a dxf reader/writer built in but we do support .obj file. On the server side you should be able to use vtkOBJWriter to generate your file from your mesh. Then I’m not exactly sure how to send it to the client via dash but I’m sure someone might be able to give you some pointers.

The hovering part is now supported (since 0.0.9). You just have to declare what you want to monitor on your view with pickingModes=['hover', 'click', 'select'] (for you just hover should do it) and then monitor hoverInfo/clickInfo/selectInfo based on what you are listening to. From there we have several examples available below using that information:

HTH,

Seb

2 Likes

Hi Sebastian,

Thank you for answering !
I was just working on the vtkOBJWriter, and I wondered , how can I get a vtkPolyData from a dash_vtk.PolyData.
The following code doesn’t work :

filename = 'some_file_name.obj'
    polydata = dash_vtk.PolyData(
        id="vtk-polydata",
        children=[
            dash_vtk.PointData(
                dash_vtk.DataArray(
                    id="vtk-array",
                    registration="setScalars",
                    name="elevation",
                    values = elevation
                )
            )
        ],
        points = points,
        polys = polys,
    )

    writer = vtk.vtkOBJWriter()
    writer.SetFileName(filename)
    writer.SetInputData(polydata)
    writer.Write()

The error :

Traceback (most recent call last):
  File "C:\Users\jfanfan\_git\albion-qa-qc\pages\vtk\callbacks.py", line 146, in updateViewCollar
    writer.SetInputData(polydata)
TypeError: SetInputData argument %Id: %V

What writer.SetInputData(xxx) expect is a vtkPolyData not a dash-vtk/polydata.

Based on what you are feeding the dash_vtk/polydata it looks like you can create a polydata like so:

vtk_polydata = vtk.vtkPolyData()

nb_points = len(points) / 3
vtk_points = vtk.vtkPoints()
vtk_points.SetNumberOfPoints(nb_points)
for i in range(nb_points):
vtk_points.SetPoint(i, points[i*3], points[i*3+1], points[i*3+2])
vtk_polydata.SetPoints(vtk_points)

vtk_polys = vtk.vtkCellArray()
[…]
vtk_polydata.SetPolys(vtk_polys)

But my thinking is that you must be getting those points/polys/elevation from somewhere?
If they are coming from VTK, you might already have your polydata. In which case, you would not need to deconstruct and reconstruct it for your use case. You can even use to_mesh helper with the dash-vtk/mesh object directly…

1 Like

To download a CSV file from disk, you can use something like this: Allowing users to download CSV on click - #14 by gerdekk

Although in this case it might need to be slightly modified to open from a file - the code might look something like this:

@app.server.route('/fileDownload/<name>')
def download_file(name):
    return flask.send_file(mem,
                           mimetype='application/octet-stream',
                           attachment_filename=f"data/{name}",
                           as_attachment=True)

@xhlu - As of Dash 1.20.0, we have an official dcc.Download component that can be used instead: dcc.Download | Dash for Python Documentation | Plotly

2 Likes

Actually, I am constructing those points and polys with a delaunay triangulation : get the points from a database then I use spicy.spatial Delaunay to get the polys.

I tried your solution :

    nb_points = int(len(points) / 3)
    vtk_points = vtk.vtkPoints()
    for i in range(nb_points):
        vtk_points.InsertNextPoint(float(points[i*3]), float(points[i*3+1]), float(points[i*3+2]))
    vtk_polydata = vtk.vtkPolyData()
    vtk_polydata.SetPoints(vtk_points)

but the coordinates of the points were converted to ints for no reason.

So I ended up writing directly in a file and it worked :

    vtk_polys = f.vtk_polys(polys)
    nb_points = int(len(points) / 3)
    nb_polys = int(len(vtk_polys) / 3)
    print(nb_polys)
    with open(filepath, 'w') as file:
        for i in range(nb_points):
            file.write("v %.4f %.4f %.4f\n" % (float(points[i*3]), float(points[i*3+1]), float(points[i*3+2])))
        for i in range(nb_polys):
            file.write("f %d %d %d\n" % (int(vtk_polys[i*3] + 1), int(vtk_polys[i*3+1] + 1), int(vtk_polys[i*3+2] + 1)))
        file.close()

The vtk_polys function is used to remove all the “3” in polys :
[3, x0, y0, z0, 3, x1, y1, z1 ...][x0, y0, z0, x1, y1, z1 ...]

For the hover : it works just fine with the Sebastian’s solution !

Thank you everyone for your time and precious help !

Hi,

I have a 3D FEM mesh with some values associated with the elements (“damage_data”). When hoovering, I’m trying to show these values using "pickingModes=[‘hover’]. Is this possible ?. Code:

vtk_view = html.Div(
    dash_vtk.View(
        id='vtk-view',
        background=[1, 1, 1],
        cameraPosition=[1, 0, 0],
        pickingModes=['hover'],
        children=[
            dash_vtk.GeometryRepresentation(
                [
                    dash_vtk.PolyData(
                        id='weld_damage',
                        points=flat_points,
                        polys=flat_Cells_welds,
                        #children=None
                    ),
                ],
                colorMapPreset='Plasma (matplotlib)',
                colorDataRange=color_range,
                property={'edgeVisibility': False},
            ),
            
        ],
    ),
    style={"width": "100%", "height": "100%"}
)

hover_info_div = html.Div(id='Id_hover_info')

...

@app.callback(
    Output('weld_damage', 'children'),
    Input('damage_dropdown', 'value')
)

def damage_display(dropdown_value):
    damage_data = list(Damage[dropdown_value])
    return [
            dash_vtk.CellData(
                
                dash_vtk.DataArray(
                    id='weld_damage_array',
                    registration='setScalars',
                    name='onCells',
                    #values=list(Damage['Max_damage'])
                    values=damage_data,
                )
            )
            ]
        
        
@app.callback(
    Output('Id_hover_info', 'children'),
    Input('vtk-view', 'hoverInfo')

)

def fea_vtk_hover(hover_info):
    if hover_info is not None:
        hover_stuff = [[html.P(f'{k}: {hover_info[k]}'), html.Br()] for k in hover_info.keys()]
        return sum(hover_stuff, [])
    else:
        return ['']

CapturePreformatted text