MNE-CPP 0.1.9
A Framework for Electrophysiology
Loading...
Searching...
No Matches
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
63using namespace UTILSLIB;
64using namespace Eigen;
65
66//=============================================================================================================
67// DEFINE MEMBER METHODS
68//=============================================================================================================
69
70MatrixXf 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
80void 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
94bool 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
132MatrixXf 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
152MatrixXf 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
194MatrixXf 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}
Warp class declaration.
Eigen::MatrixXf readsLm(const QString &electrodeFileName)
Definition warp.cpp:152
Eigen::MatrixXf calculate(const Eigen::MatrixXf &sLm, const Eigen::MatrixXf &dLm, const Eigen::MatrixXf &sVert)