36 mProcess =
new QProcess(
this);
37 connect(mProcess, SIGNAL(stateChanged(QProcess::ProcessState)),
this, SLOT(processStateChanged(QProcess::ProcessState)));
38 connect(mProcess, SIGNAL(error(QProcess::ProcessError)),
this, SLOT(processError(QProcess::ProcessError)));
39 connect(mProcess, SIGNAL(
finished(
int, QProcess::ExitStatus)),
this, SLOT(processFinished(
int, QProcess::ExitStatus)));
44 disconnect(mProcess, SIGNAL(error(QProcess::ProcessError)),
this, SLOT(processError(QProcess::ProcessError)));
50 disconnect(mProcess, SIGNAL(readyRead()),
this, SLOT(processReadyRead()));
54 connect(mProcess, SIGNAL(readyRead()),
this, SLOT(processReadyRead()));
56 mProcess->setProcessChannelMode(QProcess::MergedChannels);
57 mProcess->setReadChannel(QProcess::StandardOutput);
66 QStringList parameterfiles)
71 if (!fixed || !moving)
73 reportWarning(
"Failed to start elastiX registration, fixed or missing image missing.");
77 if (mProcess->state() != QProcess::NotRunning)
79 reportWarning(
"Failed to start elastiX registration, process already running");
84 QDir().mkpath(outdir);
86 QString initFilename = this->writeInitTransformToElastixfile(fixed, moving, outdir);
87 this->writeInitTransformToCalfile(fixed, moving, outdir);
92 cmd <<
"\"" + application +
"\"";
93 cmd <<
"-f" << mServices->patient()->getActivePatientFolder()+
"/"+fixed->getFilename();
94 cmd <<
"-m" << mServices->patient()->getActivePatientFolder()+
"/"+moving->getFilename();
95 cmd <<
"-out" << outdir;
96 cmd <<
"-t0" << initFilename;
97 for (
int i=0; i<parameterfiles.size(); ++i)
98 cmd <<
"-p" << parameterfiles[i];
100 QString commandLine = cmd.join(
" ");
101 report(QString(
"Executing registration with command line: [%1]").arg(commandLine));
105 QString path = QFileInfo(application).absolutePath();
106 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
107 env.insert(
"LD_LIBRARY_PATH", path);
108 mProcess->setProcessEnvironment(env);
110 mProcess->start(commandLine);
121 std::cout <<
"TODO: check ElastixExecuter::isFinished()" << std::endl;
122 return mProcess->atEnd();
127 return mProcess->state()!=QProcess::NotRunning;
130 QString ElastixExecuter::writeInitTransformToElastixfile(
150 Transform3D ffMf = this->getFileTransform_ddMd(mFixed);
151 Transform3D mmMm = this->getFileTransform_ddMd(mMoving);
160 QString elastiXText = QString(
""
161 "// Input transform file\n"
162 "// Auto-generated by CustusX on %1\n"
164 "(Transform \"EulerTransform\")\n"
165 "(NumberOfParameters 6)\n"
166 "(TransformParameters %2 %3)\n"
167 "(InitialTransformParametersFileName \"NoInitialTransform\")\n"
168 "(HowToCombineTransforms \"Compose\")\n"
170 "// EulerTransform specific\n"
171 "(CenterOfRotationPoint %4)\n"
172 "(ComputeZYX \"false\")\n"
178 QFile initTransformFile(outdir+
"/t0.txt");
179 if (!initTransformFile.open(QIODevice::WriteOnly | QIODevice::Text))
181 reportWarning(QString(
"Failed to open file %1 for writing.").arg(initTransformFile.fileName()));
183 initTransformFile.write(elastiXText.toLatin1());
184 return initTransformFile.fileName();
187 QString ElastixExecuter::writeInitTransformToCalfile(
192 Transform3D mMf = moving->get_rMd().inv() * fixed->get_rMd();
194 TransformFile file(outdir+
"/moving_M_fixed_initial.cal");
197 return file.fileName();
200 void ElastixExecuter::processReadyRead()
202 report(QString(mProcess->readAllStandardOutput()));
205 void ElastixExecuter::processError(QProcess::ProcessError error)
208 msg +=
"Registration process reported an error: ";
212 case QProcess::FailedToStart:
213 msg +=
"Failed to start";
215 case QProcess::Crashed:
218 case QProcess::Timedout:
221 case QProcess::WriteError:
222 msg +=
"Write Error";
224 case QProcess::ReadError:
227 case QProcess::UnknownError:
228 msg +=
"Unknown Error";
231 msg +=
"Invalid error";
237 void ElastixExecuter::processFinished(
int code, QProcess::ExitStatus status)
239 if (status == QProcess::CrashExit)
244 void ElastixExecuter::processStateChanged(QProcess::ProcessState newState)
249 msg +=
"Registration process";
251 if (newState == QProcess::Running)
256 if (newState == QProcess::NotRunning)
261 if (newState == QProcess::Starting)
267 QString ElastixExecuter::findMostRecentTransformOutputFile()
const
272 QString filename = QString(mLastOutdir +
"/TransformParameters.%1.txt").arg(i);
273 if (!QFileInfo(filename).exists())
282 QString patFolder = mServices->patient()->getActivePatientFolder();
290 Transform3D mmMff = this->getAffineResult_mmMff(ok);
291 Transform3D ffMf = this->getFileTransform_ddMd(mFixed);
292 Transform3D mmMm = this->getFileTransform_ddMd(mMoving);
294 return mmMm.inv() * mmMff * ffMf;
297 Transform3D ElastixExecuter::getAffineResult_mmMff(
bool* ok)
299 QString filename = this->findMostRecentTransformOutputFile();
302 if (filename.isEmpty())
307 TransformFile file(mLastOutdir+
"/moving_M_fixed_registered.cal");
320 ElastixParameterFile file(filename);
322 bool useDirectionCosines = file.readParameterBool(
"UseDirectionCosines");
323 if (useDirectionCosines)
325 reportWarning(
"Elastix UseDirectionCosines is not supported. Result is probably wrong.");
328 QString transformType = file.readParameterString(
"Transform");
329 if (transformType==
"EulerTransform")
337 else if (transformType==
"AffineTransform")
350 reportWarning(QString(
"TransformType [%1] is not supported by CustusX. Registration result from %2 ignored.").arg(transformType).arg(filename));
353 filename = file.readParameterString(
"InitialTransformParametersFileName");
354 if (filename.isEmpty() || filename==
"NoInitialTransform")
372 QString filename = QString(mLastOutdir +
"/result.%1.mhd").arg(i);
373 if (!QFileInfo(filename).exists())
378 if (retval.isEmpty())
381 QString paramFilename = QString(mLastOutdir +
"/TransformParameters.%1.txt").arg(i-1);
387 report(QString(
"Reading result file %1 created with transform %2").arg(retval).arg(
transform));
410 if (transformType!=
"EulerTransform")
411 reportError(
"Assert failure: attempting to read EulerTransform");
414 if (numberOfParameters!=6)
416 reportWarning(QString(
"Expected 6 Euler parameters, got %1").arg(numberOfParameters));
417 return Transform3D::Identity();
433 if (transformType!=
"AffineTransform")
434 reportError(
"Assert failure: attempting to read AffineTransform");
437 if (numberOfParameters!=12)
439 reportWarning(QString(
"Expected 12 Euler parameters, got %1").arg(numberOfParameters));
440 return Transform3D::Identity();
447 for (
int r=0; r<3; ++r)
448 for (
int c=0; c<3; ++c)
450 for (
int r=0; r<3; ++r)
458 if (!mFile.open(QIODevice::ReadOnly | QIODevice::Text))
460 reportWarning(QString(
"Can't open ElastiX result file %1").arg(filename));
462 mText = QString(mFile.readAll());
466 QString ElastixParameterFile::readParameterRawValue(QString key)
468 QStringList lines = mText.split(
'\n');
470 QString regexpStr = QString(
""
482 QRegExp rx(regexpStr);
498 QString retval = this->readParameterRawValue(key);
499 if (retval.startsWith(
"\"") && retval.endsWith(
"\""))
501 retval = retval.replace(0, 1,
"");
502 retval = retval.replace(retval.size()-1, 1,
"");
511 return (text==
"true") ? true :
false;
516 QString retval = this->readParameterRawValue(key);
517 return retval.toInt();
522 QString retval = this->readParameterRawValue(key);