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();
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");
323 if (useDirectionCosines)
325 reportWarning(
"Elastix UseDirectionCosines is not supported. Result is probably wrong.");
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));
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);
385 if ((transform==
"BSplineTransform") || (transform==
"SplineKernelTransform"))
387 report(QString(
"Reading result file %1 created with transform %2").arg(retval).arg(transform));
409 QString transformType = this->readParameterString(
"Transform");
410 if (transformType!=
"EulerTransform")
411 reportError(
"Assert failure: attempting to read EulerTransform");
413 int numberOfParameters = this->readParameterInt(
"NumberOfParameters");
414 if (numberOfParameters!=6)
416 reportWarning(QString(
"Expected 6 Euler parameters, got %1").arg(numberOfParameters));
417 return Transform3D::Identity();
419 std::vector<double> tp = this->readParameterDoubleVector(
"TransformParameters");
420 std::vector<double> cor = this->readParameterDoubleVector(
"CenterOfRotationPoint");
432 QString transformType = this->readParameterString(
"Transform");
433 if (transformType!=
"AffineTransform")
434 reportError(
"Assert failure: attempting to read AffineTransform");
436 int numberOfParameters = this->readParameterInt(
"NumberOfParameters");
437 if (numberOfParameters!=12)
439 reportWarning(QString(
"Expected 12 Euler parameters, got %1").arg(numberOfParameters));
440 return Transform3D::Identity();
442 std::vector<double> tp = this->readParameterDoubleVector(
"TransformParameters");
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);
QString qstring_cast(const T &val)
ElastixParameterFile(QString filename)
bool setInput(QString application, DataPtr fixed, DataPtr moving, QString outdir, QStringList parameterfiles)
DoubleBoundingBox3D transform(const Transform3D &m, const DoubleBoundingBox3D &bb)
void finished()
should be emitted when at the end of postProcessingSlot
QString readParameterString(QString key)
void reportError(QString msg)
Base class for algorithms that wants to time their execution.
virtual bool isFinished() const
int readParameterInt(QString key)
std::string toString(T const &value)
converts any type to a string
ElastixExecuter(RegServicesPtr services, QObject *parent=NULL)
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
QString timestampSecondsFormatNice()
QString getNonlinearResultVolume(bool *ok=0)
boost::shared_ptr< class Data > DataPtr
boost::shared_ptr< class CustomMetaImage > CustomMetaImagePtr
void reportWarning(QString msg)
boost::shared_ptr< class RegServices > RegServicesPtr
bool readParameterBool(QString key)
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
virtual ~ElastixExecuter()
virtual bool isRunning() const
std::vector< double > readParameterDoubleVector(QString key)
void aboutToStart()
emitted at start of execute. Use to perform preprocessing
Transform3D readEulerTransform()
void setDisplayProcessMessages(bool on)
Transform3D readAffineTransform()
std::vector< double > convertQString2DoubleVector(const QString &input, bool *ok)
Transform3D getAffineResult_mMf(bool *ok=0)
void started(int maxSteps)
emitted at start of run.
Namespace for all CustusX production code.