MNE-CPP  0.1.9
A Framework for Electrophysiology
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 
55 using namespace UTILSLIB;
56 using namespace FIFFLIB;
57 using namespace Eigen;
58 
59 //=============================================================================================================
60 // DEFINE MEMBER METHODS
61 //=============================================================================================================
62 
63 FiffProj::FiffProj()
64 : kind(-1)
65 , active(false)
66 , desc("")
67 , data(new FiffNamedMatrix)
68 {
69 
70 }
71 
72 //=============================================================================================================
73 
74 FiffProj::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 
85 FiffProj::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 
97 {
98 
99 }
100 
101 //=============================================================================================================
102 
103 void 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 
115 fiff_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 }
fiff_proj.h
FiffProj class declaration.
FIFFLIB::FiffProj::~FiffProj
~FiffProj()
Definition: fiff_proj.cpp:96
FIFFLIB::FiffProj::data
FiffNamedMatrix::SDPtr data
Definition: fiff_proj.h:158
FIFFLIB::FiffProj::activate_projs
static void activate_projs(QList< FiffProj > &p_qListFiffProj)
Definition: fiff_proj.cpp:103
FIFFLIB::FiffProj
SSP projector data.
Definition: fiff_proj.h:75
k
int k
Definition: fiff_tag.cpp:322
FIFFLIB::FiffProj::active
bool active
Definition: fiff_proj.h:155
FIFFLIB::FiffProj::FiffProj
FiffProj()
Definition: fiff_proj.cpp:63
FIFFLIB::FiffNamedMatrix
A named matrix.
Definition: fiff_named_matrix.h:76
FIFFLIB::FiffProj::make_projector
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)
Definition: fiff_proj.cpp:115
mnemath.h
MNEMath class declaration.