SMILX  1.01
milxQtRegistration.cpp
1 #include "milxQtRegistration.h"
2 #include "milxQtFile.h"
3 
4 
6 {
7  // Create the temporary files for the registration
8  if (createFiles() == EXIT_FAILURE)
9  {
10  return EXIT_FAILURE;
11  }
12 
13  // Start the registration
14  workDone = false;
15 
16  // Keep the time of start
17  this->startTime = QDateTime::currentMSecsSinceEpoch();
18 
19  if (this->type == AffineItk)
20  {
21  MainWindow->printInfo("New Itk Affine registration started.\n");
23  }
24  else if (this->type == DemonItk)
25  {
26  MainWindow->printInfo("New Itk Demon registration started.\n");
27  this->regAlgos->demon_async(params);
28  }
29 #ifdef USE_NIFTI_REG
30  else if (this->type == AladinNifti)
31  {
32  MainWindow->printInfo("New Nifti Aladin registration started.\n");
33  this->regAlgos->aladin_async(params);
34  }
35  else if (this->type == F3DNifti)
36  {
37  MainWindow->printInfo("New Nifti F3D registration started.\n");
38  this->regAlgos->f3d_async(params);
39  }
40 #endif
41 #ifdef USE_ELASTIX
42  else if (this->type == ElastixAffine)
43  {
44  MainWindow->printInfo("New Elastix Affine registration started.\n");
45  this->regAlgos->elastix_async(params);
46  }
47  else if (this->type == ElastixBSpline)
48  {
49  MainWindow->printInfo("New Elastix Bspline registration started.\n");
50  this->regAlgos->elastix_async(params);
51  }
52 #endif
53  return EXIT_SUCCESS;
54 }
55 
56 // Create the files required for the registration
58 {
59  // Image to register filename
60  QString filename = QFileInfo(path).baseName();
61 
62  // Create the tmp files
63  params.floatingName = createFile(QDir::tempPath() + QDir::separator() + "smili_reg_img_XXXXXX.nii.gz");
64  params.referenceName = createFile(QDir::tempPath() + QDir::separator() + "smili_reg_ref_XXXXXX.nii.gz");
65 
66  // Output path
67  params.outputName = createFile(this->outputFolder + QDir::separator() + filename + "_" + this->getAlgoName() + "_registered_XXXXXX.nii.gz");
68 
69  // If the file were not created properly
70  if (params.referenceName == "" || params.floatingName == "" || params.outputName == "")
71  {
72  return EXIT_FAILURE;
73  }
74 
75  // Create special files for nifti
76  if (this->type == F3DNifti)
77  {
78  // tmp file for nifti
79  params.cppOutputName = createFile(QDir::tempPath() + QDir::separator() + "smili_reg_cpp_XXXXXX.nii.gz");
80  if (params.cppOutputName == "")
81  {
82  return EXIT_FAILURE;
83  }
84 
85  // cpp output file for nifti
86  if (params.cpp2Def)
87  {
88  params.defOutputName = createFile(this->outputFolder + QDir::separator() + filename + "_" + this->getAlgoName() + "_deffield_XXXXXX.nii.gz");
89  if (params.defOutputName == "")
90  {
91  return EXIT_FAILURE;
92  }
93  }
94  }
95 
96  // Create the special file for Elastix
97  if ((this->type == ElastixAffine || this->type == ElastixBSpline) && params.customParameterFile == false)
98  {
99  params.parameterFile = createFile(QDir::tempPath() + QDir::separator() + "elastix_reg_params_XXXXXX.txt");
100  if (params.parameterFile == "")
101  {
102  return EXIT_FAILURE;
103  }
104  params.outputFolder = this->outputFolder;
105  }
106 
107  if ((this->type == ElastixAffine || this->type == ElastixBSpline) && params.customParameterFile == false)
108  {
109  // write the parameter file
110  QFile outputFile(params.parameterFile);
111  outputFile.open(QIODevice::WriteOnly);
112 
113  // Check it opened OK
114  if (!outputFile.isOpen()) {
115  // If not open !! error !
116  algoError("createFiles()", "Unable to write elastix parameter file: \"" + params.parameterFile + "\"");
117  return EXIT_FAILURE;
118  }
119  QTextStream outStream(&outputFile);
120  outStream << params.parametersTxt;
121  outputFile.close();
122  }
123 
124  // Copy the reference image and the image to register
125  if(this->window->isLoaded())
126  copyAndReplace(this->window, params.floatingName);
127  else
128  copyAndReplace(this->path, params.floatingName);
129  if(this->reference->getImage()->isLoaded())
130  copyAndReplace(this->reference->getImage(), params.referenceName);
131  else
132  copyAndReplace(this->reference->getPath(), params.referenceName);
133 
134  return EXIT_SUCCESS;
135 }
136 
137 // Return a string with the name of the algo
139 {
140  QString strTypeAlgo = "unknownalgo";
141  if (this->type == AffineItk) strTypeAlgo = "affineitk";
142  if (this->type == DemonItk) strTypeAlgo = "demonitk";
143  if (this->type == F3DNifti) strTypeAlgo = "f3dnifti";
144  if (this->type == AladinNifti) strTypeAlgo = "aladinnifti";
145  if (this->type == ElastixAffine) strTypeAlgo = "elastixaffine";
146  if (this->type == ElastixBSpline) strTypeAlgo = "elastixbspline";
147 
148  return strTypeAlgo;
149 }
150 
151 // Create the file for the Atlas and return the path
153 {
154  QString filename = QFileInfo(path).baseName();
155  return createFile(this->outputFolder + QDir::separator() + filename + "_" + this->getAlgoName() + "_atlas_XXXXXX.nii");
156 }
157 
158 // Create the similarity file containing the similarity after the registration was performed and return the filepath
160 {
161  QString filename = QFileInfo(path).baseName();
162  return createFile(this->outputFolder + QDir::separator() + filename + "_" + this->getAlgoName() + "_similarities_XXXXXX.csv");
163 }
164 
165 // Create the similarity file containing the similarity before the registration was performed and return the filepath
167 {
168  QString filename = QFileInfo(path).baseName();
169  return createFile(this->outputFolder + QDir::separator() + filename + "_" + this->getAlgoName() + "_similarities_before_XXXXXX.csv");
170 }
171 
172 // Copy a path from a QString to a char *
173 void milxQtRegistration::copyPath(char dest[FILENAME_MAX], QString src)
174 {
175  QByteArray byteArray = src.toAscii();
176  strncpy(dest, byteArray.data(), FILENAME_MAX);
177 }
178 
179 // Set the image as the reference
180 void milxQtRegistration::setIsRef(bool istheref)
181 {
182  if (istheref == true) {
183  this->checked = false;
184  }
185  this->isRefImg = istheref;
186 }
187 
188 // Is the image the reference image
190 {
191  return this->isRefImg;
192 }
193 
194 
196 {
197  this->computeSimilarities = value;
198 }
199 
200 // Return the duration of the registration
202 {
203  return (this->stopTime - this->startTime);
204 }
205 
206 
207 // Copy and replace
208 void milxQtRegistration::copyAndReplace(QString src, QString dst)
209 {
210  milxQtFile inFile, outFile;
211  milxQtImage *srcImage;
212 
213  MainWindow->printDebug("Converting image to Nifti format");
214  inFile.openImage(src, srcImage);
215 
216  outFile.saveImage(dst, srcImage);
217 }
218 
219 void milxQtRegistration::copyAndReplace(milxQtImage *src, QString dst)
220 {
221  milxQtFile outFile;
222 
223  MainWindow->printDebug("Saving image to Nifti format");
224  outFile.saveImage(dst, src);
225 }
226 
227 // Create a temporary file and store the path in a char array
228 QString milxQtRegistration::createFile(QString pathTemplate)
229 {
230  QTemporaryFile tmpFile(pathTemplate);
231  tmpFile.setAutoRemove(false);
232  if (!tmpFile.open()) {
233  algoError("createFile()", "Unable to create temporary file with template: \"" + pathTemplate + "\".\n");
234  return "";
235  }
236  tmpFile.close();
237 
238  MainWindow->printDebug("File \"" + tmpFile.fileName() + "\" created");
239 
240  return tmpFile.fileName();
241 }
242 
243 // Delete the temporary files
245 {
246  if (params.floatingName != "") {
247  if (QFile::exists(params.floatingName))
248  {
249  QFile::remove(params.floatingName);
250  MainWindow->printInfo("File \"" + params.floatingName + "\" removed");
251  }
252  }
253  if (params.referenceName != "") {
254  if (QFile::exists(params.referenceName))
255  {
256  QFile::remove(params.referenceName);
257  MainWindow->printInfo("File \"" + params.referenceName + "\" removed");
258  }
259  }
260  if (params.cppOutputName != "") {
261  if (QFile::exists(params.cppOutputName))
262  {
263  QFile::remove(params.cppOutputName);
264  MainWindow->printInfo("File \"" + params.cppOutputName + "\" removed");
265  }
266  }
267 
268  if (params.customParameterFile == false && params.parameterFile != "")
269  {
270  if (QFile::exists(params.parameterFile))
271  {
272  QFile::remove(params.parameterFile);
273  MainWindow->printInfo("File \"" + params.parameterFile + "\" removed");
274  }
275  }
276 
277  params.floatingName = "";
278  params.referenceName = "";
279  params.cppOutputName = "";
280  params.parameterFile = "";
281 }
282 
283 
285 {
286  MainWindow->printInfo("---------- Registration Completed ----------\n");
287 
288  // Keep the time of completition
289  this->stopTime = QDateTime::currentMSecsSinceEpoch();
290 
291  // We open the result
292  if (openResults)
293  {
294  MainWindow->loadFile(params.outputName);
295  }
296 
297 #ifdef USE_NIFTI_REG
298  // If we have to calculate the cpp2def, we start it
299  if (this->type == F3DNifti && params.cpp2Def)
300  {
301  MainWindow->printInfo("Deformation field computation");
302 
303  // Start cpp2def
304  this->regAlgos->cpp2def_async(params);
305 
306  return;
307  }
308 
310  {
311  this->regAlgos->similarities_async(this);
312  return;
313  }
314 #endif
315 
316  // Once done we mark the image as done and we uncheck it
317  this->workDone = true;
318  this->checked = false;
319 
320  // Otherwise we delete the temporary files
321  deleteTmpFiles();
322 
323  // We emit the done signaml
324  emit done();
325 }
326 
327 void milxQtRegistration::algoError(QString functionName, QString errorMsg)
328 {
329  // This image failed, but we marked it as done
330  this->workDone = true;
331  this->checked = false;
332 
333  // We delete the temporary files
334  deleteTmpFiles();
335 
336  // Emit the error
337  emit error(functionName, errorMsg);
338 }
339 
340 #ifdef USE_NIFTI_REG
341 
342 void milxQtRegistration::cpp2defCompleted()
343 {
344  MainWindow->printInfo("Deformation field computed\n");
345 
347  {
348  this->regAlgos->similarities_async(this);
349  return;
350  }
351 
352  // Once done we mark it as done and we unchecked the image
353  this->workDone = true;
354  this->checked = false;
355 
356  deleteTmpFiles();
357  emit done();
358 }
359 
360 void milxQtRegistration::similaritiesComputed()
361 {
362  MainWindow->printInfo("Similarities computed\n");
363 
364  // Once done we mark it as done and we unchecked the image
365  this->workDone = true;
366  this->checked = false;
367 
368  deleteTmpFiles();
369  emit done();
370 }
371 #endif
372 
373 milxQtRegistration::milxQtRegistration(QObject * parent, milxQtImage * imageWindow, milxQtMain * mainW) : QObject(parent)
374 {
375  init(imageWindow->getName());
376  MainWindow = mainW;
377  window = imageWindow;
378  openedImage = true;
379 }
380 
381 
382 milxQtRegistration::milxQtRegistration(QObject * parent, QString filepath, milxQtMain * mainW) : QObject(parent)
383 {
384  init(filepath);
385  MainWindow = mainW;
386 }
387 
389 {
390  // Delete regAlgos object
391  delete regAlgos;
392 }
393 
395 {
396  openResults = open;
397 }
398 
399 void milxQtRegistration::init(QString filepath)
400 {
401  path = filepath;
402  openedImage = false;
403  window = NULL;
404  checked = true;
405  workDone = false;
406  openResults = false;
407  isRefImg = false;
408  type = None;
409  outputFolder = QFileInfo(filepath).absolutePath();
410  regAlgos = new milxQtRegistrationAlgos(this);
411  startTime = 0;
412  stopTime = 0;
421  computeSimilarities = false;
422 
423  // Add a listener (registration completed)
424  connect(this->regAlgos, SIGNAL(registrationCompleted()), this, SLOT(registrationCompleted()));
425  connect(this->regAlgos, SIGNAL(error(QString, QString)), this, SLOT(algoError(QString, QString)));
426 
427 #ifdef USE_NIFTI_REG
428  // Add a listener (cpp2def completed) if we have nifti library
429  connect(this->regAlgos, SIGNAL(cpp2defCompleted()), this, SLOT(cpp2defCompleted()));
430 
431  // Add a listener for the similarities
432  connect(this->regAlgos, SIGNAL(similaritiesComputed()), this, SLOT(similaritiesComputed()));
433 #endif
434 }
435 
437 {
438  params.reset();
439  checked = false;
440  workDone = false;
441  startTime = 0;
442  stopTime = 0;
443  computeSimilarities = false;
452 }
453 
455 {
456  if (folder == "") {
457  outputFolder = QFileInfo(path).absolutePath();
458  }
459  else {
460  outputFolder = folder;
461  }
462 }
463 
465 {
466  return outputFolder;
467 }
468 
469 // Get the path of the image to register
471 {
472  return path;
473 }
474 
475 // get the ouput path of the image registeres
477 {
478  return params.outputName;
479 }
480 
482 {
483  checked = state;
484  if (isRef()) {
485  checked = false;
486  }
487 }
488 
490 {
491  return checked;
492 }
493 
495 {
496  return workDone;
497 }
498 
500 {
501  params = regparams;
502 }
503 
505 {
506  this->type = reg;
507 }
508 
510 {
511  reference = ref;
512 }
513 
515 {
516  return openedImage;
517 }
int createFiles()
Create the files required for the registration.
QString getAlgoName()
Return the name of the current algorithm.
void init(QString)
Initialise the class/object with default parameters.
bool isOpened()
Is the image open in SMILi.
bool isChecked()
Is the image checked (if we have to perform a registration)
void copyAndReplace(QString src, QString dst)
Copy and replace.
milxQtImage * window
MilxQt window of the image, if the image is already opened in SMILI.
Contain all the informations and functions required to register an image.
void affine_async(milxQtRegistrationParams params)
Perform a ITK affine registration asynchroniously.
~milxQtRegistration()
The standard destructor.
void algoError(QString functionName, QString errorMsg)
The registration and transformations have been done.
QString getPath()
Get the path of the file.
bool saveImage(const QString filename, vtkImageData *data)
Saves data as an image file, which is any of the following: JPEG, PNG, DICOM, TIFF, NIFTI, HDR etc.
Definition: milxQtFile.cpp:531
bool openedImage
Is the image already opened in SMILI.
This class represents the MILX Qt Image Display object using VTK.
Definition: milxQtImage.h:118
void copyPath(char dest[FILENAME_MAX], QString src)
Copy a path from a QString to a char *.
void deleteTmpFiles()
Delete the temporary files.
void done()
The registration and transformations have been done.
This class represents the MILX Qt File I/O object using VTK/ITK/Qt.
Definition: milxQtFile.h:60
void setReference(milxQtRegistration *)
Set the reference image.
bool workDone
Is the registration done.
void registrationCompleted()
The registration is completed.
void printDebug(QString msg)
Debug message wrapper for console.
Definition: milxQtMain.h:843
QString createSimilarityFileBefore()
Create the similarity file containing the similarity after the registration was performed and return ...
void setOpenResults(bool open)
Open the results after the registration.
bool openResults
Do we have to open the results after the registration.
bool isRef()
Is the image the reference image.
void printInfo(QString msg)
Info message wrapper for console.
Definition: milxQtMain.h:850
bool isWorkDone()
Is the registration/deformation field calculation completed.
milxQtMain * MainWindow
Main window of SMILI.
RegType type
Type of the registration.
void setComputeSimilarities(bool)
Set if we should compute the similarities.
QString createAtlasFile()
Create the file for the atlas and return the filepath.
void setParams(milxQtRegistrationParams)
Set the registration parameters.
double ncc
Normalized Cross Correlation.
QString createFile(QString pathtemplate)
Create a file and return the path.
milxQtSimilarities similarities_after
Similarities after the registration.
bool loadFile(const QString &filename)
Opens a file for viewing in the current tab.
Definition: milxQtMain.cpp:529
bool openImage(const QString filename, vtkImageData *data)
Opens an image file, which is any of the following: JPEG, PNG, DICOM, TIFF, NIFTI, HDR etc.
Definition: milxQtFile.cpp:75
bool isRefImg
Is this image the reference image.
bool checked
Is the image checked: do we need to perform a registration.
void setOutputFolder(QString)
Set the output folder for the registration.
double ssd
Sum Squared Difference.
bool isLoaded()
Is the data successfully loaded? Use this to check if all is ok with data display.
QString path
Path of the image.
bool computeSimilarities
Do we have to compute similarities.
QString createSimilarityFileAfter()
Create the similarity file containing the similarity after the registration was performed and return ...
QString getName()
Returns the name of the data.
Definition: milxQtWindow.h:67
milxQtRegistrationParams params
Parameters for registration.
qint64 startTime
Time start of the registration.
milxQtRegistration * reference
Reference image for the registration.
milxQtImage * getImage()
Return the image object for registration.
void setChecked(bool)
Do we have to perform a registration on this image (is the image check in the form) ...
double nmi
Normalize mutual information.
milxQtSimilarities similarities_before
Similarities before the registration.
qint64 getDuration()
Return the duration of the registration in milliseconds.
void demon_async(milxQtRegistrationParams params)
Perform a ITK demon registration asynchroniously.
void setRegType(RegType)
Set the registration type.
double lncc
Localy Normalized Cross Correlation.
void error(QString functionName, QString errorMsg)
The registration and transformations have been done.
void setIsRef(bool)
Set the image as the reference.
milxQtRegistration(QObject *parent, milxQtImage *imageWindow, milxQtMain *mainW)
The standard constructor.
int startRegistration()
Start the registrationf.
QString getOutputFolder()
Return the path of the output folder.
qint64 stopTime
Time the registration ended.
milxQtRegistrationAlgos * regAlgos
Class containing the algorithms for the registration.
This class represents the MILX Qt Main Window object using Qt.
Definition: milxQtMain.h:85
void reset()
Reset the class (It will be like no registration happened)
QString getOutputPath()
Return the path of the output file.
QString outputFolder
Path of the output folder.