MNE-CPP  0.1.9
A Framework for Electrophysiology
warp.cpp
Go to the documentation of this file.
1 //=============================================================================================================
35 //=============================================================================================================
36 // INCLUDES
37 //=============================================================================================================
38 
39 #include "warp.h"
40 
41 #include <iostream>
42 #include <fstream>
43 
44 //=============================================================================================================
45 // EIGEN INCLUDES
46 //=============================================================================================================
47 
48 #include <Eigen/LU>
49 
50 //=============================================================================================================
51 // QT INCLUDES
52 //=============================================================================================================
53 
54 #include <QDebug>
55 #include <QFile>
56 #include <QList>
57 #include <QRegularExpression>
58 
59 //=============================================================================================================
60 // USED NAMESPACES
61 //=============================================================================================================
62 
63 using namespace UTILSLIB;
64 using namespace Eigen;
65 
66 //=============================================================================================================
67 // DEFINE MEMBER METHODS
68 //=============================================================================================================
69 
70 MatrixXf Warp::calculate(const MatrixXf &sLm, const MatrixXf &dLm, const MatrixXf &sVert)
71 {
72  MatrixXf warpWeight, polWeight;
73  calcWeighting(sLm, dLm, warpWeight, polWeight);
74  MatrixXf wVert = warpVertices(sVert, sLm, warpWeight, polWeight);
75  return wVert;
76 }
77 
78 //=============================================================================================================
79 
80 void Warp::calculate(const MatrixXf & sLm, const MatrixXf &dLm, QList<MatrixXf> & vertList)
81 {
82  MatrixXf warpWeight, polWeight;
83  calcWeighting(sLm, dLm, warpWeight, polWeight);
84 
85  for (int i=0; i<vertList.size(); i++)
86  {
87  vertList.replace(i,warpVertices(vertList.at(i), sLm, warpWeight, polWeight));
88  }
89  return;
90 }
91 
92 //=============================================================================================================
93 
94 bool Warp::calcWeighting(const MatrixXf &sLm, const MatrixXf &dLm, MatrixXf& warpWeight, MatrixXf& polWeight)
95 {
96  MatrixXf K = MatrixXf::Zero(sLm.rows(),sLm.rows()); //K(i,j)=||sLm(i)-sLm(j)||
97  for (int i=0; i<sLm.rows(); i++)
98  K.col(i)=((sLm.rowwise()-sLm.row(i)).rowwise().norm());
99 
100 // std::cout << "Here is the matrix K:" << std::endl << K << std::endl;
101 
102  MatrixXf P (sLm.rows(),4); //P=[ones,sLm]
103  P << MatrixXf::Ones(sLm.rows(),1),sLm;
104 // std::cout << "Here is the matrix P:" << std::endl << P << std::endl;
105 
106  MatrixXf L ((sLm.rows()+4),(sLm.rows()+4)); //L=Full Matrix of the linear eq.
107  L << K,P,
108  P.transpose(),MatrixXf::Zero(4,4);
109 // std::cout << "Here is the matrix L:" << std::endl << L << std::endl;
110 
111  MatrixXf Y ((dLm.rows()+4),3); //Y=[dLm,Zero]
112  Y << dLm,
113  MatrixXf::Zero(4,3);
114 // std::cout << "Here is the matrix Y:" << std::endl << Y << std::endl;
115 
116  //
117  // calculate the weighting matrix (Y=L*W)
118  //
119  MatrixXf W ((dLm.rows()+4),3); //W=[warpWeight,polWeight]
120  Eigen::FullPivLU <MatrixXf> Lu(L); //LU decomposition is one method to solve lin. eq.
121  W=Lu.solve(Y);
122 // std::cout << "Here is the matrix W:" << std::endl << W << std::endl;
123 
124  warpWeight = W.topRows(sLm.rows());
125  polWeight = W.bottomRows(4);
126 
127  return true;
128 }
129 
130 //=============================================================================================================
131 
132 MatrixXf Warp::warpVertices(const MatrixXf &sVert, const MatrixXf & sLm, const MatrixXf& warpWeight, const MatrixXf& polWeight)
133 {
134  MatrixXf wVert = sVert * polWeight.bottomRows(3); //Pol. Warp
135  wVert.rowwise() += polWeight.row(0); //Translation
136 
137  //
138  // TPS Warp
139  //
140  MatrixXf K = MatrixXf::Zero(sVert.rows(),sLm.rows()); //K(i,j)=||sLm(i)-sLm(j)||
141  for (int i=0; i<sVert.rows(); i++)
142  K.row(i)=((sLm.rowwise()-sVert.row(i)).rowwise().norm().transpose());
143 // std::cout << "Here is the matrix K:" << std::endl << K << std::endl;
144 
145  wVert += K*warpWeight;
146 // std::cout << "Here is the matrix wVert:" << std::endl << wVert << std::endl;
147  return wVert;
148 }
149 
150 //=============================================================================================================
151 
152 MatrixXf Warp::readsLm(const QString &electrodeFileName)
153 {
154  MatrixXf electrodes;
155  QFile file(electrodeFileName);
156 
157  if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
158  qDebug()<<"Error opening file";
159 // return false;
160  }
161 
162  //Start reading from file
163  double numberElectrodes;
164  QTextStream in(&file);
165  int i=0;
166 
167  while(!in.atEnd())
168  {
169  QString line = in.readLine();
170  QStringList fields = line.split(QRegularExpression("\\s+"));
171 
172  //Delete last element if it is a blank character
173  if(fields.at(fields.size()-1) == "")
174  fields.removeLast();
175 
176  //Read number of electrodes
177  if(i == 0){
178  numberElectrodes = fields.at(fields.size()-1).toDouble();
179  electrodes = MatrixXf::Zero(numberElectrodes, 3);
180  }
181  //Read actual electrode positions
182  else{
183  Vector3f x;
184  x << fields.at(fields.size()-3).toFloat(),fields.at(fields.size()-2).toFloat(),fields.at(fields.size()-1).toFloat();
185  electrodes.row(i-1)=x.transpose();
186  }
187  i++;
188  }
189  return electrodes;
190 }
191 
192 //=============================================================================================================
193 
194 MatrixXf Warp::readsLm(const std::string &electrodeFileName)
195 {
196  MatrixXf electrodes;
197  std::ifstream inFile(electrodeFileName);
198 
199  if(!inFile.is_open()) {
200  qDebug()<<"Error opening file";
201  //Why are we not returning?
202 // return false;
203  }
204 
205  //Start reading from file
206  double numberElectrodes;
207  int i = 0;
208 
209  std::string line;
210  while(std::getline(inFile, line)){
211  std::vector<std::string> fields;
212  std::stringstream stream{line};
213  std::string element;
214 
215  stream >> std::ws;
216  while(stream >> element){
217  fields.push_back(std::move(element));
218  stream >> std::ws;
219  }
220 
221  //Read number of electrodes
222  if(i == 0){
223  numberElectrodes = std::stod(fields.at(fields.size()-1));
224  electrodes = MatrixXf::Zero(numberElectrodes, 3);
225  }
226 
227  //Read actual electrode positions
228  else{
229  Vector3f x;
230  x << std::stof(fields.at(fields.size()-3)), std::stof(fields.at(fields.size()-2)), std::stof(fields.at(fields.size()-1));
231  electrodes.row(i-1)=x.transpose();
232  }
233  i++;
234  }
235 
236  return electrodes;
237 }
UTILSLIB::Warp::readsLm
Eigen::MatrixXf readsLm(const QString &electrodeFileName)
Definition: warp.cpp:152
UTILSLIB::Warp::calculate
Eigen::MatrixXf calculate(const Eigen::MatrixXf &sLm, const Eigen::MatrixXf &dLm, const Eigen::MatrixXf &sVert)
warp.h
Warp class declaration.