SMILX  1.01
milxQtRobustShapeModel.cpp
1 /*=========================================================================
2  The Software is copyright (c) Commonwealth Scientific and Industrial Research Organisation (CSIRO)
3  ABN 41 687 119 230.
4  All rights reserved.
5 
6  Licensed under the CSIRO BSD 3-Clause License
7  You may not use this file except in compliance with the License.
8  You may obtain a copy of the License in the file LICENSE.md or at
9 
10  https://stash.csiro.au/projects/SMILI/repos/smili/browse/license.txt
11 
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  See the License for the specific language governing permissions and
16  limitations under the License.
17 =========================================================================*/
18 #include <ctime>
19 
20 #include "milxQtRobustShapeModel.h"
21 
22 //Used for generateModesModel
23 #include <vtkPointData.h>
24 #include <vtkFloatArray.h>
25 #include <vtkDoubleArray.h>
26 #include <vtkTensor.h>
27 #include <vtkTensorGlyph.h>
28 #include <vtkSphereSource.h>
29 #include <vtkPolyDataNormals.h>
30 #include <vtkMath.h>
31 #include <vtkSphericalTransform.h>
32 #include <vnl/vnl_double_3.h>
33 #include <vnl/algo/vnl_scatter_3x3.h>
34 //Improve Rendering
35 #include <vtkPNGWriter.h>
36 #include <vtkWindowToImageFilter.h>
37 
38 #include <milxQtFile.h>
39 #include <milxQtPlot.h>
40 
41 milxQtRobustShapeModel::milxQtRobustShapeModel(QWidget *theParent, bool contextSystem) : milxQtShapeModel(theParent, contextSystem)
42 {
43  reset();
44 
45  m_RobustSSM = RobustShapeModelType::New();
47  m_RobustSSM->DebugOn();
48 
49  m_meanModel = NULL;
50  m_modesVectorModel = NULL;
51  m_modesTensorModel = NULL;
52  m_correspondences = NULL;
53 
55  milxQtWindow::prefix = "RSSM: ";
56 
57  createActions();
58  setupTooltips();
60 }
61 
63 {
64 
65 }
66 
67 void milxQtRobustShapeModel::LoadModel(const QString filename)
68 {
69  reset();
70 
71  if(m_RobustSSM->LoadCompactModel(filename.toStdString().c_str()))
72  m_loaded = true;
73  else
74  {
75  printError("Could not open Robust SSM file.");
76  return;
77  }
78 
79  generateSSM();
80 }
81 
82 void milxQtRobustShapeModel::SetInputCollection(vtkPolyDataCollection* meshes)
83 {
84  size_t n = meshes->GetNumberOfItems();
85 
86  working(-1);
87  reset();
88 
89  meshes->InitTraversal();
90  for(size_t j = 0; j < n; j ++)
91  {
92  vtkPolyData * shape = meshes->GetNextItem();
93 
94  vtkFloatArray *weights = vtkFloatArray::New(); //owned by RSSM class
95  weights->SetNumberOfTuples(shape->GetNumberOfPoints());
96  weights->SetNumberOfComponents(1);
97  weights->FillComponent(0, 1.0);
98 
99  m_RobustSSM->AddShape(shape, weights);
100 
101  qApp->processEvents();
102  }
103  done(-1);
104 
105  m_loaded = true;
106 }
107 
108 void milxQtRobustShapeModel::SetInputCollection(vtkPolyDataCollection* meshes, QStringList &filenames)
109 {
110  const int n = meshes->GetNumberOfItems();
111 
112  working(-1);
113  reset();
114 
117  int index = 0;
118  QDialog *casePossibilities = new QDialog(this);
119  QComboBox *integerValues = new QComboBox(this);
120  QPushButton *okButton = new QPushButton(this);
121  okButton->setText("Ok");
122  QLabel *lblMessage = new QLabel(this);
123  lblMessage->setText("Choose Case ID from possibilities.");
124  QFormLayout *formLayout = new QFormLayout(this);
125  formLayout->addRow(lblMessage);
126  formLayout->addRow(tr("&Select Case ID from first file: "), integerValues);
127  formLayout->addRow(okButton);
128  casePossibilities->setLayout(formLayout);
129 
130  connect(okButton, SIGNAL(clicked(bool)), casePossibilities, SLOT(accept()));
131 
132  meshes->InitTraversal();
133  for(int j = 0; j < n; j ++)
134  {
135  QFileInfo fi(filenames[j]);
136  QRegExp rx("(\\d+)", Qt::CaseSensitive, QRegExp::RegExp2);
137 
139  int pos = 0;
140  QStringList list;
141  while ((pos = rx.indexIn(fi.baseName(), pos)) != -1)
142  {
143  list << rx.cap(1);
144  pos += rx.matchedLength(); //Move
145  }
146 
148  if(list.size() > 1 && j == 0)
149  {
150  printInfo("Please choose Case ID from possibilities for first file.");
151  for(int k = 0; k < list.size(); k ++)
152  integerValues->addItem(list[k]);
153 
154  casePossibilities->exec();
155 
156  index = integerValues->currentIndex();
157  }
158 
159  int caseID = 0;
160  if(!list.isEmpty())
161  caseID = list[index].toInt();
162 
163  m_caseIDs.append(caseID);
164 
165  vtkPolyData * shape = meshes->GetNextItem();
166 
167  vtkFloatArray *weights = vtkFloatArray::New(); //owned by RSSM class
168  weights->SetNumberOfTuples(shape->GetNumberOfPoints());
169  weights->SetNumberOfComponents(1);
170  weights->FillComponent(0, 1.0);
171 
172  m_RobustSSM->AddShape(shape, weights);
173 
174  qApp->processEvents();
175  }
176  done(-1);
177 
178  qDebug() << "Case IDs: " << m_caseIDs << endl;
179 
180  m_loaded = true;
181 }
182 
183 void milxQtRobustShapeModel::SetInputCollection(vtkPolyDataCollection* meshes, vtkPolyData *atlasSurface, QStringList &filenames)
184 {
185  const int n = meshes->GetNumberOfItems();
186 
187  working(-1);
188  reset();
189 
190  if(!atlasSurface->GetPointData()->GetScalars())
191  {
192  printError("No Scalars present on atlas surface. Aborting.");
193  return;
194  }
195 
196  vtkFloatArray *atlasWeights = vtkFloatArray::SafeDownCast(atlasSurface->GetPointData()->GetScalars());
197  if(!atlasWeights)
198  printWarning("Array not floating point type?");
199 
202  int index = 0;
203  QDialog *casePossibilities = new QDialog(this);
204  QComboBox *integerValues = new QComboBox(this);
205  QPushButton *okButton = new QPushButton(this);
206  okButton->setText("Ok");
207  QLabel *lblMessage = new QLabel(this);
208  lblMessage->setText("Choose Case ID from possibilities.");
209  QFormLayout *formLayout = new QFormLayout(this);
210  formLayout->addRow(lblMessage);
211  formLayout->addRow(tr("&Select Case ID from first file: "), integerValues);
212  formLayout->addRow(okButton);
213  casePossibilities->setLayout(formLayout);
214 
215  connect(okButton, SIGNAL(clicked(bool)), casePossibilities, SLOT(accept()));
216 
217  //Set Focused mode
218  printInfo("Using Focused Model Mode");
219  m_RobustSSM->SetTolerance(0);
220  m_RobustSSM->RandomInitialisationOff();
221  m_RobustSSM->PreAlignedOff();
222  m_RobustSSM->MissingModeOff();
223  m_RobustSSM->SetMaxIterations(3);
224 
225  meshes->InitTraversal();
226  for(int j = 0; j < n; j ++)
227  {
228  QFileInfo fi(filenames[j]);
229  QRegExp rx("(\\d+)", Qt::CaseSensitive, QRegExp::RegExp2);
230 
232  int pos = 0;
233  QStringList list;
234  while ((pos = rx.indexIn(fi.baseName(), pos)) != -1)
235  {
236  list << rx.cap(1);
237  pos += rx.matchedLength(); //Move
238  }
239 
241  if(list.size() > 1 && j == 0)
242  {
243  printInfo("Please choose Case ID from possibilities for first file.");
244  for(int k = 0; k < list.size(); k ++)
245  integerValues->addItem(list[k]);
246 
247  casePossibilities->exec();
248 
249  index = integerValues->currentIndex();
250  }
251 
252  int caseID = 0;
253  if(!list.isEmpty())
254  caseID = list[index].toInt();
255 
256  m_caseIDs.append(caseID);
257 
258  vtkPolyData * shape = meshes->GetNextItem();
259 
260  vtkFloatArray *weights = vtkFloatArray::New(); //owned by RSSM class
261  weights->DeepCopy(atlasWeights);
262 
263  m_RobustSSM->AddShape(shape, weights);
264 
265  qApp->processEvents();
266  }
267  done(-1);
268 
269  qDebug() << "Case IDs: " << m_caseIDs << endl;
270 
271  m_loaded = true;
272 }
273 
275 {
276  if(!menu)
277  return;
278 
279  menu->clear();
280 
281  menu->addSeparator()->setText(tr("View"));
282  menu->addAction(actionMean);
283  menu->addAction(actionAligned);
284  menu->addAction(actionOriginal);
285  menu->addAction(actionModesAsVectors);
286  menu->addAction(actionModesAsTensors);
287  menu->addAction(actionModesAsCollection);
288  menu->addAction(actionCorrespond);
289  plotMenu = menu->addMenu("Plot");
290  plotMenu->addAction(actionCompact);
291  plotMenu->addAction(actionSpecificity);
292  plotMenu->addAction(actionGeneralise);
293  plotMenu->addAction(actionValues);
294  plotMenu->addAction(actionModes);
295  plotMenu->addAction(actionParameters);
296  menu->addSeparator()->setText(tr("Validation/Output"));
297  menu->addAction(actionOriginalMeshes);
298  menu->addAction(actionAlignedMeshes);
299  menu->addAction(actionAlignment);
300  menu->addAction(actionPointIDs);
301  menu->addAction(actionCoordinates);
302  menu->addSeparator();
303  menu->addAction(actionReplaceOriginal);
304  alignMenu = menu->addMenu("Procrustes Mode");
305  alignMenu->addAction(actionSimilarity);
306  alignMenu->addAction(actionRigid);
307  alignMenu->addAction(actionAffine);
309  menu->addMenu(milxQtRenderWindow::viewMenu);
318  menu->addMenu(milxQtRenderWindow::colourMapMenu);
319  menu->addSeparator();
321  menu->addAction(milxQtRenderWindow::refreshAct);
322  menu->addAction(milxQtRenderWindow::resetAct);
323 }
324 
326 {
327  if(!m_loaded)
328  return;
329 
330  bool ok;
331  float precision = QInputDialog::getDouble(this, tr("Please Provide the precision of the model"),
332  tr("Precision:"), 0.9, 0.0, 1.0, 5, &ok);
333 
334  if(!ok) //cancelled
335  return;
336 
338  try
339  {
340  m_RobustSSM->SetPrecision(precision);
341  m_RobustSSM->Update();
342  }
343  catch( itk::ExceptionObject & err )
344  {
345  printError("Exception caught while generating an SSM!");
346  cout << err << endl;
347  return;
348  }
349 
350  const size_t n = m_RobustSSM->GetNumberOfShapes();
351 
353  double eigenSum = 0.0;
354  vtkSmartPointer<vtkFloatArray> eigenVals = m_RobustSSM->GetPCA()->GetEigenValues();
355  printInfo("Eigenvalues Info - #tuples: " + QString::number(eigenVals->GetNumberOfTuples()) + ", #components: " + QString::number(eigenVals->GetNumberOfComponents()));
356  for(vtkIdType j = 0; j < eigenVals->GetNumberOfTuples(); j ++)
357  eigenSum += eigenVals->GetValue(j);
358  printInfo("Sum of Eigenvalues is " + QString::number(eigenSum));
359  printInfo("Mean Scale: " + QString::number(m_RobustSSM->GetMeanShapeSize()));
360  printInfo("Number of Modes: " + QString::number(m_RobustSSM->GetNumberOfModes()));
361 
362  vtkSmartPointer<vtkLookupTable> tmpLookupTable = vtkLookupTable::SafeDownCast(milxQtRenderWindow::lookupTable);
363  tmpLookupTable->SetTableRange(0.0, n+1);
364  tmpLookupTable->Build();
365  milxQtRenderWindow::lookupTable = tmpLookupTable;
366 
368 
369  m_modelled = true;
370 }
371 
372 void milxQtRobustShapeModel::generateMeanModel(vtkSmartPointer<vtkPolyData> shape)
373 {
374  if(!m_loaded)
375  return;
376  if(!m_modelled)
377  generateSSM();
378 
379  printInfo("Generating Mean Model.");
380  if(!m_meanModel)
381  {
382  m_meanModel = new milxQtModel;
383  m_meanModel->SetInput(m_RobustSSM->GetMeanShape());
384  m_meanModel->SetScalars(m_RobustSSM->GetWeights(0));
385  }
386  if(!shape)
387  {
388  m_meanModel->setName("Mean");
389  m_meanModel->SetPoints(m_RobustSSM->GetMeanShape()->GetPoints());
390  }
391  else
392  {
393  m_meanModel->setName("Custom Shape");
394  printDebug("Adding Custom Model.");
395  m_meanModel->SetInput(shape);
396  }
397  m_meanModel->generateModel();
398 
399  AddActor(m_meanModel->GetActor());
400 
401  m_meaned = true;
402  actionMean->setChecked(true);
403 }
404 
406 {
407  bool flgNormal = true;
408 
409  if(!m_loaded)
410  return;
411  if(!m_modelled)
412  generateSSM();
413  if(!m_meaned)
415 
416  bool ok1, ok2;
417  int mode = QInputDialog::getInt(this, tr("Please Provide the mode to view (1 to n)"),
418  tr("Mode:"), 1, 1, m_RobustSSM->GetNumberOfModes(), 1, &ok1);
419  float modeWeight = QInputDialog::getDouble(this, tr("Please Provide the weight of the mode"),
420  tr("Weight:"), 3.0, -50.0, 50.0, 2, &ok2);
421 
422  m_mode = mode;
423  m_vector = false;
424  m_tensor = false;
425  m_modes = false;
426 
427  if(!ok1 || !ok2) //cancelled
428  return;
429 
430  QMessageBox msgBox;
431  msgBox.setText("A parameterised surface will be generated");
432  msgBox.setInformativeText("Do you want to display this instead of the mean surface?");
433  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
434  msgBox.setDefaultButton(QMessageBox::No);
435  int ret = msgBox.exec();
436 
441  working(-1);
442  vtkSmartPointer<vtkPolyData> meanShape = m_meanModel->GetOutput();
443  //Ensure mean is actually mean
444  meanShape->SetPoints(m_RobustSSM->GetMeanShape()->GetPoints());
445 
446  vtkSmartPointer<vtkPolyDataNormals> normals = vtkPolyDataNormals::New();
447  normals->SetInput(meanShape);
448  normals->ComputeCellNormalsOff();
449  normals->ComputePointNormalsOn();
450  normals->SplittingOff();
451  // normals->AutoOrientNormalsOn();
452  // normals->ConsistencyOn();
453  // normals->FlipNormalsOn();
454  normals->Update();
455 
456  vtkSmartPointer<vtkFloatArray> normArray =
457  vtkFloatArray::SafeDownCast(normals->GetOutput()->GetPointData()->GetNormals());
458 
459  vtkSmartPointer<vtkFloatArray> b = vtkFloatArray::New();
460  b->SetNumberOfValues(mode);
461  b->FillComponent(0, 0.0);
462  b->SetValue(mode-1, modeWeight);
463  printInfo("Generating display for mode " + QString::number(mode-1));
464 
465  vtkSmartPointer<vtkPolyData> varShape = vtkSmartPointer<vtkPolyData>::New();
466  varShape->DeepCopy(m_RobustSSM->GetParameterisedShape(b));
467 
468  vtkSmartPointer<vtkFloatArray> varScalars = vtkSmartPointer<vtkFloatArray>::New();
469  varScalars->SetName("Variation");
470  vtkSmartPointer<vtkFloatArray> varVectors = vtkSmartPointer<vtkFloatArray>::New();
471  varVectors->SetNumberOfComponents(3);
472  vtkSmartPointer<vtkFloatArray> varShapeVectors = vtkSmartPointer<vtkFloatArray>::New();
473  varShapeVectors->SetNumberOfComponents(3);
474  vtkSmartPointer<vtkFloatArray> varTensors = vtkSmartPointer<vtkFloatArray>::New();
475  varTensors->SetNumberOfComponents(9);
476 
477  printInfo("Computing Variation");
478  for(int i = 0; i < meanShape->GetNumberOfPoints(); i++)
479  {
480  vtkFloatingPointType* meanPoint = meanShape->GetPoint(i);
481  vtkFloatingPointType* varPoint = varShape->GetPoint(i);
482 
483  vtkFloatingPointType xVal = varPoint[0] - meanPoint[0];
484  vtkFloatingPointType yVal = varPoint[1] - meanPoint[1];
485  vtkFloatingPointType zVal = varPoint[2] - meanPoint[2];
486 
487  float normalPoint[3];
488  normArray->GetTupleValue(i, normalPoint);
489  vtkFloatingPointType var;
490  if(flgNormal)
491  {
492  var = xVal*normalPoint[0] + yVal*normalPoint[1] + zVal*normalPoint[2];
493  var = var*var;
494  }
495  else
496  {
497  var = xVal*xVal + yVal*yVal + zVal*zVal;
498  }
499 // std::cout << var << std::endl;
500  varVectors->InsertNextTuple3(xVal, yVal, zVal);
501  varShapeVectors->InsertNextTuple3(-xVal, -yVal, -zVal);
502  varScalars->InsertNextValue(var);
503 
504  vnl_scatter_3x3<vtkFloatingPointType> C;
505  for(int j = 0; j < m_RobustSSM->GetNumberOfShapes(); j++)
506  {
507  vtkFloatingPointType point[3];
508  m_RobustSSM->GetPCA()->GetInput(j)->GetPoint(i, point);
509  // std::cout << point[0] << " " << point[1] << " " << point[2] << std::endl;
510  vnl_double_3 point_vector;
511  point_vector[0] = point[0] - meanPoint[0];
512  point_vector[1] = point[1] - meanPoint[1];
513  point_vector[2] = point[2] - meanPoint[2];
514  // std::cout << point_vector << std::endl;
515  C.add_outer_product(point_vector);
516  }
517  // C /= m_RobustSSM->GetNumberOfShapes();
518  // std::cout << meanPoint[0] << " " << meanPoint[1] << " " << meanPoint[2] << std::endl << std::endl;
519 // std::cout << C << std::endl;
520  vtkSmartPointer<vtkTensor> tens = vtkSmartPointer<vtkTensor>::New();
521  tens->SetComponent(0,0, C(0,0));
522  tens->SetComponent(0,1, C(0,1));
523  tens->SetComponent(0,2, C(0,2));
524  tens->SetComponent(1,0, C(1,0));
525  tens->SetComponent(1,1, C(1,1));
526  tens->SetComponent(1,2, C(1,2));
527  tens->SetComponent(2,0, C(2,0));
528  tens->SetComponent(2,1, C(2,1));
529  tens->SetComponent(2,2, C(2,2));
530 
531  varTensors->InsertNextTuple(tens->T);
532 // std::cout << tens->T[0] << " " << tens->T[1] << " " << tens->T[2] << std::endl;
533 
534  qApp->processEvents();
535  }
536 
537  vtkFloatingPointType maxScalar = std::numeric_limits<vtkFloatingPointType>::min();
538  for(int i = 0; i < varScalars->GetNumberOfTuples(); i++)
539  {
540  if(varScalars->GetValue(i) > maxScalar)
541  maxScalar = varScalars->GetValue(i);
542  }
543  printInfo("Max sigma: " + QString::number(sqrt(maxScalar)) + "mm.");
544  for(int i = 0; i < varScalars->GetNumberOfTuples(); i++)
545  {
546  vtkFloatingPointType var = varScalars->GetValue(i);
547  varScalars->SetValue(i, var/maxScalar);
548  }
549 
550  meanShape->GetPointData()->SetVectors(varVectors);
551  varShape->GetPointData()->SetVectors(varShapeVectors);
552  meanShape->GetPointData()->SetScalars(varScalars);
553  //scalars dont make sense for varShape
554  meanShape->GetPointData()->SetTensors(varTensors);
555  varShape->GetPointData()->SetTensors(varTensors);
556 
557  if(ret == QMessageBox::Yes)
558  generateMeanModel(varShape);
559  else
561  done(-1);
562 
563  m_modes = true;
564 }
565 
567 {
568  if(!m_loaded)
569  return;
570  if(!m_modelled)
571  generateSSM();
572  if(!m_meaned)
574 
575  const int n = m_RobustSSM->GetNumberOfShapes();
576  bool ok1, ok2, ok3;
577  int mode = QInputDialog::getInt(this, tr("Please Provide the mode to view (1 to n)"),
578  tr("Mode:"), 1, 1, n, 1, &ok1);
579  float modeWeight = QInputDialog::getDouble(this, tr("Please Provide the range weight c of the mode (so that -c < x < c)"),
580  tr("Weight:"), 3.0, -5.0, 5.0, 2, &ok2);
581  int numberOfSurfaces = QInputDialog::getInt(this, tr("Please Provide the number of surfaces to generate"),
582  tr("Number:"), 16, 1, 1e9, 1, &ok3);
583 
584  m_mode = mode;
585 
586  if(!ok1 || !ok2 || !ok3) //cancelled
587  return;
588 
589  //Init counters etc.
590  float weightValue = -modeWeight;
591  const float weightStep = 2.0*modeWeight/(numberOfSurfaces-1);
592 
593  vtkPolyDataCollection* meshes = vtkPolyDataCollection::New();
594  QStringList surfaceNames;
595  for(int j = 0; j < numberOfSurfaces; j ++)
596  {
597  vtkSmartPointer<vtkFloatArray> b = vtkFloatArray::New();
598  b->SetNumberOfValues(mode);
599  b->FillComponent(0, 0.0);
600  b->SetValue(mode-1, weightValue);
601  printInfo("Generating surface for mode " + QString::number(mode-1));
602 
603  vtkPolyData *shape = vtkPolyData::New();
604  shape->DeepCopy(m_RobustSSM->GetParameterisedShape(b));
605 
606  meshes->AddItem(shape);
607  surfaceNames.append(QString::number(weightStep));
608 
609  weightValue += weightStep;
610  }
611 
612  printInfo("Mode Surfaces Generated");
613  emit collectionAvailable(meshes, surfaceNames);
614 }
615 
617 {
618  if(!m_loaded)
619  return;
620 
621  const int n = m_SSM->GetNumberOfShapes();
622  const int noOfPoints = m_SSM->GetShape(0)->GetNumberOfPoints();
623 
624  printInfo("Generating Correspondences.");
625  working(-1);
626  vtkSmartPointer<vtkDoubleArray> maxDeviations = vtkSmartPointer<vtkDoubleArray>::New();
627  maxDeviations->SetNumberOfComponents(3);
628  maxDeviations->SetNumberOfTuples(noOfPoints);
629  maxDeviations->SetName("Deviations");
630 
632  coordinate origin(0.0);
633  for(int l = 0; l < noOfPoints; l ++)
634  maxDeviations->SetTupleValue(l, origin.data_block());
635 
636  for(int j = 0; j < n; j ++)
637  {
638  vtkSmartPointer<vtkPolyData> currentShape = m_SSM->GetProcrustesAlignedSurface(j);
639 
640  for(int k = 0; k < n; k ++)
641  {
642  if(j == k)
643  continue;
644 
645  vtkSmartPointer<vtkPolyData> nextShape = m_SSM->GetProcrustesAlignedSurface(k);
646 
647  for(int l = 0; l < noOfPoints; l ++)
648  {
649  coordinate currentPoint(currentShape->GetPoint(l));
650  coordinate nextPoint(nextShape->GetPoint(l));
651  coordinate maxVector(maxDeviations->GetTuple(l));
652  coordinate deviation = currentPoint - nextPoint;
653 
654  double length = deviation.squared_magnitude();
655  double currentMaxLength = maxVector.squared_magnitude();
656 
657  if(length > currentMaxLength)
658  {
659  //deviation += currentPoint;
660  maxDeviations->SetTupleValue(l, deviation.data_block());
661  }
662  }
663 
664  qApp->processEvents();
665  }
666  }
667 
668  printInfo("Showing Hedgehog plot.");
669  if(!m_correspondences)
670  m_correspondences = new milxQtModel; //smart deletion
671  m_correspondences->SetInput(m_SSM->GetMeanShape());
672  m_correspondences->SetVectors(maxDeviations);
673  m_correspondences->generateHedgehog();
674 
675  AddActor(m_correspondences->GetActor());
676  m_correspond = true;
677  actionCorrespond->setChecked(true);
678  done(-1);
679 }
680 
681 //Slots
683 {
684  if(!m_modelled)
685  generateSSM();
686 
687  vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
688  vtkSmartPointer<vtkFloatArray> values = m_RobustSSM->GetPCA()->GetEvals();
689 
691  for(int j = 0; j < 3; j ++)
692  {
693  vtkSmartPointer<vtkDoubleArray> column = vtkSmartPointer<vtkDoubleArray>::New();
694  for(int k = 0; k < values->GetNumberOfTuples(); k ++)
695  column->InsertNextValue(0.0);
696  table->AddColumn(column);
697  }
698  printDebug("Compactness Table is " + QString::number(table->GetNumberOfRows()) + "x" + QString::number(table->GetNumberOfColumns()));
699 
701  table->GetColumn(0)->SetName("Mode");
702  table->GetColumn(1)->SetName("Value");
703  table->GetColumn(2)->SetName("Precision");
704 
706  double total = 0.0;
707  for (int j = 0; j < values->GetNumberOfTuples(); j++)
708  total += values->GetValue(j);
709  printInfo("Total of eigenvalues is " + QString::number(total));
710 
712  double compactness = 0.0;
713  for (int j = 0; j < values->GetNumberOfTuples(); j++)
714  {
715  compactness += values->GetValue(j)/total;
716 
717  table->SetValue(j, 0, j+1);
718  table->SetValue(j, 1, values->GetValue(j));
719  table->SetValue(j, 2, compactness);
720 
721  qApp->processEvents();
722  }
723  table->Update();
724  table->Dump();
725 
726  QPointer<milxQtPlot> plot = new milxQtPlot;
727  plot->setPlotType2D(0, 2);
728  plot->setName("Compactness of the Shape Model");
729  plot->setConsole(console);
730  plot->legend(false);
731  plot->SetSource(table);
732  plot->generatePlot(); //emits result, not connected
733 // plot->scatterPlot(table, 0, 2);
734 
735  emit resultAvailable( qobject_cast<milxQtRenderWindow*>(plot) );
736 }
737 
739 {
740  if(!m_modelled)
741  generateSSM();
742 
743  srand(time(NULL));
744 
745  bool ok;
746  int n = QInputDialog::getInt(this, tr("Please Provide the number of random shapes to use"),
747  tr("Number of Random Shapes:"), 30, 2, 1000000, 1, &ok);
748 
749  if(!ok)
750  return;
751 
752  vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
753 
755  for(int j = 0; j < 3; j ++)
756  {
757  vtkSmartPointer<vtkDoubleArray> column = vtkSmartPointer<vtkDoubleArray>::New();
758  for(int k = 0; k < n; k ++)
759  column->InsertNextValue(0.0);
760  table->AddColumn(column);
761  }
762  printDebug("Specificity Table is " + QString::number(table->GetNumberOfRows()) + "x" + QString::number(table->GetNumberOfColumns()));
763 
765  table->GetColumn(0)->SetName("Shape");
766  table->GetColumn(1)->SetName("Minimum RMSE");
767  table->GetColumn(2)->SetName("Specificity");
768 
769  working(-1);
770  double specific = 0;
771  for(int i = 0; i < n; i++)
772  {
773  vtkSmartPointer<vtkFloatArray> b = vtkSmartPointer<vtkFloatArray>::New();
774  b->SetNumberOfComponents(1);
775  b->SetNumberOfTuples(m_RobustSSM->GetNumberOfModes());
776  for(int j = 0; j < m_RobustSSM->GetNumberOfModes(); j++)
777  b->SetTuple1(j, rand()%35/10 - 1.75);
778 
779  vtkSmartPointer<vtkPolyData> shape = m_RobustSSM->GetParameterisedShape(b);
780  double minSumSquares = std::numeric_limits<double>::max();
781  for(int k = 0; k < m_RobustSSM->GetNumberOfShapes(); k ++)
782  {
783  double value = m_RobustSSM->PolyDataDistance(shape, m_RobustSSM->GetShape(k))/m_RobustSSM->GetShape(0)->GetNumberOfPoints();
784  if(value < minSumSquares)
785  minSumSquares = value;
786  }
787  specific += minSumSquares;
788 
789  table->SetValue(i, 0, i);
790  table->SetValue(i, 1, minSumSquares);
791  table->SetValue(i, 2, specific);
792 
793  qApp->processEvents();
794  }
795  specific /= n;
796  printInfo("Specificity Score: " + QString::number(specific));
797  table->Update();
798  table->Dump();
799  done(-1);
800 
801  QPointer<milxQtPlot> plot = new milxQtPlot;
802  plot->setPlotType2D(0, 1);
803  plot->setName("Specificity of the Shape Model");
804  plot->setConsole(console);
805  plot->legend(false);
806  plot->SetSource(table);
807  plot->generatePlot(); //emits result, not connected
808 // plot->scatterPlot(table, 0, 1);
809 
810  emit resultAvailable( qobject_cast<milxQtRenderWindow*>(plot) );
811 }
812 
814 {
815  if(!m_modelled)
816  generateSSM();
817 
818  vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
819 
821  for(int j = 0; j < 2; j ++)
822  {
823  vtkSmartPointer<vtkDoubleArray> column = vtkSmartPointer<vtkDoubleArray>::New();
824  for(int k = 0; k < m_RobustSSM->GetNumberOfShapes(); k ++)
825  column->InsertNextValue(0.0);
826  table->AddColumn(column);
827  }
828  printDebug("Generalisability Table is " + QString::number(table->GetNumberOfRows()) + "x" + QString::number(table->GetNumberOfColumns()));
829 
831  table->GetColumn(0)->SetName("Shape");
832  table->GetColumn(1)->SetName("Reconstruction Error");
833 
834  working(-1);
835  double generalisability = 0.0;
836  for(int i = 0; i < m_RobustSSM->GetNumberOfShapes(); i++)
837  {
839  vtkPolyData *shape = vtkPolyData::New(); //can't use smart ptrs here
840  shape->DeepCopy(m_RobustSSM->GetShape(0));
841  vtkFloatArray *weights = vtkFloatArray::New(); //can't use smart ptrs here
842  weights->DeepCopy(m_RobustSSM->GetWeights(0));
843  m_RobustSSM->RemoveShape(0); //removes weights as well
844  m_RobustSSM->Update();
845 
846  vtkSmartPointer<vtkFloatArray> b = vtkSmartPointer<vtkFloatArray>::New();
847  b->SetNumberOfComponents(1);
848  b->SetNumberOfTuples(m_RobustSSM->GetNumberOfModes());
849  b->FillComponent(0, 0.0);
850 
851  vtkSmartPointer<vtkMatrix4x4> matrix = vtkSmartPointer<vtkMatrix4x4>::New();
852  shape->GetPointData()->SetScalars(weights);
853  m_RobustSSM->GetSurfaceSimilarityParameters(shape, weights, matrix, b);
854  vtkSmartPointer<vtkPolyData> shape2 = m_RobustSSM->GetSurface(matrix, b, false);
855  double epsiSqr = m_RobustSSM->PolyDataDistance(shape, shape2)/shape->GetNumberOfPoints();
856 
857  table->SetValue(i, 0, i);
858  table->SetValue(i, 1, epsiSqr);
859 
860  generalisability += epsiSqr;
861  m_RobustSSM->AddShape(shape, weights);
862 
863  qApp->processEvents();
864  }
865  printInfo("Generalisability Score: " + QString::number(generalisability));
866  table->Update();
867  table->Dump();
868  done(-1);
869 
870  QPointer<milxQtPlot> plot = new milxQtPlot;
871  plot->setPlotType2D(0, 1);
872  plot->setName("Generalisability of the Shape Model");
873  plot->setConsole(console);
874  plot->legend(false);
875  plot->SetSource(table);
876  plot->generatePlot(); //emits result, not connected
877 // plot->scatterPlot(table, 0, 1);
878 
879  emit resultAvailable( qobject_cast<milxQtRenderWindow*>(plot) );
880 }
881 
883 {
884  if(!m_modelled)
885  generateSSM();
886 
887  vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
888  vtkSmartPointer<vtkFloatArray> values = m_RobustSSM->GetPCA()->GetEvals();
889 
891  for(int j = 0; j < 3; j ++)
892  {
893  vtkSmartPointer<vtkDoubleArray> column = vtkSmartPointer<vtkDoubleArray>::New();
894  for(int k = 0; k < values->GetNumberOfTuples(); k ++)
895  column->InsertNextValue(0.0);
896  table->AddColumn(column);
897  }
898  printDebug("Compactness Table is " + QString::number(table->GetNumberOfRows()) + "x" + QString::number(table->GetNumberOfColumns()));
899 
901  table->GetColumn(0)->SetName("Mode");
902  table->GetColumn(1)->SetName("Value");
903  table->GetColumn(2)->SetName("Precision");
904 
906  double total = 0.0;
907  for (int j = 0; j < values->GetNumberOfTuples(); j++)
908  total += values->GetValue(j);
909  printInfo("Total of eigenvalues is " + QString::number(total));
910 
912  double compactness = 0.0;
913  for (int j = 0; j < values->GetNumberOfTuples(); j++)
914  {
915  compactness += values->GetValue(j)/total;
916 
917  table->SetValue(j, 0, j+1);
918  table->SetValue(j, 1, values->GetValue(j));
919  table->SetValue(j, 2, compactness);
920 
921  qApp->processEvents();
922  }
923  table->Update();
924  table->Dump();
925 
926  QPointer<milxQtPlot> plot = new milxQtPlot;
927  plot->setPlotType2D(0, 1);
928  plot->setName("Eigenvalues of the Shape Model");
929  plot->setConsole(console);
930  plot->legend(false);
931  plot->SetSource(table);
932  plot->generatePlot(); //emits result, not connected
933 // plot->scatterPlot(table, 0, 2);
934 
935  emit resultAvailable( qobject_cast<milxQtRenderWindow*>(plot) );
936 }
937 
939 {
940  if(!m_modelled)
941  generateSSM();
942 
943  vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
944 
946  for(int j = 0; j < m_RobustSSM->GetNumberOfModes(); j ++)
947  {
948  vtkSmartPointer<vtkDoubleArray> column = vtkSmartPointer<vtkDoubleArray>::New();
949  for(int k = 0; k < m_RobustSSM->GetNumberOfShapes(); k ++)
950  column->InsertNextValue(0.0);
951  const QString nameOfColumn = "Mode " + QString::number(j+1);
952  column->SetName(nameOfColumn.toStdString().c_str());
953  table->AddColumn(column);
954  }
955  printDebug("Modes Table is " + QString::number(table->GetNumberOfRows()) + "x" + QString::number(table->GetNumberOfColumns()));
956 
957  for(int j = 0; j < m_RobustSSM->GetNumberOfShapes(); j ++)
958  {
959  vtkSmartPointer<vtkFloatArray> b = vtkSmartPointer<vtkFloatArray>::New();
960  b->SetNumberOfComponents(1);
961  b->SetNumberOfTuples(m_RobustSSM->GetNumberOfModes());
962 
963  vtkSmartPointer<vtkMatrix4x4> matrix = vtkSmartPointer<vtkMatrix4x4>::New();
964  m_RobustSSM->GetShape(j)->GetPointData()->SetScalars(m_RobustSSM->GetWeights(j));
965  m_RobustSSM->GetSurfaceSimilarityParameters(m_RobustSSM->GetShape(j), m_RobustSSM->GetWeights(j), matrix, b);
966 
967  for(int k = 0; k < m_RobustSSM->GetNumberOfModes(); k ++)
968  table->SetValue(j, k, b->GetValue(k));
969 
970  qApp->processEvents();
971  }
972 
973  QPointer<milxQtPlot> plot = new milxQtPlot;
974  plot->setPlotType3D(0, 1, 2);
975  plot->setName("Specificity of the Shape Model");
976  plot->setConsole(console);
977  plot->legend(false);
978  plot->SetSource(table);
979  plot->generatePlot(); //emits result, not connected
980 // plot->scatterPlot(table, 0, 1, 2);
981 
982  emit resultAvailable(plot);
983 }
984 
986 {
987  if(!m_modelled)
988  generateSSM();
989 
990  vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
991 
993  for(int j = 0; j < m_RobustSSM->GetNumberOfModes(); j ++)
994  {
995  vtkSmartPointer<vtkDoubleArray> column = vtkSmartPointer<vtkDoubleArray>::New();
996  for(int k = 0; k < m_RobustSSM->GetNumberOfShapes(); k ++)
997  column->InsertNextValue(0.0);
998  const QString nameOfColumn = "Mode " + QString::number(j+1);
999  column->SetName(nameOfColumn.toStdString().c_str());
1000  table->AddColumn(column);
1001  }
1002  printDebug("Parameters Table is " + QString::number(table->GetNumberOfRows()) + "x" + QString::number(table->GetNumberOfColumns()));
1003 
1004  for(int j = 0; j < m_RobustSSM->GetNumberOfShapes(); j ++)
1005  {
1006  vtkSmartPointer<vtkFloatArray> b = vtkSmartPointer<vtkFloatArray>::New();
1007  b->SetNumberOfComponents(1);
1008  b->SetNumberOfTuples(m_RobustSSM->GetNumberOfModes());
1009 
1010  vtkSmartPointer<vtkMatrix4x4> matrix = vtkSmartPointer<vtkMatrix4x4>::New();
1011  m_RobustSSM->GetShape(j)->GetPointData()->SetScalars(m_RobustSSM->GetWeights(j));
1012  m_RobustSSM->GetSurfaceSimilarityParameters(m_RobustSSM->GetShape(j), m_RobustSSM->GetWeights(j), matrix, b);
1013 
1014  for(int k = 0; k < m_RobustSSM->GetNumberOfModes(); k ++)
1015  table->SetValue(j, k, b->GetValue(k));
1016 
1017  qApp->processEvents();
1018  }
1019 
1020  QPointer<milxQtPlot> plot = new milxQtPlot;
1021  plot->setPlotTypeSurface();
1022  plot->setName("Training Shape Parameters of the Shape Model");
1023  plot->setConsole(console);
1024  plot->legend(false);
1025  plot->SetSource(table);
1026  plot->generatePlot(); //emits result, not connected
1027 // plot->surfacePlot(table);
1028 
1029  emit resultAvailable(plot);
1030 }
1031 
1032 void milxQtRobustShapeModel::reset()
1033 {
1034  m_loaded = false;
1035  m_modelled = false;
1036  m_meaned = false;
1037  m_shapesModelled = false;
1038  m_alignedShapesModelled = false;
1039  m_modes = false;
1040  m_vector = false;
1041  m_tensor = false;
1042  m_correspond = false;
1043  m_mode = 1;
1044 }
1045 
1047 {
1048  contextMenu = new QMenu(this);
1049  contextMenu->setTitle(QApplication::translate("MainWindow", "Robust Shape Modelling", 0, QApplication::UnicodeUTF8));
1050 
1051  actionMean = new QAction(this);
1052  actionMean->setText(QApplication::translate("SSM", "&Mean Model", 0, QApplication::UnicodeUTF8));
1053  actionMean->setShortcut(tr("Alt+m"));
1054  actionMean->setCheckable(true);
1055  actionMean->setChecked(false);
1056  actionAligned = new QAction(this);
1057  actionAligned->setText(QApplication::translate("SSM", "&Aligned Points", 0, QApplication::UnicodeUTF8));
1058  actionAligned->setShortcut(tr("Alt+a"));
1059  actionAligned->setCheckable(true);
1060  actionAligned->setChecked(false);
1061  actionOriginal = new QAction(this);
1062  actionOriginal->setText(QApplication::translate("SSM", "&Original Points", 0, QApplication::UnicodeUTF8));
1063  actionOriginal->setShortcut(tr("Alt+o"));
1064  actionOriginal->setCheckable(true);
1065  actionOriginal->setChecked(false);
1066  actionModesAsVectors = new QAction(this);
1067  actionModesAsVectors->setText(QApplication::translate("SSM", "Modes as &Vectors", 0, QApplication::UnicodeUTF8));
1068  actionModesAsVectors->setShortcut(tr("Alt+v"));
1069  actionModesAsVectors->setCheckable(true);
1070  actionModesAsVectors->setChecked(false);
1071  actionModesAsTensors = new QAction(this);
1072  actionModesAsTensors->setText(QApplication::translate("SSM", "Modes as &Tensors", 0, QApplication::UnicodeUTF8));
1073  actionModesAsTensors->setShortcut(tr("Alt+t"));
1074  actionModesAsTensors->setCheckable(true);
1075  actionModesAsTensors->setChecked(false);
1076  actionModesAsCollection = new QAction(this);
1077  actionModesAsCollection->setText(QApplication::translate("SSM", "Modes as Surface &Collection", 0, QApplication::UnicodeUTF8));
1078  actionModesAsCollection->setShortcut(tr("Alt+c"));
1079  actionCorrespond = new QAction(this);
1080  actionCorrespond->setText(QApplication::translate("SSM", "Correspondences as a &Hedgehog", 0, QApplication::UnicodeUTF8));
1081  actionCorrespond->setShortcut(tr("Alt+h"));
1082  actionCorrespond->setCheckable(true);
1083  actionCorrespond->setChecked(false);
1084 
1085  //plots menu
1086  actionCompact = new QAction(this);
1087  actionCompact->setText(QApplication::translate("SSM", "Compactness", 0, QApplication::UnicodeUTF8));
1088  actionCompact->setShortcut(tr("Shift+Alt+c"));
1089  actionSpecificity = new QAction(this);
1090  actionSpecificity->setText(QApplication::translate("SSM", "Specificity", 0, QApplication::UnicodeUTF8));
1091  actionSpecificity->setShortcut(tr("Shift+Alt+s"));
1092  actionGeneralise = new QAction(this);
1093  actionGeneralise->setText(QApplication::translate("SSM", "Generalisability", 0, QApplication::UnicodeUTF8));
1094  actionGeneralise->setShortcut(tr("Shift+Alt+g"));
1095  actionValues = new QAction(this);
1096  actionValues->setText(QApplication::translate("SSM", "Eigenvalues", 0, QApplication::UnicodeUTF8));
1097  actionValues->setShortcut(tr("Shift+Alt+v"));
1098  actionModes = new QAction(this);
1099  actionModes->setText(QApplication::translate("SSM", "Primary Eigenmodes", 0, QApplication::UnicodeUTF8));
1100  actionModes->setShortcut(tr("Shift+Alt+r"));
1101  actionParameters = new QAction(this);
1102  actionParameters->setText(QApplication::translate("SSM", "Training Shape Parameters", 0, QApplication::UnicodeUTF8));
1103  actionParameters->setShortcut(tr("Shift+Alt+p"));
1104 
1105  //Procrustes menu
1106  actionRigid = new QAction(this);
1107  actionRigid->setText(QApplication::translate("SSM", "Rigid", 0, QApplication::UnicodeUTF8));
1108  actionRigid->setShortcut(tr("Ctrl+Alt+r"));
1109  actionRigid->setCheckable(true);
1110  actionSimilarity = new QAction(this);
1111  actionSimilarity->setText(QApplication::translate("SSM", "Similarity", 0, QApplication::UnicodeUTF8));
1112  actionSimilarity->setShortcut(tr("Ctrl+Alt+s"));
1113  actionSimilarity->setCheckable(true);
1114  actionSimilarity->setChecked(true);
1115  actionAffine = new QAction(this);
1116  actionAffine->setText(QApplication::translate("SSM", "Affine", 0, QApplication::UnicodeUTF8));
1117  actionAffine->setShortcut(tr("Ctrl+Alt+a"));
1118  actionAffine->setCheckable(true);
1119  alignGroup = new QActionGroup(this);
1120  alignGroup->addAction(actionRigid);
1121  alignGroup->addAction(actionSimilarity);
1122  alignGroup->addAction(actionAffine);
1123 
1124  actionAlignment = new QAction(this);
1125  actionAlignment->setText(QApplication::translate("SSM", "Output &Alignment as Images", 0, QApplication::UnicodeUTF8));
1126  actionAlignment->setShortcut(tr("Alt+r"));
1127  actionOriginalMeshes = new QAction(this);
1128  actionOriginalMeshes->setText(QApplication::translate("SSM", "Output &Original Meshes", 0, QApplication::UnicodeUTF8));
1129  actionOriginalMeshes->setShortcut(tr("Shift+Alt+o"));
1130  actionAlignedMeshes = new QAction(this);
1131  actionAlignedMeshes->setText(QApplication::translate("SSM", "Output &Aligned Meshes", 0, QApplication::UnicodeUTF8));
1132  actionAlignedMeshes->setShortcut(tr("Shift+Alt+a"));
1133  actionPointIDs = new QAction(this);
1134  actionPointIDs->setText(QApplication::translate("SSM", "Output &Point IDs as Images", 0, QApplication::UnicodeUTF8));
1135  actionPointIDs->setShortcut(tr("Alt+p"));
1136  actionCoordinates = new QAction(this);
1137  actionCoordinates->setText(QApplication::translate("SSM", "Output &Coordinates as Images", 0, QApplication::UnicodeUTF8));
1138  actionCoordinates->setShortcut(tr("Alt+c"));
1139 
1140  actionReplaceOriginal = new QAction(this);
1141  actionReplaceOriginal->setText(QApplication::translate("SSM", "Replace Originals with Aligned", 0, QApplication::UnicodeUTF8));
1142  actionReplaceOriginal->setShortcut(tr("Shift+Alt+r"));
1143 }
1144 
1145 void milxQtRobustShapeModel::contextMenuEvent(QContextMenuEvent *contextEvent)
1146 {
1148 
1149  contextMenu->exec(contextEvent->globalPos());
1150 }
void LoadModel(const QString filename)
Loads a robust model as an SSM (*.rssm) file. MILX-MSK like call.
virtual void generateMeanModel(vtkSmartPointer< vtkPolyData > shape=NULL)
void printWarning(QString msg)
Warning message wrapper for console.
QPointer< milxQtModel > m_modesVectorModel
Vector Model of the modes.
int defaultView
Default view for data (default is axial)
virtual void SetInputCollection(vtkPolyDataCollection *meshes)
Uses the collection of polydata to create shape model.
QAction * actionGeneralise
generalisibility error plot action
void printError(QString msg)
Error message wrapper for console.
QAction * actionAlignment
alignment check action
QAction * actionCoordinates
coordinates check action
QAction * actionModesAsCollection
modes collection action
QAction * saveViewFileAct
Save camera view to file.
QMenu * viewMenu
Context Menu.
int m_mode
Mode being viewed.
QAction * actionOriginal
original points action
bool m_tensor
Tensors generated?
void AddActor(vtkSmartPointer< vtkProp > actor)
Add a VTK actor to this window.
bool m_alignedShapesModelled
Shapes were generated?
void createActions()
Create the actions for context menu etc.
vtkSmartPointer< vtkLookupTable > lookupTable
Lookup table for the shapes/images, base class is used to allow references to different look up table...
QMenu * plotMenu
Plot menu for SSM analysis.
QAction * actionModesAsTensors
modes action
void eigenmodes()
Plot the primary eigenmodes of the model for each training shape.
QAction * viewZY
Change view to zy-plane (Coronal)
QList< int > m_caseIDs
A list of case IDs corresponding to the models in the SSM.
QAction * actionReplaceOriginal
correspondence check action
void eigenvalues()
Plot the eigenvalues of the model.
QMenu * contextMenu
Context Menu.
Definition: milxQtWindow.h:250
QAction * actionSimilarity
similarity Procrustes action
QAction * actionCompact
compactness plot action
QAction * actionAligned
aligned points action
QPointer< milxQtModel > m_modesTensorModel
Tensor Model of the modes.
QActionGroup * alignGroup
Procrustes align gp action.
virtual void generateCollectionBasedOnMode()
bool m_modes
Modes been generated?
void compactness()
Plot the compactness of the SSM.
QAction * actionOriginalMeshes
original meshes output action
QAction * actionModesAsVectors
modes action
QAction * actionCorrespond
correspondence check action
void createConnections()
Create the connections for context menu etc.
bool m_meaned
Mean generated?
bool m_modelled
SSM Modelled?
QString prefix
Prefix of the data.
Definition: milxQtWindow.h:242
void printDebug(QString msg)
Debug message wrapper for console.
QAction * actionAlignedMeshes
alignmed meshes output action
QAction * actionModes
primary modes plot action
void parameters()
Plot the training shape parameters of the model for each training shape (leave 1 out).
This class represents the MILX Qt Model/Mesh Display object using VTK.
Definition: milxQtModel.h:115
QAction * actionRigid
rigid Procrustes action
QPointer< milxQtModel > m_correspondences
Hedgehog display of the correspondences.
The class provides 1D/2D and 3D plotting capability. This includes scatter and surface plots...
Definition: milxQtPlot.h:66
virtual void createMenu(QMenu *menu)
Create the menu for the data in this object. Used for context menu and file menus.
QAction * refreshAct
Action for refreshing the display.
void contextMenuEvent(QContextMenuEvent *event)
The context menu setup member.
bool m_correspond
Hedgehog generated?
void enableActionBasedOnView()
Enables the view actions corresponding to current view set.
QAction * actionSpecificity
specificity plot action
QAction * resetAct
Action for refreshing the display.
QMenu * colourMapMenu
Colour map menu.
void resultAvailable(milxQtRenderWindow *)
Send signal that Resultant render window is available for showing.
ShapeModelBaseType::Pointer m_SSM
The Statistical Shape Model Base Class.
QAction * saveViewAct
Save camera view.
QMenu * alignMenu
Plot menu for SSM alignment.
QAction * viewXY
Change view to xy-plane (Axial)
QPointer< milxQtModel > m_meanModel
Model of the mean.
bool m_vector
Vectors generated?
QAction * actionPointIDs
point ids check action
RobustShapeModelType::Pointer m_RobustSSM
The Statistical Shape Model.
QAction * viewZX
Change view to zx-plane (Sagittal)
void done(int value)
Send signal that computation is done. Value carries the progress,.
void specificity()
Plot the specificity of the SSM.
void setupTooltips()
Assign tooltips to each action for users benefit. The tooltips explains the function of each action...
void setView(int viewMode)
Change view to view mode identified by number. 0-axial, 1-coronal, 2-sagittal.
QAction * actionValues
primary modes plot action
QAction * actionMean
mean action
bool m_loaded
Shapes loaded?
milxQtRobustShapeModel(QWidget *theParent=0, bool contextSystem=true)
milxQtConsole * console
Console for log outputs.
Definition: milxQtWindow.h:257
void printInfo(QString msg)
Info message wrapper for console.
QAction * actionAffine
affine Procrustes action
void generalisability()
Plot the generalisability of the SSM.
void working(int value)
Send signal that computation is in progress. Value carries the progress,.
QMenu * windowPropertiesMenu
Context Menu.
QAction * actionParameters
training shape parameters plot action
QAction * loadViewAct
Load camera view.
bool m_shapesModelled
Shapes were generated?
QAction * loadViewFileAct
Load camera view to file.