CustusX  2023.01.05-dev+develop.0da12
An IGT application
cxElastixManager.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
12 
13 #include "cxElastixManager.h"
14 
15 #include <QDir>
16 
17 #include "cxTime.h"
18 #include "cxProfile.h"
19 #include "cxElastixExecuter.h"
20 #include "cxSettings.h"
21 #include "cxRegistrationService.h"
23 #include "cxPatientModelService.h"
24 #include "cxViewService.h"
25 #include "cxVolumeHelpers.h"
26 #include "cxLogger.h"
27 #include "cxFilePathProperty.h"
28 #include "cxImage.h"
29 #include "cxFileManagerService.h"
30 
31 namespace cx
32 {
33 
35  mServices(services)
36 {
37  mOptions = profile()->getXmlSettings().descend(ElastixParameters::getConfigUid());
38 
39  mParameters.reset(new ElastixParameters(mOptions));
40  connect(mParameters.get(), SIGNAL(elastixParametersChanged()), this, SIGNAL(elastixChanged()));
41 
42  mDisplayProcessMessages = BoolProperty::initialize("displayProcessMessages",
43  "Show Messages",
44  "Display messages from the running registration process in CustusX",
45  false,
46  mOptions.getElement());
47 
48  mDisableRendering = BoolProperty::initialize("disableRendering",
49  "Disable Rendering",
50  "Disable rendering while running process.\n"
51  "Can be used to avoid clash in GPU usage.",
52  false,
53  mOptions.getElement());
54 
55  mExecuter.reset(new ElastixExecuter(services));
56  connect(mExecuter.get(), SIGNAL(finished()), this, SLOT(executionFinishedSlot()));
57  connect(mExecuter.get(), SIGNAL(aboutToStart()), this, SLOT(preprocessExecuter()));
58 }
59 
61 {
62 }
63 
65 {
66  mExecuter->execute();
67 }
68 
69 void ElastixManager::preprocessExecuter()
70 {
71  QStringList parameterFiles = mParameters->getActiveParameterFiles();
72  QString timestamp = QDateTime::currentDateTime().toString(timestampSecondsFormat());
73  QDir outDir(mServices->patient()->getActivePatientFolder()+"/"+mParameters->getConfigUid()+"/"+timestamp);
74 
75  mExecuter->setDisplayProcessMessages(mDisplayProcessMessages->getValue());
76  mExecuter->setInput(mParameters->getActiveExecutable()->getEmbeddedPath().getAbsoluteFilepath(),
77  mServices->registration()->getFixedData(),
78  mServices->registration()->getMovingData(),
79  outDir.absolutePath(),
80  parameterFiles);
81 
82  if (mDisableRendering->getValue())
83  {
84  mServices->view()->enableRender(false);
85  }
86 }
87 
88 void ElastixManager::executionFinishedSlot()
89 {
90  if (mDisableRendering->getValue())
91  mServices->view()->enableRender(true);
92 
93  bool ok = false;
94  Transform3D mMf = mExecuter->getAffineResult_mMf(&ok);
95 
96  if (!ok)
97  return;
98 
99 // std::cout << "ElastixManager::executionFinishedSlot(), Linear Result mMf: \n" << mMf << std::endl;
100 
101  QStringList parameterFiles = mParameters->getActiveParameterFiles();
102  QString desc = QString("Image2Image [exe=%1]").arg(QFileInfo(mParameters->getActiveExecutable()->getValue()).fileName());
103  for (unsigned i=0; i<parameterFiles.size(); ++i)
104  desc += QString("[par=%1]").arg(QFileInfo(parameterFiles[i]).fileName());
105 
106  // Start with fMr * D * rMm = fMm'
107  // where the lhs is the existing data and the delta that is input to regmanager,
108  // and the rhs is the (inverse of the) output from ElastiX.
109  // This gives
110  // D = rMf * fMm' * mMr
111  // as the input to regmanager applyImage2ImageRegistration()
112 
113  Transform3D delta_pre_rMd =
114  mServices->registration()->getFixedData()->get_rMd()
115  * mMf.inv()
116  * mServices->registration()->getMovingData()->get_rMd().inv();
117 
118 // std::cout << "ElastixManager::executionFinishedSlot(), delta_pre_rMd: \n" << delta_pre_rMd << std::endl;
119 // std::cout << "ElastixManager::executionFinishedSlot(), expected new rMdm: \n" << mServices->registration()->getFixedData()->get_rMd() * mMf.inv() << std::endl;
120 
121 // mServices->registration()->addImage2ImageRegistration(mMf.inv(), desc);
122  mServices->registration()->addImage2ImageRegistration(delta_pre_rMd, desc);
123 
124  // add nonlinear data AFTER registering - we dont want these data to be double-registered!
125  this->addNonlinearData();
126 }
127 
132 void ElastixManager::addNonlinearData()
133 {
134  bool ok = true;
135  QString nonlinearVolumeFilename = mExecuter->getNonlinearResultVolume(&ok);
136 
137  if (!ok)
138  return;
139 
140  ImagePtr movingImage = boost::dynamic_pointer_cast<Image>(mServices->registration()->getMovingData());
141  ImagePtr raw = boost::dynamic_pointer_cast<Image>(mServices->file()->load(nonlinearVolumeFilename, nonlinearVolumeFilename));
142 
143  if (!raw)
144  {
145  report(QString("Failed to import nonlinear volume %1").arg(nonlinearVolumeFilename));
146  return;
147  }
148 
149  QString uid = movingImage->getUid() + "_nl%1";
150  QString name = movingImage->getName()+" nl%1";
151 
152  ImagePtr nlVolume = createDerivedImage(mServices->patient(),
153  uid, name,
154  raw->getBaseVtkImageData(), movingImage);
155 
156  // volume is resampled into the space of the fixed data:
157  nlVolume->get_rMd_History()->setRegistration(mServices->registration()->getFixedData()->get_rMd());
158 
159  mServices->patient()->insertData(nlVolume);
160 
161  report(QString("Added volume %1, created by a nonlinear transform").arg(nlVolume->getName()));
162 }
163 
164 } /* namespace cx */
cxResource_EXPORT ProfilePtr profile()
Definition: cxProfile.cpp:160
static BoolPropertyPtr initialize(const QString &uid, QString name, QString help, bool value, QDomNode root=QDomNode())
static QString getConfigUid()
ElastixManager(RegServicesPtr services)
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:27
Parameter and preset handling for the ElastiX registration.
QString timestampSecondsFormat()
Definition: cxTime.cpp:18
QDomElement getElement()
return the current element
ImagePtr createDerivedImage(PatientModelServicePtr dataManager, QString uid, QString name, vtkImageDataPtr raw, ImagePtr parent)
ElastiX command-line wrapper.
A volumetric data set.
Definition: cxImage.h:45
boost::shared_ptr< class RegServices > RegServicesPtr
Definition: cxRegServices.h:20
void report(QString msg)
Definition: cxLogger.cpp:69
Namespace for all CustusX production code.