52#define _USE_MATH_DEFINES
75,
trans(MatrixXf::Identity(4,4))
85,
trans(MatrixXf::Identity(4,4))
88 if(!
read(p_IODevice, *
this))
90 printf(
"\tCoordindate transform not found.\n");
99,
to(p_FiffCoordTrans.
to)
127 this->
from = from_new;
140 printf(
"Reading coordinate transform from %s...\n", pStream->streamName().toUtf8().constData());
148 bool success =
false;
153 for ( qint32 k = 0; k < pStream->dir().size(); ++k )
157 pStream->read_tag(t_pTag,pStream->dir()[k]->pos);
158 p_Trans = t_pTag->toCoordTrans();
172 printf(
"Write coordinate transform in %s...\n", pStream->streamName().toUtf8().constData());
189 MatrixX4f rr_ones(rr.rows(), 4);
195 rr_ones.block(0,0,rr.rows(),3) = rr;
196 return rr_ones*
trans.block<3,4>(0,0).transpose();
203 MatrixX4f rr_ones(rr.rows(), 4);
209 rr_ones.block(0,0,rr.rows(),3) = rr;
210 return rr_ones*
invtrans.block<3,4>(0,0).transpose();
233 default:
return "unknown";
241 this->
trans = MatrixXf::Zero(4,4);
246 this->
trans.block<3,3>(0,0) = rot;
247 this->
trans.block<3,1>(0,3) = move;
248 this->
trans(3,3) = 1.0f;
257 this->
trans = matTrans;
263 this->
trans.row(3) = Vector4f(0,0,0,1);
281 std::cout <<
"Coordinate transformation: ";
282 std::cout << (QString(
"%1 -> %2\n").arg(
frame_name(this->from)).arg(
frame_name(this->to))).toUtf8().data();
284 for (
int p = 0; p < 3; p++)
285 printf(
"\t% 8.6f % 8.6f % 8.6f\t% 7.2f mm\n",
trans(p,0),
trans(p,1),
trans(p,2),1000*
trans(p,3));
293 MatrixX4f mDevHeadT = this->
trans;
294 Matrix3f mRot = mDevHeadT.block(0,0,3,3);
295 Matrix3f mRotNew = mTransDest.block(0,0,3,3);
297 Quaternionf quat(mRot);
298 Quaternionf quatNew(mRotNew);
303 Quaternionf quatCompare;
305 quatCompare = quat*quatNew.inverse();
306 fAngle = quat.angularDistance(quatNew);
307 fAngle = fAngle * 180 /
M_PI;
316 VectorXf vTrans = this->
trans.col(3);
317 VectorXf vTransDest = mTransDest.col(3);
319 float fMove = (vTrans-vTransDest).norm();
328 for (
int j = 0; j < 3; j++) {
329 res[j] = do_move ? t.
trans(j,3) : 0.0f;
330 for (
int k = 0; k < 3; k++)
331 res[j] += t.
trans(j,k) * r[k];
333 for (
int j = 0; j < 3; j++)
342 for (
int j = 0; j < 3; j++) {
343 res[j] = do_move ? t.
invtrans(j,3) : 0.0f;
344 for (
int k = 0; k < 3; k++)
347 for (
int j = 0; j < 3; j++)
381 for (
int swapped = 0; swapped < 2 && !found; swapped++) {
386 a = s1; b = s2; found =
true;
388 a = s1.
inverted(); b = s2; found =
true;
390 a = s1; b = s2.
inverted(); found =
true;
396 if (!found || a.
from != b.
to) {
397 qCritical(
"Cannot combine coordinate transforms");
406 result.
trans.row(3) << 0.0f, 0.0f, 0.0f, 1.0f;
418 Map<const Vector3f> L(rL);
419 Map<const Vector3f> N(rN);
420 Map<const Vector3f> R(rR);
422 Vector3f diff1 = N - L;
423 Vector3f diff2 = R - L;
425 float alpha = diff1.dot(diff2) / diff2.dot(diff2);
426 Vector3f r0 = (1.0f - alpha) * L + alpha * R;
427 Vector3f ex = diff2.normalized();
428 Vector3f ey = (N - r0).normalized();
429 Vector3f ez = ex.cross(ey);
434 result.
rot().col(0) = ex;
435 result.
rot().col(1) = ey;
436 result.
rot().col(2) = ez;
449 if (!stream->open()) {
454 for (
int k = 0; k < stream->dir().size(); k++) {
456 if (!stream->read_tag(t_pTag, stream->dir()[k]->pos))
471 qCritical(
"No suitable coordinate transformation found in %s.", name.toUtf8().constData());
495 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
496 qCritical(
"Cannot open %s", name.toUtf8().constData());
500 QTextStream in(&file);
505 while (!in.atEnd() && row < 4) {
506 QString line = in.readLine();
508 int commentIdx = line.indexOf(
'#');
510 line = line.left(commentIdx);
511 line = line.trimmed();
516 QStringList parts = line.simplified().split(
' ', Qt::SkipEmptyParts);
517 if (parts.size() < 4) {
518 qCritical(
"Cannot read the coordinate transformation from %s",
519 name.toUtf8().constData());
522 bool ok1, ok2, ok3, ok4;
523 rot(row, 0) = parts[0].toFloat(&ok1);
524 rot(row, 1) = parts[1].toFloat(&ok2);
525 rot(row, 2) = parts[2].toFloat(&ok3);
526 moveVec[row] = parts[3].toFloat(&ok4) / 1000.0f;
527 if (!ok1 || !ok2 || !ok3 || !ok4) {
528 qCritical(
"Bad floating point number in coordinate transformation");
537 qCritical(
"Cannot read the coordinate transformation from %s",
538 name.toUtf8().constData());
560 qint32* t_pInt32 = (qint32*)tag->data();
561 t.
from = t_pInt32[0];
564 float* t_pFloat = (
float*)tag->data();
567 for (r = 0; r < 3; ++r) {
568 t.
trans(r, 3) = t_pFloat[11 + r];
569 for (c = 0; c < 3; ++c) {
570 t.
trans(r, c) = t_pFloat[2 + count];
577 for (r = 0; r < 3; ++r) {
578 t.
invtrans(r, 3) = t_pFloat[23 + r];
579 for (c = 0; c < 3; ++c) {
580 t.
invtrans(r, c) = t_pFloat[14 + count];
599 for (k = 0; k < node->nent(); k++)
600 kind = node->dir[k]->kind;
601 pos = node->dir[k]->pos;
603 if (!stream->read_tag(t_pTag, pos))
615 printf(
"No suitable coordinate transformation found");
633 Eigen::MatrixXf fromPts(np, 3), toPts(np, 3);
634 for (
int j = 0; j < np; ++j)
635 for (
int c = 0; c < 3; ++c) {
636 fromPts(j, c) = fromp[j][c];
637 toPts(j, c) = top[j][c];
641 Eigen::Vector3f from0 = fromPts.colwise().mean();
642 Eigen::Vector3f to0 = toPts.colwise().mean();
644 Eigen::MatrixXf fromC = fromPts.rowwise() - from0.transpose();
645 Eigen::MatrixXf toC = toPts.rowwise() - to0.transpose();
650 Eigen::VectorXf wVec = Eigen::Map<Eigen::VectorXf>(w, np);
651 S = fromC.transpose() * wVec.asDiagonal() * toC;
653 S = fromC.transpose() * toC;
657 Eigen::JacobiSVD<Eigen::Matrix3f> svd(S, Eigen::ComputeFullU | Eigen::ComputeFullV);
658 Eigen::Matrix3f R = svd.matrixV() * svd.matrixU().transpose();
661 Eigen::Vector3f moveVec = to0 - R * from0;
664 for (
int p = 0; p < np; ++p) {
665 Eigen::Vector3f rr = R * fromPts.row(p).transpose() + moveVec;
666 float diff = (toPts.row(p).transpose() - rr).norm();
667 if (diff > max_diff) {
668 printf(
"Too large difference in matching : %7.1f > %7.1f mm",
669 1000.0f * diff, 1000.0f * max_diff);
FiffTag class declaration, which provides fiff tag I/O and processing methods.
#define FIFFV_MNE_COORD_MNI_TAL
#define FIFFV_MNE_COORD_FS_TAL_LTZ
#define FIFFV_COORD_MRI_SLICE
#define FIFFV_MNE_COORD_CTF_DEVICE
#define FIFFV_COORD_DEVICE
#define FIFFV_COORD_MRI_DISPLAY
#define FIFFV_MNE_COORD_MRI_VOXEL
#define FIFFV_MNE_COORD_CTF_HEAD
#define FIFFV_COORD_ISOTRAK
#define FIFFV_COORD_UNKNOWN
#define FIFFV_MNE_COORD_FS_TAL_GTZ
#define FIFFV_MNE_COORD_RAS
FiffStream class declaration.
FiffDirNode class declaration, which provides fiff dir tree processing methods.
#define FIFFT_COORD_TRANS_STRUCT
FiffCoordTrans class declaration.
FIFF file I/O and data structures (raw, epochs, evoked, covariance, forward).
static FiffCoordTrans readTransformFromNode(FiffStream::SPtr &stream, const FiffDirNode::SPtr &node, int from, int to)
static FiffCoordTrans combine(int from, int to, const FiffCoordTrans &t1, const FiffCoordTrans &t2)
static FiffCoordTrans identity(int from, int to)
static FiffCoordTrans readMriTransform(const QString &name)
FiffCoordTrans inverted() const
static FiffCoordTrans readMeasTransform(const QString &name)
void write(QIODevice &p_IODevice)
Writes the transformation to file.
static FiffCoordTrans procrustesAlign(int from_frame, int to_frame, float **fromp, float **top, float *w, int np, float max_diff)
float translationTo(Eigen::MatrixX4f mTransDest)
static FiffCoordTrans fromCardinalPoints(int from, int to, const float *rL, const float *rN, const float *rR)
static FiffCoordTrans readTransform(const QString &name, int from, int to)
Eigen::MatrixX3f apply_inverse_trans(const Eigen::MatrixX3f &rr, bool do_move=true) const
static FiffCoordTrans readFShead2mriTransform(const QString &name)
Eigen::MatrixX3f apply_trans(const Eigen::MatrixX3f &rr, bool do_move=true) const
static bool read(QIODevice &p_IODevice, FiffCoordTrans &p_Trans)
float angleTo(Eigen::MatrixX4f mTransDest)
Eigen::Matrix< float, 4, 4, Eigen::DontAlign > trans
static FiffCoordTrans readFromTag(const QSharedPointer< FiffTag > &tag)
void writeToStream(FiffStream *p_pStream)
Writes the transformation to a FIFF stream.
static QString frame_name(int frame)
static bool addInverse(FiffCoordTrans &t)
Eigen::Matrix< float, 4, 4, Eigen::DontAlign > invtrans
static FiffCoordTrans readTransformAscii(const QString &name, int from, int to)
QSharedPointer< FiffDirNode > SPtr
fiff_long_t write_coord_trans(const FiffCoordTrans &trans)
static FiffStream::SPtr start_file(QIODevice &p_IODevice)
QSharedPointer< FiffStream > SPtr
QSharedPointer< FiffTag > SPtr