Commit c84c5018 authored by demian's avatar demian

ENH: Added W/L controls for fiber bundles (mantis ID: 0002789)

git-svn-id: http://svn.slicer.org/Slicer4/trunk@21573 3bd1e089-480b-0410-8dfb-8563597acbee
parent c1ecc2b0
......@@ -202,7 +202,9 @@ class test_tractography_displayTest(unittest.TestCase):
"""Run as few or as many tests as needed here.
"""
self.setUp()
#self.test_TestTractographyDisplaySelectSolidColor()
self.test_TestWindowLevel(display_node='Line')
self.test_TestWindowLevel(display_node='Tube')
self.test_TestWindowLevel(display_node='Glyph')
self.test_TestTractographyDisplayColorBy(display_node='Line')
self.test_TestTractographyDisplayColorBy(display_node='Tube')
self.test_TestTractographyDisplayColorBy(display_node='Glyph')
......@@ -241,7 +243,11 @@ class test_tractography_displayTest(unittest.TestCase):
if not visibility.checked:
visibility.click()
solidColor = slicer.util.findChildren(tubeTab, text=widget_text)[0]
solidColor = slicer.util.findChildren(tubeTab, text=widget_text)
if len(solidColor) == 0:
raise ValueError("Widget %s not found" % widget_text)
else:
solidColor = solidColor[0]
solidColor.click()
if displayNode and displayNode.GetColorMode() != color_code:
......@@ -252,9 +258,8 @@ class test_tractography_displayTest(unittest.TestCase):
visibility.click()
def test_TestTractographyDisplaySelectSolidColor(self):
self.delayDisplay("Starting the test")
def test_TestWindowLevel(self, display_node='Tube'):
self.delayDisplay("Starting the test Window Level")
self.delayDisplay('Showing Advanced Display\n')
advancedDisplay = slicer.util.findChildren(text='Advanced Display')[0]
......@@ -262,39 +267,40 @@ class test_tractography_displayTest(unittest.TestCase):
self.delayDisplay('Selecting tract1\n')
tractNode = slicer.util.getNode('tract1')
displayNode = getattr(tractNode, 'Get%sDisplayNode' % display_node)()
tree = slicer.util.findChildren(name='TractographyDisplayTreeView')[0]
model = tree.model()
modelIndex = model.indexFromMRMLNode(tractNode)
tree.setCurrentIndex(modelIndex)
tubeTab = slicer.util.findChildren(advancedDisplay, name='TubeTab')[0]
tubeTab = slicer.util.findChildren(advancedDisplay, name='%sTab' % display_node)[0]
slicer.util.findChildren(tubeTab, text='Of Tensor Property')[0].click()
visibility = slicer.util.findChildren(tubeTab, text='Visibility')[0]
visibility = slicer.util.findChildren(tubeTab, text='Visibility')[0]
if not visibility.checked:
visibility.click()
solidColor = slicer.util.findChildren(tubeTab, text='Solid Color')[0]
solidColor.click()
displayNode = tractNode.GetTubeDisplayNode()
if displayNode and displayNode.GetColorMode() != displayNode.colorModeSolid:
self.delayDisplay('Setting Color Mode To Solid Did not Work')
assert(False)
else:
self.delayDisplay("Setting Color Mode To Solid Color Worked")
autoWL = slicer.util.findChildren(tubeTab, text='Auto W/L')[0]
#self.delayDisplay('Deleting tract node and toggling visibility')
#slicer.mrmlScene.RemoveNode(tractNode)
assert(not autoWL.checked or displayNode.GetAutoScalarRange())
assert(autoWL.checked or not displayNode.GetAutoScalarRange())
self.delayDisplay('Default Window Level Agrees with Display Node\n')
#visibility = slicer.util.findChildren(name='VisibilityCheckBox')[0]
autoWL.click()
assert(not autoWL.checked or displayNode.GetAutoScalarRange())
assert(autoWL.checked or not displayNode.GetAutoScalarRange())
self.delayDisplay('Changes in Window Level Agrees with Display Node\n')
#visibility.checked = False
if autoWL.checked:
autoWL.click()
#self.delayDisplay('Toggled with checked property - okay?')
slider = slicer.util.findChildren(tubeTab, name='FiberBundleColorRangeWidget')[0]
slider.setMinimumValue(.1)
slider.setMaximumValue(.8)
scalar_range = displayNode.GetScalarRange()
assert((scalar_range[0] == .1) and (scalar_range[1] == .8))
self.delayDisplay('Changes in Window Level Values Agree with Display Node\n')
#self.delayDisplay('Now try with click button...')
#visibility.clicked()
#self.delayDisplay('Did we crash?')
#self.delayDisplay('No... then test passed!')
autoWL.click()
visibility.click()
......@@ -226,7 +226,6 @@ void vtkMRMLFiberBundleTubeDisplayNode::UpdatePolyDataPipeline()
(DiffusionTensorDisplayPropertiesNode != NULL))
{
this->ScalarVisibilityOn( );
this->AutoScalarRangeOn( );
this->TensorToColor->SetExtractScalar(1);
switch ( DiffusionTensorDisplayPropertiesNode->GetColorGlyphBy( ))
......
......@@ -144,7 +144,7 @@
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
<number>1</number>
</property>
<widget class="QWidget" name="LineTab">
<attribute name="title">
......@@ -346,7 +346,7 @@
</hint>
<hint type="destinationlabel">
<x>111</x>
<y>477</y>
<y>443</y>
</hint>
</hints>
</connection>
......@@ -362,7 +362,7 @@
</hint>
<hint type="destinationlabel">
<x>111</x>
<y>477</y>
<y>443</y>
</hint>
</hints>
</connection>
......@@ -377,8 +377,8 @@
<y>43</y>
</hint>
<hint type="destinationlabel">
<x>159</x>
<y>477</y>
<x>183</x>
<y>443</y>
</hint>
</hints>
</connection>
......@@ -394,7 +394,7 @@
</hint>
<hint type="destinationlabel">
<x>111</x>
<y>484</y>
<y>450</y>
</hint>
</hints>
</connection>
......@@ -425,8 +425,8 @@
<y>349</y>
</hint>
<hint type="destinationlabel">
<x>258</x>
<y>396</y>
<x>270</x>
<y>351</y>
</hint>
</hints>
</connection>
......@@ -457,8 +457,8 @@
<y>174</y>
</hint>
<hint type="destinationlabel">
<x>342</x>
<y>401</y>
<x>354</x>
<y>351</y>
</hint>
</hints>
</connection>
......
......@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>432</width>
<height>470</height>
<width>441</width>
<height>779</height>
</rect>
</property>
<property name="sizePolicy">
......@@ -89,7 +89,7 @@ QCheckBox::indicator:unchecked {
</sizepolicy>
</property>
<property name="title">
<string>Scalar Colormap</string>
<string>Fiber Bundle Coloring</string>
</property>
<property name="flat">
<bool>false</bool>
......@@ -132,41 +132,6 @@ QCheckBox::indicator:unchecked {
</item>
</layout>
</item>
<item row="7" column="0">
<widget class="QLabel" name="ScalarRangeLabel">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Set range:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="qMRMLRangeWidget" name="ColorByScalarInvariantDisplayRange">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<layout class="QHBoxLayout" name="Layout_ScalarPropertySelect">
<item>
......@@ -222,6 +187,9 @@ QCheckBox::indicator:unchecked {
</item>
<item row="6" column="0" colspan="2">
<widget class="QRadioButton" name="ColorByCellScalarsRadioButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Of Fiber Cluster Group ID</string>
</property>
......@@ -233,46 +201,77 @@ QCheckBox::indicator:unchecked {
</attribute>
</widget>
</item>
<item row="7" column="0" colspan="2">
<layout class="QHBoxLayout" name="Layout_SolidColorPropertySelect">
<item>
<widget class="QRadioButton" name="ColorBySolidColorRadioButton">
<property name="text">
<string>Solid Color</string>
</property>
<attribute name="buttonGroup">
<string>buttonGroup</string>
</attribute>
</widget>
</item>
<item>
<widget class="ctkColorPickerButton" name="ColorBySolidColorPicker"/>
</item>
</layout>
</item>
<item row="10" column="0">
<widget class="QLabel" name="ScalarRangeLabel">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Set range:</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QCheckBox" name="AutoWL">
<property name="text">
<string>Auto W/L</string>
</property>
</widget>
</item>
<item row="9" column="0" colspan="2">
<widget class="qMRMLRangeWidget" name="FiberBundleColorRangeWidget">
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="maximumValue">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="Layout_SolidColorSelector">
<item>
<widget class="QCheckBox" name="ColorBySolidColorCheckBox">
<property name="text">
<string>Solid color</string>
</property>
<property name="autoExclusive">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string>buttonGroup</string>
</attribute>
</widget>
</item>
<item>
<widget class="ctkColorPickerButton" name="ColorBySolidColorPicker"/>
</item>
</layout>
</item>
<item>
<widget class="ctkCollapsibleGroupBox" name="MaterialPropertyGroupBox">
<property name="title">
<string>&amp;Material Properties</string>
</property>
<property name="collapsed">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="ctkMaterialPropertyWidget" name="MaterialPropertyWidget"/>
</item>
</layout>
</widget>
<widget class="ctkCollapsibleGroupBox" name="MaterialPropertyGroupBox">
<property name="title">
<string>&amp;Material Properties</string>
</property>
<property name="collapsed">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="ctkMaterialPropertyWidget" name="MaterialPropertyWidget"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
......@@ -300,55 +299,56 @@ QCheckBox::indicator:unchecked {
</widget>
<customwidgets>
<customwidget>
<class>qSlicerWidget</class>
<extends>QWidget</extends>
<header>qSlicerWidget.h</header>
<container>1</container>
<class>qMRMLColorTableComboBox</class>
<extends>qMRMLNodeComboBox</extends>
<header>qMRMLColorTableComboBox.h</header>
</customwidget>
<customwidget>
<class>ctkSliderWidget</class>
<class>qMRMLNodeComboBox</class>
<extends>QWidget</extends>
<header>ctkSliderWidget.h</header>
<header>qMRMLNodeComboBox.h</header>
</customwidget>
<customwidget>
<class>qMRMLNodeComboBox</class>
<class>qMRMLRangeWidget</class>
<extends>ctkRangeWidget</extends>
<header>qMRMLRangeWidget.h</header>
</customwidget>
<customwidget>
<class>qSlicerWidget</class>
<extends>QWidget</extends>
<header>qMRMLNodeComboBox.h</header>
<header>qSlicerWidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ctkVTKDataSetArrayComboBox</class>
<extends>QComboBox</extends>
<header>ctkVTKDataSetArrayComboBox.h</header>
</customwidget>
<customwidget>
<class>ctkCollapsibleGroupBox</class>
<extends>QGroupBox</extends>
<header>ctkCollapsibleGroupBox.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ctkColorPickerButton</class>
<extends>QPushButton</extends>
<header>ctkColorPickerButton.h</header>
</customwidget>
<customwidget>
<class>ctkRangeWidget</class>
<class>ctkMaterialPropertyWidget</class>
<extends>QWidget</extends>
<header>ctkRangeWidget.h</header>
</customwidget>
<customwidget>
<class>qMRMLColorTableComboBox</class>
<extends>qMRMLNodeComboBox</extends>
<header>qMRMLColorTableComboBox.h</header>
</customwidget>
<customwidget>
<class>qMRMLRangeWidget</class>
<extends>ctkRangeWidget</extends>
<header>qMRMLRangeWidget.h</header>
<header>ctkMaterialPropertyWidget.h</header>
</customwidget>
<customwidget>
<class>ctkCollapsibleGroupBox</class>
<class>ctkRangeWidget</class>
<extends>QWidget</extends>
<header>ctkCollapsibleGroupBox.h</header>
<header>ctkRangeWidget.h</header>
</customwidget>
<customwidget>
<class>ctkMaterialPropertyWidget</class>
<class>ctkSliderWidget</class>
<extends>QWidget</extends>
<header>ctkMaterialPropertyWidget.h</header>
<header>ctkSliderWidget.h</header>
</customwidget>
</customwidgets>
<tabstops>
......@@ -357,11 +357,12 @@ QCheckBox::indicator:unchecked {
<tabstop>ColorByScalarInvariantComboBox</tabstop>
<tabstop>ColorByScalarRadioButton</tabstop>
<tabstop>ColorByScalarComboBox</tabstop>
<tabstop>ColorByCellScalarsRadioButton</tabstop>
<tabstop>ColorByMeanFiberOrientationRadioButton</tabstop>
<tabstop>ColorByPointFiberOrientationRadioButton</tabstop>
<tabstop>ColorByCellScalarsRadioButton</tabstop>
<tabstop>ColorBySolidColorCheckBox</tabstop>
<tabstop>ColorBySolidColorRadioButton</tabstop>
<tabstop>ColorBySolidColorPicker</tabstop>
<tabstop>MaterialPropertyGroupBox</tabstop>
</tabstops>
<resources/>
<connections>
......@@ -376,8 +377,8 @@ QCheckBox::indicator:unchecked {
<y>121</y>
</hint>
<hint type="destinationlabel">
<x>296</x>
<y>198</y>
<x>338</x>
<y>192</y>
</hint>
</hints>
</connection>
......@@ -388,12 +389,12 @@ QCheckBox::indicator:unchecked {
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>61</x>
<y>75</y>
<x>71</x>
<y>72</y>
</hint>
<hint type="destinationlabel">
<x>419</x>
<y>77</y>
<x>425</x>
<y>74</y>
</hint>
</hints>
</connection>
......
......@@ -15,6 +15,7 @@
// VTK includes
#include <math.h>
//------------------------------------------------------------------------------
class qSlicerTractographyDisplayWidgetPrivate:
public Ui_qSlicerTractographyDisplayWidget
......@@ -59,17 +60,15 @@ void qSlicerTractographyDisplayWidgetPrivate::init()
QObject::connect( this->VisibilityCheckBox, SIGNAL(clicked(bool)), q, SLOT(setVisibility(bool)) );
QObject::connect( this->ColorByCellScalarsRadioButton, SIGNAL(clicked()), q, SLOT(setColorByCellScalars()) );
QObject::connect( this->ColorBySolidColorCheckBox, SIGNAL(clicked()), q, SLOT(setColorBySolid()) );
QObject::connect( this->ColorBySolidColorRadioButton, SIGNAL(clicked()), q, SLOT(setColorBySolid()) );
QObject::connect( this->ColorBySolidColorPicker, SIGNAL(colorChanged(QColor)), q, SLOT(onColorBySolidChanged(QColor)) );
QObject::connect( this->ColorByScalarsColorTableComboBox, SIGNAL(currentNodeChanged(vtkMRMLNode*)), q,
SLOT(setColorByCellScalarsColorTable(vtkMRMLNode*)) );
QObject::connect( this->ColorByScalarInvariantRadioButton, SIGNAL(clicked()), q, SLOT(setColorByScalarInvariant()) );
QObject::connect( this->ColorByScalarInvariantComboBox, SIGNAL(currentIndexChanged(int)), q,
SLOT(onColorByScalarInvariantChanged(int)) );
QObject::connect( this->ColorByScalarInvariantDisplayRange, SIGNAL(rangeChanged(double,double)), q,
SLOT(setColorByScalarInvariantDisplayRange(double,double)) );
QObject::connect( this->ColorByScalarRadioButton, SIGNAL(clicked()), q, SLOT(setColorByScalar()) );
QObject::connect( this->ColorByScalarComboBox, SIGNAL(currentIndexChanged(int)), q,
......@@ -94,6 +93,14 @@ void qSlicerTractographyDisplayWidgetPrivate::init()
q, SLOT(setSpecularPower(double)));
QObject::connect(this->MaterialPropertyWidget, SIGNAL(backfaceCullingChanged(bool)),
q, SLOT(setBackfaceCulling(bool)));
QObject::connect(this->AutoWL, SIGNAL(clicked(bool)),
q, SLOT(setAutoWindowLevel(bool)));
QObject::connect(this->FiberBundleColorRangeWidget, SIGNAL(valuesChanged(double, double)),
q, SLOT(setWindowLevel(double, double)));
QObject::connect(this->FiberBundleColorRangeWidget, SIGNAL(rangeChanged(double, double)),
q, SLOT(setWindowLevelLimits(double, double)));
}
......@@ -334,17 +341,7 @@ void qSlicerTractographyDisplayWidget::setColorByScalarInvariant()
}
d->FiberBundleDisplayNode->SetColorModeToScalar();
d->FiberBundleDisplayNode->SetScalarVisibility(1);
}
//------------------------------------------------------------------------------
void qSlicerTractographyDisplayWidget::setColorByScalarInvariantDisplayRange(double min, double max)
{
Q_D(qSlicerTractographyDisplayWidget);
if (!d->FiberBundleDisplayNode)
{
return;
}
d->FiberBundleDisplayNode->SetScalarRange(min, max);
this->updateScalarRange();
}
//------------------------------------------------------------------------------
......@@ -361,7 +358,9 @@ void qSlicerTractographyDisplayWidget::onColorByScalarInvariantChanged(int scala
if (displayPropertiesNode)
{
displayPropertiesNode->SetColorGlyphBy(d->ColorByScalarInvariantComboBox->itemData(scalarInvariantIndex).toInt());
}
d->FiberBundleDisplayNode->Modified();
this->updateScalarRange();
}
}
//------------------------------------------------------------------------------
......@@ -390,6 +389,46 @@ void qSlicerTractographyDisplayWidget::setColorByCellScalarsColorTable(vtkMRMLNo
d->FiberBundleDisplayNode->SetAndObserveColorNodeID(colortableNode->GetID());
}
//------------------------------------------------------------------------------
void qSlicerTractographyDisplayWidget::setAutoWindowLevel(bool value)
{
if (this->m_updating)
return;
Q_D(qSlicerTractographyDisplayWidget);
if (!d->FiberBundleDisplayNode)
{
return;
}
d->FiberBundleDisplayNode->SetAutoScalarRange(value);
}
//------------------------------------------------------------------------------
void qSlicerTractographyDisplayWidget::setWindowLevel(double minValue, double maxValue)
{
if (this->m_updating)
return;
Q_D(qSlicerTractographyDisplayWidget);
if (!d->FiberBundleDisplayNode)
{
return;
}
d->FiberBundleDisplayNode->SetScalarRange(minValue, maxValue);
}
//------------------------------------------------------------------------------
void qSlicerTractographyDisplayWidget::setWindowLevelLimits(double minValue, double maxValue)
{
if (this->m_updating)
return;
Q_D(qSlicerTractographyDisplayWidget);
const double step = (maxValue - minValue) / 100.;
d->FiberBundleColorRangeWidget->setSingleStep(step);
d->FiberBundleColorRangeWidget->setDecimals(ceil(fabs(log10(step))));
}
//------------------------------------------------------------------------------
void qSlicerTractographyDisplayWidget::setOpacity(double opacity)
{
......@@ -518,6 +557,41 @@ bool qSlicerTractographyDisplayWidget::backfaceCulling()const
return d->MaterialPropertyWidget->backfaceCulling();
}
//------------------------------------------------------------------------------
void qSlicerTractographyDisplayWidget::updateScalarRange()
{
Q_D(qSlicerTractographyDisplayWidget);
if ( !d->FiberBundleNode || !d->FiberBundleDisplayNode)
{
return;
}
double range[2];
bool was_updating = this->m_updating;
this->m_updating = true;
d->FiberBundleDisplayNode->GetScalarRange(range);
if (d->FiberBundleDisplayNode->GetAutoScalarRange())
{
d->FiberBundleColorRangeWidget->setMinimumValue(range[0]);
d->FiberBundleColorRangeWidget->setMaximumValue(range[1]);
d->FiberBundleColorRangeWidget->setRange(range[0], range[1]);
}
else
{
d->FiberBundleColorRangeWidget->setMinimumValue(range[0]);
d->FiberBundleColorRangeWidget->setMaximumValue(range[1]);
if ((d->FiberBundleColorRangeWidget->minimum() > range[0]) ||
(d->FiberBundleColorRangeWidget->maximum() < range[1]))
d->FiberBundleColorRangeWidget->setRange(range[0], range[1]);
}
const double step = (range[1] - range[0]) / 100.;
d->FiberBundleColorRangeWidget->setSingleStep(step);
d->FiberBundleColorRangeWidget->setDecimals(ceil(fabs(log10(step))));
this->m_updating = was_updating;
}
//------------------------------------------------------------------------------
void qSlicerTractographyDisplayWidget::updateWidgetFromMRML()
......@@ -581,7 +655,7 @@ void qSlicerTractographyDisplayWidget::updateWidgetFromMRML()
double color[3];
d->FiberBundleDisplayNode->GetColor(color);
d->ColorBySolidColorPicker->setColor(QColor::fromRgbF(color[0],color[1],color[2]) );
d->ColorBySolidColorCheckBox->setChecked(1);
d->ColorBySolidColorRadioButton->setChecked(1);
}
break;
case vtkMRMLFiberBundleDisplayNode::colorModeUseCellScalars:
......@@ -604,6 +678,27 @@ void qSlicerTractographyDisplayWidget::updateWidgetFromMRML()
}
break;
}
if (
d->FiberBundleDisplayNode->GetColorMode() == vtkMRMLFiberBundleDisplayNode::colorModeScalarData ||
d->FiberBundleDisplayNode->GetColorMode() == vtkMRMLFiberBundleDisplayNode::colorModeScalar
)
{
d->AutoWL->setEnabled(1);
d->AutoWL->setChecked(d->FiberBundleDisplayNode->GetAutoScalarRange());
if (d->FiberBundleDisplayNode->GetAutoScalarRange())
{
d->FiberBundleColorRangeWidget->setEnabled(0);
}
else
{
d->FiberBundleColorRangeWidget->setEnabled(1);
}
this->updateScalarRange();
} else {
d->AutoWL->setEnabled(0);
d->FiberBundleColorRangeWidget->setEnabled(0);
}
d->MaterialPropertyWidget->setColor(
QColor::fromRgbF(d->FiberBundleDisplayNode->GetColor()[0],
......@@ -617,6 +712,4 @@ void qSlicerTractographyDisplayWidget::updateWidgetFromMRML()
d->MaterialPropertyWidget->setBackfaceCulling(d->FiberBundleDisplayNode->GetBackfaceCulling());
this->m_updating = 0;