v2.0.0
Loading...
Searching...
No Matches
fiff_raw_data.cpp
Go to the documentation of this file.
1//=============================================================================================================
36
37//=============================================================================================================
38// INCLUDES
39//=============================================================================================================
40
41#include "fiff_raw_data.h"
42#include "fiff_events.h"
43#include "fiff_tag.h"
44#include "fiff_stream.h"
45#include "cstdlib"
46
47#include <stdexcept>
48//=============================================================================================================
49// USED NAMESPACES
50//=============================================================================================================
51
52using namespace FIFFLIB;
53using namespace Eigen;
54
55//=============================================================================================================
56// DEFINE MEMBER METHODS
57//=============================================================================================================
58
64
65//=============================================================================================================
66
67FiffRawData::FiffRawData(QIODevice &p_IODevice)
68: first_samp(-1)
69, last_samp(-1)
70{
71 //setup FiffRawData object
72 if(!FiffStream::setup_read_raw(p_IODevice, *this))
73 {
74 throw std::runtime_error("Error during fiff setup raw read");
75 }
76}
77
78//=============================================================================================================
79
80FiffRawData::FiffRawData(QIODevice &p_IODevice, bool b_littleEndian)
81: first_samp(-1)
82, last_samp(-1)
83{
84 //setup FiffRawData object
85 if(!FiffStream::setup_read_raw(p_IODevice, *this, false, b_littleEndian))
86 {
87 throw std::runtime_error("Error during fiff setup raw read");
88 }
89}
90
91//=============================================================================================================
92
94: file(p_FiffRawData.file)
95, info(p_FiffRawData.info)
96, first_samp(p_FiffRawData.first_samp)
97, last_samp(p_FiffRawData.last_samp)
98, cals(p_FiffRawData.cals)
99, rawdir(p_FiffRawData.rawdir)
100, proj(p_FiffRawData.proj)
101, comp(p_FiffRawData.comp)
102{
103}
104
105//=============================================================================================================
106
110
111//=============================================================================================================
112
114{
115 info.clear();
116 first_samp = -1;
117 last_samp = -1;
118 cals = RowVectorXd();
119 rawdir.clear();
120 proj = MatrixXd();
121 comp.clear();
122}
123
124//=============================================================================================================
125#include <QElapsedTimer>
126#include <QDebug>
127bool FiffRawData::read_raw_segment(MatrixXd& data,
128 MatrixXd& times,
129 fiff_int_t from,
130 fiff_int_t to,
131 const RowVectorXi& sel,
132 bool do_debug) const
133{
134 bool projAvailable = true;
135
136 if (this->proj.size() == 0) {
137 //qDebug() << "FiffRawData::read_raw_segment - No projectors setup. Consider calling MNE::setup_compensators.";
138 projAvailable = false;
139 }
140
141 if(from == -1)
142 from = this->first_samp;
143 if(to == -1)
144 to = this->last_samp;
145 //
146 // Initial checks
147 //
148 if(from < this->first_samp)
149 from = this->first_samp;
150 if(to > this->last_samp)
151 to = this->last_samp;
152 //
153 if(from > to)
154 {
155 qWarning("No data in this range %d ... %d = %9.3f ... %9.3f secs...", from, to, (static_cast<float>(from))/this->info.sfreq, (static_cast<float>(to))/this->info.sfreq);
156 return false;
157 }
158 //printf("Reading %d ... %d = %9.3f ... %9.3f secs...", from, to, (static_cast<float>(from))/this->info.sfreq, (static_cast<float>(to))/this->info.sfreq);
159 //
160 // Initialize the data and calibration vector
161 //
162 qint32 nchan = this->info.nchan;
163 qint32 dest = 0;//1;
164 qint32 i, k, r;
165
166 using T = Eigen::Triplet<double>;
167 std::vector<T> tripletList;
168 tripletList.reserve(nchan);
169 for(i = 0; i < nchan; ++i)
170 tripletList.push_back(T(i, i, this->cals[i]));
171
172 SparseMatrix<double> cal(nchan, nchan);
173 cal.setFromTriplets(tripletList.begin(), tripletList.end());
174// cal.makeCompressed();
175
176 MatrixXd mult_full;
177 //
178 if (sel.size() == 0)
179 {
180 data = MatrixXd(nchan, to-from+1);
181// data->setZero();
182 if (projAvailable || this->comp.kind != -1)
183 {
184 if (!projAvailable)
185 mult_full = this->comp.data->data*cal;
186 else if (this->comp.kind == -1)
187 mult_full = this->proj*cal;
188 else
189 mult_full = this->proj*this->comp.data->data*cal;
190 }
191 }
192 else
193 {
194 data = MatrixXd(sel.size(),to-from+1);
195// data->setZero();
196
197 MatrixXd selVect(sel.size(), nchan);
198
199 selVect.setZero();
200
201 if (!projAvailable && this->comp.kind == -1)
202 {
203 tripletList.clear();
204 tripletList.reserve(sel.size());
205 for(i = 0; i < sel.size(); ++i)
206 tripletList.push_back(T(i, i, this->cals[sel[i]]));
207 cal = SparseMatrix<double>(sel.size(), sel.size());
208 cal.setFromTriplets(tripletList.begin(), tripletList.end());
209 }
210 else
211 {
212 if (!projAvailable)
213 {
214 qDebug() << "This has to be debugged! #1";
215 for( i = 0; i < sel.size(); ++i)
216 selVect.row(i) = this->comp.data->data.block(sel[i],0,1,nchan);
217 mult_full = selVect*cal;
218 }
219 else if (this->comp.kind == -1)
220 {
221 for( i = 0; i < sel.size(); ++i)
222 selVect.row(i) = this->proj.block(sel[i],0,1,nchan);
223
224 mult_full = selVect*cal;
225 }
226 else
227 {
228 qDebug() << "This has to be debugged! #3";
229 for( i = 0; i < sel.size(); ++i)
230 selVect.row(i) = this->proj.block(sel[i],0,1,nchan);
231
232 mult_full = selVect*this->comp.data->data*cal;
233 }
234 }
235 }
236
237 //
238 // Make mult sparse
239 //
240 tripletList.clear();
241 tripletList.reserve(mult_full.rows()*mult_full.cols());
242 for(i = 0; i < mult_full.rows(); ++i)
243 for(k = 0; k < mult_full.cols(); ++k)
244 if(mult_full(i,k) != 0)
245 tripletList.push_back(T(i, k, mult_full(i,k)));
246
247 SparseMatrix<double> mult(mult_full.rows(),mult_full.cols());
248 if(tripletList.size() > 0)
249 mult.setFromTriplets(tripletList.begin(), tripletList.end());
250// mult.makeCompressed();
251
253 if (!this->file->device()->isOpen())
254 {
255 if (!this->file->device()->open(QIODevice::ReadOnly))
256 {
257 qWarning("Cannot open file %s",this->info.filename.toUtf8().constData());
258 }
259 fid = this->file;
260 }
261 else
262 {
263 fid = this->file;
264 }
265
266 MatrixXd one, newData, tmp_data;
267 FiffRawDir thisRawDir;
268 FiffTag::UPtr t_pTag;
269 fiff_int_t first_pick, last_pick, picksamp;
270 for(k = 0; k < this->rawdir.size(); ++k)
271 {
272 thisRawDir = this->rawdir[k];
273 //
274 // Do we need this buffer
275 //
276 if (thisRawDir.last > from)
277 {
278 if (thisRawDir.ent->kind == -1)
279 {
280 //
281 // Take the easy route: skip is translated to zeros
282 //
283 if(do_debug)
284 qDebug("S");
285 if (sel.cols() <= 0)
286 one.resize(nchan,thisRawDir.nsamp);
287 else
288 one.resize(sel.cols(),thisRawDir.nsamp);
289
290 one.setZero();
291 }
292 else
293 {
294 fid->read_tag(t_pTag, thisRawDir.ent->pos);
295 //
296 // Depending on the state of the projection and selection
297 // we proceed a little bit differently
298 //
299 if (mult.cols() == 0)
300 {
301 if (sel.cols() == 0)
302 {
303 if (t_pTag->type == FIFFT_DAU_PACK16)
304 one = cal*(Map< MatrixDau16 >( t_pTag->toDauPack16(),nchan, thisRawDir.nsamp)).cast<double>();
305 else if(t_pTag->type == FIFFT_INT)
306 one = cal*(Map< MatrixXi >( t_pTag->toInt(),nchan, thisRawDir.nsamp)).cast<double>();
307 else if(t_pTag->type == FIFFT_FLOAT)
308 one = cal*(Map<const MatrixXf>(t_pTag->toFloat(),nchan, thisRawDir.nsamp)).cast<double>();
309 else if(t_pTag->type == FIFFT_SHORT)
310 one = cal*(Map< MatrixShort >( t_pTag->toShort(),nchan, thisRawDir.nsamp)).cast<double>();
311 else
312 qWarning("Data Storage Format not known yet [1]!! Type: %d\n", t_pTag->type);
313 }
314 else
315 {
316 //ToDo find a faster solution for this!! --> make cal and mul sparse like in MATLAB
317 newData.resize(sel.cols(), thisRawDir.nsamp); //ToDo this can be done much faster, without newData
318
319 if (t_pTag->type == FIFFT_DAU_PACK16)
320 {
321 tmp_data = (Map< MatrixDau16 > ( t_pTag->toDauPack16(),nchan, thisRawDir.nsamp)).cast<double>();
322
323 for(r = 0; r < sel.size(); ++r)
324 newData.block(r,0,1,thisRawDir.nsamp) = tmp_data.block(sel[r],0,1,thisRawDir.nsamp);
325 }
326 else if(t_pTag->type == FIFFT_INT)
327 {
328 tmp_data = (Map< MatrixXi >( t_pTag->toInt(),nchan, thisRawDir.nsamp)).cast<double>();
329
330 for(r = 0; r < sel.size(); ++r)
331 newData.block(r,0,1,thisRawDir.nsamp) = tmp_data.block(sel[r],0,1,thisRawDir.nsamp);
332 }
333 else if(t_pTag->type == FIFFT_FLOAT)
334 {
335 tmp_data = (Map<const MatrixXf>(t_pTag->toFloat(),nchan, thisRawDir.nsamp)).cast<double>();
336
337 for(r = 0; r < sel.size(); ++r)
338 newData.block(r,0,1,thisRawDir.nsamp) = tmp_data.block(sel[r],0,1,thisRawDir.nsamp);
339 }
340 else if(t_pTag->type == FIFFT_SHORT)
341 {
342 tmp_data = (Map< MatrixShort > ( t_pTag->toShort(),nchan, thisRawDir.nsamp)).cast<double>();
343
344 for(r = 0; r < sel.size(); ++r)
345 newData.block(r,0,1,thisRawDir.nsamp) = tmp_data.block(sel[r],0,1,thisRawDir.nsamp);
346 }
347 else
348 {
349 qWarning("Data Storage Format not known yet [2]!! Type: %d\n", t_pTag->type);
350 }
351
352 one = cal*newData;
353 }
354 }
355 else
356 {
357 if (t_pTag->type == FIFFT_DAU_PACK16)
358 one = mult*(Map< MatrixDau16 >( t_pTag->toDauPack16(),nchan, thisRawDir.nsamp)).cast<double>();
359 else if(t_pTag->type == FIFFT_INT)
360 one = mult*(Map< MatrixXi >( t_pTag->toInt(),nchan, thisRawDir.nsamp)).cast<double>();
361 else if(t_pTag->type == FIFFT_FLOAT)
362 one = mult*(Map<const MatrixXf>(t_pTag->toFloat(),nchan, thisRawDir.nsamp)).cast<double>();
363 else
364 qWarning("Data Storage Format not known yet [3]!! Type: %d\n", t_pTag->type);
365 }
366 }
367 //
368 // The picking logic is a bit complicated
369 //
370 if (to >= thisRawDir.last && from <= thisRawDir.first)
371 {
372 //
373 // We need the whole buffer
374 //
375 first_pick = 0;//1;
376 last_pick = thisRawDir.nsamp - 1;
377 if (do_debug)
378 qDebug("W");
379 }
380 else if (from > thisRawDir.first)
381 {
382 first_pick = from - thisRawDir.first;// + 1;
383 if(to < thisRawDir.last)
384 {
385 //
386 // Something from the middle
387 //
388// qDebug() << "This needs to be debugged!";
389 last_pick = thisRawDir.nsamp + to - thisRawDir.last - 1;//is this alright?
390 if (do_debug)
391 qDebug("M");
392 }
393 else
394 {
395 //
396 // From the middle to the end
397 //
398 last_pick = thisRawDir.nsamp - 1;
399 if (do_debug)
400 qDebug("E");
401 }
402 }
403 else
404 {
405 //
406 // From the beginning to the middle
407 //
408 first_pick = 0;//1;
409 last_pick = to - thisRawDir.first;// + 1;
410 if (do_debug)
411 qDebug("B");
412 }
413 //
414 // Now we are ready to pick
415 //
416 picksamp = last_pick - first_pick + 1;
417
418 if(do_debug)
419 {
420 qDebug() << "first_pick: " << first_pick;
421 qDebug() << "last_pick: " << last_pick;
422 qDebug() << "picksamp: " << picksamp;
423 }
424
425 if (picksamp > 0)
426 {
427// for(r = 0; r < data->rows(); ++r)
428// for(c = 0; c < picksamp; ++c)
429// (*data)(r,dest + c) = one(r,first_pick + c);
430 data.block(0,dest,data.rows(),picksamp) = one.block(0, first_pick, data.rows(), picksamp);
431
432 dest += picksamp;
433 }
434 }
435 //
436 // Done?
437 //
438 if (thisRawDir.last >= to)
439 {
440 //printf(" [done]\n");
441 break;
442 }
443 }
444
445 if (!this->file->device()->isOpen()) {
446 this->file->device()->close();
447 }
448
449 times = MatrixXd(1, to-from+1);
450
451 for (i = 0; i < times.cols(); ++i)
452 times(0, i) = static_cast<float>(from+i) / this->info.sfreq;
453
454 return true;
455}
456
457//=============================================================================================================
458
459bool FiffRawData::read_raw_segment(MatrixXd& data,
460 MatrixXd& times,
461 SparseMatrix<double>& multSegment,
462 fiff_int_t from,
463 fiff_int_t to,
464 const RowVectorXi& sel,
465 bool do_debug) const
466{
467 bool projAvailable = true;
468
469 if (this->proj.size() == 0) {
470 //qInfo() << "FiffRawData::read_raw_segment - No projectors setup. Consider calling MNE::setup_compensators.";
471 projAvailable = false;
472 }
473
474 if(from == -1)
475 from = this->first_samp;
476 if(to == -1)
477 to = this->last_samp;
478 //
479 // Initial checks
480 //
481 if(from < this->first_samp)
482 from = this->first_samp;
483 if(to > this->last_samp)
484 to = this->last_samp;
485 //
486 if(from > to)
487 {
488 qWarning("No data in this range\n");
489 return false;
490 }
491 //printf("Reading %d ... %d = %9.3f ... %9.3f secs...", from, to, (static_cast<float>(from))/this->info.sfreq, (static_cast<float>(to))/this->info.sfreq);
492 //
493 // Initialize the data and calibration vector
494 //
495 qint32 nchan = this->info.nchan;
496 qint32 dest = 0;//1;
497 qint32 i, k, r;
498
499 using T = Eigen::Triplet<double>;
500 std::vector<T> tripletList;
501 tripletList.reserve(nchan);
502 for(i = 0; i < nchan; ++i)
503 tripletList.push_back(T(i, i, this->cals[i]));
504
505 SparseMatrix<double> cal(nchan, nchan);
506 cal.setFromTriplets(tripletList.begin(), tripletList.end());
507// cal.makeCompressed();
508
509 MatrixXd mult_full;
510 //
511 if (sel.size() == 0)
512 {
513 data = MatrixXd(nchan, to-from+1);
514// data->setZero();
515 if (projAvailable || this->comp.kind != -1)
516 {
517 if (!projAvailable)
518 mult_full = this->comp.data->data*cal;
519 else if (this->comp.kind == -1)
520 mult_full = this->proj*cal;
521 else
522 mult_full = this->proj*this->comp.data->data*cal;
523 }
524 }
525 else
526 {
527 data = MatrixXd(sel.size(),to-from+1);
528// data->setZero();
529
530 MatrixXd selVect(sel.size(), nchan);
531
532 selVect.setZero();
533
534 if (!projAvailable && this->comp.kind == -1)
535 {
536 tripletList.clear();
537 tripletList.reserve(sel.size());
538 for(i = 0; i < sel.size(); ++i)
539 tripletList.push_back(T(i, i, this->cals[sel[i]]));
540 cal = SparseMatrix<double>(sel.size(), sel.size());
541 cal.setFromTriplets(tripletList.begin(), tripletList.end());
542 }
543 else
544 {
545 if (!projAvailable)
546 {
547 qDebug() << "This has to be debugged! #1";
548 for( i = 0; i < sel.size(); ++i)
549 selVect.row(i) = this->comp.data->data.block(sel[i],0,1,nchan);
550 mult_full = selVect*cal;
551 }
552 else if (this->comp.kind == -1)
553 {
554 for( i = 0; i < sel.size(); ++i)
555 selVect.row(i) = this->proj.block(sel[i],0,1,nchan);
556
557 mult_full = selVect*cal;
558 }
559 else
560 {
561 qDebug() << "This has to be debugged! #3";
562 for( i = 0; i < sel.size(); ++i)
563 selVect.row(i) = this->proj.block(sel[i],0,1,nchan);
564
565 mult_full = selVect*this->comp.data->data*cal;
566 }
567 }
568 }
569
570 //
571 // Make mult sparse
572 //
573 tripletList.clear();
574 tripletList.reserve(mult_full.rows()*mult_full.cols());
575 for(i = 0; i < mult_full.rows(); ++i)
576 for(k = 0; k < mult_full.cols(); ++k)
577 if(mult_full(i,k) != 0)
578 tripletList.push_back(T(i, k, mult_full(i,k)));
579
580 SparseMatrix<double> mult(mult_full.rows(),mult_full.cols());
581 if(tripletList.size() > 0)
582 mult.setFromTriplets(tripletList.begin(), tripletList.end());
583// mult.makeCompressed();
584
585 //
586
588 if (!this->file->device()->isOpen())
589 {
590 if (!this->file->device()->open(QIODevice::ReadOnly))
591 {
592 qWarning("Cannot open file %s",this->info.filename.toUtf8().constData());
593 }
594 fid = this->file;
595 }
596 else
597 {
598 fid = this->file;
599 }
600
601 MatrixXd one;
602 fiff_int_t first_pick, last_pick, picksamp;
603 for(k = 0; k < this->rawdir.size(); ++k)
604 {
605 FiffRawDir thisRawDir = this->rawdir[k];
606 //
607 // Do we need this buffer
608 //
609 if (thisRawDir.last > from)
610 {
611 if (thisRawDir.ent->kind == -1)
612 {
613 //
614 // Take the easy route: skip is translated to zeros
615 //
616 if(do_debug)
617 qDebug("S");
618 if (sel.cols() <= 0)
619 one.resize(nchan,thisRawDir.nsamp);
620 else
621 one.resize(sel.cols(),thisRawDir.nsamp);
622
623 one.setZero();
624 }
625 else
626 {
627 FiffTag::UPtr t_pTag;
628 fid->read_tag(t_pTag, thisRawDir.ent->pos);
629 //
630 // Depending on the state of the projection and selection
631 // we proceed a little bit differently
632 //
633 if (mult.cols() == 0)
634 {
635 if (sel.cols() == 0)
636 {
637 if (t_pTag->type == FIFFT_DAU_PACK16)
638 one = cal*(Map< MatrixDau16 >( t_pTag->toDauPack16(),nchan, thisRawDir.nsamp)).cast<double>();
639 else if(t_pTag->type == FIFFT_INT)
640 one = cal*(Map< MatrixXi >( t_pTag->toInt(),nchan, thisRawDir.nsamp)).cast<double>();
641 else if(t_pTag->type == FIFFT_FLOAT)
642 one = cal*(Map<const MatrixXf>(t_pTag->toFloat(),nchan, thisRawDir.nsamp)).cast<double>();
643 else if(t_pTag->type == FIFFT_SHORT)
644 one = cal*(Map< MatrixShort >( t_pTag->toShort(),nchan, thisRawDir.nsamp)).cast<double>();
645 else
646 qWarning("Data Storage Format not known yet [1]!! Type: %d\n", t_pTag->type);
647 }
648 else
649 {
650
651 //ToDo find a faster solution for this!! --> make cal and mul sparse like in MATLAB
652 MatrixXd newData(sel.cols(), thisRawDir.nsamp); //ToDo this can be done much faster, without newData
653
654 if (t_pTag->type == FIFFT_DAU_PACK16)
655 {
656 MatrixXd tmp_data = (Map< MatrixDau16 > ( t_pTag->toDauPack16(),nchan, thisRawDir.nsamp)).cast<double>();
657
658 for(r = 0; r < sel.size(); ++r)
659 newData.block(r,0,1,thisRawDir.nsamp) = tmp_data.block(sel[r],0,1,thisRawDir.nsamp);
660 }
661 else if(t_pTag->type == FIFFT_INT)
662 {
663 MatrixXd tmp_data = (Map< MatrixXi >( t_pTag->toInt(),nchan, thisRawDir.nsamp)).cast<double>();
664
665 for(r = 0; r < sel.size(); ++r)
666 newData.block(r,0,1,thisRawDir.nsamp) = tmp_data.block(sel[r],0,1,thisRawDir.nsamp);
667 }
668 else if(t_pTag->type == FIFFT_FLOAT)
669 {
670 MatrixXd tmp_data = (Map<const MatrixXf>(t_pTag->toFloat(),nchan, thisRawDir.nsamp)).cast<double>();
671
672 for(r = 0; r < sel.size(); ++r)
673 newData.block(r,0,1,thisRawDir.nsamp) = tmp_data.block(sel[r],0,1,thisRawDir.nsamp);
674 }
675 else if(t_pTag->type == FIFFT_SHORT)
676 {
677 MatrixXd tmp_data = (Map< MatrixShort > ( t_pTag->toShort(),nchan, thisRawDir.nsamp)).cast<double>();
678
679 for(r = 0; r < sel.size(); ++r)
680 newData.block(r,0,1,thisRawDir.nsamp) = tmp_data.block(sel[r],0,1,thisRawDir.nsamp);
681 }
682 else
683 {
684 qWarning("Data Storage Format not known yet [2]!! Type: %d\n", t_pTag->type);
685 }
686
687 one = cal*newData;
688 }
689 }
690 else
691 {
692 if (t_pTag->type == FIFFT_DAU_PACK16)
693 one = mult*(Map< MatrixDau16 >( t_pTag->toDauPack16(),nchan, thisRawDir.nsamp)).cast<double>();
694 else if(t_pTag->type == FIFFT_INT)
695 one = mult*(Map< MatrixXi >( t_pTag->toInt(),nchan, thisRawDir.nsamp)).cast<double>();
696 else if(t_pTag->type == FIFFT_FLOAT)
697 one = mult*(Map<const MatrixXf>(t_pTag->toFloat(),nchan, thisRawDir.nsamp)).cast<double>();
698 else
699 qWarning("Data Storage Format not known yet [3]!! Type: %d\n", t_pTag->type);
700 }
701 }
702 //
703 // The picking logic is a bit complicated
704 //
705 if (to >= thisRawDir.last && from <= thisRawDir.first)
706 {
707 //
708 // We need the whole buffer
709 //
710 first_pick = 0;//1;
711 last_pick = thisRawDir.nsamp - 1;
712 if (do_debug)
713 qDebug("W");
714 }
715 else if (from > thisRawDir.first)
716 {
717 first_pick = from - thisRawDir.first;// + 1;
718 if(to < thisRawDir.last)
719 {
720 //
721 // Something from the middle
722 //
723// qDebug() << "This needs to be debugged!";
724 last_pick = thisRawDir.nsamp + to - thisRawDir.last - 1;//is this alright?
725 if (do_debug)
726 qDebug("M");
727 }
728 else
729 {
730 //
731 // From the middle to the end
732 //
733 last_pick = thisRawDir.nsamp - 1;
734 if (do_debug)
735 qDebug("E");
736 }
737 }
738 else
739 {
740 //
741 // From the beginning to the middle
742 //
743 first_pick = 0;//1;
744 last_pick = to - thisRawDir.first;// + 1;
745 if (do_debug)
746 qDebug("B");
747 }
748 //
749 // Now we are ready to pick
750 //
751 picksamp = last_pick - first_pick + 1;
752
753 if(do_debug)
754 {
755 qDebug() << "first_pick: " << first_pick;
756 qDebug() << "last_pick: " << last_pick;
757 qDebug() << "picksamp: " << picksamp;
758 }
759
760 if (picksamp > 0)
761 {
762// for(r = 0; r < data->rows(); ++r)
763// for(c = 0; c < picksamp; ++c)
764// (*data)(r,dest + c) = one(r,first_pick + c);
765 data.block(0,dest,data.rows(),picksamp) = one.block(0, first_pick, data.rows(), picksamp);
766
767 dest += picksamp;
768 }
769 }
770 //
771 // Done?
772 //
773 if (thisRawDir.last >= to)
774 {
775 //printf(" [done]\n");
776 break;
777 }
778 }
779
780 if(mult.cols()==0)
781 multSegment = cal;
782 else
783 multSegment = mult;
784
785 if (!this->file->device()->isOpen()) {
786 this->file->device()->close();
787 }
788
789 times = MatrixXd(1, to-from+1);
790
791 for (i = 0; i < times.cols(); ++i)
792 times(0, i) = static_cast<float>(from+i) / this->info.sfreq;
793
794 return true;
795}
796
797//=============================================================================================================
798
800 MatrixXd& times,
801 float from,
802 float to,
803 const RowVectorXi& sel) const
804{
805 //
806 // Convert to samples
807 //
808 from = floor(from*this->info.sfreq);
809 to = ceil(to*this->info.sfreq);
810 //
811 // Read it
812 //
813 return this->read_raw_segment(data, times, (qint32)from, (qint32)to, sel);
814}
815
816//=============================================================================================================
817
818bool FiffRawData::save(QIODevice &p_IODevice,
819 const RowVectorXi &picks,
820 int decim,
821 int from,
822 int to) const
823{
824 if (decim < 1) decim = 1;
825
826 int firstSamp = (from >= 0) ? from : first_samp;
827 int lastSamp = (to >= 0) ? to : last_samp;
828
829 if (firstSamp > lastSamp) {
830 qWarning() << "[FiffRawData::save] Invalid sample range.";
831 return false;
832 }
833
834 // Prepare output info
835 FiffInfo outInfo;
836 if (picks.size() > 0) {
837 outInfo = info.pick_info(picks);
838 } else {
839 outInfo = info;
840 }
841
842 // Adjust sampling frequency for decimation
843 if (decim > 1) {
844 outInfo.sfreq = info.sfreq / static_cast<float>(decim);
845 }
846
847 // Use the standard start_writing_raw pipeline
848 RowVectorXd calsOut;
849 FiffStream::SPtr pStream = FiffStream::start_writing_raw(p_IODevice, outInfo, calsOut, picks);
850 if (!pStream) {
851 qWarning() << "[FiffRawData::save] Cannot start writing raw file.";
852 return false;
853 }
854
855 // Write data in blocks
856 const int blockSize = 2000;
857 int blockSamples = decim * blockSize;
858
859 for (int samp = firstSamp; samp <= lastSamp; samp += blockSamples) {
860 int nsamp = qMin(blockSamples, lastSamp - samp + 1);
861
862 MatrixXd segData;
863 MatrixXd segTimes;
864 if (!read_raw_segment(segData, segTimes, samp, samp + nsamp - 1, picks)) {
865 qWarning() << "[FiffRawData::save] Error reading data at sample" << samp;
866 pStream->finish_writing_raw();
867 return false;
868 }
869
870 // Decimate if needed
871 if (decim > 1) {
872 int nOut = (nsamp + decim - 1) / decim;
873 MatrixXd decimData(segData.rows(), nOut);
874 for (int s = 0, idx = 0; s < nsamp && idx < nOut; s += decim, ++idx) {
875 decimData.col(idx) = segData.col(s);
876 }
877 segData = decimData;
878 }
879
880 pStream->write_raw_buffer(segData, calsOut);
881 }
882
883 pStream->finish_writing_raw();
884
885 qInfo() << "[FiffRawData::save] Saved raw data from sample" << firstSamp
886 << "to" << lastSamp << "(decim=" << decim << ")";
887 return true;
888}
FiffRawData class declaration.
FiffEvents class declaration.
#define FIFFT_INT
Definition fiff_file.h:231
#define FIFFT_SHORT
Definition fiff_file.h:230
#define FIFFT_DAU_PACK16
Definition fiff_file.h:243
#define FIFFT_FLOAT
Definition fiff_file.h:232
FiffStream class declaration.
FiffTag class declaration, which provides fiff tag I/O and processing methods.
FIFF file I/O and data structures (raw, epochs, evoked, covariance, forward).
qint32 fiff_int_t
Definition fiff_types.h:89
FIFF measurement file information.
Definition fiff_info.h:86
Eigen::RowVectorXd cals
bool read_raw_segment(Eigen::MatrixXd &data, Eigen::MatrixXd &times, fiff_int_t from=-1, fiff_int_t to=-1, const Eigen::RowVectorXi &sel=defaultRowVectorXi, bool do_debug=false) const
FiffStream::SPtr file
bool save(QIODevice &p_IODevice, const Eigen::RowVectorXi &picks=Eigen::RowVectorXi(), int decim=1, int from=-1, int to=-1) const
Eigen::MatrixXd proj
bool read_raw_segment_times(Eigen::MatrixXd &data, Eigen::MatrixXd &times, float from, float to, const Eigen::RowVectorXi &sel=defaultRowVectorXi) const
QList< FiffRawDir > rawdir
FiffDirEntry::SPtr ent
QSharedPointer< FiffStream > SPtr
static bool setup_read_raw(QIODevice &p_IODevice, FiffRawData &data, bool allow_maxshield=true, bool is_littleEndian=false)
static FiffStream::SPtr start_writing_raw(QIODevice &p_IODevice, const FiffInfo &info, Eigen::RowVectorXd &cals, Eigen::MatrixXi sel=defaultMatrixXi, bool bResetRange=true)
std::unique_ptr< FiffTag > UPtr
Definition fiff_tag.h:158