v2.0.0
Loading...
Searching...
No Matches
fiff_coord_trans_set.cpp
Go to the documentation of this file.
1//=============================================================================================================
13
14//=============================================================================================================
15// INCLUDES
16//=============================================================================================================
17
19#include "fiff_constants.h"
20#include "fiff_stream.h"
21#include "fiff_tag.h"
22
23//=============================================================================================================
24// QT INCLUDES
25//=============================================================================================================
26
27#include <QFile>
28#include <QRegularExpression>
29#include <QTextStream>
30
31//=============================================================================================================
32// EIGEN INCLUDES
33//=============================================================================================================
34
35#include <Eigen/Core>
36
37//=============================================================================================================
38// USED NAMESPACES
39//=============================================================================================================
40
41using namespace FIFFLIB;
42using namespace Eigen;
43
44//=============================================================================================================
45// DEFINE MEMBER METHODS
46//=============================================================================================================
47
49{
50 QFile file(path);
51 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
52 return FiffCoordTrans();
53 }
54 // "Transform_Type = Linear; Linear_Transform = <3 x 4 matrix, translation in mm> ;"
55 const QString text = QTextStream(&file).readAll();
56 static const QRegularExpression linear(QStringLiteral("Transform_Type\\s*=\\s*Linear\\s*;\\s*Linear_Transform\\s*=([^;]*);"),
57 QRegularExpression::CaseInsensitiveOption);
58 const QRegularExpressionMatch match = linear.match(text);
59 const QStringList values = match.captured(1).split(QRegularExpression(QStringLiteral("\\s+")), Qt::SkipEmptyParts);
60 if (!match.hasMatch() || values.size() != 12) {
61 return FiffCoordTrans();
62 }
63 Matrix3f rot;
64 Vector3f move;
65 for (int row = 0; row < 3; ++row) {
66 for (int col = 0; col < 4; ++col) {
67 bool ok = false;
68 const float value = values[4 * row + col].toFloat(&ok);
69 if (!ok) {
70 return FiffCoordTrans();
71 }
72 if (col < 3) {
73 rot(row, col) = value;
74 } else {
75 move[row] = value / 1000.0f;
76 }
77 }
78 }
80}
81
82//=============================================================================================================
83
84bool FiffCoordTransSet::addTalairach(const QString& xfmPath)
85{
86 const FiffCoordTrans rasMni = readMniTransform(xfmPath);
87 if (rasMni.isEmpty()) {
88 return false;
89 }
90 // M. Brett's MNI -> Talairach approximation, separately above and below the AC-PC plane.
91 Matrix3f above;
92 above << 0.99f, 0.0f, 0.0f, 0.0f, 0.9688f, 0.046f, 0.0f, -0.0485f, 0.9189f;
93 Matrix3f below;
94 below << 0.99f, 0.0f, 0.0f, 0.0f, 0.9688f, 0.042f, 0.0f, -0.0485f, 0.839f;
95 RAS_MNI_tal_t = rasMni;
98 return true;
99}
100
101//=============================================================================================================
102
103int FiffCoordTransSet::read(const QString& path)
104{
105 QFile file(path);
106 FiffStream::SPtr stream(new FiffStream(&file));
107 if (!stream->open()) {
108 return -1;
109 }
110 const struct
111 {
112 int from;
113 int to;
115 } links[] = {
121 };
122 int count = 0;
123 FiffTag::UPtr tag;
124 for (const auto& entry : stream->dir()) {
125 if (entry->kind != FIFF_COORD_TRANS || !stream->read_tag(tag, entry->pos)) {
126 continue;
127 }
128 const FiffCoordTrans t = tag->toCoordTrans();
129 for (const auto& link : links) {
130 if (t.from == link.from && t.to == link.to) {
131 this->*link.member = t;
132 ++count;
133 } else if (t.from == link.to && t.to == link.from) {
134 this->*link.member = t.inverted();
135 ++count;
136 }
137 }
138 }
139 stream->close();
140 return count;
141}
142
143//=============================================================================================================
144
146{
148 if (!t->isEmpty()) {
149 stream.write_coord_trans(*t);
150 }
151 }
152}
153
154//=============================================================================================================
155
156MatrixX3f FiffCoordTransSet::headToMni(const MatrixX3f& rr) const
157{
158 if (head_surf_RAS_t.isEmpty() || surf_RAS_RAS_t.isEmpty() || RAS_MNI_tal_t.isEmpty()) {
159 return MatrixX3f();
160 }
161 return RAS_MNI_tal_t.apply_trans(surf_RAS_RAS_t.apply_trans(head_surf_RAS_t.apply_trans(rr)));
162}
163
164//=============================================================================================================
165
166MatrixX3f FiffCoordTransSet::mniToTalairach(const MatrixX3f& rr) const
167{
168 if (MNI_tal_tal_gtz_t.isEmpty() || MNI_tal_tal_ltz_t.isEmpty()) {
169 return MatrixX3f();
170 }
171 const MatrixX3f above = MNI_tal_tal_gtz_t.apply_trans(rr);
172 const MatrixX3f below = MNI_tal_tal_ltz_t.apply_trans(rr);
173 MatrixX3f result(rr.rows(), 3);
174 for (Index k = 0; k < rr.rows(); ++k) {
175 result.row(k) = rr(k, 2) > 0.0f ? above.row(k) : below.row(k);
176 }
177 return result;
178}
Symbolic FIFF tag, block, value, unit and channel-type constants shared across FIFFLIB.
#define FIFFV_MNE_COORD_MNI_TAL
#define FIFFV_MNE_COORD_FS_TAL_LTZ
#define FIFFV_COORD_HEAD
#define FIFFV_COORD_MRI
#define FIFFV_MNE_COORD_FS_TAL_GTZ
#define FIFFV_MNE_COORD_RAS
FIFF tag: the 16-byte tag header (kind, type, size, next) plus its decoded payload.
The MNE-C transform chain from MEG head coordinates to MNI and FreeSurfer Talairach coordinates.
FIFF binary tag-stream layer: wraps a QIODevice to read and write FIFF tags, directories,...
#define FIFF_COORD_TRANS
Definition fiff_file.h:468
return FiffCoordTrans(from_frame, to_frame, R, moveVec)
FIFF file I/O, in-memory data structures and high-level readers/writers.
Labelled 4x4 FIFF affine: source frame, destination frame, rotation, translation and cached inverse.
FiffCoordTrans inverted() const
The chain of transforms from MEG head coordinates to MNI and FreeSurfer Talairach coordinates.
Eigen::MatrixX3f mniToTalairach(const Eigen::MatrixX3f &rr) const
bool addTalairach(const QString &xfmPath)
int read(const QString &path)
void write(FiffStream &stream) const
Eigen::MatrixX3f headToMni(const Eigen::MatrixX3f &rr) const
static FiffCoordTrans readMniTransform(const QString &path)
FIFF tag-stream reader/writer: wraps a QIODevice and exposes typed read_* / write_* methods for every...
QSharedPointer< FiffStream > SPtr
fiff_long_t write_coord_trans(const FiffCoordTrans &trans)
std::unique_ptr< FiffTag > UPtr
Definition fiff_tag.h:165