20 #include "milxQtShapeModel.h" 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> 31 #include <vtkSphericalTransform.h> 32 #include <vnl/vnl_double_3.h> 33 #include <vnl/algo/vnl_scatter_3x3.h> 35 #include <vtkPNGWriter.h> 36 #include <vtkWindowToImageFilter.h> 38 #include <milxQtFile.h> 39 #include <milxQtPlot.h> 70 if(
m_SSM->LoadModel(filename.toStdString().c_str()))
83 size_t n = meshes->GetNumberOfItems();
88 meshes->InitTraversal();
89 for(
size_t j = 0; j < n; j ++)
91 m_SSM->AddShape(meshes->GetNextItem());
93 qApp->processEvents();
102 const int n = meshes->GetNumberOfItems();
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);
122 connect(okButton, SIGNAL(clicked(
bool)), casePossibilities, SLOT(accept()));
124 meshes->InitTraversal();
125 for(
int j = 0; j < n; j ++)
127 QFileInfo fi(filenames[j]);
128 QRegExp rx(
"(\\d+)", Qt::CaseSensitive, QRegExp::RegExp2);
133 while ((pos = rx.indexIn(fi.baseName(), pos)) != -1)
136 pos += rx.matchedLength();
140 if(list.size() > 1 && j == 0)
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]);
146 casePossibilities->exec();
148 index = integerValues->currentIndex();
153 caseID = list[index].toInt();
157 m_SSM->AddShape(meshes->GetNextItem());
159 qApp->processEvents();
163 qDebug() <<
"Case IDs: " <<
m_caseIDs << endl;
202 menu->addSeparator()->setText(tr(
"View"));
217 menu->addSeparator()->setText(tr(
"Validation/Output"));
223 menu->addSeparator();
226 alignMenu = menu->addMenu(
"Procrustes Mode");
241 menu->addSeparator();
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);
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();
264 if(ret == QMessageBox::Yes)
278 catch( itk::ExceptionObject & err )
280 printError(
"Exception caught while generating an SSM!");
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));
298 tmpLookupTable->SetTableRange(0.0, n+1);
299 tmpLookupTable->Build();
346 const int n =
m_SSM->GetNumberOfShapes();
349 printInfo(
"Generating Original Models.");
350 for(
int j = 0; j < n; j ++)
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);
369 qApp->processEvents();
372 printInfo(
"Done. Displaying Original Models.");
391 const int n =
m_SSM->GetNumberOfShapes();
394 for(
int j = 0; j < n; j ++)
402 shape->
setName( QString::number(j) );
403 shape->setLargeDataSetMode(
true);
405 shape->SetInput(
m_SSM->GetProcrustesAlignedSurface(j));
408 shape->generatePoints(colour[0], colour[1], colour[2]);
409 shape->SetOpacity(0.1);
418 qApp->processEvents();
421 printInfo(
"Done. Displaying Aligned Models.");
434 bool flgNormal =
true;
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);
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();
469 vtkSmartPointer<vtkPolyData> meanShape =
m_meanModel->GetOutput();
471 meanShape->SetPoints(
m_StandardSSM->GetMeanShape()->GetPoints());
473 vtkSmartPointer<vtkPolyDataNormals> normals = vtkPolyDataNormals::New();
474 normals->SetInput(meanShape);
475 normals->ComputeCellNormalsOff();
476 normals->ComputePointNormalsOn();
477 normals->SplittingOff();
483 vtkSmartPointer<vtkFloatArray> normArray =
484 vtkFloatArray::SafeDownCast(normals->GetOutput()->GetPointData()->GetNormals());
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));
492 vtkSmartPointer<vtkPolyData> varShape = vtkSmartPointer<vtkPolyData>::New();
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);
505 for(
int i = 0; i < meanShape->GetNumberOfPoints(); i++)
507 vtkFloatingPointType* meanPoint = meanShape->GetPoint(i);
508 vtkFloatingPointType* varPoint = varShape->GetPoint(i);
510 vtkFloatingPointType xVal = varPoint[0] - meanPoint[0];
511 vtkFloatingPointType yVal = varPoint[1] - meanPoint[1];
512 vtkFloatingPointType zVal = varPoint[2] - meanPoint[2];
514 float normalPoint[3];
515 normArray->GetTupleValue(i, normalPoint);
516 vtkFloatingPointType var;
519 var = xVal*normalPoint[0] + yVal*normalPoint[1] + zVal*normalPoint[2];
524 var = xVal*xVal + yVal*yVal + zVal*zVal;
527 varVectors->InsertNextTuple3(xVal, yVal, zVal);
528 varShapeVectors->InsertNextTuple3(-xVal, -yVal, -zVal);
529 varScalars->InsertNextValue(var);
531 vnl_scatter_3x3<vtkFloatingPointType> C;
534 vtkFloatingPointType point[3];
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];
542 C.add_outer_product(point_vector);
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));
558 varTensors->InsertNextTuple(tens->T);
561 qApp->processEvents();
564 vtkFloatingPointType maxScalar = std::numeric_limits<vtkFloatingPointType>::min();
565 for(
int i = 0; i < varScalars->GetNumberOfTuples(); i++)
567 if(varScalars->GetValue(i) > maxScalar)
568 maxScalar = varScalars->GetValue(i);
570 printInfo(
"Max sigma: " + QString::number(sqrt(maxScalar)) +
"mm.");
571 for(
int i = 0; i < varScalars->GetNumberOfTuples(); i++)
573 vtkFloatingPointType var = varScalars->GetValue(i);
574 varScalars->SetValue(i, var/maxScalar);
577 meanShape->GetPointData()->SetVectors(varVectors);
578 varShape->GetPointData()->SetVectors(varShapeVectors);
579 meanShape->GetPointData()->SetScalars(varScalars);
581 meanShape->GetPointData()->SetTensors(varTensors);
582 varShape->GetPointData()->SetTensors(varTensors);
584 if(ret == QMessageBox::Yes)
602 const int n =
m_SSM->GetNumberOfShapes();
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);
613 if(!ok1 || !ok2 || !ok3)
617 float weightValue = -modeWeight;
618 const float weightStep = 2.0*modeWeight/(numberOfSurfaces-1);
620 vtkPolyDataCollection* meshes = vtkPolyDataCollection::New();
621 QStringList surfaceNames;
622 for(
int j = 0; j < numberOfSurfaces; j ++)
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));
630 vtkPolyData *shape = vtkPolyData::New();
631 shape->DeepCopy(
m_SSM->GetParameterisedShape(b));
633 meshes->AddItem(shape);
634 surfaceNames.append(QString::number(weightStep));
636 weightValue += weightStep;
640 emit collectionAvailable(meshes, surfaceNames);
655 vtkSmartPointer<vtkPolyData> meanShape =
m_meanModel->GetOutput();
700 const int n =
m_SSM->GetNumberOfShapes();
701 const int noOfPoints =
m_SSM->GetShape(0)->GetNumberOfPoints();
703 printInfo(
"Generating Correspondences.");
705 vtkSmartPointer<vtkDoubleArray> maxDeviations = vtkSmartPointer<vtkDoubleArray>::New();
706 maxDeviations->SetNumberOfComponents(3);
707 maxDeviations->SetNumberOfTuples(noOfPoints);
708 maxDeviations->SetName(
"Deviations");
711 coordinate origin(0.0);
712 for(
int l = 0; l < noOfPoints; l ++)
713 maxDeviations->SetTupleValue(l, origin.data_block());
715 for(
int j = 0; j < n; j ++)
717 vtkSmartPointer<vtkPolyData> currentShape =
m_SSM->GetProcrustesAlignedSurface(j);
719 for(
int k = 0; k < n; k ++)
724 vtkSmartPointer<vtkPolyData> nextShape =
m_SSM->GetProcrustesAlignedSurface(k);
726 for(
int l = 0; l < noOfPoints; l ++)
728 coordinate currentPoint(currentShape->GetPoint(l));
729 coordinate nextPoint(nextShape->GetPoint(l));
730 coordinate maxVector(maxDeviations->GetTuple(l));
731 coordinate deviation = currentPoint - nextPoint;
733 double length = deviation.squared_magnitude();
734 double currentMaxLength = maxVector.squared_magnitude();
736 if(length > currentMaxLength)
739 maxDeviations->SetTupleValue(l, deviation.data_block());
743 qApp->processEvents();
787 int n =
m_SSM->GetNumberOfShapes();
794 for(
int j = 0; j < n; j ++)
801 for(
int j = 0; j < n; j ++)
814 const int n =
m_SSM->GetNumberOfShapes();
821 for(
int j = 0; j < n; j ++)
828 for(
int j = 0; j < n; j ++)
915 vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
916 vtkSmartPointer<vtkFloatArray> values =
m_StandardSSM->GetPCA()->GetEvals();
919 for(
int j = 0; j < 3; j ++)
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);
926 printDebug(
"Compactness Table is " + QString::number(table->GetNumberOfRows()) +
"x" + QString::number(table->GetNumberOfColumns()));
929 table->GetColumn(0)->SetName(
"Mode");
930 table->GetColumn(1)->SetName(
"Value");
931 table->GetColumn(2)->SetName(
"Precision");
935 for (
int j = 0; j < values->GetNumberOfTuples(); j++)
936 total += values->GetValue(j);
937 printInfo(
"Total of eigenvalues is " + QString::number(total));
941 for (
int j = 0; j < values->GetNumberOfTuples(); j++)
943 compactness += values->GetValue(j)/total;
945 table->SetValue(j, 0, j+1);
946 table->SetValue(j, 1, values->GetValue(j));
947 table->SetValue(j, 2, compactness);
949 qApp->processEvents();
955 plot->setPlotType2D(0, 2);
956 plot->setName(
"Compactness of the Shape Model");
959 plot->SetSource(table);
960 plot->generatePlot();
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);
981 vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
984 for(
int j = 0; j < 3; j ++)
986 vtkSmartPointer<vtkDoubleArray> column = vtkSmartPointer<vtkDoubleArray>::New();
987 for(
int k = 0; k < n; k ++)
988 column->InsertNextValue(0.0);
989 table->AddColumn(column);
991 printDebug(
"Specificity Table is " + QString::number(table->GetNumberOfRows()) +
"x" + QString::number(table->GetNumberOfColumns()));
994 table->GetColumn(0)->SetName(
"Shape");
995 table->GetColumn(1)->SetName(
"Minimum RMSE");
996 table->GetColumn(2)->SetName(
"Specificity");
1000 for(
int i = 0; i < n; i++)
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);
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 ++)
1012 double value =
m_SSM->PolyDataDistance(shape,
m_SSM->GetShape(k))/
m_SSM->GetShape(0)->GetNumberOfPoints();
1013 if(value < minSumSquares)
1014 minSumSquares = value;
1016 specific += minSumSquares;
1018 table->SetValue(i, 0, i);
1019 table->SetValue(i, 1, minSumSquares);
1020 table->SetValue(i, 2, specific);
1022 qApp->processEvents();
1025 printInfo(
"Specificity Score: " + QString::number(specific));
1031 plot->setPlotType2D(0, 1);
1032 plot->setName(
"Specificity of the Shape Model");
1034 plot->legend(
false);
1035 plot->SetSource(table);
1036 plot->generatePlot();
1048 vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
1051 for(
int j = 0; j < 2; j ++)
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);
1058 printDebug(
"Generalisability Table is " + QString::number(table->GetNumberOfRows()) +
"x" + QString::number(table->GetNumberOfColumns()));
1061 table->GetColumn(0)->SetName(
"Shape");
1062 table->GetColumn(1)->SetName(
"Reconstruction Error");
1066 for(
int i = 0; i <
m_SSM->GetNumberOfShapes(); i++)
1069 vtkPolyData *shape = vtkPolyData::New();
1070 shape->DeepCopy(
m_SSM->GetShape(0));
1071 m_SSM->RemoveShape(0);
1074 vtkSmartPointer<vtkFloatArray> b = vtkSmartPointer<vtkFloatArray>::New();
1075 b->SetNumberOfComponents(1);
1076 b->SetNumberOfTuples(
m_SSM->GetNumberOfModes());
1077 b->FillComponent(0, 0.0);
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();
1084 table->SetValue(i, 0, i);
1085 table->SetValue(i, 1, epsiSqr);
1087 generalisability += epsiSqr;
1088 m_SSM->AddShape(shape);
1090 qApp->processEvents();
1092 printInfo(
"Generalisability Score: " + QString::number(generalisability));
1098 plot->setPlotType2D(0, 1);
1099 plot->setName(
"Generalisability of the Shape Model");
1101 plot->legend(
false);
1102 plot->SetSource(table);
1103 plot->generatePlot();
1115 vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
1116 vtkSmartPointer<vtkFloatArray> values =
m_StandardSSM->GetPCA()->GetEvals();
1119 for(
int j = 0; j < 3; j ++)
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);
1126 printDebug(
"Compactness Table is " + QString::number(table->GetNumberOfRows()) +
"x" + QString::number(table->GetNumberOfColumns()));
1129 table->GetColumn(0)->SetName(
"Mode");
1130 table->GetColumn(1)->SetName(
"Value");
1131 table->GetColumn(2)->SetName(
"Precision");
1135 for (
int j = 0; j < values->GetNumberOfTuples(); j++)
1136 total += values->GetValue(j);
1137 printInfo(
"Total of eigenvalues is " + QString::number(total));
1141 for (
int j = 0; j < values->GetNumberOfTuples(); j++)
1143 compactness += values->GetValue(j)/total;
1145 table->SetValue(j, 0, j+1);
1146 table->SetValue(j, 1, values->GetValue(j));
1147 table->SetValue(j, 2, compactness);
1149 qApp->processEvents();
1155 plot->setPlotType2D(0, 1);
1156 plot->setName(
"Eigenvalues of the Shape Model");
1158 plot->legend(
false);
1159 plot->SetSource(table);
1160 plot->generatePlot();
1172 vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
1175 for(
int j = 0; j <
m_SSM->GetNumberOfModes(); j ++)
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);
1184 printDebug(
"Modes Table is " + QString::number(table->GetNumberOfRows()) +
"x" + QString::number(table->GetNumberOfColumns()));
1186 for(
int j = 0; j <
m_SSM->GetNumberOfShapes(); j ++)
1188 double scale, tx, ty, tz, theta, phi, psi;
1189 vtkSmartPointer<vtkFloatArray> b = vtkSmartPointer<vtkFloatArray>::New();
1190 b->SetNumberOfComponents(1);
1191 b->SetNumberOfTuples(
m_SSM->GetNumberOfModes());
1193 m_SSM->GetSurfaceSimilarityParameters(
m_SSM->GetShape(j),
scale, tx, ty, tz, theta, phi, psi, b);
1195 for(
int k = 0; k <
m_SSM->GetNumberOfModes(); k ++)
1196 table->SetValue(j, k, b->GetValue(k));
1198 qApp->processEvents();
1202 plot->setPlotType3D(0, 1, 2);
1203 plot->setName(
"Specificity of the Shape Model");
1205 plot->legend(
false);
1206 plot->SetSource(table);
1207 plot->generatePlot();
1219 vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
1222 for(
int j = 0; j <
m_SSM->GetNumberOfModes(); j ++)
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);
1231 printDebug(
"Parameters Table is " + QString::number(table->GetNumberOfRows()) +
"x" + QString::number(table->GetNumberOfColumns()));
1233 for(
int j = 0; j <
m_SSM->GetNumberOfShapes(); j ++)
1235 double scale, tx, ty, tz, theta, phi, psi;
1236 vtkSmartPointer<vtkFloatArray> b = vtkSmartPointer<vtkFloatArray>::New();
1237 b->SetNumberOfComponents(1);
1238 b->SetNumberOfTuples(
m_SSM->GetNumberOfModes());
1240 m_SSM->GetSurfaceSimilarityParameters(
m_SSM->GetShape(j),
scale, tx, ty, tz, theta, phi, psi, b);
1242 for(
int k = 0; k <
m_SSM->GetNumberOfModes(); k ++)
1243 table->SetValue(j, k, b->GetValue(k));
1245 qApp->processEvents();
1249 plot->setPlotTypeSurface();
1250 plot->setName(
"Training Shape Parameters of the Shape Model");
1252 plot->legend(
false);
1253 plot->SetSource(table);
1254 plot->generatePlot();
1264 m_SSM->SetPoseType(1);
1266 m_SSM->SetPoseType(2);
1268 m_SSM->SetPoseType(3);
1270 m_SSM->RemoveProcrustesAlignedPoints();
1295 msgBox.setText(
"Models now aligned. Set the window to desired view and try again.");
1303 QSettings settings(
"Shekhar Chandra",
"milxQt");
1304 QString path = settings.value(
"recentPath").toString(), filenamePrefix;
1306 QFileDialog *fileSaver =
new QFileDialog(
this);
1308 filenamePrefix = fileSaver->getSaveFileName(
this,
1309 tr(
"Select File Name Prefix to Save"),
1311 tr(
"All Files (*.*)"));
1313 if(filenamePrefix.isEmpty())
1319 QFileInfo fi(filenamePrefix);
1320 QString filename = fi.path()+
"/" + fi.baseName();
1322 const int n =
m_SSM->GetNumberOfShapes();
1324 for(
int j = 0; j < n; j ++)
1329 qApp->processEvents();
1348 QSettings settings(
"Shekhar Chandra",
"milxQt");
1349 QString path = settings.value(
"recentPath").toString(), filenamePrefix;
1351 QFileDialog *fileSaver =
new QFileDialog(
this);
1353 filenamePrefix = fileSaver->getSaveFileName(
this,
1354 tr(
"Select File Name Prefix to Save"),
1356 tr(
"All Files (*.*)"));
1358 if(filenamePrefix.isEmpty())
1364 QFileInfo fi(filenamePrefix);
1365 QString filename = fi.path()+
"/" + fi.baseName();
1366 QString ext = fi.suffix();
1370 const int n =
m_SSM->GetNumberOfShapes();
1372 for(
int j = 0; j < n; j ++)
1377 QPointer<milxQtFile> writer =
new milxQtFile;
1378 QString paddedNumber = QString(
"%1").arg(j, 3, 10, QChar(
'0'));
1379 QString newFilename = filename + paddedNumber +
"." + ext;
1382 qApp->processEvents();
1398 QSettings settings(
"Shekhar Chandra",
"milxQt");
1399 QString path = settings.value(
"recentPath").toString(), filenamePrefix;
1401 QFileDialog *fileSaver =
new QFileDialog(
this);
1403 filenamePrefix = fileSaver->getSaveFileName(
this,
1404 tr(
"Select File Name Prefix to Save"),
1406 tr(
"All Files (*.*)"));
1408 if(filenamePrefix.isEmpty())
1414 QFileInfo fi(filenamePrefix);
1415 QString filename = fi.path()+
"/" + fi.baseName();
1416 QString ext = fi.suffix();
1420 const int n =
m_SSM->GetNumberOfShapes();
1422 for(
int j = 0; j < n; j ++)
1427 QPointer<milxQtFile> writer =
new milxQtFile;
1428 QString paddedNumber = QString(
"%1").arg(j, 3, 10, QChar(
'0'));
1429 QString newFilename = filename + paddedNumber +
"." + ext;
1432 qApp->processEvents();
1451 msgBox.setText(
"Models now aligned. Set the window to desired view and try again.");
1459 QSettings settings(
"Shekhar Chandra",
"milxQt");
1460 QString path = settings.value(
"recentPath").toString(), filenamePrefix;
1462 QFileDialog *fileSaver =
new QFileDialog(
this);
1464 filenamePrefix = fileSaver->getSaveFileName(
this,
1465 tr(
"Select File Name Prefix to Save"),
1467 tr(
"All Files (*.*)"));
1469 if(filenamePrefix.isEmpty())
1475 QFileInfo fi(filenamePrefix);
1476 QString filename = fi.path()+
"/" + fi.baseName();
1478 const int noOfPoints =
m_SSM->GetShape(0)->GetNumberOfPoints();
1479 const int n =
m_SSM->GetNumberOfShapes();
1482 vtkSmartPointer<vtkLookupTable> colorLookupTable = vtkSmartPointer<vtkLookupTable>::New();
1483 colorLookupTable->SetTableRange(0, noOfPoints);
1484 colorLookupTable->Build();
1486 vtkSmartPointer<vtkUnsignedCharArray> colors = vtkSmartPointer<vtkUnsignedCharArray>::New();
1487 colors->SetNumberOfComponents(3);
1488 colors->SetName(
"Colors");
1490 for(
int j = 0; j < noOfPoints; j ++)
1494 colorLookupTable->GetColor(j, dcolor);
1496 unsigned char color[3];
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]);
1502 colors->InsertNextTupleValue(color);
1505 for(
int j = 0; j < n; j ++)
1511 qApp->processEvents();
1516 for(
int j = 0; j < n; j ++)
1521 qApp->processEvents();
1541 msgBox.setText(
"Models now aligned. Set the window to desired view and try again.");
1549 QSettings settings(
"Shekhar Chandra",
"milxQt");
1550 QString path = settings.value(
"recentPath").toString(), filenamePrefix;
1552 QFileDialog *fileSaver =
new QFileDialog(
this);
1554 filenamePrefix = fileSaver->getSaveFileName(
this,
1555 tr(
"Select File Name Prefix to Save"),
1557 tr(
"All Files (*.*)"));
1559 if(filenamePrefix.isEmpty())
1565 QFileInfo fi(filenamePrefix);
1566 QString filename = fi.path()+
"/" + fi.baseName();
1568 const int noOfPoints =
m_SSM->GetShape(0)->GetNumberOfPoints();
1569 const int n =
m_SSM->GetNumberOfShapes();
1572 vtkSmartPointer<vtkLookupTable> colorLookupTable = vtkSmartPointer<vtkLookupTable>::New();
1573 colorLookupTable->SetTableRange(0, 2.0*vtkMath::Pi() * 2.0*vtkMath::Pi());
1574 colorLookupTable->Build();
1576 for(
int j = 0; j < n; j ++)
1578 vtkSmartPointer<vtkPolyData> shape =
m_SSM->GetProcrustesAlignedSurface(j);
1580 vtkSmartPointer<vtkSphericalTransform> transform = vtkSmartPointer<vtkSphericalTransform>::New();
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();
1588 vtkSmartPointer<vtkUnsignedCharArray> colors = vtkSmartPointer<vtkUnsignedCharArray>::New();
1589 colors->SetNumberOfComponents(3);
1590 colors->SetNumberOfTuples(noOfPoints);
1591 colors->SetName(
"Colors");
1593 for(
int k = 0; k < noOfPoints; k ++)
1595 double dcolor[3], point[3];
1596 transformedShape->GetPoint(k, point);
1599 colorLookupTable->GetColor(point[1]*point[2], dcolor);
1601 unsigned char color[3];
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]);
1607 colors->SetTupleValue(k, color);
1614 qApp->processEvents();
1633 const int n =
m_SSM->GetNumberOfShapes();
1635 printInfo(
"Replacing Original Models.");
1636 for(
int j = 0; j < n; j ++)
1639 m_SSM->GetShape(j)->SetPoints(
m_SSM->GetAlignedPoints(j));
1642 double otherCentroidSize =
m_models[j]->centroidSize();
1646 vtkSmartPointer<vtkTransform> transformer = vtkSmartPointer<vtkTransform>::New();
1648 transformer->Scale(otherCentroidSize, otherCentroidSize, otherCentroidSize);
1650 m_models[j]->SetTransform(transformer);
1653 qApp->processEvents();
1683 void milxQtShapeModel::reset()
1699 const int n =
m_SSM->GetNumberOfShapes();
1702 offScreenWin->generateRender();
1703 offScreenWin->SetBackground(1, 1, 1);
1704 offScreenWin->OffScreenRenderingOn();
1705 vtkRenderer *ren = offScreenWin->GetRenderer();
1708 printInfo(
"Found " + QString::number(n) +
" shapes to check.");
1709 for(
int j = 0; j < n; j ++)
1711 QString tmpName = filename + QString::number(j) +
".png";
1715 offScreenWin->Render();
1717 qApp->processEvents();
1719 vtkSmartPointer<vtkWindowToImageFilter> windowToImage = vtkSmartPointer<vtkWindowToImageFilter>::New();
1720 windowToImage->SetInput(offScreenWin->GetRenderWindow());
1721 windowToImage->Update();
1723 vtkSmartPointer<vtkPNGWriter> writer = vtkSmartPointer<vtkPNGWriter>::New();
1724 writer->SetFileName(tmpName.toStdString().c_str());
1725 writer->SetInput(windowToImage->GetOutput());
1730 qApp->processEvents();
1737 contextMenu->setTitle(QApplication::translate(
"MainWindow",
"Shape Modelling", 0, QApplication::UnicodeUTF8));
1740 actionMean->setText(QApplication::translate(
"SSM",
"&Mean Model", 0, QApplication::UnicodeUTF8));
1745 actionAligned->setText(QApplication::translate(
"SSM",
"&Aligned Points", 0, QApplication::UnicodeUTF8));
1750 actionOriginal->setText(QApplication::translate(
"SSM",
"&Original Points", 0, QApplication::UnicodeUTF8));
1755 actionModesAsVectors->setText(QApplication::translate(
"SSM",
"Modes as &Vectors", 0, QApplication::UnicodeUTF8));
1760 actionModesAsTensors->setText(QApplication::translate(
"SSM",
"Modes as &Tensors", 0, QApplication::UnicodeUTF8));
1765 actionModesAsCollection->setText(QApplication::translate(
"SSM",
"Modes as Surface &Collection", 0, QApplication::UnicodeUTF8));
1768 actionCorrespond->setText(QApplication::translate(
"SSM",
"Correspondences as a &Hedgehog", 0, QApplication::UnicodeUTF8));
1775 actionCompact->setText(QApplication::translate(
"SSM",
"Compactness", 0, QApplication::UnicodeUTF8));
1778 actionSpecificity->setText(QApplication::translate(
"SSM",
"Specificity", 0, QApplication::UnicodeUTF8));
1781 actionGeneralise->setText(QApplication::translate(
"SSM",
"Generalisability", 0, QApplication::UnicodeUTF8));
1784 actionValues->setText(QApplication::translate(
"SSM",
"Eigenvalues", 0, QApplication::UnicodeUTF8));
1787 actionModes->setText(QApplication::translate(
"SSM",
"Primary Eigenmodes", 0, QApplication::UnicodeUTF8));
1790 actionParameters->setText(QApplication::translate(
"SSM",
"Training Shape Parameters", 0, QApplication::UnicodeUTF8));
1795 actionRigid->setText(QApplication::translate(
"SSM",
"Rigid", 0, QApplication::UnicodeUTF8));
1799 actionSimilarity->setText(QApplication::translate(
"SSM",
"Similarity", 0, QApplication::UnicodeUTF8));
1804 actionAffine->setText(QApplication::translate(
"SSM",
"Affine", 0, QApplication::UnicodeUTF8));
1813 actionAlignment->setText(QApplication::translate(
"SSM",
"Output &Alignment as Images", 0, QApplication::UnicodeUTF8));
1816 actionOriginalMeshes->setText(QApplication::translate(
"SSM",
"Output &Original Meshes", 0, QApplication::UnicodeUTF8));
1819 actionAlignedMeshes->setText(QApplication::translate(
"SSM",
"Output &Aligned Meshes", 0, QApplication::UnicodeUTF8));
1822 actionPointIDs->setText(QApplication::translate(
"SSM",
"Output &Point IDs as Images", 0, QApplication::UnicodeUTF8));
1825 actionCoordinates->setText(QApplication::translate(
"SSM",
"Output &Coordinates as Images", 0, QApplication::UnicodeUTF8));
1829 actionReplaceOriginal->setText(QApplication::translate(
"SSM",
"Replace Originals with Aligned", 0, QApplication::UnicodeUTF8));
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.");
1883 actionCompact->setToolTip(
"Plot the compactness of the shape model.");
1884 actionCompact->setStatusTip(
"Plot the compactness 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.");
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.");
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.");
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.");
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?
void generateVectorField()
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.
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.
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.
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.
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...
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.
void generateTensorField()
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.
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.
void generateCorrespondences()