SlicerQR Development

@lasson, thanks you so much that worked! :slight_smile:

1 Like

@jcfr

Hello JC, I’m looking to remove slice planes rendering in the 3D view because I want to replace it with a surface render. How can I clear that out?

Thanks.

@spycolyf I believe you are looking for the following example in the Slicer Script repository titled Show slice views in 3D window. You had posted previously an image (seen below) which was detailing volume rendering being shown at the same time as Slice views showing in the 3D View.
image.

@lassoan

Could you extract from 1/159 to 43/159 of this topic to a new topic, “Slicer Module Local Installation Footprint” (for want of a much better name)?

Thanks.

Done. The new topic is here:

@jcfr @pieper @lassoan

Hello JC,

Whenever the user zooms and pans, and then pushes the EnableWLButton to window/level, the zoom and pan resets forcing the user to zoom and pan all over again. The code that causes this is…

self._parameterNode.SetParameter("WindowLevelEnabled", "true" if self.ui.EnableWLButton.checked else "false")

How do I use the WL widget without resetting the zoom and pan?

Thanks

This doesn’t happen in regular slicer so it must be something to do with your customizations not handling the end of the pan/zoom interactions.

Yes, that;s true. Slicer does not have this issue. However @jcfr implements many if the UI actions using the self._parameterNode.SetParameter function and each of them reset my views, Here are all of those features that use the self._parameterNode.SetParameter function, each resetting my views…

    self._parameterNode.SetParameter("ReferenceMarkersVisible", "true" if self.ui.ShowReferenceMarkersButton.checked else "false")
    self._parameterNode.SetParameter("SlabEnabled", "true" if slabEnabled else "false")
    self._parameterNode.SetParameter("SlabMode", QReadsLogic.slabModeToString(self.slabModeButtonGroup.checkedId()))
    self._parameterNode.SetParameter("SlabThicknessInMm", str(self.ui.SlabThicknessSliderWidget.value))
    self._parameterNode.SetParameter("InverseGray", "true" if self.ui.InverseGrayButton.checked else "false")
    self._parameterNode.SetParameter("Zoom", self.ui.ZoomComboBox.currentText)
    self._parameterNode.SetParameter("OrientationMarkerType",
      str(slicer.util.getNodesByClass('vtkMRMLAbstractViewNode')[0].GetOrientationMarkerType()))
    self._parameterNode.SetParameter("RulerVisible", "true" if self.ui.RulerVisibleButton.checked else "false")
    self._parameterNode.SetParameter("OrientationMarkerType", str(nextOrientationMarkerType))

OK, might have something to do with this…

def setParameterNode(self, inputParameterNode):
    """
    Set and observe parameter node.
    Observation is needed because when the parameter node is changed then the GUI must be updated immediately.
    """
    if inputParameterNode:
      self.logic.setDefaultParameters(inputParameterNode)

    # Unobserve previously selected parameter node and add an observer to the newly selected.
    # Changes of parameter node are observed so that whenever parameters are changed by a script or any other module
    # those are reflected immediately in the GUI.
    if self._parameterNode is not None:
      self.removeObserver(self._parameterNode, vtk.vtkCommand.ModifiedEvent, self.updateGUIFromParameterNode)
    self._parameterNode = inputParameterNode
    if self._parameterNode is not None:
      self.addObserver(self._parameterNode, vtk.vtkCommand.ModifiedEvent, self.updateGUIFromParameterNode)

    # Initial GUI update
    self.updateGUIFromParameterNode()

@jcfr, is there a way to, for instance, enable he window/level widget without resetting the views?

Thanks

Hi Doug, I looked at the code here:

This two functions or calls may have something to do with the causes of view-reset you are looking for:

centerSlice
sliceLogic.FitSliceToAll()

I started looking for keywords in code as reset and found that. I also looked for ‘sliceLogic’ mentions as it may be related to the cause of your problem.

Hope this helps

OK, thanks @mau_igna_06, I’ll have a look at that. But since only self._parameterNode.SetParameter calls cause this slice view reset behavior, I’m suspecting it’s the setParameterNode function causing it.

Have a look…

