Fraxinus  18.10
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 "cxDataReaderWriter.h"
22 #include "cxRegistrationService.h"
24 #include "cxPatientModelService.h"
25 #include "cxViewService.h"
26 #include "cxVolumeHelpers.h"
27 #include "cxLogger.h"
28 #include "cxFilePathProperty.h"
29 
30 namespace cx
31 {
32 
34  mServices(services)
35 {
36  mOptions = profile()->getXmlSettings().descend(ElastixParameters::getConfigUid());
37 
38  mParameters.reset(new ElastixParameters(mOptions));
39  connect(mParameters.get(), SIGNAL(elastixParametersChanged()), this, SIGNAL(elastixChanged()));
40 
41  mDisplayProcessMessages = BoolProperty::initialize("displayProcessMessages",
42  "Show Messages",
43  "Display messages from the running registration process in CustusX",
44  false,
45  mOptions.getElement());
46 
47  mDisableRendering = BoolProperty::initialize("disableRendering",
48  "Disable Rendering",
49  "Disable rendering while running process.\n"
50  "Can be used to avoid clash in GPU usage.",
51  false,
52  mOptions.getElement());
53 
54  mExecuter.reset(new ElastixExecuter(services));
55  connect(mExecuter.get(), SIGNAL(finished()), this, SLOT(executionFinishedSlot()));
56  connect(mExecuter.get(), SIGNAL(aboutToStart()), this, SLOT(preprocessExecuter()));
57 }
58 
60 {
61 }
62 
64 {
65  mExecuter->execute();
66 }
67 
68 void ElastixManager::preprocessExecuter()
69 {
70  QStringList parameterFiles = mParameters->getActiveParameterFiles();
71  QString timestamp = QDateTime::currentDateTime().toString(timestampSecondsFormat());
72  QDir outDir(mServices->patient()->getActivePatientFolder()+"/"+mParameters->getConfigUid()+"/"+timestamp);
73 
74  mExecuter->setDisplayProcessMessages(mDisplayProcessMessages->getValue());
75  mExecuter->setInput(mParameters->getActiveExecutable()->getEmbeddedPath().getAbsoluteFilepath(),
76  mServices->registration()->getFixedData(),
77  mServices->registration()->getMovingData(),
78  outDir.absolutePath(),
79  parameterFiles);
80 
81  if (mDisableRendering->getValue())
82  {
83  mServices->view()->enableRender(false);
84  }
85 }
86 
87 void ElastixManager::executionFinishedSlot()
88 {
89  if (mDisableRendering->getValue())
90  mServices->view()->enableRender(true);
91 
92  bool ok = false;
93  Transform3D mMf = mExecuter->getAffineResult_mMf(&ok);
94 
95  if (!ok)
96  return;
97 
98 // std::cout << "ElastixManager::executionFinishedSlot(), Linear Result mMf: \n" << mMf << std::endl;
99 
100  QStringList parameterFiles = mParameters->getActiveParameterFiles();
101  QString desc = QString("Image2Image [exe=%1]").arg(QFileInfo(mParameters->getActiveExecutable()->getValue()).fileName());
102  for (unsigned i=0; i<parameterFiles.size(); ++i)
103  desc += QString("[par=%1]").arg(QFileInfo(parameterFiles[i]).fileName());
104 
105  // Start with fMr * D * rMm = fMm'
106  // where the lhs is the existing data and the delta that is input to regmanager,
107  // and the rhs is the (inverse of the) output from ElastiX.
108  // This gives
109  // D = rMf * fMm' * mMr
110  // as the input to regmanager applyImage2ImageRegistration()
111 
112  Transform3D delta_pre_rMd =
113  mServices->registration()->getFixedData()->get_rMd()
114  * mMf.inv()
115  * mServices->registration()->getMovingData()->get_rMd().inv();
116 
117 // std::cout << "ElastixManager::executionFinishedSlot(), delta_pre_rMd: \n" << delta_pre_rMd << std::endl;
118 // std::cout << "ElastixManager::executionFinishedSlot(), expected new rMdm: \n" << mServices->registration()->getFixedData()->get_rMd() * mMf.inv() << std::endl;
119 
120 // mServices->registration()->addImage2ImageRegistration(mMf.inv(), desc);
121  mServices->registration()->addImage2ImageRegistration(delta_pre_rMd, desc);
122 
123  // add nonlinear data AFTER registering - we dont want these data to be double-registered!
124  this->addNonlinearData();
125 }
126 
131 void ElastixManager::addNonlinearData()
132 {
133  bool ok = true;
134  QString nonlinearVolumeFilename = mExecuter->getNonlinearResultVolume(&ok);
135 
136  if (!ok)
137  return;
138 
139  ImagePtr movingImage = boost::dynamic_pointer_cast<Image>(mServices->registration()->getMovingData());
140  ImagePtr raw = boost::dynamic_pointer_cast<Image>(MetaImageReader().load(nonlinearVolumeFilename, nonlinearVolumeFilename));
141 
142  if (!raw)
143  {
144  report(QString("Failed to import nonlinear volume %1").arg(nonlinearVolumeFilename));
145  return;
146  }
147 
148  QString uid = movingImage->getUid() + "_nl%1";
149  QString name = movingImage->getName()+" nl%1";
150 
151  ImagePtr nlVolume = createDerivedImage(mServices->patient(),
152  uid, name,
153  raw->getBaseVtkImageData(), movingImage);
154 
155  // volume is resampled into the space of the fixed data:
156  nlVolume->get_rMd_History()->setRegistration(mServices->registration()->getFixedData()->get_rMd());
157 
158  mServices->patient()->insertData(nlVolume);
159 
160  report(QString("Added volume %1, created by a nonlinear transform").arg(nlVolume->getName()));
161 }
162 
163 } /* 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.
virtual DataPtr load(const QString &uid, const QString &filename)
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
Reader for metaheader .mhd files.
Namespace for all CustusX production code.