18 #include "milxQtSSMPlugin.h" 23 #include <milxQtFile.h> 28 MainWindow = qobject_cast<
milxQtMain *>(theParent);
34 pluginName =
"Statistical Shape Model (SSM)";
44 dock =
new QDockWidget(tr(
"Manager"), MainWindow);
45 dock->setFeatures(QDockWidget::AllDockWidgetFeatures);
47 dock->setObjectName(
"Manager");
50 txtAtlasName =
new QLineEdit;
51 btnAtlasName =
new QPushButton;
52 comboSurfaceNames =
new QListWidget;
53 btnSurfaceNames =
new QPushButton;
54 btnClearSurfaceNames =
new QPushButton;
62 milxQtSSMPlugin::~milxQtSSMPlugin()
66 cerr <<
"SSM Destroyed" << endl;
76 QString openSSMExt =
"Shape Model Files (*.ssm *.rssm)";
103 QString saveSSMExt =
"Shape Model Files (*.ssm *.rssm)";
110 cout <<
"Loading Collection via the SSM Plugin" << endl;
113 shapes.last()->setConsole(
console);
114 shapes.last()->SetInputCollection(collection, filenames);
117 connect(shapes.last(), SIGNAL(collectionAvailable(vtkPolyDataCollection*, QStringList&)),
this, SLOT(passOnCollection(vtkPolyDataCollection*, QStringList&)));
118 cout <<
"Loaded Collection as a Normal SSM." << endl;
121 QStringList headingList;
123 headingList <<
"Index" <<
"Case ID";
126 caseTabIndex =
manager->newTab(
"Case Browser", headingList);
130 manager->clearTab(caseTabIndex);
132 cout <<
"Loading cases into browser." << endl;
133 QList< int > cases = shapes.last()->getCaseIDs();
134 for(
int j = 0; j < cases.size(); j ++)
136 QStringList caseList;
138 caseList << QString::number(j) <<
"Case " + QString::number(cases[j]);
140 manager->addItem(caseTabIndex, caseList, Qt::NoItemFlags);
144 cout <<
"Done." << endl;
149 cout <<
"Loading Collection via the SSM Plugin" << endl;
152 robustShapes.last()->setConsole(
console);
153 robustShapes.last()->SetInputCollection(collection, atlasSurface, filenames);
156 connect(robustShapes.last(), SIGNAL(collectionAvailable(vtkPolyDataCollection*, QStringList&)),
this, SLOT(passOnCollection(vtkPolyDataCollection*, QStringList&)));
157 cout <<
"Loaded Collection as a Robust SSM." << endl;
159 if(!robustShapes.last()->isLoaded())
161 cout <<
"Model failed to be loaded. See log/terminal output." << endl;
166 QStringList headingList;
168 headingList <<
"Index" <<
"Case ID";
171 caseTabIndex =
manager->newTab(
"Case Browser", headingList);
175 manager->clearTab(caseTabIndex);
177 cout <<
"Loading cases into browser." << endl;
178 QList< int > cases = robustShapes.last()->getCaseIDs();
179 for(
int j = 0; j < cases.size(); j ++)
181 QStringList caseList;
183 caseList << QString::number(j) <<
"Case " + QString::number(cases[j]);
185 manager->addItem(caseTabIndex, caseList, Qt::NoItemFlags);
189 cout <<
"Done." << endl;
194 if(filename.contains(
".rssm", Qt::CaseInsensitive))
196 cout <<
"Loading as Robust Shape Model" << endl;
199 robustShapes.last()->setConsole(
console);
200 robustShapes.last()->openModel(filename);
203 connect(robustShapes.last(), SIGNAL(collectionAvailable(vtkPolyDataCollection*, QStringList&)),
this, SLOT(passOnCollection(vtkPolyDataCollection*, QStringList&)));
205 else if(filename.contains(
".ssm", Qt::CaseInsensitive))
207 cout <<
"Loading as Normal Shape Model" << endl;
210 shapes.last()->setConsole(
console);
211 shapes.last()->openModel(filename);
214 connect(shapes.last(), SIGNAL(collectionAvailable(vtkPolyDataCollection*, QStringList&)),
this, SLOT(passOnCollection(vtkPolyDataCollection*, QStringList&)));
218 cout <<
"File extension not supported." << endl;
223 cout <<
"Loaded SSM File." << endl;
228 cout <<
"Saving as an SSM file" << endl;
229 if(filename.contains(
".rssm", Qt::CaseInsensitive))
230 robustShapes.last()->saveModel(filename);
231 else if(filename.contains(
".ssm", Qt::CaseInsensitive))
232 shapes.last()->saveModel(filename);
235 cout <<
"File Extension not support!" << endl;
240 cout <<
"Done." << endl;
247 cout <<
"Creating Normal SSM Model for display." << endl;
248 shapes.last()->generateMeanModel();
249 shapes.last()->setName(dataName);
250 shapes.last()->generateRender();
252 return shapes.last();
255 cout <<
"Creating Robust SSM Model for display." << endl;
256 robustShapes.last()->generateMeanModel();
257 robustShapes.last()->setName(dataName);
258 robustShapes.last()->generateRender();
260 return robustShapes.last();
267 QPointer<milxQtModel> model = shapes.last()->getMeanModel();
268 model->setName(dataName +
" - Mean Model");
269 model->setDeletableOnClose(
false);
274 QPointer<milxQtModel> model = robustShapes.last()->getMeanModel();
275 model->setName(dataName +
" - Mean Model");
276 model->setDeletableOnClose(
false);
281 bool milxQtSSMPlugin::isPluginRobustWindow(QWidget *window)
291 if(pluginWindow(window) == 0)
321 void milxQtSSMPlugin::preStartTasks()
323 cout <<
"Pre Start Tasks" << endl;
324 if(dataName.contains(
".rssm", Qt::CaseInsensitive))
326 cout <<
"Loading as Robust Shape Model" << endl;
330 else if(dataName.contains(
".ssm", Qt::CaseInsensitive))
332 cout <<
"Loading as Normal Shape Model" << endl;
338 void milxQtSSMPlugin::postStartTasks()
340 cout <<
"Post Start Tasks" << endl;
341 if(dataName.contains(
".rssm", Qt::CaseInsensitive))
343 robustShapes.last()->generateMeanModel();
344 robustShapes.last()->generateRender();
346 else if(dataName.contains(
".ssm", Qt::CaseInsensitive))
348 shapes.last()->generateMeanModel();
349 shapes.last()->generateRender();
352 cout <<
"Creating Shape Model Display" << endl;
354 cout <<
"Creating Mean Display" << endl;
357 cout <<
"Updating Plugin" << endl;
366 QMutexLocker locker(&mutex);
370 QTime *timer =
new QTime;
373 cout <<
"Executing load." << endl;
374 if(dataName.contains(
".rssm", Qt::CaseInsensitive))
376 robustShapes.last()->setName(dataName);
377 robustShapes.last()->openModel(dataName);
378 robustShapes.last()->generateSSM();
380 else if(dataName.contains(
".ssm", Qt::CaseInsensitive))
382 shapes.last()->setName(dataName);
383 shapes.last()->openModel(dataName);
384 shapes.last()->generateSSM();
397 cout <<
"Completed load." << endl;
399 duration = timer->elapsed();
400 cout <<
"Computation took: " << QString::number(duration/1000.0).toStdString() <<
" secs" << endl;
406 void milxQtSSMPlugin::update()
409 manager->clearTab(modelTabIndex);
415 if(!shapes.isEmpty() || !robustShapes.isEmpty())
431 QStringList headings;
433 headings <<
"Model Name" <<
"# Shapes" <<
"Weight" <<
"";
435 modelTabIndex =
manager->newTab(
"Model Browser", headings);
442 manager->clearTab(modelTabIndex);
460 foreach(QPointer<milxQtShapeModel> currModel, shapes)
462 QStringList modelEntry;
464 size_t n = currModel->GetNumberOfShapes();
468 modelEntry << currModel->strippedName() << QString::number(n) <<
"1.0";
470 manager->addItem(modelTabIndex, modelEntry, Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
481 const int n = shapes.last()->GetNumberOfShapes();
483 cout <<
"Creating a Multi-Model by Fusing " << n <<
" Shapes together." << endl;
484 vtkPolyDataCollection* collection = vtkPolyDataCollection::New();
485 for(
int j = 0; j < n; j ++)
489 foreach(QPointer<milxQtShapeModel> shape, shapes)
491 hybridModel->
AddInput( shape->GetShape(j) );
494 qApp->processEvents();
501 collection->AddItem( hybridModel->
GetOutput() );
503 qApp->processEvents();
511 cout <<
"Displayed Hybrid Shape." << endl;
517 void milxQtSSMPlugin::focusedModel()
519 int ret = wizard.exec();
521 if(ret == QDialog::Rejected)
527 atlasFilename = txtAtlasName->text();
530 cout <<
"Opening atlas model" << endl;
531 vtkSmartPointer<vtkPolyData> atlasMesh;
533 QPointer<milxQtModel> atlasModel =
new milxQtModel;
534 atlasModel->
setName(atlasFilename);
535 atlasModel->SetInput(atlasMesh);
536 atlasModel->generateModel();
540 vtkPolyDataCollection* modelCollection = vtkPolyDataCollection::New();
546 if(!file->openModelCollection(modelCollection, surfaceFilenames))
548 cout <<
"Unable to read selected files." << endl;
553 cout <<
"Computing Model..." << endl;
566 QSettings settings(
"Shekhar Chandra",
"milxQt");
568 QString exts = openModelExts.c_str();
569 QString path = settings.value(
"recentPath").toString();
571 QFileDialog *fileOpener =
new QFileDialog;
572 atlasFilename = fileOpener->getOpenFileName(&wizard,
573 tr(
"Select Atlas Surface to Open"),
575 tr(exts.toStdString().c_str()) );
576 txtAtlasName->setText(atlasFilename);
581 QSettings settings(
"Shekhar Chandra",
"milxQt");
583 QString exts = openModelExts.c_str();
584 QString path = settings.value(
"recentPath").toString();
586 QFileDialog *fileOpener =
new QFileDialog;
587 surfaceFilenames = fileOpener->getOpenFileNames(&wizard,
588 tr(
"Select Training Surfaces to Open"),
590 tr(exts.toStdString().c_str()) );
591 comboSurfaceNames->insertItems(0, surfaceFilenames);
594 void milxQtSSMPlugin::closedSSM(QWidget *win)
597 shapes.removeAll(tmpModel);
601 void milxQtSSMPlugin::passOnCollection(vtkPolyDataCollection *modelCollection, QStringList &filenames)
603 cout <<
"Passing On Collection Signal" << endl;
607 void milxQtSSMPlugin::createActions()
610 actionMultiModel->setText(QApplication::translate(
"SSMPlugin",
"Create &Multi-Model", 0, QApplication::UnicodeUTF8));
613 actionFocusModel->setText(QApplication::translate(
"SSMPlugin",
"Create &Focused Model", 0, QApplication::UnicodeUTF8));
617 void milxQtSSMPlugin::createMenu()
619 menuSSM =
new QMenu(MainWindow);
620 menuSSM->setTitle(QApplication::translate(
"SSMPlugin",
"Shape Models", 0, QApplication::UnicodeUTF8));
628 void milxQtSSMPlugin::createWizard()
632 QWizardPage *introPage =
new QWizardPage;
633 introPage->setTitle(
"Introduction");
635 QLabel *label1 =
new QLabel(
"This wizard will help you create a focused model from your training surfaces.");
636 label1->setWordWrap(
true);
637 QLabel *label2 =
new QLabel(
"You will be asked to provide an atlas/template mesh with scalars representing the weights for the model.");
638 label2->setWordWrap(
true);
639 QLabel *label3 =
new QLabel(
"You will be asked to provide training surfaces (with correspondences pre-computed) for the model.");
640 label3->setWordWrap(
true);
641 QVBoxLayout *introLayout =
new QVBoxLayout;
642 introLayout->addWidget(label1);
643 introLayout->addWidget(label2);
644 introLayout->addWidget(label3);
645 introPage->setLayout(introLayout);
648 QWizardPage *atlasPage =
new QWizardPage;
649 atlasPage->setTitle(
"Atlas Surface with Weights");
651 QLabel *label4 =
new QLabel(
"Please provide an atlas/template mesh with scalars representing the weights for the model.");
652 QLabel *label4b =
new QLabel(
"Atlas/template mesh with scalars must have correspondence with training surfaces.");
653 QLabel *label4c =
new QLabel(
"Atlas/template mesh with scalars must not have zero values. Replace any with very small values.");
654 label4->setWordWrap(
true);
657 btnAtlasName->setText(
"Browse...");
658 QHBoxLayout *atlasNameLayout =
new QHBoxLayout;
659 atlasNameLayout->addWidget(txtAtlasName);
660 atlasNameLayout->addWidget(btnAtlasName);
661 QGroupBox *atlasGroupBox =
new QGroupBox(
"Atlas/Template Surface Filename");
662 atlasGroupBox->setLayout(atlasNameLayout);
663 QVBoxLayout *atlasLayout =
new QVBoxLayout;
664 atlasLayout->addWidget(label4);
665 atlasLayout->addWidget(label4b);
666 atlasLayout->addWidget(label4c);
667 atlasLayout->addWidget(atlasGroupBox);
668 atlasPage->setLayout(atlasLayout);
671 QWizardPage *surfacesPage =
new QWizardPage;
672 surfacesPage->setTitle(
"Training Surfaces");
674 QLabel *label5 =
new QLabel(
"Please provide training surfaces (with correspondences pre-computed) for the model.");
675 label5->setWordWrap(
true);
679 btnSurfaceNames->setText(
"Add...");
680 btnClearSurfaceNames->setText(
"Clear");
681 QFormLayout *surfaceNamesLayout =
new QFormLayout;
682 surfaceNamesLayout->addRow(btnClearSurfaceNames, btnSurfaceNames);
683 surfaceNamesLayout->addRow(comboSurfaceNames);
684 QGroupBox *surfacesGroupBox =
new QGroupBox(
"Atlas/Template Surface Filename");
685 surfacesGroupBox->setLayout(surfaceNamesLayout);
686 QVBoxLayout *surfacesLayout =
new QVBoxLayout;
687 surfacesLayout->addWidget(label5);
688 surfacesLayout->addWidget(surfacesGroupBox);
689 surfacesPage->setLayout(surfacesLayout);
692 wizard.addPage(introPage);
693 wizard.addPage(atlasPage);
694 wizard.addPage(surfacesPage);
696 wizard.setWindowTitle(
"Focused Model Wizard");
699 void milxQtSSMPlugin::createConnections()
707 connect(btnClearSurfaceNames, SIGNAL(clicked()), comboSurfaceNames, SLOT(clear()));
QPointer< milxQtManager > manager
Manager widget.
bool threaded
Threaded plugin?
QWidget * currentModel
Current model being viewed/processed.
QAction * actionMultiModel
hybrid model action
void save(QString filename)
Save the result as a file using the plugin. [Implement this in your plugin].
bool isPluginWindow(QWidget *window)
Is the window provided a plugin generated window? In this case a milxQtShapeModel window...
bool modelManagerCreated
Model Manager tab has been created?
void setName(const QString filename)
Set the name of the data.
void showAtlasFileDialog()
virtual void SetInputCollection(vtkPolyDataCollection *meshes)
Uses the collection of polydata to create shape model.
This class represents the MILX Qt Render Window Display object using QVTK.
bool consoleWindow
console window?
A manager (tabbed) widget class for displaying information about data such as case ID etc...
QStringList saveExtensions()
Get a list of supported file format extensions. [Implement this in your plugin].
bool extension
Extension rather than a plugin?
This class represents the MILX Qt File I/O object using VTK/ITK/Qt.
void showSurfacesFileDialog()
milxQtRobustShapeModel * pluginRobustWindow(QWidget *window)
void AddInput(vtkSmartPointer< vtkPolyData > mesh)
Assigns and coninually appends meshes provided to the class, preparing for display. Call generateModel() and then show() to display.
void resultAvailable(milxQtRenderWindow *)
Send signal that Resultant render window is available for showing.
static bool OpenModel(const std::string filename, vtkSmartPointer< vtkPolyData > &data)
Opens a model file, which can be a VTK XML, Legacy VTK PolyData File (i.e. either a *...
QPointer< QDockWidget > dock
Dock widget.
milxQtModel * modelResult()
Get the model result. The result can then be displayed in milxQtMain etc. [Implement this in your plu...
QAction * actionFocusModel
focus model action
void updateManager(QWidget *newWindow)
QStringList openExtensions()
Get a list of supported file format extensions. [Implement this in your plugin].
This class represents the MILX Qt Model/Mesh Display object using VTK.
bool dockable
Dockable plugin?
milxQtShapeModel * hybridShapeModel
Hybrid model.
milxQtConsole * console
console for logging
milxQtRenderWindow * genericResult()
Get the generic result, which is a milxQtRenderWindow. The result can then be displayed in milxQtMain...
void generateModel(float red=defaultColour, float green=defaultColour, float blue=defaultColour)
Generates the model so that its ready for display. It requires that data has been set or assigned alr...
void SetInputCollection(vtkPolyDataCollection *collection, QStringList &filenames)
Pass a collection to internal plugin class. [Implement this in your plugin].
The interface for any plugins that can be made for milxQtMain.
milxQtSSMPlugin(QObject *theParent=0)
vtkSmartPointer< vtkPolyData > GetOutput()
Returns the mesh data object (PolyData) used internally VTK style.
int GetNumberOfShapes()
Returns the number of shapes in the Statistical Shape Model. Assumes SSM has been generated (via gene...
bool caseManagerCreated
Model Manager tab has been created?
QString saveFileSupport()
Get the file support string for saving (extension wildcard list). [Implement this in your plugin]...
This class represents the MILX Qt Main Window object using Qt.
QString openFileSupport()
Get the file support string for opening (extension wildcard list). [Implement this in your plugin]...
void open(QString filename)
Open the file using the plugin. [Implement this in your plugin].
QString name()
Get the Name of the plugin. [Implement this in your plugin].