SMILX  1.01
milxQtShapeModel.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 "milxQtShapeModel.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 milxQtShapeModel::milxQtShapeModel(QWidget *theParent, bool contextSystem) : milxQtRenderWindow(theParent, contextSystem)
42 {
43  reset();
44 
45  m_StandardSSM = ShapeModelType::New();
47 
48  m_meanModel = NULL;
49  m_modesVectorModel = NULL;
50  m_modesTensorModel = NULL;
51  m_correspondences = NULL;
52 
54  milxQtWindow::prefix = "SSM: ";
55 
56  createActions();
57  setupTooltips();
59 }
60 
62 {
63 
64 }
65 
66 void milxQtShapeModel::LoadModel(const QString filename)
67 {
68  reset();
69 
70  if(m_SSM->LoadModel(filename.toStdString().c_str()))
71  m_loaded = true;
72  else
73  {
74  printError("Could not open Robust SSM file.");
75  return;
76  }
77 
78  generateSSM();
79 }
80 
81 void milxQtShapeModel::SetInputCollection(vtkPolyDataCollection* meshes)
82 {
83  size_t n = meshes->GetNumberOfItems();
84 
85  working(-1);
86  reset();
87 
88  meshes->InitTraversal();
89  for(size_t j = 0; j < n; j ++)
90  {
91  m_SSM->AddShape(meshes->GetNextItem());
92 
93  qApp->processEvents();
94  }
95  done(-1);
96 
97  m_loaded = true;
98 }
99 
100 void milxQtShapeModel::SetInputCollection(vtkPolyDataCollection* meshes, QStringList &filenames)
101 {
102  const int n = meshes->GetNumberOfItems();
103 
104  working(-1);
105  reset();
106 
109  int index = 0;
110  QDialog *casePossibilities = new QDialog(this);
111  QComboBox *integerValues = new QComboBox(this);
112  QPushButton *okButton = new QPushButton(this);
113  okButton->setText("Ok");
114  QLabel *lblMessage = new QLabel(this);
115  lblMessage->setText("Choose Case ID from possibilities.");
116  QFormLayout *formLayout = new QFormLayout(this);
117  formLayout->addRow(lblMessage);
118  formLayout->addRow(tr("&Select Case ID from first file: "), integerValues);
119  formLayout->addRow(okButton);
120  casePossibilities->setLayout(formLayout);
121 
122  connect(okButton, SIGNAL(clicked(bool)), casePossibilities, SLOT(accept()));
123 
124  meshes->InitTraversal();
125  for(int j = 0; j < n; j ++)
126  {
127  QFileInfo fi(filenames[j]);
128  QRegExp rx("(\\d+)", Qt::CaseSensitive, QRegExp::RegExp2);
129 
131  int pos = 0;
132  QStringList list;
133  while ((pos = rx.indexIn(fi.baseName(), pos)) != -1)
134  {
135  list << rx.cap(1);
136  pos += rx.matchedLength(); //Move
137  }
138 
140  if(list.size() > 1 && j == 0)
141  {
142  printInfo("Please choose Case ID from possibilities for first file.");
143  for(int k = 0; k < list.size(); k ++)
144  integerValues->addItem(list[k]);
145 
146  casePossibilities->exec();
147 
148  index = integerValues->currentIndex();
149  }
150 
151  int caseID = 0;
152  if(!list.isEmpty())
153  caseID = list[index].toInt();
154 
155  m_caseIDs.append(caseID);
156 
157  m_SSM->AddShape(meshes->GetNextItem());
158 
159  qApp->processEvents();
160  }
161  done(-1);
162 
163  qDebug() << "Case IDs: " << m_caseIDs << endl;
164 
165  m_loaded = true;
166 }
167 
168 QPointer<milxQtModel> milxQtShapeModel::getMeanModel()
169 {
170  if(!m_loaded)
171  return NULL;
172  if(!m_modelled)
173  generateSSM();
174  if(!m_meaned)
175  {
177  RemoveActor(m_meanModel->GetActor());
178  }
179 
180  return m_meanModel;
181 }
182 
184 {
186  return m_modesVectorModel->GetOutput();
187  else if(m_modesTensorModel)
188  return m_modesTensorModel->GetOutput();
189  else if(m_correspondences)
190  return m_correspondences->GetOutput();
191  else
192  return m_meanModel->GetOutput();
193 }
194 
196 {
197  if(!menu)
198  return;
199 
200  menu->clear();
201 
202  menu->addSeparator()->setText(tr("View"));
203  menu->addAction(actionMean);
204  menu->addAction(actionAligned);
205  menu->addAction(actionOriginal);
206  menu->addAction(actionModesAsVectors);
207  menu->addAction(actionModesAsTensors);
208  menu->addAction(actionModesAsCollection);
209  menu->addAction(actionCorrespond);
210  plotMenu = menu->addMenu("Plot");
211  plotMenu->addAction(actionCompact);
212  plotMenu->addAction(actionSpecificity);
213  plotMenu->addAction(actionGeneralise);
214  plotMenu->addAction(actionValues);
215  plotMenu->addAction(actionModes);
216  plotMenu->addAction(actionParameters);
217  menu->addSeparator()->setText(tr("Validation/Output"));
218  menu->addAction(actionOriginalMeshes);
219  menu->addAction(actionAlignedMeshes);
220  menu->addAction(actionAlignment);
221  menu->addAction(actionPointIDs);
222  menu->addAction(actionCoordinates);
223  menu->addSeparator();
224  menu->addAction(actionReplaceOriginal);
225  //Align
226  alignMenu = menu->addMenu("Procrustes Mode");
227  alignMenu->addAction(actionSimilarity);
228  alignMenu->addAction(actionRigid);
229  alignMenu->addAction(actionAffine);
231  menu->addMenu(milxQtRenderWindow::viewMenu);
240  menu->addMenu(milxQtRenderWindow::colourMapMenu);
241  menu->addSeparator();
243  menu->addAction(milxQtRenderWindow::refreshAct);
244  menu->addAction(milxQtRenderWindow::resetAct);
245 }
246 
248 {
249  if(!m_loaded)
250  return;
251  printDebug("Generating SSM");
252 
253  bool ok;
254  float precision = QInputDialog::getDouble(this, tr("Please Provide the precision of the model"),
255  tr("Precision:"), 0.9, 0.0, 1.0, 5, &ok);
256 
257  QMessageBox msgBox;
258  msgBox.setText("The mean surface/shape will be used in the model");
259  msgBox.setInformativeText("Do you want to use the first surface instead of the mean?");
260  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
261  msgBox.setDefaultButton(QMessageBox::No);
262  int ret = msgBox.exec();
263 
264  if(ret == QMessageBox::Yes)
265  {
266  m_StandardSSM->TimepointModeOn();
267  }
268 
269  if(!ok) //cancelled
270  return;
271 
273  try
274  {
275  m_StandardSSM->SetPrecision(precision);
276  m_StandardSSM->Update();
277  }
278  catch( itk::ExceptionObject & err )
279  {
280  printError("Exception caught while generating an SSM!");
281  cout << err << endl;
282  return;
283  }
284 
285  const size_t n = m_StandardSSM->GetNumberOfShapes();
286 
288  double eigenSum = 0.0;
289  vtkSmartPointer<vtkFloatArray> eigenVals = m_StandardSSM->GetPCA()->GetEvals();
290  printInfo("Eigenvalues Info - #tuples: " + QString::number(eigenVals->GetNumberOfTuples()) + ", #components: " + QString::number(eigenVals->GetNumberOfComponents()));
291  for(vtkIdType j = 0; j < eigenVals->GetNumberOfTuples(); j ++)
292  eigenSum += eigenVals->GetValue(j);
293  printInfo("Sum of Eigenvalues is " + QString::number(eigenSum));
294  printInfo("Mean Scale: " + QString::number(m_StandardSSM->GetMeanShapeSize()));
295  printInfo("Number of Modes: " + QString::number(m_StandardSSM->GetNumberOfModes()));
296 
297  vtkSmartPointer<vtkLookupTable> tmpLookupTable = vtkLookupTable::SafeDownCast(milxQtRenderWindow::lookupTable);
298  tmpLookupTable->SetTableRange(0.0, n+1);
299  tmpLookupTable->Build();
300  milxQtRenderWindow::lookupTable = tmpLookupTable;
301 
303 
304  m_modelled = true;
305 }
306 
307 void milxQtShapeModel::generateMeanModel(vtkSmartPointer<vtkPolyData> shape)
308 {
309  if(!m_loaded)
310  return;
311  if(!m_modelled)
312  generateSSM();
313 
314  printInfo("Generating Mean Model.");
315  if(!m_meanModel)
316  {
317  m_meanModel = new milxQtModel;
318  m_meanModel->SetInput(m_SSM->GetMeanShape());
319  }
320  if(!shape)
321  {
322  m_meanModel->setName("Mean");
323  m_meanModel->SetPoints(m_SSM->GetMeanShape()->GetPoints());
324  }
325  else
326  {
327  m_meanModel->setName("Custom Shape");
328  printDebug("Adding Custom Model.");
329  m_meanModel->SetInput(shape);
330  }
331  m_meanModel->generateModel();
332 
333  AddActor(m_meanModel->GetActor());
334 
335  m_meaned = true;
336  actionMean->setChecked(true);
337 }
338 
339 void milxQtShapeModel::generateModels(const bool display)
340 {
341  if(!m_loaded)
342  return;
343  if(!m_modelled)
344  generateSSM();
345 
346  const int n = m_SSM->GetNumberOfShapes();
347 
348  working(-1);
349  printInfo("Generating Original Models.");
350  for(int j = 0; j < n; j ++)
351  {
352  double colour[3];
353 
354  milxQtRenderWindow::lookupTable->GetColor(j, colour);
355 
357  QPointer<milxQtModel> shape = new milxQtModel;
358  shape->setName( QString::number(j) );
359  shape->setLargeDataSetMode(true);
360  shape->SetInput(m_SSM->GetShape(j));
361  shape->generatePoints(colour[0], colour[1], colour[2]);
362  shape->SetOpacity(0.1);
363 
364  m_models.append(shape);
365 
366  if(display)
367  AddActor(m_models.last()->GetActor());
368 
369  qApp->processEvents();
371  }
372  printInfo("Done. Displaying Original Models.");
373 
374  if(display)
375  {
377  actionOriginal->setChecked(true);
378  }
379  m_shapesModelled = true;
380  done(-1);
381 }
382 
384 {
385  if(!m_loaded)
386  return;
387  if(!m_modelled)
388  generateSSM();
389 
390  emit working(-1);
391  const int n = m_SSM->GetNumberOfShapes();
392 
393  printInfo("Generating Aligned Models.");
394  for(int j = 0; j < n; j ++)
395  {
396  double colour[3];
397 
398  milxQtRenderWindow::lookupTable->GetColor(j, colour);
399 
401  QPointer<milxQtModel> shape = new milxQtModel;
402  shape->setName( QString::number(j) );
403  shape->setLargeDataSetMode(true);
404  //printDebug("Get Aligned Shape " + QString::number(j));
405  shape->SetInput(m_SSM->GetProcrustesAlignedSurface(j)); //Crashes sometimes?
406 // shape->SetInput(m_SSM->GetMeanShape());
407 // shape->SetPoints(m_SSM->GetAlignedPoints(j));
408  shape->generatePoints(colour[0], colour[1], colour[2]);
409  shape->SetOpacity(0.1);
410  shape->Update();
411 
412  //printDebug("Add to Aligned Models Set");
413  m_alignedModels.append(shape);
414 
415  if(display)
416  AddActor(m_alignedModels.last()->GetActor());
417 
418  qApp->processEvents();
420  }
421  printInfo("Done. Displaying Aligned Models.");
422 
423  if(display)
424  {
426  actionAligned->setChecked(true);
427  }
429  done(-1);
430 }
431 
433 {
434  bool flgNormal = true;
435 
436  if(!m_loaded)
437  return;
438  if(!m_modelled)
439  generateSSM();
440  if(!m_meaned)
442 
443  bool ok1, ok2;
444  int mode = QInputDialog::getInt(this, tr("Please Provide the mode to view (1 to n)"),
445  tr("Mode:"), 1, 1, m_StandardSSM->GetNumberOfModes(), 1, &ok1);
446  float modeWeight = QInputDialog::getDouble(this, tr("Please Provide the weight of the mode"),
447  tr("Weight:"), 3.0, -50.0, 50.0, 2, &ok2);
448 
449  m_mode = mode;
450  m_vector = false;
451  m_tensor = false;
452  m_modes = false;
453 
454  if(!ok1 || !ok2) //cancelled
455  return;
456 
457  QMessageBox msgBox;
458  msgBox.setText("A parameterised surface will be generated");
459  msgBox.setInformativeText("Do you want to display this instead of the mean surface?");
460  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
461  msgBox.setDefaultButton(QMessageBox::No);
462  int ret = msgBox.exec();
463 
468  working(-1);
469  vtkSmartPointer<vtkPolyData> meanShape = m_meanModel->GetOutput();
470  //Ensure mean is actually mean
471  meanShape->SetPoints(m_StandardSSM->GetMeanShape()->GetPoints());
472 
473  vtkSmartPointer<vtkPolyDataNormals> normals = vtkPolyDataNormals::New();
474  normals->SetInput(meanShape);
475  normals->ComputeCellNormalsOff();
476  normals->ComputePointNormalsOn();
477  normals->SplittingOff();
478  // normals->AutoOrientNormalsOn();
479  // normals->ConsistencyOn();
480  // normals->FlipNormalsOn();
481  normals->Update();
482 
483  vtkSmartPointer<vtkFloatArray> normArray =
484  vtkFloatArray::SafeDownCast(normals->GetOutput()->GetPointData()->GetNormals());
485 
486  vtkSmartPointer<vtkFloatArray> b = vtkFloatArray::New();
487  b->SetNumberOfValues(mode);
488  b->FillComponent(0, 0.0);
489  b->SetValue(mode-1, modeWeight);
490  printInfo("Generating display for mode " + QString::number(mode-1));
491 
492  vtkSmartPointer<vtkPolyData> varShape = vtkSmartPointer<vtkPolyData>::New();
493  varShape->DeepCopy(m_StandardSSM->GetParameterisedShape(b));
494 
495  vtkSmartPointer<vtkFloatArray> varScalars = vtkSmartPointer<vtkFloatArray>::New();
496  varScalars->SetName("Variation");
497  vtkSmartPointer<vtkFloatArray> varVectors = vtkSmartPointer<vtkFloatArray>::New();
498  varVectors->SetNumberOfComponents(3);
499  vtkSmartPointer<vtkFloatArray> varShapeVectors = vtkSmartPointer<vtkFloatArray>::New();
500  varShapeVectors->SetNumberOfComponents(3);
501  vtkSmartPointer<vtkFloatArray> varTensors = vtkSmartPointer<vtkFloatArray>::New();
502  varTensors->SetNumberOfComponents(9);
503 
504  printInfo("Computing Variation");
505  for(int i = 0; i < meanShape->GetNumberOfPoints(); i++)
506  {
507  vtkFloatingPointType* meanPoint = meanShape->GetPoint(i);
508  vtkFloatingPointType* varPoint = varShape->GetPoint(i);
509 
510  vtkFloatingPointType xVal = varPoint[0] - meanPoint[0];
511  vtkFloatingPointType yVal = varPoint[1] - meanPoint[1];
512  vtkFloatingPointType zVal = varPoint[2] - meanPoint[2];
513 
514  float normalPoint[3];
515  normArray->GetTupleValue(i, normalPoint);
516  vtkFloatingPointType var;
517  if(flgNormal)
518  {
519  var = xVal*normalPoint[0] + yVal*normalPoint[1] + zVal*normalPoint[2];
520  var = var*var;
521  }
522  else
523  {
524  var = xVal*xVal + yVal*yVal + zVal*zVal;
525  }
526  // std::cout << var << std::endl;
527  varVectors->InsertNextTuple3(xVal, yVal, zVal);
528  varShapeVectors->InsertNextTuple3(-xVal, -yVal, -zVal);
529  varScalars->InsertNextValue(var);
530 
531  vnl_scatter_3x3<vtkFloatingPointType> C;
532  for(int j = 0; j < m_StandardSSM->GetNumberOfShapes(); j++)
533  {
534  vtkFloatingPointType point[3];
535  m_StandardSSM->GetPCA()->GetInput(j)->GetPoint(i, point);
536  // std::cout << point[0] << " " << point[1] << " " << point[2] << std::endl;
537  vnl_double_3 point_vector;
538  point_vector[0] = point[0] - meanPoint[0];
539  point_vector[1] = point[1] - meanPoint[1];
540  point_vector[2] = point[2] - meanPoint[2];
541  // std::cout << point_vector << std::endl;
542  C.add_outer_product(point_vector);
543  }
544  // C /= m_StandardSSM->GetNumberOfShapes();
545  // std::cout << meanPoint[0] << " " << meanPoint[1] << " " << meanPoint[2] << std::endl << std::endl;
546  // std::cout << C << std::endl;
547  vtkSmartPointer<vtkTensor> tens = vtkSmartPointer<vtkTensor>::New();
548  tens->SetComponent(0,0, C(0,0));
549  tens->SetComponent(0,1, C(0,1));
550  tens->SetComponent(0,2, C(0,2));
551  tens->SetComponent(1,0, C(1,0));
552  tens->SetComponent(1,1, C(1,1));
553  tens->SetComponent(1,2, C(1,2));
554  tens->SetComponent(2,0, C(2,0));
555  tens->SetComponent(2,1, C(2,1));
556  tens->SetComponent(2,2, C(2,2));
557 
558  varTensors->InsertNextTuple(tens->T);
559  // std::cout << tens->T[0] << " " << tens->T[1] << " " << tens->T[2] << std::endl;
560 
561  qApp->processEvents();
562  }
563 
564  vtkFloatingPointType maxScalar = std::numeric_limits<vtkFloatingPointType>::min();
565  for(int i = 0; i < varScalars->GetNumberOfTuples(); i++)
566  {
567  if(varScalars->GetValue(i) > maxScalar)
568  maxScalar = varScalars->GetValue(i);
569  }
570  printInfo("Max sigma: " + QString::number(sqrt(maxScalar)) + "mm.");
571  for(int i = 0; i < varScalars->GetNumberOfTuples(); i++)
572  {
573  vtkFloatingPointType var = varScalars->GetValue(i);
574  varScalars->SetValue(i, var/maxScalar);
575  }
576 
577  meanShape->GetPointData()->SetVectors(varVectors);
578  varShape->GetPointData()->SetVectors(varShapeVectors);
579  meanShape->GetPointData()->SetScalars(varScalars);
580  //scalars dont make sense for varShape
581  meanShape->GetPointData()->SetTensors(varTensors);
582  varShape->GetPointData()->SetTensors(varTensors);
583 
584  if(ret == QMessageBox::Yes)
585  generateMeanModel(varShape);
586  else
588  done(-1);
589 
590  m_modes = true;
591 }
592 
594 {
595  if(!m_loaded)
596  return;
597  if(!m_modelled)
598  generateSSM();
599  if(!m_meaned)
601 
602  const int n = m_SSM->GetNumberOfShapes();
603  bool ok1, ok2, ok3;
604  int mode = QInputDialog::getInt(this, tr("Please Provide the mode to view (1 to n)"),
605  tr("Mode:"), 1, 1, n, 1, &ok1);
606  float modeWeight = QInputDialog::getDouble(this, tr("Please Provide the range weight c of the mode (so that -c < x < c)"),
607  tr("Weight:"), 3.0, -5.0, 5.0, 2, &ok2);
608  int numberOfSurfaces = QInputDialog::getInt(this, tr("Please Provide the number of surfaces to generate"),
609  tr("Number:"), 16, 1, 1e9, 1, &ok3);
610 
611  m_mode = mode;
612 
613  if(!ok1 || !ok2 || !ok3) //cancelled
614  return;
615 
616  //Init counters etc.
617  float weightValue = -modeWeight;
618  const float weightStep = 2.0*modeWeight/(numberOfSurfaces-1);
619 
620  vtkPolyDataCollection* meshes = vtkPolyDataCollection::New();
621  QStringList surfaceNames;
622  for(int j = 0; j < numberOfSurfaces; j ++)
623  {
624  vtkSmartPointer<vtkFloatArray> b = vtkFloatArray::New();
625  b->SetNumberOfValues(mode);
626  b->FillComponent(0, 0.0);
627  b->SetValue(mode-1, weightValue);
628  printInfo("Generating surface for mode " + QString::number(mode-1));
629 
630  vtkPolyData *shape = vtkPolyData::New();
631  shape->DeepCopy(m_SSM->GetParameterisedShape(b));
632 
633  meshes->AddItem(shape);
634  surfaceNames.append(QString::number(weightStep));
635 
636  weightValue += weightStep;
637  }
638 
639  printInfo("Mode Surfaces Generated");
640  emit collectionAvailable(meshes, surfaceNames);
641 }
642 
644 {
645  if(!m_loaded)
646  return;
647  if(!m_modes)
648  generateModes();
649  if(!m_modes) //Failed or cancelled, stop
650  return;
651  if(!m_meaned)
653 
654  printInfo("Generating Vector Field.");
655  vtkSmartPointer<vtkPolyData> meanShape = m_meanModel->GetOutput();
656 
657  if(!m_modesVectorModel)
658  m_modesVectorModel = new milxQtModel; //smart deletion
659  m_modesVectorModel->setName("Modes As Vectors");
660  m_modesVectorModel->setLargeDataSetMode(true); //May Improve performance for large dataset
661  m_modesVectorModel->SetInput(meanShape);
662  m_modesVectorModel->generateVectorField(1.0);
663  m_modesVectorModel->ImmediateModeRenderingOn(); //May Improve performance for large dataset
664 
665  AddActor(m_modesVectorModel->GetActor());
666  m_vector = true;
667  actionModesAsVectors->setChecked(true);
668 }
669 
671 {
672  if(!m_loaded)
673  return;
674  if(!m_modes)
675  generateModes();
676  if(!m_modes) //Failed or cancelled, stop
677  return;
678  if(!m_meaned)
680 
681  printInfo("Generating Tensor Field.");
682  if(!m_modesTensorModel)
683  m_modesTensorModel = new milxQtModel; //smart deletion
684  m_modesTensorModel->setName("Modes As Tensors");
685  m_modesTensorModel->setLargeDataSetMode(true); //May Improve performance for large dataset
686  m_modesTensorModel->SetInput(m_meanModel->GetOutput());
687  m_modesTensorModel->generateTensorField(1.0);
688  m_modesTensorModel->ImmediateModeRenderingOn(); //May Improve performance for large dataset
689 
690  AddActor(m_modesTensorModel->GetActor());
691  m_tensor = true;
692  actionModesAsTensors->setChecked(true);
693 }
694 
696 {
697  if(!m_loaded)
698  return;
699 
700  const int n = m_SSM->GetNumberOfShapes();
701  const int noOfPoints = m_SSM->GetShape(0)->GetNumberOfPoints();
702 
703  printInfo("Generating Correspondences.");
704  working(-1);
705  vtkSmartPointer<vtkDoubleArray> maxDeviations = vtkSmartPointer<vtkDoubleArray>::New();
706  maxDeviations->SetNumberOfComponents(3);
707  maxDeviations->SetNumberOfTuples(noOfPoints);
708  maxDeviations->SetName("Deviations");
709 
711  coordinate origin(0.0);
712  for(int l = 0; l < noOfPoints; l ++)
713  maxDeviations->SetTupleValue(l, origin.data_block());
714 
715  for(int j = 0; j < n; j ++)
716  {
717  vtkSmartPointer<vtkPolyData> currentShape = m_SSM->GetProcrustesAlignedSurface(j);
718 
719  for(int k = 0; k < n; k ++)
720  {
721  if(j == k)
722  continue;
723 
724  vtkSmartPointer<vtkPolyData> nextShape = m_SSM->GetProcrustesAlignedSurface(k);
725 
726  for(int l = 0; l < noOfPoints; l ++)
727  {
728  coordinate currentPoint(currentShape->GetPoint(l));
729  coordinate nextPoint(nextShape->GetPoint(l));
730  coordinate maxVector(maxDeviations->GetTuple(l));
731  coordinate deviation = currentPoint - nextPoint;
732 
733  double length = deviation.squared_magnitude();
734  double currentMaxLength = maxVector.squared_magnitude();
735 
736  if(length > currentMaxLength)
737  {
738  //deviation += currentPoint;
739  maxDeviations->SetTupleValue(l, deviation.data_block());
740  }
741  }
742 
743  qApp->processEvents();
744  }
745  }
746 
747  printInfo("Showing Hedgehog plot.");
748  if(!m_correspondences)
749  m_correspondences = new milxQtModel; //smart deletion
750  m_correspondences->SetInput(m_SSM->GetMeanShape());
751  m_correspondences->SetVectors(maxDeviations);
752  m_correspondences->generateHedgehog();
753 
754  AddActor(m_correspondences->GetActor());
755  m_correspond = true;
756  actionCorrespond->setChecked(true);
757  done(-1);
758 }
759 
760 //Slots
762 {
763  if(!m_loaded && !m_modelled)
764  return;
765 
766  if(actionMean->isChecked())
767  {
768  if(!m_meaned)
770 
771  AddActor(m_meanModel->GetActor());
772  }
773  else
774  {
775  if(m_meaned)
776  RemoveActor(m_meanModel->GetActor());
777  }
778 
780 }
781 
783 {
784  if(!m_loaded && !m_modelled)
785  return;
786 
787  int n = m_SSM->GetNumberOfShapes();
788 
789  if(actionAligned->isChecked())
790  {
793  else
794  for(int j = 0; j < n; j ++)
795  AddActor(m_alignedModels[j]->GetActor());
796  }
797  else
798  {
800  {
801  for(int j = 0; j < n; j ++)
802  RemoveActor(m_alignedModels[j]->GetActor());
803  }
804  }
805 
807 }
808 
810 {
811  if(!m_loaded && !m_modelled)
812  return;
813 
814  const int n = m_SSM->GetNumberOfShapes();
815 
816  if(actionOriginal->isChecked())
817  {
818  if(!m_shapesModelled)
819  generateModels();
820  else
821  for(int j = 0; j < n; j ++)
822  AddActor(m_models[j]->GetActor());
823  }
824  else
825  {
826  if(m_shapesModelled)
827  {
828  for(int j = 0; j < n; j ++)
829  RemoveActor(m_models[j]->GetActor());
830  }
831  }
832 
834 }
835 
837 {
838  if(!m_loaded && !m_modelled)
839  return;
840 
841  if(actionModesAsVectors->isChecked())
842  {
843  m_modes = false; //Force re-computation of modes
845 
846  if(m_vector)
847  AddActor(m_modesVectorModel->GetActor());
848  }
849  else
850  {
851  if(m_modes && m_vector)
852  RemoveActor(m_modesVectorModel->GetActor());
853  }
854 
856 }
857 
859 {
860  if(!m_loaded && !m_modelled)
861  return;
862 
863  if(actionModesAsTensors->isChecked())
864  {
865  m_modes = false; //Force re-computation of modes
867 
868  if(m_tensor)
869  AddActor(m_modesTensorModel->GetActor());
870  }
871  else
872  {
873  if(m_modes && m_tensor)
874  RemoveActor(m_modesTensorModel->GetActor());
875  }
876 
878 }
879 
881 {
882  if(!m_loaded && !m_modelled)
883  return;
884 
886 }
887 
889 {
890  if(!m_loaded)
891  return;
892 
893  if(actionCorrespond->isChecked())
894  {
895  if(!m_correspond)
897 
898  AddActor(m_correspondences->GetActor());
899  }
900  else
901  {
902  if(m_correspond)
903  RemoveActor(m_correspondences->GetActor());
904  }
905 
907 }
908 
910 {
911  if(!m_modelled)
912  generateSSM();
913  printDebug("Generating Plot");
914 
915  vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
916  vtkSmartPointer<vtkFloatArray> values = m_StandardSSM->GetPCA()->GetEvals();
917 
919  for(int j = 0; j < 3; j ++)
920  {
921  vtkSmartPointer<vtkDoubleArray> column = vtkSmartPointer<vtkDoubleArray>::New();
922  for(int k = 0; k < values->GetNumberOfTuples(); k ++)
923  column->InsertNextValue(0.0);
924  table->AddColumn(column);
925  }
926  printDebug("Compactness Table is " + QString::number(table->GetNumberOfRows()) + "x" + QString::number(table->GetNumberOfColumns()));
927 
929  table->GetColumn(0)->SetName("Mode");
930  table->GetColumn(1)->SetName("Value");
931  table->GetColumn(2)->SetName("Precision");
932 
934  double total = 0.0;
935  for (int j = 0; j < values->GetNumberOfTuples(); j++)
936  total += values->GetValue(j);
937  printInfo("Total of eigenvalues is " + QString::number(total));
938 
940  double compactness = 0.0;
941  for (int j = 0; j < values->GetNumberOfTuples(); j++)
942  {
943  compactness += values->GetValue(j)/total;
944 
945  table->SetValue(j, 0, j+1);
946  table->SetValue(j, 1, values->GetValue(j));
947  table->SetValue(j, 2, compactness);
948 
949  qApp->processEvents();
950  }
951  table->Update();
952  table->Dump();
953 
954  QPointer<milxQtPlot> plot = new milxQtPlot;
955  plot->setPlotType2D(0, 2);
956  plot->setName("Compactness of the Shape Model");
957  plot->setConsole(console);
958  plot->legend(false);
959  plot->SetSource(table);
960  plot->generatePlot(); //emits result, not connected
961 // plot->scatterPlot(table, 0, 2);
962 
963  emit resultAvailable( qobject_cast<milxQtRenderWindow*>(plot) );
964 }
965 
967 {
968  if(!m_modelled)
969  generateSSM();
970  printDebug("Generating Plot");
971 
972  srand(time(NULL));
973 
974  bool ok;
975  int n = QInputDialog::getInt(this, tr("Please Provide the number of random shapes to use"),
976  tr("Number of Random Shapes:"), 30, 2, 1000000, 1, &ok);
977 
978  if(!ok)
979  return;
980 
981  vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
982 
984  for(int j = 0; j < 3; j ++)
985  {
986  vtkSmartPointer<vtkDoubleArray> column = vtkSmartPointer<vtkDoubleArray>::New();
987  for(int k = 0; k < n; k ++)
988  column->InsertNextValue(0.0);
989  table->AddColumn(column);
990  }
991  printDebug("Specificity Table is " + QString::number(table->GetNumberOfRows()) + "x" + QString::number(table->GetNumberOfColumns()));
992 
994  table->GetColumn(0)->SetName("Shape");
995  table->GetColumn(1)->SetName("Minimum RMSE");
996  table->GetColumn(2)->SetName("Specificity");
997 
998  working(-1);
999  double specific = 0;
1000  for(int i = 0; i < n; i++)
1001  {
1002  vtkSmartPointer<vtkFloatArray> b = vtkSmartPointer<vtkFloatArray>::New();
1003  b->SetNumberOfComponents(1);
1004  b->SetNumberOfTuples(m_SSM->GetNumberOfModes());
1005  for(int j = 0; j < m_SSM->GetNumberOfModes(); j++)
1006  b->SetTuple1(j, rand()%35/10 - 1.75);
1007 
1008  vtkSmartPointer<vtkPolyData> shape = m_SSM->GetParameterisedShape(b);
1009  double minSumSquares = std::numeric_limits<double>::max();
1010  for(int k = 0; k < m_SSM->GetNumberOfShapes(); k ++)
1011  {
1012  double value = m_SSM->PolyDataDistance(shape, m_SSM->GetShape(k))/m_SSM->GetShape(0)->GetNumberOfPoints();
1013  if(value < minSumSquares)
1014  minSumSquares = value;
1015  }
1016  specific += minSumSquares;
1017 
1018  table->SetValue(i, 0, i);
1019  table->SetValue(i, 1, minSumSquares);
1020  table->SetValue(i, 2, specific);
1021 
1022  qApp->processEvents();
1023  }
1024  specific /= n;
1025  printInfo("Specificity Score: " + QString::number(specific));
1026  table->Update();
1027  table->Dump();
1028  done(-1);
1029 
1030  QPointer<milxQtPlot> plot = new milxQtPlot;
1031  plot->setPlotType2D(0, 1);
1032  plot->setName("Specificity of the Shape Model");
1033  plot->setConsole(console);
1034  plot->legend(false);
1035  plot->SetSource(table);
1036  plot->generatePlot(); //emits result, not connected
1037 // plot->scatterPlot(table, 0, 1);
1038 
1039  emit resultAvailable( qobject_cast<milxQtRenderWindow*>(plot) );
1040 }
1041 
1043 {
1044  if(!m_modelled)
1045  generateSSM();
1046  printDebug("Generating Plot");
1047 
1048  vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
1049 
1051  for(int j = 0; j < 2; j ++)
1052  {
1053  vtkSmartPointer<vtkDoubleArray> column = vtkSmartPointer<vtkDoubleArray>::New();
1054  for(int k = 0; k < m_SSM->GetNumberOfShapes(); k ++)
1055  column->InsertNextValue(0.0);
1056  table->AddColumn(column);
1057  }
1058  printDebug("Generalisability Table is " + QString::number(table->GetNumberOfRows()) + "x" + QString::number(table->GetNumberOfColumns()));
1059 
1061  table->GetColumn(0)->SetName("Shape");
1062  table->GetColumn(1)->SetName("Reconstruction Error");
1063 
1064  working(-1);
1065  double generalisability = 0.0;
1066  for(int i = 0; i < m_SSM->GetNumberOfShapes(); i++)
1067  {
1069  vtkPolyData *shape = vtkPolyData::New(); //can't use smart ptrs here
1070  shape->DeepCopy(m_SSM->GetShape(0));
1071  m_SSM->RemoveShape(0);
1072  m_SSM->Update();
1073 
1074  vtkSmartPointer<vtkFloatArray> b = vtkSmartPointer<vtkFloatArray>::New();
1075  b->SetNumberOfComponents(1);
1076  b->SetNumberOfTuples(m_SSM->GetNumberOfModes());
1077  b->FillComponent(0, 0.0);
1078 
1079  double tx, ty, tz, scale, theta, phi, psi;
1080  m_SSM->GetSurfaceSimilarityParameters(shape, scale, tx, ty, tz, theta, phi, psi, b);
1081  vtkSmartPointer<vtkPolyData> shape2 = m_SSM->GetSurface(scale, tx, ty, tz, theta, phi, psi, b);
1082  double epsiSqr = m_SSM->PolyDataDistance(shape, shape2)/shape->GetNumberOfPoints();
1083 
1084  table->SetValue(i, 0, i);
1085  table->SetValue(i, 1, epsiSqr);
1086 
1087  generalisability += epsiSqr;
1088  m_SSM->AddShape(shape);
1089 
1090  qApp->processEvents();
1091  }
1092  printInfo("Generalisability Score: " + QString::number(generalisability));
1093  table->Update();
1094  table->Dump();
1095  done(-1);
1096 
1097  QPointer<milxQtPlot> plot = new milxQtPlot;
1098  plot->setPlotType2D(0, 1);
1099  plot->setName("Generalisability of the Shape Model");
1100  plot->setConsole(console);
1101  plot->legend(false);
1102  plot->SetSource(table);
1103  plot->generatePlot(); //emits result, not connected
1104 // plot->scatterPlot(table, 0, 1);
1105 
1106  emit resultAvailable( qobject_cast<milxQtRenderWindow*>(plot) );
1107 }
1108 
1110 {
1111  if(!m_modelled)
1112  generateSSM();
1113  printDebug("Generating Plot");
1114 
1115  vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
1116  vtkSmartPointer<vtkFloatArray> values = m_StandardSSM->GetPCA()->GetEvals();
1117 
1119  for(int j = 0; j < 3; j ++)
1120  {
1121  vtkSmartPointer<vtkDoubleArray> column = vtkSmartPointer<vtkDoubleArray>::New();
1122  for(int k = 0; k < values->GetNumberOfTuples(); k ++)
1123  column->InsertNextValue(0.0);
1124  table->AddColumn(column);
1125  }
1126  printDebug("Compactness Table is " + QString::number(table->GetNumberOfRows()) + "x" + QString::number(table->GetNumberOfColumns()));
1127 
1129  table->GetColumn(0)->SetName("Mode");
1130  table->GetColumn(1)->SetName("Value");
1131  table->GetColumn(2)->SetName("Precision");
1132 
1134  double total = 0.0;
1135  for (int j = 0; j < values->GetNumberOfTuples(); j++)
1136  total += values->GetValue(j);
1137  printInfo("Total of eigenvalues is " + QString::number(total));
1138 
1140  double compactness = 0.0;
1141  for (int j = 0; j < values->GetNumberOfTuples(); j++)
1142  {
1143  compactness += values->GetValue(j)/total;
1144 
1145  table->SetValue(j, 0, j+1);
1146  table->SetValue(j, 1, values->GetValue(j));
1147  table->SetValue(j, 2, compactness);
1148 
1149  qApp->processEvents();
1150  }
1151  table->Update();
1152  table->Dump();
1153 
1154  QPointer<milxQtPlot> plot = new milxQtPlot;
1155  plot->setPlotType2D(0, 1);
1156  plot->setName("Eigenvalues of the Shape Model");
1157  plot->setConsole(console);
1158  plot->legend(false);
1159  plot->SetSource(table);
1160  plot->generatePlot(); //emits result, not connected
1161 // plot->scatterPlot(table, 0, 2);
1162 
1163  emit resultAvailable( qobject_cast<milxQtRenderWindow*>(plot) );
1164 }
1165 
1167 {
1168  if(!m_modelled)
1169  generateSSM();
1170  printDebug("Generating Plot");
1171 
1172  vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
1173 
1175  for(int j = 0; j < m_SSM->GetNumberOfModes(); j ++)
1176  {
1177  vtkSmartPointer<vtkDoubleArray> column = vtkSmartPointer<vtkDoubleArray>::New();
1178  for(int k = 0; k < m_SSM->GetNumberOfShapes(); k ++)
1179  column->InsertNextValue(0.0);
1180  const QString nameOfColumn = "Mode " + QString::number(j+1);
1181  column->SetName(nameOfColumn.toStdString().c_str());
1182  table->AddColumn(column);
1183  }
1184  printDebug("Modes Table is " + QString::number(table->GetNumberOfRows()) + "x" + QString::number(table->GetNumberOfColumns()));
1185 
1186  for(int j = 0; j < m_SSM->GetNumberOfShapes(); j ++)
1187  {
1188  double scale, tx, ty, tz, theta, phi, psi; //Unused
1189  vtkSmartPointer<vtkFloatArray> b = vtkSmartPointer<vtkFloatArray>::New();
1190  b->SetNumberOfComponents(1);
1191  b->SetNumberOfTuples(m_SSM->GetNumberOfModes());
1192 
1193  m_SSM->GetSurfaceSimilarityParameters(m_SSM->GetShape(j), scale, tx, ty, tz, theta, phi, psi, b);
1194 
1195  for(int k = 0; k < m_SSM->GetNumberOfModes(); k ++)
1196  table->SetValue(j, k, b->GetValue(k));
1197 
1198  qApp->processEvents();
1199  }
1200 
1201  QPointer<milxQtPlot> plot = new milxQtPlot;
1202  plot->setPlotType3D(0, 1, 2);
1203  plot->setName("Specificity of the Shape Model");
1204  plot->setConsole(console);
1205  plot->legend(false);
1206  plot->SetSource(table);
1207  plot->generatePlot(); //emits result, not connected
1208 // plot->scatterPlot(table, 0, 1, 2);
1209 
1210  emit resultAvailable(plot);
1211 }
1212 
1214 {
1215  if(!m_modelled)
1216  generateSSM();
1217  printDebug("Generating Plot");
1218 
1219  vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
1220 
1222  for(int j = 0; j < m_SSM->GetNumberOfModes(); j ++)
1223  {
1224  vtkSmartPointer<vtkDoubleArray> column = vtkSmartPointer<vtkDoubleArray>::New();
1225  for(int k = 0; k < m_SSM->GetNumberOfShapes(); k ++)
1226  column->InsertNextValue(0.0);
1227  const QString nameOfColumn = "Mode " + QString::number(j+1);
1228  column->SetName(nameOfColumn.toStdString().c_str());
1229  table->AddColumn(column);
1230  }
1231  printDebug("Parameters Table is " + QString::number(table->GetNumberOfRows()) + "x" + QString::number(table->GetNumberOfColumns()));
1232 
1233  for(int j = 0; j < m_SSM->GetNumberOfShapes(); j ++)
1234  {
1235  double scale, tx, ty, tz, theta, phi, psi; //Unused
1236  vtkSmartPointer<vtkFloatArray> b = vtkSmartPointer<vtkFloatArray>::New();
1237  b->SetNumberOfComponents(1);
1238  b->SetNumberOfTuples(m_SSM->GetNumberOfModes());
1239 
1240  m_SSM->GetSurfaceSimilarityParameters(m_SSM->GetShape(j), scale, tx, ty, tz, theta, phi, psi, b);
1241 
1242  for(int k = 0; k < m_SSM->GetNumberOfModes(); k ++)
1243  table->SetValue(j, k, b->GetValue(k));
1244 
1245  qApp->processEvents();
1246  }
1247 
1248  QPointer<milxQtPlot> plot = new milxQtPlot;
1249  plot->setPlotTypeSurface();
1250  plot->setName("Training Shape Parameters of the Shape Model");
1251  plot->setConsole(console);
1252  plot->legend(false);
1253  plot->SetSource(table);
1254  plot->generatePlot(); //emits result, not connected
1255 // plot->surfacePlot(table);
1256 
1257  emit resultAvailable(plot);
1258 }
1259 
1261 {
1262  //Change the Procrustes mode of the SSM based on option set
1263  if(actionRigid->isChecked())
1264  m_SSM->SetPoseType(1); //rigid
1265  else if(actionSimilarity->isChecked())
1266  m_SSM->SetPoseType(2); //similarity
1267  else
1268  m_SSM->SetPoseType(3); //affine
1269 
1270  m_SSM->RemoveProcrustesAlignedPoints();
1271  //same as m_SSM->SetValid(false); //force recomputation
1272  m_modelled = false;
1273  m_meaned = false;
1274  m_modes = false;
1275  m_alignedShapesModelled = false;
1277  aligned();
1278  modesAsVectors();
1279  modesAsTensors();
1280 }
1281 
1283 {
1284  if(!m_loaded && !m_modelled)
1285  return;
1286 
1287  working(-1);
1288  milxQtRenderWindow::renderer->InteractiveOff();
1289 
1291  {
1292  generateAlignedModels(false);
1293 
1294  QMessageBox msgBox;
1295  msgBox.setText("Models now aligned. Set the window to desired view and try again.");
1296  msgBox.exec();
1297 
1298  milxQtRenderWindow::renderer->InteractiveOn();
1299  done(-1);
1300  return;
1301  }
1302 
1303  QSettings settings("Shekhar Chandra", "milxQt");
1304  QString path = settings.value("recentPath").toString(), filenamePrefix;
1305 
1306  QFileDialog *fileSaver = new QFileDialog(this);
1307 
1308  filenamePrefix = fileSaver->getSaveFileName(this,
1309  tr("Select File Name Prefix to Save"),
1310  path,
1311  tr("All Files (*.*)"));
1312 
1313  if(filenamePrefix.isEmpty())
1314  {
1315  done(-1);
1316  return;
1317  }
1318 
1319  QFileInfo fi(filenamePrefix);
1320  QString filename = fi.path()+ "/" + fi.baseName();
1321 
1322  const int n = m_SSM->GetNumberOfShapes();
1323 
1324  for(int j = 0; j < n; j ++)
1325  {
1326  m_alignedModels[j]->SetOpacity(1.0);
1327  m_alignedModels[j]->generateSurface();
1328 
1329  qApp->processEvents();
1330  }
1331 
1332  outputSnapshots(filename);
1333 
1334  milxQtRenderWindow::renderer->InteractiveOn();
1335  done(-1);
1336 }
1337 
1339 {
1340  if(!m_loaded && !m_modelled)
1341  return;
1342 
1343  working(-1);
1344 
1346  generateAlignedModels(false);
1347 
1348  QSettings settings("Shekhar Chandra", "milxQt");
1349  QString path = settings.value("recentPath").toString(), filenamePrefix;
1350 
1351  QFileDialog *fileSaver = new QFileDialog(this);
1352 
1353  filenamePrefix = fileSaver->getSaveFileName(this,
1354  tr("Select File Name Prefix to Save"),
1355  path,
1356  tr("All Files (*.*)"));
1357 
1358  if(filenamePrefix.isEmpty())
1359  {
1360  done(-1);
1361  return;
1362  }
1363 
1364  QFileInfo fi(filenamePrefix);
1365  QString filename = fi.path()+ "/" + fi.baseName();
1366  QString ext = fi.suffix();
1367  if(ext.isEmpty())
1368  ext = "vtk";
1369 
1370  const int n = m_SSM->GetNumberOfShapes();
1371 
1372  for(int j = 0; j < n; j ++)
1373  {
1374  m_alignedModels[j]->SetOpacity(1.0);
1375  m_alignedModels[j]->generateSurface();
1376 
1377  QPointer<milxQtFile> writer = new milxQtFile;
1378  QString paddedNumber = QString("%1").arg(j, 3, 10, QChar('0')); //Zero pad the number
1379  QString newFilename = filename + paddedNumber + "." + ext;
1380  writer->saveModel(newFilename, m_alignedModels[j]);
1381 
1382  qApp->processEvents();
1383  }
1384 
1385  done(-1);
1386 }
1387 
1389 {
1390  if(!m_loaded && !m_modelled)
1391  return;
1392 
1393  working(-1);
1394 
1395  if(!m_shapesModelled)
1396  generateModels(false);
1397 
1398  QSettings settings("Shekhar Chandra", "milxQt");
1399  QString path = settings.value("recentPath").toString(), filenamePrefix;
1400 
1401  QFileDialog *fileSaver = new QFileDialog(this);
1402 
1403  filenamePrefix = fileSaver->getSaveFileName(this,
1404  tr("Select File Name Prefix to Save"),
1405  path,
1406  tr("All Files (*.*)"));
1407 
1408  if(filenamePrefix.isEmpty())
1409  {
1410  done(-1);
1411  return;
1412  }
1413 
1414  QFileInfo fi(filenamePrefix);
1415  QString filename = fi.path()+ "/" + fi.baseName();
1416  QString ext = fi.suffix();
1417  if(ext.isEmpty())
1418  ext = "vtk";
1419 
1420  const int n = m_SSM->GetNumberOfShapes();
1421 
1422  for(int j = 0; j < n; j ++)
1423  {
1424  m_models[j]->SetOpacity(1.0);
1425  m_models[j]->generateSurface();
1426 
1427  QPointer<milxQtFile> writer = new milxQtFile;
1428  QString paddedNumber = QString("%1").arg(j, 3, 10, QChar('0')); //Zero pad the number
1429  QString newFilename = filename + paddedNumber + "." + ext;
1430  writer->saveModel(newFilename, m_models[j]);
1431 
1432  qApp->processEvents();
1433  }
1434 
1435  done(-1);
1436 }
1437 
1439 {
1440  if(!m_loaded && !m_modelled)
1441  return;
1442 
1443  working(-1);
1444  milxQtRenderWindow::renderer->InteractiveOff();
1445 
1447  {
1448  generateAlignedModels(false);
1449 
1450  QMessageBox msgBox;
1451  msgBox.setText("Models now aligned. Set the window to desired view and try again.");
1452  msgBox.exec();
1453 
1454  milxQtRenderWindow::renderer->InteractiveOn();
1455  done(-1);
1456  return;
1457  }
1458 
1459  QSettings settings("Shekhar Chandra", "milxQt");
1460  QString path = settings.value("recentPath").toString(), filenamePrefix;
1461 
1462  QFileDialog *fileSaver = new QFileDialog(this);
1463 
1464  filenamePrefix = fileSaver->getSaveFileName(this,
1465  tr("Select File Name Prefix to Save"),
1466  path,
1467  tr("All Files (*.*)"));
1468 
1469  if(filenamePrefix.isEmpty())
1470  {
1471  done(-1);
1472  return;
1473  }
1474 
1475  QFileInfo fi(filenamePrefix);
1476  QString filename = fi.path()+ "/" + fi.baseName();
1477 
1478  const int noOfPoints = m_SSM->GetShape(0)->GetNumberOfPoints();
1479  const int n = m_SSM->GetNumberOfShapes();
1480 
1482  vtkSmartPointer<vtkLookupTable> colorLookupTable = vtkSmartPointer<vtkLookupTable>::New();
1483  colorLookupTable->SetTableRange(0, noOfPoints);
1484  colorLookupTable->Build();
1485 
1486  vtkSmartPointer<vtkUnsignedCharArray> colors = vtkSmartPointer<vtkUnsignedCharArray>::New();
1487  colors->SetNumberOfComponents(3);
1488  colors->SetName("Colors");
1489 
1490  for(int j = 0; j < noOfPoints; j ++)
1491  {
1492  double dcolor[3];
1493 
1494  colorLookupTable->GetColor(j, dcolor);
1495 
1496  unsigned char color[3];
1497 
1498  color[0] = static_cast<unsigned char>(255.0 * dcolor[0]);
1499  color[1] = static_cast<unsigned char>(255.0 * dcolor[1]);
1500  color[2] = static_cast<unsigned char>(255.0 * dcolor[2]);
1501 
1502  colors->InsertNextTupleValue(color);
1503  }
1504 
1505  for(int j = 0; j < n; j ++)
1506  {
1507  m_alignedModels[j]->SetScalars(colors);
1508  m_alignedModels[j]->SetOpacity(1.0);
1509  m_alignedModels[j]->generateSurface();
1510 
1511  qApp->processEvents();
1512  }
1513 
1514  outputSnapshots(filename);
1515 
1516  for(int j = 0; j < n; j ++)
1517  {
1518  m_alignedModels[j]->SetOpacity(0.1);
1519  m_alignedModels[j]->generatePoints();
1520 
1521  qApp->processEvents();
1522  }
1523 
1524  milxQtRenderWindow::renderer->InteractiveOn();
1525  done(-1);
1526 }
1527 
1529 {
1530  if(!m_loaded && !m_modelled)
1531  return;
1532 
1533  working(-1);
1534  milxQtRenderWindow::renderer->InteractiveOff();
1535 
1537  {
1538  generateAlignedModels(false);
1539 
1540  QMessageBox msgBox;
1541  msgBox.setText("Models now aligned. Set the window to desired view and try again.");
1542  msgBox.exec();
1543 
1544  milxQtRenderWindow::renderer->InteractiveOn();
1545  done(-1);
1546  return;
1547  }
1548 
1549  QSettings settings("Shekhar Chandra", "milxQt");
1550  QString path = settings.value("recentPath").toString(), filenamePrefix;
1551 
1552  QFileDialog *fileSaver = new QFileDialog(this);
1553 
1554  filenamePrefix = fileSaver->getSaveFileName(this,
1555  tr("Select File Name Prefix to Save"),
1556  path,
1557  tr("All Files (*.*)"));
1558 
1559  if(filenamePrefix.isEmpty())
1560  {
1561  done(-1);
1562  return;
1563  }
1564 
1565  QFileInfo fi(filenamePrefix);
1566  QString filename = fi.path()+ "/" + fi.baseName();
1567 
1568  const int noOfPoints = m_SSM->GetShape(0)->GetNumberOfPoints();
1569  const int n = m_SSM->GetNumberOfShapes();
1570 
1572  vtkSmartPointer<vtkLookupTable> colorLookupTable = vtkSmartPointer<vtkLookupTable>::New();
1573  colorLookupTable->SetTableRange(0, 2.0*vtkMath::Pi() * 2.0*vtkMath::Pi()); //2 pi by 2 pi
1574  colorLookupTable->Build();
1575 
1576  for(int j = 0; j < n; j ++)
1577  {
1578  vtkSmartPointer<vtkPolyData> shape = m_SSM->GetProcrustesAlignedSurface(j);
1579 
1580  vtkSmartPointer<vtkSphericalTransform> transform = vtkSmartPointer<vtkSphericalTransform>::New();
1581 
1582  vtkSmartPointer<vtkTransformPolyDataFilter> transformShape = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
1583  transformShape->SetInput(shape);
1584  transformShape->SetTransform(transform->GetInverse());
1585  transformShape->Update();
1586  vtkSmartPointer<vtkPolyData> transformedShape = transformShape->GetOutput();
1587 
1588  vtkSmartPointer<vtkUnsignedCharArray> colors = vtkSmartPointer<vtkUnsignedCharArray>::New();
1589  colors->SetNumberOfComponents(3);
1590  colors->SetNumberOfTuples(noOfPoints);
1591  colors->SetName("Colors");
1592 
1593  for(int k = 0; k < noOfPoints; k ++)
1594  {
1595  double dcolor[3], point[3];
1596  transformedShape->GetPoint(k, point);
1597  //cerr << "Point: (" << point[0] << ", " << point[1] << ", " << point[2] << ")" << endl;
1598 
1599  colorLookupTable->GetColor(point[1]*point[2], dcolor);
1600 
1601  unsigned char color[3];
1602 
1603  color[0] = static_cast<unsigned char>(255.0 * dcolor[0]);
1604  color[1] = static_cast<unsigned char>(255.0 * dcolor[1]);
1605  color[2] = static_cast<unsigned char>(255.0 * dcolor[2]);
1606 
1607  colors->SetTupleValue(k, color);
1608  }
1609 
1610  m_alignedModels[j]->SetScalars(colors);
1611  m_alignedModels[j]->SetOpacity(1.0);
1612  m_alignedModels[j]->generateSurface();
1613 
1614  qApp->processEvents();
1615  }
1616 
1617  outputSnapshots(filename);
1618 
1619  milxQtRenderWindow::renderer->InteractiveOn();
1620  done(-1);
1621 }
1622 
1624 {
1625  if(!m_loaded)
1626  return;
1627  if(!m_modelled)
1628  generateAlignedModels(false);
1629  if(!m_shapesModelled)
1630  generateModels(false);
1631 
1632  emit working(-1);
1633  const int n = m_SSM->GetNumberOfShapes();
1634 
1635  printInfo("Replacing Original Models.");
1636  for(int j = 0; j < n; j ++)
1637  {
1638 // m_SSM->SetShape(m_SSM->GetProcrustesAlignedSurface(j), j); //!< Set model to shape filter
1639  m_SSM->GetShape(j)->SetPoints(m_SSM->GetAlignedPoints(j));
1640 
1641 // coordinate otherCentroid = m_models[j]->centroid();
1642  double otherCentroidSize = m_models[j]->centroidSize();
1643 
1644  m_models[j]->SetPoints(m_SSM->GetAlignedPoints(j));
1645 
1646  vtkSmartPointer<vtkTransform> transformer = vtkSmartPointer<vtkTransform>::New();
1647 // transformer->Translate(otherCentroid[0], otherCentroid[1], otherCentroid[2]);
1648  transformer->Scale(otherCentroidSize, otherCentroidSize, otherCentroidSize);
1649 
1650  m_models[j]->SetTransform(transformer);
1651  m_models[j]->refresh();
1652 
1653  qApp->processEvents();
1654  }
1655 
1656  done(-1);
1657 }
1658 
1660 {
1661  if(m_modesVectorModel)
1662  {
1663  m_modesVectorModel->SetLookupTable(lookupTable);
1664  m_modesVectorModel->updateLookupTable();
1665  }
1666  else if(m_modesTensorModel)
1667  {
1668  m_modesTensorModel->SetLookupTable(lookupTable);
1669  m_modesTensorModel->updateLookupTable();
1670  }
1671  else if(m_correspondences)
1672  {
1673  m_correspondences->SetLookupTable(lookupTable);
1674  m_correspondences->updateLookupTable();
1675  }
1676  else
1677  {
1678  m_meanModel->SetLookupTable(lookupTable);
1679  m_meanModel->updateLookupTable();
1680  }
1681 }
1682 
1683 void milxQtShapeModel::reset()
1684 {
1685  m_loaded = false;
1686  m_modelled = false;
1687  m_meaned = false;
1688  m_shapesModelled = false;
1689  m_alignedShapesModelled = false;
1690  m_modes = false;
1691  m_vector = false;
1692  m_tensor = false;
1693  m_correspond = false;
1694  m_mode = 1;
1695 }
1696 
1697 void milxQtShapeModel::outputSnapshots(const QString filename)
1698 {
1699  const int n = m_SSM->GetNumberOfShapes();
1700 
1701  QPointer<milxQtRenderWindow> offScreenWin = new milxQtRenderWindow;
1702  offScreenWin->generateRender(); //Call this, otherwise blank output always
1703  offScreenWin->SetBackground(1, 1, 1);
1704  offScreenWin->OffScreenRenderingOn();
1705  vtkRenderer *ren = offScreenWin->GetRenderer();
1706  ren->SetActiveCamera(milxQtRenderWindow::renderer->GetActiveCamera());
1707 
1708  printInfo("Found " + QString::number(n) + " shapes to check.");
1709  for(int j = 0; j < n; j ++)
1710  {
1711  QString tmpName = filename + QString::number(j) + ".png";
1712  printInfo("Saving " + tmpName);
1713 
1714  ren->AddActor(m_alignedModels[j]->GetActor());
1715  offScreenWin->Render();
1716 
1717  qApp->processEvents();
1718 
1719  vtkSmartPointer<vtkWindowToImageFilter> windowToImage = vtkSmartPointer<vtkWindowToImageFilter>::New();
1720  windowToImage->SetInput(offScreenWin->GetRenderWindow());
1721  windowToImage->Update();
1722 
1723  vtkSmartPointer<vtkPNGWriter> writer = vtkSmartPointer<vtkPNGWriter>::New();
1724  writer->SetFileName(tmpName.toStdString().c_str());
1725  writer->SetInput(windowToImage->GetOutput());
1726  writer->Write();
1727 
1728  ren->RemoveActor(m_alignedModels[j]->GetActor());
1729 
1730  qApp->processEvents();
1731  }
1732 }
1733 
1735 {
1736  contextMenu = new QMenu(this);
1737  contextMenu->setTitle(QApplication::translate("MainWindow", "Shape Modelling", 0, QApplication::UnicodeUTF8));
1738 
1739  actionMean = new QAction(this);
1740  actionMean->setText(QApplication::translate("SSM", "&Mean Model", 0, QApplication::UnicodeUTF8));
1741  actionMean->setShortcut(tr("Alt+m"));
1742  actionMean->setCheckable(true);
1743  actionMean->setChecked(false);
1744  actionAligned = new QAction(this);
1745  actionAligned->setText(QApplication::translate("SSM", "&Aligned Points", 0, QApplication::UnicodeUTF8));
1746  actionAligned->setShortcut(tr("Alt+a"));
1747  actionAligned->setCheckable(true);
1748  actionAligned->setChecked(false);
1749  actionOriginal = new QAction(this);
1750  actionOriginal->setText(QApplication::translate("SSM", "&Original Points", 0, QApplication::UnicodeUTF8));
1751  actionOriginal->setShortcut(tr("Alt+o"));
1752  actionOriginal->setCheckable(true);
1753  actionOriginal->setChecked(false);
1754  actionModesAsVectors = new QAction(this);
1755  actionModesAsVectors->setText(QApplication::translate("SSM", "Modes as &Vectors", 0, QApplication::UnicodeUTF8));
1756  actionModesAsVectors->setShortcut(tr("Alt+v"));
1757  actionModesAsVectors->setCheckable(true);
1758  actionModesAsVectors->setChecked(false);
1759  actionModesAsTensors = new QAction(this);
1760  actionModesAsTensors->setText(QApplication::translate("SSM", "Modes as &Tensors", 0, QApplication::UnicodeUTF8));
1761  actionModesAsTensors->setShortcut(tr("Alt+t"));
1762  actionModesAsTensors->setCheckable(true);
1763  actionModesAsTensors->setChecked(false);
1764  actionModesAsCollection = new QAction(this);
1765  actionModesAsCollection->setText(QApplication::translate("SSM", "Modes as Surface &Collection", 0, QApplication::UnicodeUTF8));
1766  actionModesAsCollection->setShortcut(tr("Alt+c"));
1767  actionCorrespond = new QAction(this);
1768  actionCorrespond->setText(QApplication::translate("SSM", "Correspondences as a &Hedgehog", 0, QApplication::UnicodeUTF8));
1769  actionCorrespond->setShortcut(tr("Alt+h"));
1770  actionCorrespond->setCheckable(true);
1771  actionCorrespond->setChecked(false);
1772 
1773  //plots menu
1774  actionCompact = new QAction(this);
1775  actionCompact->setText(QApplication::translate("SSM", "Compactness", 0, QApplication::UnicodeUTF8));
1776  actionCompact->setShortcut(tr("Shift+Alt+c"));
1777  actionSpecificity = new QAction(this);
1778  actionSpecificity->setText(QApplication::translate("SSM", "Specificity", 0, QApplication::UnicodeUTF8));
1779  actionSpecificity->setShortcut(tr("Shift+Alt+s"));
1780  actionGeneralise = new QAction(this);
1781  actionGeneralise->setText(QApplication::translate("SSM", "Generalisability", 0, QApplication::UnicodeUTF8));
1782  actionGeneralise->setShortcut(tr("Shift+Alt+g"));
1783  actionValues = new QAction(this);
1784  actionValues->setText(QApplication::translate("SSM", "Eigenvalues", 0, QApplication::UnicodeUTF8));
1785  actionValues->setShortcut(tr("Shift+Alt+v"));
1786  actionModes = new QAction(this);
1787  actionModes->setText(QApplication::translate("SSM", "Primary Eigenmodes", 0, QApplication::UnicodeUTF8));
1788  actionModes->setShortcut(tr("Shift+Alt+r"));
1789  actionParameters = new QAction(this);
1790  actionParameters->setText(QApplication::translate("SSM", "Training Shape Parameters", 0, QApplication::UnicodeUTF8));
1791  actionParameters->setShortcut(tr("Shift+Alt+p"));
1792 
1793  //Procrustes menu
1794  actionRigid = new QAction(this);
1795  actionRigid->setText(QApplication::translate("SSM", "Rigid", 0, QApplication::UnicodeUTF8));
1796  actionRigid->setShortcut(tr("Ctrl+Alt+r"));
1797  actionRigid->setCheckable(true);
1798  actionSimilarity = new QAction(this);
1799  actionSimilarity->setText(QApplication::translate("SSM", "Similarity", 0, QApplication::UnicodeUTF8));
1800  actionSimilarity->setShortcut(tr("Ctrl+Alt+s"));
1801  actionSimilarity->setCheckable(true);
1802  actionSimilarity->setChecked(true);
1803  actionAffine = new QAction(this);
1804  actionAffine->setText(QApplication::translate("SSM", "Affine", 0, QApplication::UnicodeUTF8));
1805  actionAffine->setShortcut(tr("Ctrl+Alt+a"));
1806  actionAffine->setCheckable(true);
1807  alignGroup = new QActionGroup(this);
1808  alignGroup->addAction(actionRigid);
1809  alignGroup->addAction(actionSimilarity);
1810  alignGroup->addAction(actionAffine);
1811 
1812  actionAlignment = new QAction(this);
1813  actionAlignment->setText(QApplication::translate("SSM", "Output &Alignment as Images", 0, QApplication::UnicodeUTF8));
1814  actionAlignment->setShortcut(tr("Alt+r"));
1815  actionOriginalMeshes = new QAction(this);
1816  actionOriginalMeshes->setText(QApplication::translate("SSM", "Output &Original Meshes", 0, QApplication::UnicodeUTF8));
1817  actionOriginalMeshes->setShortcut(tr("Shift+Alt+o"));
1818  actionAlignedMeshes = new QAction(this);
1819  actionAlignedMeshes->setText(QApplication::translate("SSM", "Output &Aligned Meshes", 0, QApplication::UnicodeUTF8));
1820  actionAlignedMeshes->setShortcut(tr("Shift+Alt+a"));
1821  actionPointIDs = new QAction(this);
1822  actionPointIDs->setText(QApplication::translate("SSM", "Output &Point IDs as Images", 0, QApplication::UnicodeUTF8));
1823  actionPointIDs->setShortcut(tr("Alt+p"));
1824  actionCoordinates = new QAction(this);
1825  actionCoordinates->setText(QApplication::translate("SSM", "Output &Coordinates as Images", 0, QApplication::UnicodeUTF8));
1826  actionCoordinates->setShortcut(tr("Alt+c"));
1827 
1828  actionReplaceOriginal = new QAction(this);
1829  actionReplaceOriginal->setText(QApplication::translate("SSM", "Replace Originals with Aligned", 0, QApplication::UnicodeUTF8));
1830  actionReplaceOriginal->setShortcut(tr("Shift+Alt+r"));
1831 }
1832 
1834 {
1835  //Operations
1836  connect(actionMean, SIGNAL(triggered()), this, SLOT(mean()));
1837  connect(actionAligned, SIGNAL(triggered()), this, SLOT(aligned()));
1838  connect(actionOriginal, SIGNAL(triggered()), this, SLOT(original()));
1839  connect(actionModesAsVectors, SIGNAL(triggered()), this, SLOT(modesAsVectors()));
1840  connect(actionModesAsTensors, SIGNAL(triggered()), this, SLOT(modesAsTensors()));
1841  connect(actionModesAsCollection, SIGNAL(triggered()), this, SLOT(modesAsCollection()));
1842  connect(actionCorrespond, SIGNAL(triggered()), this, SLOT(correspondences()));
1843 
1844  //Plot
1845  connect(actionCompact, SIGNAL(triggered()), this, SLOT(compactness()));
1846  connect(actionSpecificity, SIGNAL(triggered()), this, SLOT(specificity()));
1847  connect(actionGeneralise, SIGNAL(triggered()), this, SLOT(generalisability()));
1848  connect(actionValues, SIGNAL(triggered()), this, SLOT(eigenvalues()));
1849  connect(actionModes, SIGNAL(triggered()), this, SLOT(eigenmodes()));
1850  connect(actionParameters, SIGNAL(triggered()), this, SLOT(parameters()));
1851 
1852  //Procrustes
1853  connect(actionRigid, SIGNAL(triggered()), this, SLOT(procrustes()));
1854  connect(actionSimilarity, SIGNAL(triggered()), this, SLOT(procrustes()));
1855  connect(actionAffine, SIGNAL(triggered()), this, SLOT(procrustes()));
1856 
1857  connect(actionAlignment, SIGNAL(triggered()), this, SLOT(alignment()));
1858  connect(actionOriginalMeshes, SIGNAL(triggered()), this, SLOT(originalMeshes()));
1859  connect(actionAlignedMeshes, SIGNAL(triggered()), this, SLOT(alignedMeshes()));
1860  connect(actionPointIDs, SIGNAL(triggered()), this, SLOT(pointIds()));
1861  connect(actionCoordinates, SIGNAL(triggered()), this, SLOT(coordinates()));
1862  connect(actionReplaceOriginal, SIGNAL(triggered()), this, SLOT(replaceOriginal()));
1863 }
1864 
1866 {
1867  actionMean->setToolTip("Show the mean of the Statistical Shape Model");
1868  actionMean->setStatusTip("Show the mean of the Statistical Shape Model");
1869  actionAligned->setToolTip("Show the aligned shapes of the Statistical Shape Model");
1870  actionAligned->setStatusTip("Show the aligned shapes of the Statistical Shape Model");
1871  actionOriginal->setToolTip("Show the original (unmodified) shapes of the Statistical Shape Model");
1872  actionOriginal->setStatusTip("Show the original (unmodified) shapes of the Statistical Shape Model");
1873  actionModesAsVectors->setToolTip("Show the first mode of the Statistical Shape Model as a vector field");
1874  actionModesAsVectors->setStatusTip("Show the first mode of the Statistical Shape Model as a vector field");
1875  actionModesAsTensors->setToolTip("Show the first mode of the Statistical Shape Model as an ellipsoidal tensor field");
1876  actionModesAsTensors->setStatusTip("Show the first mode of the Statistical Shape Model as an ellipsoidal tensor field");
1877  actionModesAsCollection->setToolTip("Show the modes of the Statistical Shape Model as a collection of surfaces");
1878  actionModesAsCollection->setStatusTip("Show the modes of the Statistical Shape Model as a collection of surfaces");
1879  actionCorrespond->setToolTip("Show a measure of the maximum deviation of the correspondences between shapes as a hedgehog plot.");
1880  actionCorrespond->setStatusTip("Show a measure of the maximum deviation of the correspondences between shapes as a hedgehog plot.");
1881 
1882  //Plot
1883  actionCompact->setToolTip("Plot the compactness of the shape model.");
1884  actionCompact->setStatusTip("Plot the compactness of the shape model.");
1885  actionSpecificity->setToolTip("Plot the specificity of the shape model.");
1886  actionSpecificity->setStatusTip("Plot the specificity of the shape model.");
1887  actionGeneralise->setToolTip("Plot the generalisability of the shape model.");
1888  actionGeneralise->setStatusTip("Plot the generalisability of the shape model.");
1889  actionValues->setToolTip("Plot the eigenvalues within the shape model.");
1890  actionValues->setStatusTip("Plot the eigenvalues within the shape model.");
1891  actionModes->setToolTip("Plot the three primary modes of the training shapes within the shape model.");
1892  actionModes->setStatusTip("Plot the three primary modes of the training shapes within the shape model.");
1893  actionParameters->setToolTip("Plot the shape parameters of the training shapes within the shape model.");
1894  actionParameters->setStatusTip("Plot the shape parameters of the training shapes within the shape model.");
1895 
1896  //Procrustes
1897  actionRigid->setToolTip("Procrustes alignment of surfaces to rigid landmark transform.");
1898  actionRigid->setStatusTip("Procrustes alignment of surfaces to rigid landmark transform.");
1899  actionSimilarity->setToolTip("Procrustes alignment of surfaces to rigid+scale landmark transform.");
1900  actionSimilarity->setStatusTip("Procrustes alignment of surfaces to rigid+scale landmark transform.");
1901  actionAffine->setToolTip("Procrustes alignment of surfaces to affine landmark transform.");
1902  actionAffine->setStatusTip("Procrustes alignment of surfaces to affine landmark transform.");
1903 
1904  actionAlignment->setToolTip("Output each aligned shape as a PNG image via Off-screen rendering.");
1905  actionAlignment->setStatusTip("Output each aligned shape as a PNG image via Off-screen rendering.");
1906  actionOriginalMeshes->setToolTip("Output each original model as a poly data file.");
1907  actionOriginalMeshes->setStatusTip("Output each original model as a poly data file.");
1908  actionAlignedMeshes->setToolTip("Output each aligned shape as a poly data file.");
1909  actionAlignedMeshes->setStatusTip("Output each aligned shape as a poly data file.");
1910  actionPointIDs->setToolTip("Output each aligned shape with point IDs coloured as a PNG image via Off-screen rendering.");
1911  actionPointIDs->setStatusTip("Output each aligned shape with point IDs coloured as a PNG image via Off-screen rendering.");
1912  actionCoordinates->setToolTip("Output the coordinates (as scalars) of each shape as a PNG image via Off-screen rendering.");
1913  actionCoordinates->setStatusTip("Output the coordinates (as scalars) of each shape as a PNG image via Off-screen rendering.");
1914  actionReplaceOriginal->setToolTip("Replace the original meshes with the aligned ones within the SSM. Aligned meshes are rescaled to original mesh size.");
1915  actionReplaceOriginal->setStatusTip("Replace the original meshes with the aligned ones within the SSM. Aligned meshes are rescaled to original mesh size.");
1916 }
1917 
1918 void milxQtShapeModel::contextMenuEvent(QContextMenuEvent *contextEvent)
1919 {
1921 
1922  contextMenu->exec(contextEvent->globalPos());
1923 }
QPointer< milxQtModel > m_modesVectorModel
Vector Model of the modes.
int defaultView
Default view for data (default is axial)
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
void generateAlignedModels(const bool display=true)
void RemoveActor(vtkSmartPointer< vtkProp > actor)
Remove the VTK actor from this window.
void procrustes()
Change the procrustes mode of the SSM (causes recomputation of the model).
void pointIds()
Output each aligned shape coloured by the point IDs as a PNG image in a directory and prefix provided...
QAction * actionModesAsCollection
modes collection action
QAction * saveViewFileAct
Save camera view to file.
void compactness()
Plot the compactness of the SSM.
QMenu * viewMenu
Context Menu.
void setName(const QString filename)
Set the name of the data.
virtual void generateSSM()
int m_mode
Mode being viewed.
QAction * actionOriginal
original points action
bool m_tensor
Tensors generated?
virtual void SetInputCollection(vtkPolyDataCollection *meshes)
Uses the collection of polydata to create shape model.
vtkSmartPointer< vtkRenderer > renderer
Renderer for the data.
void alignedMeshes()
Output each aligned shape as a poly data file in a directory and prefix provided by the user (interna...
void AddActor(vtkSmartPointer< vtkProp > actor)
Add a VTK actor to this window.
void parameters()
Plot the training shape parameters of the model for each training shape (leave 1 out).
This class represents the MILX Qt Render Window Display object using QVTK.
void modesAsVectors()
Show the modes variation as a vector field.
bool m_alignedShapesModelled
Shapes were generated?
void originalMeshes()
Output each original shape as a poly data file in a directory and prefix provided by the user (intern...
void correspondences()
Compare points from each shape to measure the correspondence as a hedgehog plot.
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 mean()
Show the mean model in the window.
void outputSnapshots(const QString filename)
QAction * viewZY
Change view to zy-plane (Coronal)
QAction * actionReplaceOriginal
correspondence check action
void contextMenuEvent(QContextMenuEvent *event)
The context menu setup member.
void specificity()
Plot the specificity of the SSM.
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.
This class represents the MILX Qt File I/O object using VTK/ITK/Qt.
Definition: milxQtFile.h:60
QActionGroup * alignGroup
Procrustes align gp action.
bool m_modes
Modes been generated?
QList< QPointer< milxQtModel > > m_models
Original Models in the SSM.
bool saveModel(const QString filename, vtkPolyData *data, const bool binary=false)
Saves a model as a file, which can be a VTK XML or Legacy VTK PolyData File (i.e. either a *...
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
void createActions()
Create the actions for context menu etc.
QAction * actionModes
primary modes plot action
This class represents the MILX Qt Model/Mesh Display object using VTK.
Definition: milxQtModel.h:115
void Render()
Force Render or Update of the display.
virtual void updateLookupTable()
Update the colour maps depending on whats been generated for the model.
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
void replaceOriginal()
Replace the original (unaligned) meshes with the aligned ones. The new meshes are unnormalised as com...
QAction * refreshAct
Action for refreshing the display.
void aligned()
Show the aligned models in the window as a set of coloured point clouds.
bool m_correspond
Hedgehog generated?
virtual vtkDataSet * GetDataSet()
Get the data, depending on whats been generated, return that dataset.
void enableActionBasedOnView()
Enables the view actions corresponding to current view set.
ShapeModelType::Pointer m_StandardSSM
The Statistical Shape Model.
void resultAvailable(milxQtRenderWindow *)
Send signal that Resultant render window is available for showing.
virtual void generateMeanModel(vtkSmartPointer< vtkPolyData > shape=NULL)
QAction * actionSpecificity
specificity plot action
QAction * resetAct
Action for refreshing the display.
QMenu * colourMapMenu
Colour map menu.
void generalisability()
Plot the generalisability of the SSM.
ShapeModelBaseType::Pointer m_SSM
The Statistical Shape Model Base Class.
void generateRender()
Generate the render so it is ready for display. Should be called before showing the window...
void modesAsCollection()
Show the modes variation as a collection of surfaces.
QAction * saveViewAct
Save camera view.
QMenu * alignMenu
Plot menu for SSM alignment.
virtual void createMenu(QMenu *menu)
Create the menu for the data in this object. Used for context menu and file menus.
QAction * viewXY
Change view to xy-plane (Axial)
virtual ~milxQtShapeModel()
void coordinates()
Output each aligned shape coloured by the coordinates as a PNG image in a directory and prefix provid...
QPointer< milxQtModel > m_meanModel
Model of the mean.
bool m_vector
Vectors generated?
QAction * actionPointIDs
point ids check action
void eigenmodes()
Plot the primary eigenmodes of the model for each training shape.
QAction * viewZX
Change view to zx-plane (Sagittal)
void done(int value)
Send signal that computation is done. Value carries the progress,.
void alignment()
Output each aligned shape as a PNG image in a directory and prefix provided by the user (internally v...
vtkSmartPointer< vtkScalarBarActor > scale
Scale for the display.
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.
void LoadModel(const QString filename)
Loads a model as an SSM (*.ssm) file. MILX-MSK like call.
QAction * actionValues
primary modes plot action
QAction * actionMean
mean action
milxQtRenderWindow(QWidget *theParent=0, bool contextSystem=true)
The standard constructor.
virtual void generateModes()
bool m_loaded
Shapes loaded?
void eigenvalues()
Plot the eigenvalues of the model.
void modesAsTensors()
Show the modes variation as a ellipsoidal tensor field.
milxQtConsole * console
Console for log outputs.
Definition: milxQtWindow.h:257
void printInfo(QString msg)
Info message wrapper for console.
QAction * actionAffine
affine Procrustes action
QList< QPointer< milxQtModel > > m_alignedModels
Aligned Models in the SSM.
QList< int > m_caseIDs
A list of case IDs corresponding to the models in the SSM.
void generateModels(const bool display=true)
milxQtShapeModel(QWidget *theParent=0, bool contextSystem=true)
void working(int value)
Send signal that computation is in progress. Value carries the progress,.
QPointer< milxQtModel > getMeanModel()
Returns the mean model of the Statistical Shape Model. Assumes SSM has been generated (via generateSS...
QMenu * windowPropertiesMenu
Context Menu.
virtual void generateCollectionBasedOnMode()
QAction * actionParameters
training shape parameters plot action
void original()
Show the original models in the window as a set of coloured point clouds.
QAction * loadViewAct
Load camera view.
bool m_shapesModelled
Shapes were generated?
QAction * loadViewFileAct
Load camera view to file.