Each of the following calls reset the views…

    self._parameterNode.SetParameter("ReferenceMarkersVisible", "true" if self.ui.ShowReferenceMarkersButton.checked else "false")
    self._parameterNode.SetParameter("SlabEnabled", "true" if slabEnabled else "false")
    self._parameterNode.SetParameter("SlabMode", QReadsLogic.slabModeToString(self.slabModeButtonGroup.checkedId()))
    self._parameterNode.SetParameter("SlabThicknessInMm", str(self.ui.SlabThicknessSliderWidget.value))
    self._parameterNode.SetParameter("InverseGray", "true" if self.ui.InverseGrayButton.checked else "false")
    self._parameterNode.SetParameter("Zoom", self.ui.ZoomComboBox.currentText)
    self._parameterNode.SetParameter("OrientationMarkerType",
      str(slicer.util.getNodesByClass('vtkMRMLAbstractViewNode')[0].GetOrientationMarkerType()))
    self._parameterNode.SetParameter("RulerVisible", "true" if self.ui.RulerVisibleButton.checked else "false")
    self._parameterNode.SetParameter("OrientationMarkerType", str(nextOrientationMarkerType))

Do you think the following function is the culprit? It does a removeObserver followed by an add observer

def setParameterNode(self, inputParameterNode):
    """
    Set and observe parameter node.
    Observation is needed because when the parameter node is changed then the GUI must be updated immediately.
    """
    if inputParameterNode:
      self.logic.setDefaultParameters(inputParameterNode)

    # Unobserve previously selected parameter node and add an observer to the newly selected.
    # Changes of parameter node are observed so that whenever parameters are changed by a script or any other module
    # those are reflected immediately in the GUI.
    if self._parameterNode is not None:
      self.removeObserver(self._parameterNode, vtk.vtkCommand.ModifiedEvent, self.updateGUIFromParameterNode)
    self._parameterNode = inputParameterNode
    if self._parameterNode is not None:
      self.addObserver(self._parameterNode, vtk.vtkCommand.ModifiedEvent, self.updateGUIFromParameterNode)

    # Initial GUI update
    self.updateGUIFromParameterNode()

@lassoan, @jcfr , @pieper

Good afternoon everyone,

All of this time I’ve been focused on optimizing everything for CT. Now that that’s all prefect, MR and PET images have issues. For both PET and MR, the initial W/L’s are messed up and I can’t adjust it manually. They both look like this…

This looks like overflow or underflow of some sort. I was expecting the W/L to be initially read from the header.

Any hint as I begin to investigate the Python code?

Thanks

In fact, the window/level is from the DICOM header - from the first slice. However, for whole-body images the first slice is often almost empty, so it could be better to use the center slice instead - see:

The transparency for low values is a feature of the colormap. You should be able to change the colormap and/or adjust the window/level. If you show multiple series (e.g., PET and CT) then left-click-and-drag may adjust the other volume that you expect.

We have improved PET/CT default colormap selection - see these commits. I would recommend to try PET/CT loading in recent Slicer Preview Release and if you like the changes then update your custom application to use a recent master version of Slicer and use the DICOM module for load DICOM data.

You should also have a look at the PET related extensions (just type PET in the extension search box) and in particular the dicom plugin:

https://www.slicer.org/wiki/Documentation/Nightly/Extensions/PET-IndiC

By default, the windows level is automatically adjusted:

Otherwise, here is the relevant function called when brightness/contract are updated or is one of the preset is selected:

Here are the window level presets:

To ensure the community can help you, you may also consider updating the code base KitwareMedical/SlicerQReads to include your recent updates (e.g Volume Cropper, …) or sharing a link to the relevant fork including the changes.

@lassoan - FYI: I’m on Slicer version 4.13. Also, for those particular images the first W/L setting is center=8438.388323078, width=16876.776646156 which is comparable to the middle slices.

So it does appear that it’s reading it from the header.

@pieper - 1) It does the same thing with MR series, Is the PET extension necessary for getting the PET W/L fixed?

JC, yes I wish I could, I’ll have to clear that with management. I’ll try to get up the courage to ask. They do not have the appetite to hear about more issues as this “should have been released a long time ago.” But I hear you loud and clear because I could definitely use the help from the slicer community and this may happen after I get this used and loved by the physician users. Without this help, it’s a real struggle. But, these (w/l) are the kinds of issues that will turn them off and frustrate them completely on first use.

But, to reiterate, I’d love to do what you say, so we are in the same boat. I’ll keep trying to encourage management.

Thanks

Probably the only issue is that you use a color table that maps very bright voxels to be transparent. There several beautiful PET color tables (those that are specified in the DICOM standard and a few others). Is there a particular reason you don’t use those? Which color table do you use?