some questions about volume rendering

I am using wslink and remote rendering to display the results of 3D reconstruction of medical images and cut through boxwidget on the web page, but the web page only displays images. After that, I displayed an official case with boxwedgt on the web page, showing the peripheral border, but unable to operate, and python.exe exited abnormally. I want to know whether it is feasible to display images on the front-end web page and cut them through remote rendering, or is my project missing some key configurations?
Web page display

The effect I want

Are you using trame, or some other way to achieve remote rendering? Do you get an error, or is it a silent exit?

And how did you setup your widget on the server side?

I don’t seem to have this problem with trame implementation, but I do have this problem when I configure the vtk server separately and make use of remoteview,When I added the border and cutting function to the 3D image, there were two cases, one is the border does not show, the other is silent exit

it is the python code

import os  

# import vtk modules.
import vtk as vk
from vtk.web import protocols
from vtk.web import wslink as vtk_wslink
from wslink import server
import argparse


class _WebCone(vtk_wslink.ServerProtocol):
    # Application configuration
    view = None
    authKey = "wslink-secret"

    def initialize(self):
        # Bring used componets
        self.registerVtkWebProtocol(protocols.vtkWebMouseHandler())
        self.registerVtkWebProtocol(protocols.vtkWebViewPort())
        self.registerVtkWebProtocol(protocols.vtkWebPublishImageDelivery(decode=False))
        self.registerVtkWebProtocol(protocols.vtkWebViewPortGeometryDelivery())

        # Update authentication key to use
        self.updateSecret(_WebCone.authKey)

        # tell the C++ web app to use no encoding.
        # ParaViewWebPublishImageDelivery must be set to decode=False to match.
        self.getApplication().SetImageEncoding(0)

        # Create default pipeline (Only once for all the session)
        if not _WebCone.view:
            class IPWCallback:  # 回调函数
                def __init__(self, plane, mapper):
                    self.plane = plane
                    self.mapper = mapper

                def __call__(self, caller, ev):
                    rep = caller.GetRepresentation()
                    rep.GetPlanes(self.plane)
                    self.mapper.SetClippingPlanes(self.plane)

            l_reader = vk.vtkDICOMImageReader()

            l_reader.SetDirectoryName(
                "C:/Users/users_evptg5m/Desktop/datadicoms/manifest-1661804494842/CMB-PCA/CMB-PCA-MSB-02917/09-24-1958-NA-CT CAP-33859/4.000000-BONE-43921")
            l_renderer = vk.vtkRenderer()
            l_renderer.SetBackground(0.3, 0.3, 0.3)

            l_render_windows = vk.vtkRenderWindow()
            l_render_windows.AddRenderer(l_renderer)
            l_render_windows.SetSize(900, 900)

            l_trackball = vk.vtkInteractorStyleTrackballCamera()

            l_iren = vk.vtkRenderWindowInteractor()
            l_iren.SetInteractorStyle(l_trackball)
            l_iren.SetRenderWindow(l_render_windows)
            l_iren.GetInteractorStyle().SetDefaultRenderer(l_renderer)
            l_iren.SetDesiredUpdateRate(15)

            l_render_windows.Render()

            l_gpu_mapper = vk.vtkGPUVolumeRayCastMapper()
            l_gpu_mapper.SetInputConnection(l_reader.GetOutputPort())

            wl = 260.00
            ww = 270.00

            l_color = vk.vtkColorTransferFunction()
            l_color.SetColorSpaceToRGB()
            l_color.AddRGBPoint(wl - ww / 2, 0, 0, 0)
            l_color.AddRGBPoint(wl - ww / 2 + 94 * (ww / 255.0), 1., 21. / 255.0, 27. / 255.0)
            l_color.AddRGBPoint(wl - ww / 2 + 147 * (ww / 255.0), 1., 176. / 255.0, 9. / 255.0)
            l_color.AddRGBPoint(wl - ww / 2 + 201 * (ww / 255.0), 1., 241. / 255.0, 39. / 255.0)
            l_color.AddRGBPoint(wl - ww / 2 + 255 * (ww / 255.0), 1, 1, 1.)
            l_color.Build()

            l_opacity = vk.vtkPiecewiseFunction()
            l_opacity.AddPoint(wl - ww / 2, 0)
            l_opacity.AddPoint(wl + ww / 2, 1)

            l_volume_property = vk.vtkVolumeProperty()
            l_volume_property.SetColor(l_color)
            l_volume_property.SetScalarOpacity(l_opacity)
            l_volume_property.SetInterpolationTypeToLinear()
            l_volume_property.ShadeOn()
            l_volume_property.SetAmbient(0.15)
            l_volume_property.SetDiffuse(0.8)
            l_volume_property.SetSpecular(0.25)
            l_volume_property.SetSpecularPower(40)

            l_volume = vk.vtkVolume()
            l_volume.SetProperty(l_volume_property)
            l_volume.SetMapper(l_gpu_mapper)
            l_renderer.AddVolume(l_volume)
            l_renderer.ResetCamera()

            l_box_rep = vk.vtkBoxRepresentation()
            l_box_rep.SetInsideOut(True)

            l_voi_widget = vk.vtkBoxWidget2()
            l_voi_widget.SetRepresentation(l_box_rep)
            l_voi_widget.SetInteractor(l_iren)
            l_voi_widget.GetRepresentation().SetPlaceFactor(1.)
            l_voi_widget.GetRepresentation().PlaceWidget(l_reader.GetOutput().GetBounds())
            l_voi_widget.SetEnabled(True)

            l_planes = vk.vtkPlanes()

            my_callback = IPWCallback(l_planes, l_gpu_mapper)

            l_voi_widget.AddObserver('InteractionEvent', my_callback)


            # VTK Web application specific
            _WebCone.view = l_render_windows
            self.getApplication().GetObjectIdMap().SetActiveObject("VIEW", l_render_windows)


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description="VTK/Web Cone web-application")

    # Add default arguments
    server.add_arguments(parser)

    # Extract arguments
    args = parser.parse_args()

    # Configure our current application
    _WebCone.authKey = args.authKey

    # Start server
    server.start_webserver(options=args, protocol=_WebCone)

