Multiple 3D viewers

Dear All,

I have a question regarding an “automatic visualization” workflow.
The basic is that I have a large number of DICOM files from multiple specimen, and I would like to create a kind of thumbnail/preview image of each file using 3D rendering.

If I use the “Triple 3D” option and the three main keys (Home/End/Page Down) in the different windows, this is the result I get:

The question is that:

  • how could I split the window to contain six 3D viewers?
  • and is it possible to predefine the desired views in each 3D viewer?
    (I show an example below what I’ve created in an image editor)

It means that the:

  • 1st viewer shows the image from the right (Shift+Page Down) and also rotates it with 90° clockwise (in order to have a horizontal arrangement);
  • 2nd viewer shows the image from the left (Page Down) and also rotates it with 90° counterclockwise;
  • 3rd viewer shows the image from the front (Home);
  • 4st viewer shows the image from the top (Shift+End) and also rotates it with 90° clockwise;
  • 5st viewer shows the image from the bottom (End) and also rotates it with 90° counterclockwise;
  • 6st viewer shows the image from the back (Shift+Home) and also rotates it with 180°;

By doing so, it would be preferred if the images would have the same magnification (if I link the 3D viewers currently all of the images will show the same aspect, but I want to keep the different sides while zooming in and out).

What is your opinion, could it be done somehow?
(I should add that I’m not an expert with the Python, so I cannot create a script in my own).

Thanks for the help in advance!

Do you just went show the different views of the 3d model?
Maybe you can take it by vtk/blender.

This is all very doable, by defining custom layouts and scripting the cameras. But yes, it requires python so maybe you can find a collaborator to help you.

It is only a volume rendered image without any segmentation and further 3D-modelling, what I would like to automatically export from a larger series, so unfortunately I can’t use the Blender (but indeed it is a good idea).

Thanks! I will then look for a possible cooperator who can help me with this topic by creating that script.

I’ve copy-pasted a script from code snippets in the script repsository that does something like that you need:

# Set inputs

# Load a volume (just for this demo, we load a sample data set)
import SampleData
volumeNode = SampleData.SampleDataLogic().downloadCTChest()

# Set output folder and filename
outputScreenshotsFilenamePattern = slicer.app.temporaryPath+"/screenshots/screenshot_%d.png"
outputGalleryFilename = slicer.app.temporaryPath+"/screenshots/gallery.png"

# Set up volume rendering
volRenLogic = slicer.modules.volumerendering.logic()
displayNode = volRenLogic.CreateDefaultVolumeRenderingNodes(volumeNode)
displayNode.SetVisibility(True)
displayNode.GetVolumePropertyNode().Copy(volRenLogic.GetPresetByName('CT-Chest-Contrast-Enhanced'))

# Set up visualization for screenshots
slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUp3DView)
threeDWidget = slicer.app.layoutManager().threeDWidget(0)
threeDView = threeDWidget.threeDView()
threeDView.resetCamera()
originalZoomFactor = threeDView.zoomFactor
threeDView.zoomFactor = 0.25
threeDView.zoomIn()
threeDView.setZoomFactor(originalZoomFactor)
threeDViewNode = threeDWidget.mrmlViewNode()
threeDViewNode.SetBackgroundColor(0,0,0)
threeDViewNode.SetBackgroundColor2(0,0,0)
threeDViewNode.SetAxisLabelsVisible(False)
threeDViewNode.SetBoxVisible(False)
threeDViewNode.SetOrientationMarkerType(threeDViewNode.OrientationMarkerTypeAxes)

# Create output folders
import os
filedir = os.path.dirname(outputScreenshotsFilenamePattern)
if not os.path.exists(filedir):
    os.makedirs(filedir)

# Capture screenshots
numberOfScreenshots = 6
axisIndex = [0, 2, 4, 1, 3, 5]  # order of views in the gallery image
import ScreenCapture
cap = ScreenCapture.ScreenCaptureLogic()
for screenshotIndex in range(numberOfScreenshots):
    threeDView.rotateToViewAxis(axisIndex[screenshotIndex])
    slicer.util.forceRenderAllViews()
    outputFilename = outputScreenshotsFilenamePattern % screenshotIndex
    cap.captureImageFromView(threeDView, outputFilename)

# Create gallery view of all images
cap.createLightboxImage(3,  # number of columns
    os.path.dirname(outputScreenshotsFilenamePattern),
    os.path.basename(outputScreenshotsFilenamePattern),
    numberOfScreenshots,
    outputGalleryFilename)
2 Likes

Dear Andras, thank you very much for your help!
I will try this script, and if I have anything more to ask, I’ll let you know.
Thanks again!

1 Like

FYI, I needed to add
import os
at the top.

1 Like

Thank you for the remark!