MNE-CPP 0.1.9
A Framework for Electrophysiology
Loading...
Searching...
No Matches
fiff_proj.cpp
Go to the documentation of this file.
1//=============================================================================================================
37//=============================================================================================================
38// INCLUDES
39//=============================================================================================================
40
41#include "fiff_proj.h"
42#include <stdio.h>
43#include <utils/mnemath.h>
44
45//=============================================================================================================
46// EIGEN INCLUDES
47//=============================================================================================================
48
49#include <Eigen/SVD>
50
51//=============================================================================================================
52// USED NAMESPACES
53//=============================================================================================================
54
55using namespace UTILSLIB;
56using namespace FIFFLIB;
57using namespace Eigen;
58
59//=============================================================================================================
60// DEFINE MEMBER METHODS
61//=============================================================================================================
62
64: kind(-1)
65, active(false)
66, desc("")
67, data(new FiffNamedMatrix)
68{
69
70}
71
72//=============================================================================================================
73
74FiffProj::FiffProj(const FiffProj& p_FiffProj)
75: kind(p_FiffProj.kind)
76, active(p_FiffProj.active)
77, desc(p_FiffProj.desc)
78, data(p_FiffProj.data)
79{
80
81}
82
83//=============================================================================================================
84
85FiffProj::FiffProj( fiff_int_t p_kind, bool p_active, QString p_desc, FiffNamedMatrix& p_data)
86: kind(p_kind)
87, active(p_active)
88, desc(p_desc)
89, data(new FiffNamedMatrix(p_data))
90{
91
92}
93
94//=============================================================================================================
95
100
101//=============================================================================================================
102
103void FiffProj::activate_projs(QList<FiffProj> &p_qListFiffProj)
104{
105 // Activate the projection items
106 QList<FiffProj>::Iterator it;
107 for(it = p_qListFiffProj.begin(); it != p_qListFiffProj.end(); ++it)
108 it->active = true;
109
110 printf("\t%lld projection items activated.\n", p_qListFiffProj.size());
111}
112
113//=============================================================================================================
114
115fiff_int_t FiffProj::make_projector(const QList<FiffProj>& projs, const QStringList& ch_names, MatrixXd& proj, const QStringList& bads, MatrixXd& U)
116{
117 fiff_int_t nchan = ch_names.size();
118 if (nchan == 0)
119 {
120 printf("No channel names specified\n");//ToDo throw here
121 return 0;
122 }
123
124// if(proj)
125// delete proj;
126 proj = MatrixXd::Identity(nchan,nchan);
127 fiff_int_t nproj = 0;
128 U = MatrixXd();
129
130 //
131 // Check trivial cases first
132 //
133 if (projs.size() == 0)
134 return 0;
135
136 fiff_int_t nvec = 0;
137 fiff_int_t k, l;
138 for (k = 0; k < projs.size(); ++k)
139 {
140 if (projs[k].active)
141 {
142 ++nproj;
143 nvec += projs[k].data->nrow;
144 }
145 }
146
147 if (nproj == 0) {
148 printf("FiffProj::make_projector - No projectors nproj=0\n");
149 return 0;
150 }
151
152 if (nvec <= 0) {
153 printf("FiffProj::make_projector - No rows in projector matrices found nvec<=0\n");
154 return 0;
155 }
156
157 //
158 // Pick the appropriate entries
159 //
160 MatrixXd vecs = MatrixXd::Zero(nchan,nvec);
161 nvec = 0;
162 fiff_int_t nonzero = 0;
163 qint32 p, c, i, j, v;
164 double onesize;
165 bool isBad = false;
166 RowVectorXi sel(nchan);
167 RowVectorXi vecSel(nchan);
168 sel.setConstant(-1);
169 vecSel.setConstant(-1);
170 for (k = 0; k < projs.size(); ++k)
171 {
172 if (projs[k].active)
173 {
174 FiffProj one = projs[k];
175
176 QMap<QString, int> uniqueMap;
177 for(l = 0; l < one.data->col_names.size(); ++l)
178 uniqueMap[one.data->col_names[l] ] = 0;
179
180 if (one.data->col_names.size() != uniqueMap.keys().size())
181 {
182 printf("Channel name list in projection item %d contains duplicate items",k);
183 return 0;
184 }
185
186 //
187 // Get the two selection vectors to pick correct elements from
188 // the projection vectors omitting bad channels
189 //
190 sel.resize(nchan);
191 vecSel.resize(nchan);
192 sel.setConstant(-1);
193 vecSel.setConstant(-1);
194 p = 0;
195 for (c = 0; c < nchan; ++c)
196 {
197 for (i = 0; i < one.data->col_names.size(); ++i)
198 {
199 if (QString::compare(ch_names.at(c),one.data->col_names[i]) == 0)
200 {
201 isBad = false;
202 for (j = 0; j < bads.size(); ++j)
203 {
204 if (QString::compare(ch_names.at(c),bads.at(j)) == 0)
205 {
206 isBad = true;
207 }
208 }
209
210 if (!isBad && sel[p] != c)
211 {
212 sel[p] = c;
213 vecSel[p] = i;
214 ++p;
215 }
216
217 }
218 }
219 }
220 sel.conservativeResize(p);
221 vecSel.conservativeResize(p);
222 //
223 // If there is something to pick, pickit
224 //
225 if (sel.cols() > 0)
226 for (v = 0; v < one.data->nrow; ++v)
227 for (i = 0; i < p; ++i)
228 vecs(sel[i],nvec+v) = one.data->data(v,vecSel[i]);
229
230 //
231 // Rescale for more straightforward detection of small singular values
232 //
233 for (v = 0; v < one.data->nrow; ++v)
234 {
235 onesize = sqrt((vecs.col(nvec+v).transpose()*vecs.col(nvec+v))(0,0));
236 if (onesize > 0.0)
237 {
238 vecs.col(nvec+v) = vecs.col(nvec+v)/onesize;
239 ++nonzero;
240 }
241 }
242 nvec += one.data->nrow;
243 }
244 }
245 //
246 // Check whether all of the vectors are exactly zero
247 //
248 if (nonzero == 0)
249 return 0;
250
251 //
252 // Reorthogonalize the vectors
253 //
254 JacobiSVD<MatrixXd> svd(vecs.block(0,0,vecs.rows(),nvec), ComputeFullU);
255 //Sort singular values and singular vectors
256 VectorXd S = svd.singularValues();
257 MatrixXd t_U = svd.matrixU();
258 MNEMath::sort<double>(S, t_U);
259
260 //
261 // Throw away the linearly dependent guys
262 //
263 nproj = 0;
264 for(k = 0; k < S.size(); ++k)
265 if (S[k]/S[0] > 1e-2)
266 ++nproj;
267
268 U = t_U.block(0, 0, t_U.rows(), nproj);
269
270 //
271 // Here is the celebrated result
272 //
273 proj -= U*U.transpose();
274
275 return nproj;
276}
int k
Definition fiff_tag.cpp:324
FiffProj class declaration.
MNEMath class declaration.
SSP projector data.
Definition fiff_proj.h:75
FiffNamedMatrix::SDPtr data
Definition fiff_proj.h:158
static fiff_int_t make_projector(const QList< FiffProj > &projs, const QStringList &ch_names, Eigen::MatrixXd &proj, const QStringList &bads=defaultQStringList, Eigen::MatrixXd &U=defaultMatrixXd)
static void activate_projs(QList< FiffProj > &p_qListFiffProj)