it is the js code

import vtkWSLinkClient from '@kitware/vtk.js/IO/Core/WSLinkClient';
import SmartConnect from 'wslink/src/SmartConnect';
import vtkRemoteView from '@kitware/vtk.js/Rendering/Misc/RemoteView';

vtkWSLinkClient.setSmartConnectClass(SmartConnect);

document.body.style.padding = '0';
document.body.style.margin = '0';

const divRenderer = document.createElement('div');
document.body.appendChild(divRenderer);

divRenderer.style.position = 'relative';
divRenderer.style.width = '100vw';
divRenderer.style.height = '100vh';
divRenderer.style.overflow = 'hidden';

const clientToConnect = vtkWSLinkClient.newInstance();

// Error
clientToConnect.onConnectionError((httpReq) => {
 const message =
   (httpReq && httpReq.response && httpReq.response.error) ||
   `Connection error`;
 console.error(message);
 console.log(httpReq);
});

// Close
clientToConnect.onConnectionClose((httpReq) => {
 const message =
   (httpReq && httpReq.response && httpReq.response.error) ||
   `Connection close`;
 console.error(message);
 console.log(httpReq);
});

// hint: if you use the launcher.py and ws-proxy just leave out sessionURL
// (it will be provided by the launcher)
const config = {
 application: 'cone',
 sessionURL: 'ws://localhost:1234/ws',
};

// Connect
clientToConnect
 .connect(config)
 .then((validClient) => {
   const viewStream = clientToConnect.getImageStream().createViewStream('-1');

   const view = vtkRemoteView.newInstance({
     rpcWheelEvent: 'viewport.mouse.zoom.wheel',
     viewStream,
   });
   const session = validClient.getConnection().getSession();
   view.setSession(session);
   view.setContainer(divRenderer);
   view.setInteractiveRatio(0.1); // the scaled image compared to the clients view resolution
   view.setInteractiveQuality(50); // jpeg quality

   window.addEventListener('resize', view.resize);
 })
 .catch((error) => {
   console.error(error);
 });

Maybe js lacks dependencies or the callback function is wrong?

Hello,

You can diagnose front-end issues with the web development features present in any of the major web browsers.

best,

Paulo

What about the working version in trame?

At first glance I don’t see anything wrong…

thank you for your answer, I will try it.

1 Like

Thank you, The above display does not use trame. And it’s normal for me to use trame. Now I’m ready to work with trame.

1 Like