MNE-CPP  0.1.9
A Framework for Electrophysiology
fiff_coord_trans.cpp
Go to the documentation of this file.
1 //=============================================================================================================
37 //=============================================================================================================
38 // INCLUDES
39 //=============================================================================================================
40 
41 #include "fiff_coord_trans.h"
42 
43 #include "fiff_stream.h"
44 #include "fiff_tag.h"
45 #include "fiff_dir_node.h"
46 
47 #include <iostream>
48 
49 #define _USE_MATH_DEFINES
50 #include <math.h>
51 
52 //=============================================================================================================
53 // EIGEN INCLUDES
54 //=============================================================================================================
55 
56 #include <Eigen/Dense>
57 
58 //=============================================================================================================
59 // USED NAMESPACES
60 //=============================================================================================================
61 
62 using namespace FIFFLIB;
63 using namespace Eigen;
64 
65 //=============================================================================================================
66 // DEFINE MEMBER METHODS
67 //=============================================================================================================
68 
70 : from(-1)
71 , to(-1)
72 , trans(MatrixXf::Identity(4,4))
73 , invtrans(MatrixXf::Identity(4,4))
74 {
75 }
76 
77 //=============================================================================================================
78 
79 FiffCoordTrans::FiffCoordTrans(QIODevice &p_IODevice)
80 : from(-1)
81 , to(-1)
82 , trans(MatrixXf::Identity(4,4))
83 , invtrans(MatrixXf::Identity(4,4))
84 {
85  if(!read(p_IODevice, *this))
86  {
87  printf("\tCoordindate transform not found.\n");//ToDo Throw here
88  return;
89  }
90 }
91 
92 //=============================================================================================================
93 
95 : from(p_FiffCoordTrans.from)
96 , to(p_FiffCoordTrans.to)
97 , trans(p_FiffCoordTrans.trans)
98 , invtrans(p_FiffCoordTrans.invtrans)
99 {
100 }
101 
102 //=============================================================================================================
103 
105 {
106 }
107 
108 //=============================================================================================================
109 
111 {
112  from = -1;
113  to = -1;
114  trans.setIdentity();
115  invtrans.setIdentity();
116 }
117 
118 //=============================================================================================================
119 
121 {
122  fiff_int_t from_new = this->to;
123  this->to = this->from;
124  this->from = from_new;
125  this->trans = this->trans.inverse().eval();
126  this->invtrans = this->invtrans.inverse().eval();
127 
128  return true;
129 }
130 
131 //=============================================================================================================
132 
133 bool FiffCoordTrans::read(QIODevice& p_IODevice, FiffCoordTrans& p_Trans)
134 {
135  FiffStream::SPtr pStream(new FiffStream(&p_IODevice));
136 
137  printf("Reading coordinate transform from %s...\n", pStream->streamName().toUtf8().constData());
138  if(!pStream->open())
139  return false;
140 
141  //
142  // Locate and read the coordinate transformation
143  //
144  FiffTag::SPtr t_pTag;
145  bool success = false;
146 
147  //
148  // Get the MRI <-> head coordinate transformation
149  //
150  for ( qint32 k = 0; k < pStream->dir().size(); ++k )
151  {
152  if ( pStream->dir()[k]->kind == FIFF_COORD_TRANS )
153  {
154  pStream->read_tag(t_pTag,pStream->dir()[k]->pos);
155  p_Trans = t_pTag->toCoordTrans();
156  success = true;
157  }
158  }
159 
160  return success;
161 }
162 
163 //=============================================================================================================
164 
165 void FiffCoordTrans::write(QIODevice &qIODevice)
166 {
167  // Create the file and save the essentials
168  FiffStream::SPtr pStream = FiffStream::start_file(qIODevice);
169  printf("Write coordinate transform in %s...\n", pStream->streamName().toUtf8().constData());
170  this->writeToStream(pStream.data());
171  pStream->end_file();
172  qIODevice.close();
173 }
174 
175 //=============================================================================================================
176 
178 {
179  pStream->write_coord_trans(*this);
180 }
181 
182 //=============================================================================================================
183 
184 MatrixX3f FiffCoordTrans::apply_trans(const MatrixX3f& rr, bool do_move) const
185 {
186  MatrixX4f rr_ones = do_move ? MatrixX4f::Ones(rr.rows(),4) : MatrixX4f::Zero(rr.rows(),4);
187  rr_ones.block(0,0,rr.rows(),3) = rr;
188  return rr_ones*trans.block<3,4>(0,0).transpose();
189 }
190 
191 //=============================================================================================================
192 
193 MatrixX3f FiffCoordTrans::apply_inverse_trans(const MatrixX3f& rr, bool do_move) const
194 {
195  MatrixX4f rr_ones = do_move ? MatrixX4f::Ones(rr.rows(),4) : MatrixX4f::Zero(rr.rows(),4);
196  rr_ones.block(0,0,rr.rows(),3) = rr;
197  return rr_ones*invtrans.block<3,4>(0,0).transpose();
198 }
199 
200 //=============================================================================================================
201 
202 QString FiffCoordTrans::frame_name (int frame)
203 {
204  switch(frame) {
205  case FIFFV_COORD_UNKNOWN: return "unknown";
206  case FIFFV_COORD_DEVICE: return "MEG device";
207  case FIFFV_COORD_ISOTRAK: return "isotrak";
208  case FIFFV_COORD_HPI: return "hpi";
209  case FIFFV_COORD_HEAD: return "head";
210  case FIFFV_COORD_MRI: return "MRI (surface RAS)";
211  case FIFFV_MNE_COORD_MRI_VOXEL: return "MRI voxel";
212  case FIFFV_COORD_MRI_SLICE: return "MRI slice";
213  case FIFFV_COORD_MRI_DISPLAY: return "MRI display";
214  case FIFFV_MNE_COORD_CTF_DEVICE: return "CTF MEG device";
215  case FIFFV_MNE_COORD_CTF_HEAD: return "CTF/4D/KIT head";
216  case FIFFV_MNE_COORD_RAS: return "RAS (non-zero origin)";
217  case FIFFV_MNE_COORD_MNI_TAL: return "MNI Talairach";
218  case FIFFV_MNE_COORD_FS_TAL_GTZ: return "Talairach (MNI z > 0)";
219  case FIFFV_MNE_COORD_FS_TAL_LTZ: return "Talairach (MNI z < 0)";
220  default: return "unknown";
221  }
222 }
223 
224 //=============================================================================================================
225 
226 FiffCoordTrans FiffCoordTrans::make(int from, int to, const Matrix3f& rot, const VectorXf& move)
227 {
228  FiffCoordTrans t;
229  t.trans = MatrixXf::Zero(4,4);
230 
231  t.from = from;
232  t.to = to;
233 
234  t.trans.block<3,3>(0,0) = rot;
235  t.trans.block<3,1>(0,3) = move;
236  t.trans(3,3) = 1.0f;
237 
239 
240  return t;
241 }
242 
243 //=============================================================================================================
244 
245 FiffCoordTrans FiffCoordTrans::make(int from, int to, const Matrix4f& matTrans, bool bStandard)
246 {
247  FiffCoordTrans t;
248 
249  t.trans = matTrans;
250  t.from = from;
251  t.to = to;
252 
253  if(bStandard) {
254  // make sure that it is a standard transform if requested
255  t.trans.row(3) = Vector4f(0,0,0,1);
256  }
257 
259 
260  return t;
261 }
262 
263 //=============================================================================================================
264 
266 {
267  t.invtrans = t.trans.inverse().eval();
268  return true;
269 }
270 
271 //=============================================================================================================
272 
274 {
275  std::cout << "Coordinate transformation: ";
276  std::cout << (QString("%1 -> %2\n").arg(frame_name(this->from)).arg(frame_name(this->to))).toUtf8().data();
277 
278  for (int p = 0; p < 3; p++)
279  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));
280  printf("\t% 8.6f % 8.6f % 8.6f % 7.2f\n",trans(3,0),trans(3,1),trans(3,2),trans(3,3));
281 }
282 
283 //=============================================================================================================
284 
285 float FiffCoordTrans::angleTo(Eigen::MatrixX4f mTransDest)
286 {
287  MatrixX4f mDevHeadT = this->trans;
288  Matrix3f mRot = mDevHeadT.block(0,0,3,3);
289  Matrix3f mRotNew = mTransDest.block(0,0,3,3);
290 
291  Quaternionf quat(mRot);
292  Quaternionf quatNew(mRotNew);
293 
294  float fAngle;
295 
296  // calculate rotation
297  Quaternionf quatCompare;
298 
299  quatCompare = quat*quatNew.inverse();
300  fAngle = quat.angularDistance(quatNew);
301  fAngle = fAngle * 180 / M_PI;
302 
303  return fAngle;
304 }
305 
306 //=============================================================================================================
307 
308 float FiffCoordTrans::translationTo(Eigen::MatrixX4f mTransDest)
309 {
310  VectorXf vTrans = this->trans.col(3);
311  VectorXf vTransDest = mTransDest.col(3);
312 
313  float fMove = (vTrans-vTransDest).norm();
314  return fMove;
315 }
316 
317 //=============================================================================================================
318 
320 {
321  FiffCoordTransOld tOld;
322  tOld.from = this->from;
323  tOld.to = this->to;
324  tOld.rot = this->trans.block(0,0,3,3);
325  tOld.move = this->trans.block(0,3,3,1);
326  tOld.invrot = this->invtrans.block(0,0,3,3);
327  tOld.invmove = this->invtrans.block(0,3,3,1);
328 
329  return tOld;
330 }
#define FIFFV_MNE_COORD_MRI_VOXEL
FiffCoordTrans class declaration.
FiffStream class declaration.
#define FIFFV_MNE_COORD_CTF_DEVICE
void writeToStream(FiffStream *p_pStream)
Writes the transformation to stream.
Coordinate transformation description.
fiff_long_t write_coord_trans(const FiffCoordTrans &trans)
float angleTo(Eigen::MatrixX4f mTransDest)
#define FIFFV_MNE_COORD_FS_TAL_LTZ
float translationTo(Eigen::MatrixX4f mTransDest)
QSharedPointer< FiffTag > SPtr
Definition: fiff_tag.h:152
void write(QIODevice &p_IODevice)
Writes the transformation to file.
FIFF File I/O routines.
Definition: fiff_stream.h:104
Coordinate transformation descriptor.
FiffDirNode class declaration, which provides fiff dir tree processing methods.
static bool read(QIODevice &p_IODevice, FiffCoordTrans &p_Trans)
Eigen::Matrix< float, 4, 4, Eigen::DontAlign > invtrans
Eigen::Matrix< float, 4, 4, Eigen::DontAlign > trans
static bool addInverse(FiffCoordTrans &t)
Eigen::MatrixX3f apply_trans(const Eigen::MatrixX3f &rr, bool do_move=true) const
#define FIFF_COORD_TRANS
Definition: fiff_file.h:475
#define FIFFV_MNE_COORD_RAS
Eigen::MatrixX3f apply_inverse_trans(const Eigen::MatrixX3f &rr, bool do_move=true) const
static FiffStream::SPtr start_file(QIODevice &p_IODevice)
QSharedPointer< FiffStream > SPtr
Definition: fiff_stream.h:107
#define FIFFV_MNE_COORD_CTF_HEAD
#define FIFFV_MNE_COORD_MNI_TAL
FiffTag class declaration, which provides fiff tag I/O and processing methods.
static QString frame_name(int frame)
#define FIFFV_MNE_COORD_FS_TAL_GTZ
FiffCoordTransOld toOld()
static FiffCoordTrans make(int from, int to, const Eigen::Matrix3f &rot, const Eigen::VectorXf &move)