v2.0.0
Loading...
Searching...
No Matches
mne_raw_data.cpp
Go to the documentation of this file.
1//=============================================================================================================
36
37//=============================================================================================================
38// INCLUDES
39//=============================================================================================================
40
41#include "mne_raw_data.h"
42
43#include <QFile>
44#include <QTextStream>
45
46#include <Eigen/Core>
47
48#define _USE_MATH_DEFINES
49#include <math.h>
50
51//=============================================================================================================
52// USED NAMESPACES
53//=============================================================================================================
54
55using namespace Eigen;
56using namespace FIFFLIB;
57using namespace MNELIB;
58
59#ifndef TRUE
60#define TRUE 1
61#endif
62
63#ifndef FALSE
64#define FALSE 0
65#endif
66
67#ifndef FAIL
68#define FAIL -1
69#endif
70
71#ifndef OK
72#define OK 0
73#endif
74
75#define MALLOC_36(x,t) (t *)malloc((x)*sizeof(t))
76#define REALLOC_36(x,y,t) (t *)((x == NULL) ? malloc((y)*sizeof(t)) : realloc((x),(y)*sizeof(t)))
77
78#define ALLOC_CMATRIX_36(x,y) mne_cmatrix_36((x),(y))
79
80#if defined(_WIN32) || defined(_WIN64)
81#define snprintf _snprintf
82#define vsnprintf _vsnprintf
83#define strcasecmp _stricmp
84#define strncasecmp _strnicmp
85#endif
86
87static void matrix_error(int kind, int nr, int nc)
88
89{
90 if (kind == 1)
91 printf("Failed to allocate memory pointers for a %d x %d matrix\n",nr,nc);
92 else if (kind == 2)
93 printf("Failed to allocate memory for a %d x %d matrix\n",nr,nc);
94 else
95 printf("Allocation error for a %d x %d matrix\n",nr,nc);
96 if (sizeof(void *) == 4) {
97 printf("This is probably because you seem to be using a computer with 32-bit architecture.\n");
98 printf("Please consider moving to a 64-bit platform.");
99 }
100 printf("Cannot continue. Sorry.\n");
101 exit(1);
102}
103
104float **mne_cmatrix_36(int nr,int nc)
105
106{
107 int i;
108 float **m;
109 float *whole;
110
111 m = MALLOC_36(nr,float *);
112 if (!m) matrix_error(1,nr,nc);
113 whole = MALLOC_36(nr*nc,float);
114 if (!whole) matrix_error(2,nr,nc);
115
116 for(i=0;i<nr;i++)
117 m[i] = whole + i*nc;
118 return m;
119}
120
121#define FREE_36(x) if ((char *)(x) != NULL) free((char *)(x))
122
123#define FREE_CMATRIX_36(m) mne_free_cmatrix_36((m))
124
125void mne_free_cmatrix_36 (float **m)
126{
127 if (m) {
128 FREE_36(*m);
129 FREE_36(m);
130 }
131}
132
133namespace MNELIB
134{
135
144{
145 struct Entry {
147 };
148
149 std::vector<Entry> entries;
150 int next = 0;
151
152 explicit RingBuffer(int nslots)
153 : entries(static_cast<size_t>(nslots))
154 , next(0)
155 {}
156
158 void allocate(int nrow, int ncol, MNERawBufDef::RowMajorMatrixXf *res)
159 {
160 if (next >= static_cast<int>(entries.size()))
161 next = 0;
162 Entry &e = entries[static_cast<size_t>(next++)];
163 if (e.user) // evict old occupant
164 e.user->resize(0, 0);
165 res->resize(nrow, ncol);
166 e.user = res;
167 }
168};
169
170}
171
172void mne_free_name_list_36(char **list, int nlist)
173/*
174 * Free a name list array
175 */
176{
177 int k;
178 if (list == NULL || nlist == 0)
179 return;
180 for (k = 0; k < nlist; k++) {
181#ifdef FOO
182 printf("%d %s\n",k,list[k]);
183#endif
184 FREE_36(list[k]);
185 }
186 FREE_36(list);
187 return;
188}
189
190//============================= misc_util.c =============================
191
192void mne_string_to_name_list(const QString& s, QStringList& listp,int &nlistp)
193/*
194 * Convert a colon-separated list into a string array
195 */
196{
197 QStringList list;
198
199 if (!s.isEmpty() && s.size() > 0) {
201 //list = s.split(":");
202 }
203 listp = list;
204 nlistp = list.size();
205 return;
206}
207
208QString mne_name_list_to_string(const QStringList& list)
209/*
210 * Convert a string array to a colon-separated string
211 */
212{
213 int nlist = list.size();
214 QString res;
215 if (nlist == 0 || list.isEmpty())
216 return res;
217// res[0] = '\0';
218 for (int k = 0; k < nlist-1; k++) {
219 res += list[k];
220 res += ":";
221 }
222 res += list[nlist-1];
223 return res;
224}
225
226QString mne_channel_names_to_string(const QList<FIFFLIB::FiffChInfo>& chs,
227 int nch)
228/*
229 * Make a colon-separated string out of channel names
230 */
231{
232 QStringList names;
233 QString res;
234 if (nch <= 0)
235 return res;
236 for (int k = 0; k < nch; k++)
237 names.append(chs[k].ch_name);
238 res = mne_name_list_to_string(names);
239 return res;
240}
241
242void mne_channel_names_to_name_list(const QList<FIFFLIB::FiffChInfo>& chs,
243 int nch,
244 QStringList& listp,
245 int &nlistp)
246
247{
248 QString s = mne_channel_names_to_string(chs,nch);
249 mne_string_to_name_list(s,listp,nlistp);
250 return;
251}
252
253//============================= mne_apply_filter.c =============================
254
255namespace MNELIB
256{
257
265{
266 std::vector<float> freq_resp;
267 std::vector<float> eog_freq_resp;
268 std::vector<float> precalc;
269
270 explicit FilterData(int resp_size)
271 : freq_resp(static_cast<size_t>(resp_size), 1.0f)
272 , eog_freq_resp(static_cast<size_t>(resp_size), 1.0f)
273 {}
274};
275
276}
277
279 const MNEFilterDef& f2)
280/*
281 * Return 0 if the two filter definitions are same, 1 otherwise
282 */
283{
284 if (f1.filter_on != f2.filter_on ||
285 std::fabs(f1.lowpass - f2.lowpass) > 0.1 ||
286 std::fabs(f1.lowpass_width - f2.lowpass_width) > 0.1 ||
287 std::fabs(f1.highpass - f2.highpass) > 0.1 ||
288 std::fabs(f1.highpass_width - f2.highpass_width) > 0.1 ||
289 std::fabs(f1.eog_lowpass - f2.eog_lowpass) > 0.1 ||
290 std::fabs(f1.eog_lowpass_width - f2.eog_lowpass_width) > 0.1 ||
291 std::fabs(f1.eog_highpass - f2.eog_highpass) > 0.1 ||
292 std::fabs(f1.eog_highpass_width - f2.eog_highpass_width) > 0.1)
293 return 1;
294 else
295 return 0;
296}
297
298//============================= mne_fft.c =============================
299
300void mne_fft_ana(float *data, int np, std::vector<float>& /*precalc*/)
301/*
302 * FFT analysis for real data
303 */
304{
305 Q_UNUSED(data);
306 Q_UNUSED(np);
307 printf("##################### DEBUG Error: FFT analysis needs to be implemented");
308 return;
309}
310
311void mne_fft_syn(float *data, int np, std::vector<float>& /*precalc*/)
312/*
313 * FFT synthesis for real data
314 */
315{
316 Q_UNUSED(data);
317 Q_UNUSED(np);
318 printf("##################### DEBUG Error: FFT synthesis needs to be implemented");
319 return;
320}
321
322int mne_apply_filter(const MNEFilterDef& filter, FilterData *d, float *data, int ns, int zero_pad, float dc_offset, int kind)
323/*
324 * Do the magick trick
325 */
326{
327 int k,p,n;
328 float *freq_resp;
329
330 if (ns != filter.size + 2*filter.taper_size) {
331 printf("Incorrect data length in apply_filter");
332 return FAIL;
333 }
334 /*
335 * Zero padding
336 */
337 if (zero_pad) {
338 for (k = 0; k < filter.taper_size; k++)
339 data[k] = 0.0;
340 for (k = filter.taper_size + filter.size; k < ns; k++)
341 data[k] = 0.0;
342 }
343 if (!filter.filter_on) /* Nothing else to do */
344 return OK;
345 /*
346 * Make things nice by compensating for the dc offset
347 */
348 if (dc_offset != 0.0) {
349 for (k = filter.taper_size; k < filter.taper_size + filter.size; k++)
350 data[k] = data[k] - dc_offset;
351 }
352 if (!d)
353 return OK;
354 if (d->freq_resp.empty())
355 return OK;
356 /*
357 * Next comes the FFT
358 */
359 mne_fft_ana(data,ns,d->precalc);
360 /*
361 * Multiply with the frequency response
362 * See FFTpack doc for details of the arrangement
363 */
364 n = ns % 2 == 0 ? ns/2 : (ns+1)/2;
365 p = 0;
366 /*
367 * No imaginary part for the DC component
368 */
369 if (kind == FIFFV_EOG_CH)
370 freq_resp = d->eog_freq_resp.data();
371 else
372 freq_resp = d->freq_resp.data();
373 data[p] = data[p]*freq_resp[0]; p++;
374 /*
375 * The other components
376 */
377 for (k = 1 ; k < n ; k++) {
378 data[p] = data[p]*freq_resp[k]; p++;
379 data[p] = data[p]*freq_resp[k]; p++;
380 }
381 /*
382 * Then the last value
383 */
384 if (ns % 2 == 0)
385 data[p] = data[p]*freq_resp[k];
386
387 mne_fft_syn(data,ns,d->precalc);
388
389 return OK;
390}
391
392std::unique_ptr<FilterData> mne_create_filter_response(const MNEFilterDef& filter,
393 float sfreq,
394 int *highpass_effective)
395/*
396 * Create a frequency response
397 */
398{
399 int resp_size;
400 int k,s,w,f;
401 int highpasss,lowpasss;
402 int highpass_widths,lowpass_widths;
403 float lowpass,highpass,lowpass_width,highpass_width;
404 float *freq_resp;
405 float pi4 = M_PI/4.0;
406 float mult,add,c;
407
408 resp_size = (filter.size + 2*filter.taper_size)/2 + 1;
409
410 auto filter_data = std::make_unique<FilterData>(resp_size);
411 *highpass_effective = FALSE;
412
413 for (f = 0; f < 2; f++) {
414 highpass = f == 0 ? filter.highpass : filter.eog_highpass;
415 highpass_width = f == 0 ? filter.highpass_width : filter.eog_highpass_width;
416 lowpass = f == 0 ? filter.lowpass : filter.eog_lowpass;
417 lowpass_width = f == 0 ? filter.lowpass_width : filter.eog_lowpass_width;
418 freq_resp = f == 0 ? filter_data->freq_resp.data() : filter_data->eog_freq_resp.data();
419 /*
420 * Start simple first
421 */
422 highpasss = ((resp_size-1)*highpass)/(0.5*sfreq);
423 lowpasss = ((resp_size-1)*lowpass)/(0.5*sfreq);
424
425 lowpass_widths = ((resp_size-1)*lowpass_width)/(0.5*sfreq);
426 lowpass_widths = (lowpass_widths+1)/2; /* What user specified */
427
428 if (filter.highpass_width > 0.0) {
429 highpass_widths = ((resp_size-1)*highpass_width)/(0.5*sfreq);
430 highpass_widths = (highpass_widths+1)/2; /* What user specified */
431 }
432 else
433 highpass_widths = 3; /* Minimal */
434
435 if (filter.filter_on) {
436 printf("filter : %7.3f ... %6.1f Hz bins : %d ... %d of %d hpw : %d lpw : %d\n",
437 highpass,
438 lowpass,
439 highpasss,
440 lowpasss,
441 resp_size,
442 highpass_widths,
443 lowpass_widths);
444 }
445 if (highpasss > highpass_widths + 1) {
446 w = highpass_widths;
447 mult = 1.0/w;
448 add = 3.0;
449 for (k = 0; k < highpasss-w+1; k++)
450 freq_resp[k] = 0.0;
451 for (k = -w+1, s = highpasss-w+1; k < w; k++, s++) {
452 if (s >= 0 && s < resp_size) {
453 c = cos(pi4*(k*mult+add));
454 freq_resp[s] = freq_resp[s]*c*c;
455 }
456 }
457 *highpass_effective = TRUE;
458 }
459 else
460 *highpass_effective = *highpass_effective || (filter.highpass == 0.0);
461
462 if (lowpass_widths > 0) {
463 w = lowpass_widths;
464 mult = 1.0/w;
465 add = 1.0;
466 for (k = -w+1, s = lowpasss-w+1; k < w; k++, s++) {
467 if (s >= 0 && s < resp_size) {
468 c = cos(pi4*(k*mult+add));
469 freq_resp[s] = freq_resp[s]*c*c;
470 }
471 }
472 for (k = s; k < resp_size; k++)
473 freq_resp[k] = 0.0;
474 }
475 else {
476 for (k = lowpasss; k < resp_size; k++)
477 freq_resp[k] = 0.0;
478 }
479 if (filter.filter_on) {
480 if (*highpass_effective)
481 printf("Highpass filter will work as specified.\n");
482 else
483 printf("NOTE: Highpass filter omitted due to a too low corner frequency.\n");
484 }
485 else
486 printf("NOTE: Filter is presently switched off.\n");
487 }
488 return filter_data;
489}
490
491//============================= mne_raw_routines.c =============================
492
493int mne_read_raw_buffer_t(//fiffFile in, /* Input file */
494 FiffStream::SPtr& stream,
495 const FiffDirEntry::SPtr& ent, /* The directory entry to read */
496 MNERawBufDef::RowMajorMatrixXf& data, /* Matrix [npick x nsamp] to fill */
497 int nchan, /* Number of channels in the data */
498 int nsamp, /* Expected number of samples */
499 const QList<FIFFLIB::FiffChInfo>& chs, /* Channel info for ALL channels */
500 int *pickno, /* Which channels to pick */
501 int npick) /* How many */
502
503{
504 FiffTag::SPtr t_pTag;
505// fiffTagRec tag;
506 fiff_short_t *this_samples;
507 fiff_float_t *this_samplef;
508 fiff_int_t *this_sample;
509
510 int s,c;
511 int do_all;
512 float *mult;
513
514// tag.data = NULL;
515
516 if (npick == 0) {
517 pickno = MALLOC_36(nchan, int);
518 for (c = 0; c < nchan; c++)
519 pickno[c] = c;
520 do_all = TRUE;
521 npick = nchan;
522 }
523 else
524 do_all = FALSE;
525
526 mult = MALLOC_36(npick,float);
527 for (c = 0; c < npick; c++)
528 mult[c] = chs[pickno[c]].cal*chs[pickno[c]].range;
529
530// if (fiff_read_this_tag(in->fd,ent->pos,&tag) == FIFF_FAIL)
531// goto bad;
532 if (!stream->read_tag(t_pTag,ent->pos))
533 goto bad;
534
535 if (ent->type == FIFFT_FLOAT) {
536 if ((int)(t_pTag->size()/(sizeof(fiff_float_t)*nchan)) != nsamp) {
537 printf("Incorrect number of samples in buffer.");
538 goto bad;
539 }
540 qDebug() << "ToDo: Check whether this_samplef contains the right stuff!!! - use VectorXf instead";
541 this_samplef = t_pTag->toFloat();
542 for (s = 0; s < nsamp; s++, this_samplef += nchan) {
543 for (c = 0; c < npick; c++)
544 data(c,s) = mult[c]*this_samplef[pickno[c]];
545 }
546 }
547 else if (ent->type == FIFFT_SHORT || ent->type == FIFFT_DAU_PACK16) {
548 if ((int)(t_pTag->size()/(sizeof(fiff_short_t)*nchan)) != nsamp) {
549 printf("Incorrect number of samples in buffer.");
550 goto bad;
551 }
552 qDebug() << "ToDo: Check whether this_samples contains the right stuff!!! - use VectorXi instead";
553 this_samples = (fiff_short_t *)t_pTag->data();
554 for (s = 0; s < nsamp; s++, this_samples += nchan) {
555 for (c = 0; c < npick; c++)
556 data(c,s) = mult[c]*this_samples[pickno[c]];
557 }
558 }
559 else if (ent->type == FIFFT_INT) {
560 if ((int)(t_pTag->size()/(sizeof(fiff_int_t)*nchan)) != nsamp) {
561 printf("Incorrect number of samples in buffer.");
562 goto bad;
563 }
564 qDebug() << "ToDo: Check whether this_sample contains the right stuff!!! - use VectorXi instead";
565 this_sample = t_pTag->toInt();
566 for (s = 0; s < nsamp; s++, this_sample += nchan) {
567 for (c = 0; c < npick; c++)
568 data(c,s) = mult[c]*this_sample[pickno[c]];
569 }
570 }
571 else {
572 printf("We are not prepared to handle raw data type: %d",ent->type);
573 goto bad;
574 }
575 if (do_all)
576 FREE_36(pickno);
577 FREE_36(mult);
578// FREE_36(tag.data);
579 return OK;
580
581bad : {
582 if (do_all)
583 FREE_36(pickno);
584// FREE_36(tag.data);
585 return FAIL;
586 }
587}
588
589//============================= mne_process_bads.c =============================
590
592 const FiffDirNode::SPtr& pNode, QStringList& listp, int& nlistp)
593{
594 FiffDirNode::SPtr node,bad;
595 QList<FiffDirNode::SPtr> temp;
596 QStringList list;
597 int nlist = 0;
598 FiffTag::SPtr t_pTag;
599 QString names;
600
601 if (pNode->isEmpty())
602 node = stream->dirtree();
603 else
604 node = pNode;
605
606 temp = node->dir_tree_find(FIFFB_MNE_BAD_CHANNELS);
607 if (temp.size() > 0) {
608 bad = temp[0];
609
610 bad->find_tag(stream, FIFF_MNE_CH_NAME_LIST, t_pTag);
611 if (t_pTag) {
612 names = t_pTag->toString();
613 mne_string_to_name_list(names,list,nlist);
614 }
615 }
616 listp = list;
617 nlistp = nlist;
618 return OK;
619}
620
621int mne_read_bad_channel_list(const QString& name, QStringList& listp, int& nlistp)
622
623{
624 QFile file(name);
625 FiffStream::SPtr stream(new FiffStream(&file));
626
627 int res;
628
629 if(!stream->open())
630 return FAIL;
631
632 res = mne_read_bad_channel_list_from_node(stream,stream->dirtree(),listp,nlistp);
633
634 stream->close();
635
636 return res;
637}
638
639int mne_sparse_vec_mult2(FiffSparseMatrix* mat, /* The sparse matrix */
640 float *vector, /* Vector to be multiplied */
641 float *res) /* Result of the multiplication */
642/*
643 * Multiply a vector by a sparse matrix.
644 */
645{
646 int i,j;
647
648 if (mat->coding == FIFFTS_MC_RCS) {
649 for (i = 0; i < mat->m; i++) {
650 res[i] = 0.0;
651 for (j = mat->ptrs[i]; j < mat->ptrs[i+1]; j++)
652 res[i] += mat->data[j]*vector[mat->inds[j]];
653 }
654 return 0;
655 }
656 else if (mat->coding == FIFFTS_MC_CCS) {
657 for (i = 0; i < mat->m; i++)
658 res[i] = 0.0;
659 for (i = 0; i < mat->n; i++)
660 for (j = mat->ptrs[i]; j < mat->ptrs[i+1]; j++)
661 res[mat->inds[j]] += mat->data[j]*vector[i];
662 return 0;
663 }
664 else {
665 qWarning("mne_sparse_vec_mult2: unknown sparse matrix storage type: %d",mat->coding);
666 return -1;
667 }
668}
669
670int mne_sparse_mat_mult2(FiffSparseMatrix* mat, /* The sparse matrix */
671 const MNERawBufDef::RowMajorMatrixXf& mult, /* Matrix to be multiplied */
672 int ncol, /* How many columns in the above */
673 float **res) /* Result of the multiplication */
674/*
675 * Multiply a dense matrix by a sparse matrix.
676 */
677{
678 int i,j,k;
679 float val;
680
681 if (mat->coding == FIFFTS_MC_RCS) {
682 for (i = 0; i < mat->m; i++) {
683 for (k = 0; k < ncol; k++) {
684 val = 0.0;
685 for (j = mat->ptrs[i]; j < mat->ptrs[i+1]; j++)
686 val += mat->data[j]*mult(mat->inds[j],k);
687 res[i][k] = val;
688 }
689 }
690 }
691 else if (mat->coding == FIFFTS_MC_CCS) {
692 for (k = 0; k < ncol; k++) {
693 for (i = 0; i < mat->m; i++)
694 res[i][k] = 0.0;
695 for (i = 0; i < mat->n; i++)
696 for (j = mat->ptrs[i]; j < mat->ptrs[i+1]; j++)
697 res[mat->inds[j]][k] += mat->data[j]*mult(i,k);
698 }
699 }
700 else {
701 qWarning("mne_sparse_mat_mult2: unknown sparse matrix storage type: %d",mat->coding);
702 return -1;
703 }
704 return 0;
705}
706
707#define APPROX_RING_BUF_SIZE (600*1024*1024)
708
709static int approx_ring_buf_size = APPROX_RING_BUF_SIZE;
710
711//=============================================================================================================
712// DEFINE MEMBER METHODS
713//=============================================================================================================
714
716:info(nullptr)
717,nbad(0)
718,first_samp(0)
719,omit_samp(0)
721,proj(nullptr)
722,sss(nullptr)
723,comp(nullptr)
726,max_event(0)
728,deriv(nullptr)
729,deriv_matched(nullptr)
730{
731}
732
733//=============================================================================================================
734
736{
737// fiff_close(this->file);
738 this->stream->close();
739 this->filename.clear();
740 this->ch_names.clear();
741
742 this->badlist.clear();
743
744 this->dig_trigger.clear();
745 this->event_list.reset();
746}
747
748//=============================================================================================================
749
750void MNERawData::add_filter_response(int *highpass_effective)
751/*
752 * Add the standard filter frequency response function
753 */
754{
755 /*
756 * Free the previous filter definition
757 */
758 filter_data.reset();
759 /*
760 * Nothing more to do if there is no filter
761 */
762 if (!filter)
763 return;
764 /*
765 * Create a new one
766 */
768 info->sfreq,
769 highpass_effective);
770}
771
772//=============================================================================================================
773
775/*
776 * These will hold the filtered data
777 */
778{
779 MNEFilterDef* filter = this->filter.get();
780 int nfilt_buf;
781 int k;
782 int firstsamp;
783 int nring_buf;
784 int highpass_effective;
785
786 this->filt_bufs.clear();
787 this->filt_ring.reset();
788
789 if (!this->filter)
790 return;
791
792 for (nfilt_buf = 0, firstsamp = this->first_samp-filter->taper_size;
793 firstsamp < this->nsamp + this->first_samp;
794 firstsamp = firstsamp + filter->size)
795 nfilt_buf++;
796#ifdef DEBUG
797 printf("%d filter buffers needed\n",nfilt_buf);
798#endif
799 this->filt_bufs.resize(nfilt_buf);
800 for (k = 0, firstsamp = this->first_samp-filter->taper_size; k < nfilt_buf; k++,
801 firstsamp = firstsamp + filter->size) {
802 filt_bufs[k].ns = filter->size + 2*filter->taper_size;
803 filt_bufs[k].firsts = firstsamp;
804 filt_bufs[k].lasts = firstsamp + filt_bufs[k].ns - 1;
805 // bufs[k].ent = NULL;
806 filt_bufs[k].nchan = this->info->nchan;
807 filt_bufs[k].is_skip = FALSE;
808 filt_bufs[k].valid = FALSE;
809 filt_bufs[k].ch_filtered = Eigen::VectorXi::Zero(this->info->nchan);
810 filt_bufs[k].comp_status = MNE_CTFV_NOGRAD;
811 }
812 nring_buf = approx_ring_buf_size/((2*filter->taper_size+filter->size)*
813 this->info->nchan*sizeof(float));
814 this->filt_ring = std::make_unique<RingBuffer>(nring_buf);
815 add_filter_response(&highpass_effective);
816
817 return;
818}
819
820//=============================================================================================================
821
823/*
824 * load just one
825 */
826{
827 if (buf->ent->kind == FIFF_DATA_SKIP) {
828 printf("Cannot load a skip");
829 return FAIL;
830 }
831 if (buf->vals.size() == 0) { /* The data space may have been reused */
832 buf->valid = FALSE;
833 ring->allocate(buf->nchan,buf->ns,&buf->vals);
834 }
835 if (buf->valid)
836 return OK;
837
838#ifdef DEBUG
839 printf("Read buffer %d .. %d\n",buf->firsts,buf->lasts);
840#endif
841
843 buf->ent,
844 buf->vals,
845 buf->nchan,
846 buf->ns,
847 info->chInfo,
848 NULL,0) != OK) {
849 buf->valid = FALSE;
850 return FAIL;
851 }
852 buf->valid = TRUE;
853 buf->comp_status = comp_file;
854 return OK;
855}
856
857//=============================================================================================================
858
860/*
861 * Apply compensation channels
862 */
863{
864
865 if (!comp)
866 return OK;
867 if (!comp->undo && !comp->current)
868 return OK;
869 if (buf->comp_status == comp_now)
870 return OK;
871 if (buf->vals.size() == 0)
872 return OK;
873 /*
874 * vals is now a RowMajorMatrixXf — wrap in a column-major MatrixXf for compensation
875 */
876 {
877 Eigen::MatrixXf dataMat = buf->vals; /* implicit copy/conversion */
878
879 if (comp->undo) {
880 std::swap(comp->current, comp->undo);
881 /*
882 * Undo the previous compensation
883 */
884 if (comp->apply_transpose(FALSE, dataMat) != OK) {
885 std::swap(comp->current, comp->undo);
886 goto bad;
887 }
888 std::swap(comp->current, comp->undo);
889 }
890 if (comp->current) {
891 /*
892 * Apply new compensation
893 */
894 if (comp->apply_transpose(TRUE, dataMat) != OK)
895 goto bad;
896 }
897 /*
898 * Copy result back to buf->vals
899 */
900 buf->vals = dataMat;
901 }
902 buf->comp_status = comp_now;
903 return OK;
904
905bad :
906 return FAIL;
907}
908
909//=============================================================================================================
910
911int MNERawData::pick_data(mneChSelection sel, int firsts, int ns, float **picked)
912/*
913 * Data from a selection of channels
914 */
915{
916 int k,s,p,start,c,fills;
917 int ns2,s2;
918 MNERawBufDef* this_buf;
919 float *values;
920 int need_some;
921
922 float **deriv_vals = NULL;
923 int deriv_ns = 0;
924 int nderiv = 0;
925
926 if (firsts < first_samp) {
927 for (s = 0, p = firsts; p < first_samp; s++, p++) {
928 if (sel)
929 for (c = 0; c < sel->nchan; c++)
930 picked[c][s] = 0.0;
931 else
932 for (c = 0; c < info->nchan; c++)
933 picked[c][s] = 0.0;
934 }
935 ns = ns - s;
936 firsts = first_samp;
937 }
938 else
939 s = 0;
940 /*
941 * There is possibly nothing to do
942 */
943 if (sel) {
944 for (c = 0, need_some = FALSE; c < sel->nchan; c++) {
945 if (sel->pick[c] >= 0 || sel->pick_deriv[c] >= 0) {
946 need_some = TRUE;
947 break;
948 }
949 }
950 if (!need_some)
951 return OK;
952 }
953 /*
954 * Have to to the hard work
955 */
956 for (k = 0, this_buf = bufs.data(), s = 0; k < (int)bufs.size(); k++, this_buf++) {
957 if (this_buf->lasts >= firsts) {
958 start = firsts - this_buf->firsts;
959 if (start < 0)
960 start = 0;
961 if (this_buf->is_skip) {
962 for (p = start; p < this_buf->ns && ns > 0; p++, ns--, s++) {
963 if (sel) {
964 for (c = 0; c < sel->nchan; c++)
965 if (sel->pick[c] >= 0)
966 picked[c][s] = 0.0;
967 }
968 else {
969 for (c = 0; c < info->nchan; c++)
970 picked[c][s] = 0.0;
971 }
972 }
973 }
974 else {
975 /*
976 * Load the buffer
977 */
978 if (load_one_buffer(this_buf) != OK)
979 return FAIL;
980 /*
981 * Apply compensation
982 */
983 if (compensate_buffer(this_buf) != OK)
984 return FAIL;
985 ns2 = s2 = 0;
986 if (sel) {
987 /*
988 * Do we need the derived channels?
989 */
990 if (sel->nderiv > 0 && deriv_matched) {
991 if (deriv_ns < this_buf->ns || nderiv != deriv_matched->deriv_data->nrow) {
992 FREE_CMATRIX_36(deriv_vals);
993 deriv_vals = ALLOC_CMATRIX_36(deriv_matched->deriv_data->nrow,this_buf->ns);
994 nderiv = deriv_matched->deriv_data->nrow;
995 deriv_ns = this_buf->ns;
996 }
997 if (mne_sparse_mat_mult2(deriv_matched->deriv_data->data.get(),this_buf->vals,this_buf->ns,deriv_vals) == FAIL) {
998 FREE_CMATRIX_36(deriv_vals);
999 return FAIL;
1000 }
1001 }
1002 for (c = 0; c < sel->nchan; c++) {
1003 /*
1004 * First pick the ordinary channels...
1005 */
1006 if (sel->pick[c] >= 0) {
1007 for (p = start, s2 = s, ns2 = ns; p < this_buf->ns && ns2 > 0; p++, ns2--, s2++)
1008 picked[c][s2] = this_buf->vals(sel->pick[c], p);
1009 }
1010 /*
1011 * ...then the derived ones
1012 */
1013 else if (sel->pick_deriv[c] >= 0 && deriv_matched) {
1014 values = deriv_vals[sel->pick_deriv[c]];
1015 for (p = start, s2 = s, ns2 = ns; p < this_buf->ns && ns2 > 0; p++, ns2--, s2++)
1016 picked[c][s2] = values[p];
1017 }
1018 }
1019 }
1020 else {
1021 for (c = 0; c < info->nchan; c++)
1022 for (p = start, s2 = s, ns2 = ns; p < this_buf->ns && ns2 > 0; p++, ns2--, s2++)
1023 picked[c][s2] = this_buf->vals(c, p);
1024 }
1025 s = s2;
1026 ns = ns2;
1027 }
1028 if (ns == 0)
1029 break;
1030 }
1031 }
1032 /*
1033 * Extend with the last available sample or zero if the request is beyond the data
1034 */
1035 if (s > 0) {
1036 fills = s-1;
1037 for (; ns > 0; ns--, s++) {
1038 if (sel)
1039 for (c = 0; c < sel->nchan; c++)
1040 picked[c][s] = picked[c][fills];
1041 else
1042 for (c = 0; c < info->nchan; c++)
1043 picked[c][s] = picked[c][fills];
1044 }
1045 }
1046 else {
1047 for (; ns > 0; ns--, s++) {
1048 if (sel)
1049 for (c = 0; c < sel->nchan; c++)
1050 picked[c][s] = 0;
1051 else
1052 for (c = 0; c < info->nchan; c++)
1053 picked[c][s] = 0;
1054 }
1055 }
1056 FREE_CMATRIX_36(deriv_vals);
1057 return OK;
1058}
1059
1060//=============================================================================================================
1061
1062int MNERawData::pick_data_proj(mneChSelection sel, int firsts, int ns, float **picked)
1063/*
1064 * Data from a set of channels, apply projection
1065 */
1066{
1067 int k,s,p,start,c,fills;
1068 MNERawBufDef* this_buf;
1070 float *pvalues;
1071 float *deriv_pvalues = NULL;
1072
1073 if (!proj || (sel && !proj->affect(sel->chspick,sel->nchan) && !proj->affect(sel->chspick_nospace,sel->nchan)))
1074 return pick_data(sel,firsts,ns,picked);
1075
1076 if (firsts < first_samp) {
1077 for (s = 0, p = firsts; p < first_samp; s++, p++) {
1078 if (sel)
1079 for (c = 0; c < sel->nchan; c++)
1080 picked[c][s] = 0.0;
1081 else
1082 for (c = 0; c < info->nchan; c++)
1083 picked[c][s] = 0.0;
1084 }
1085 ns = ns - s;
1086 firsts = first_samp;
1087 }
1088 else
1089 s = 0;
1090 pvalues = MALLOC_36(info->nchan,float);
1091 for (k = 0, this_buf = bufs.data(); k < (int)bufs.size(); k++, this_buf++) {
1092 if (this_buf->lasts >= firsts) {
1093 start = firsts - this_buf->firsts;
1094 if (start < 0)
1095 start = 0;
1096 if (this_buf->is_skip) {
1097 for (p = start; p < this_buf->ns && ns > 0; p++, ns--, s++) {
1098 if (sel) {
1099 for (c = 0; c < sel->nchan; c++)
1100 if (sel->pick[c] >= 0)
1101 picked[c][s] = 0.0;
1102 }
1103 else {
1104 for (c = 0; c < info->nchan; c++)
1105 picked[c][s] = 0.0;
1106 }
1107 }
1108 }
1109 else {
1110 /*
1111 * Load the buffer
1112 */
1113 if (load_one_buffer(this_buf) != OK)
1114 return FAIL;
1115 /*
1116 * Apply compensation
1117 */
1118 if (compensate_buffer(this_buf) != OK)
1119 return FAIL;
1120 /*
1121 * Apply projection
1122 */
1123 values = &this_buf->vals;
1124 if (sel && sel->nderiv > 0 && deriv_matched)
1125 deriv_pvalues = MALLOC_36(deriv_matched->deriv_data->nrow,float);
1126 for (p = start; p < this_buf->ns && ns > 0; p++, ns--, s++) {
1127 for (c = 0; c < info->nchan; c++)
1128 pvalues[c] = (*values)(c,p);
1129 if (proj->project_vector(pvalues,info->nchan,TRUE) != OK)
1130 qWarning()<<"Error";
1131 if (sel) {
1132 if (sel->nderiv > 0 && deriv_matched) {
1133 if (mne_sparse_vec_mult2(deriv_matched->deriv_data->data.get(),pvalues,deriv_pvalues) == FAIL)
1134 return FAIL;
1135 }
1136 for (c = 0; c < sel->nchan; c++) {
1137 /*
1138 * First try the ordinary channels...
1139 */
1140 if (sel->pick[c] >= 0)
1141 picked[c][s] = pvalues[sel->pick[c]];
1142 /*
1143 * ...then the derived ones
1144 */
1145 else if (sel->pick_deriv[c] >= 0 && deriv_matched)
1146 picked[c][s] = deriv_pvalues[sel->pick_deriv[c]];
1147 }
1148 }
1149 else {
1150 for (c = 0; c < info->nchan; c++) {
1151 picked[c][s] = pvalues[c];
1152 }
1153 }
1154 }
1155 }
1156 if (ns == 0)
1157 break;
1158 }
1159 }
1160 FREE_36(deriv_pvalues);
1161 FREE_36(pvalues);
1162 /*
1163 * Extend with the last available sample or zero if the request is beyond the data
1164 */
1165 if (s > 0) {
1166 fills = s-1;
1167 for (; ns > 0; ns--, s++) {
1168 if (sel)
1169 for (c = 0; c < sel->nchan; c++)
1170 picked[c][s] = picked[c][fills];
1171 else
1172 for (c = 0; c < info->nchan; c++)
1173 picked[c][s] = picked[c][fills];
1174 }
1175 }
1176 else {
1177 for (; ns > 0; ns--, s++) {
1178 if (sel)
1179 for (c = 0; c < sel->nchan; c++)
1180 picked[c][s] = 0;
1181 else
1182 for (c = 0; c < info->nchan; c++)
1183 picked[c][s] = 0;
1184 }
1185 }
1186 return OK;
1187}
1188
1189//=============================================================================================================
1190
1192/*
1193 * Load and filter one buffer
1194 */
1195{
1196 int k;
1197 int res;
1198
1199 float **vals;
1200
1201 if (buf->vals.size() == 0) {
1202 buf->valid = FALSE;
1203 filt_ring->allocate(buf->nchan, buf->ns,&buf->vals);
1204 }
1205 if (buf->valid)
1206 return OK;
1207
1208 vals = MALLOC_36(buf->nchan,float *);
1209 for (k = 0; k < buf->nchan; k++) {
1210 buf->ch_filtered[k] = FALSE;
1211 vals[k] = buf->vals.row(k).data() + filter->taper_size;
1212 }
1213
1214 res = pick_data_proj(NULL,buf->firsts + filter->taper_size,buf->ns - 2*filter->taper_size,vals);
1215
1216 FREE_36(vals);
1217
1218#ifdef DEBUG
1219 if (res == OK)
1220 printf("Loaded filtered buffer %d...%d %d %d last = %d\n",
1221 buf->firsts,buf->lasts,buf->lasts-buf->firsts+1,buf->ns,first_samp + nsamp);
1222#endif
1223 buf->valid = res == OK;
1224 return res;
1225}
1226
1227//=============================================================================================================
1228
1229int MNERawData::pick_data_filt(mneChSelection sel, int firsts, int ns, float **picked)
1230/*
1231 * Data for a selection (filtered and picked)
1232 */
1233{
1234 int k,s,bs,c;
1235 int bs1,bs2,s1,s2,lasts;
1236 MNERawBufDef* this_buf;
1237 float *values;
1238 float **deriv_vals = NULL;
1239 Eigen::VectorXf dc;
1240 float dc_offset;
1241 int deriv_ns = 0;
1242 int nderiv = 0;
1243 int filter_was;
1244
1245 if (!filter->filter_on)
1246 return pick_data_proj(sel,firsts,ns,picked);
1247
1248 if (sel) {
1249 for (s = 0; s < ns; s++)
1250 for (c = 0; c < sel->nchan; c++)
1251 picked[c][s] = 0.0;
1252 }
1253 else {
1254 for (s = 0; s < ns; s++)
1255 for (c = 0; c < info->nchan; c++)
1256 picked[c][s] = 0.0;
1257 }
1258 lasts = firsts + ns - 1;
1259 /*
1260 * Take into account the initial dc offset (compensate and project)
1261 */
1262 if (first_sample_val.size() > 0) {
1263 dc = first_sample_val;
1264 /*
1265 * Is this correct??
1266 */
1267 if (comp && comp->current)
1268 if (comp->apply(TRUE,dc) != OK)
1269 goto bad;
1270 if (proj)
1271 if (proj->project_vector(dc.data(),info->nchan,TRUE) != OK)
1272 goto bad;
1273 }
1274 filter_was = filter->filter_on;
1275 /*
1276 * Find the first buffer to consider
1277 */
1278 for (k = 0, this_buf = filt_bufs.data(); k < (int)filt_bufs.size(); k++, this_buf++) {
1279 if (this_buf->lasts >= firsts)
1280 break;
1281 }
1282 for (; k < (int)filt_bufs.size() && this_buf->firsts <= lasts; k++, this_buf++) {
1283#ifdef DEBUG
1284 printf("this_buf (%d): %d..%d\n",k,this_buf->firsts,this_buf->lasts);
1285#endif
1286 /*
1287 * Load the buffer first and apply projection
1288 */
1289 if (load_one_filt_buf(this_buf) != OK)
1290 goto bad;
1291 /*
1292 * Then filter all relevant channels (not stimuli)
1293 */
1294 if (sel) {
1295 for (c = 0; c < sel->nchan; c++) {
1296 if (sel->pick[c] >= 0) {
1297 if (!this_buf->ch_filtered[sel->pick[c]]) {
1298 /*
1299 * Do not filter stimulus channels
1300 */
1301 dc_offset = 0.0;
1302 if (info->chInfo[sel->pick[c]].kind == FIFFV_STIM_CH)
1303 filter->filter_on = FALSE;
1304 else if (dc.size() > 0)
1305 dc_offset = dc[sel->pick[c]];
1306 if (mne_apply_filter(*filter,filter_data.get(),this_buf->vals.row(sel->pick[c]).data(),this_buf->ns,TRUE,
1307 dc_offset,info->chInfo[sel->pick[c]].kind) != OK) {
1308 filter->filter_on = filter_was;
1309 goto bad;
1310 }
1311 this_buf->ch_filtered[sel->pick[c]] = TRUE;
1312 filter->filter_on = filter_was;
1313 }
1314 }
1315 }
1316 /*
1317 * Also check channels included in derivations if they are used
1318 */
1319 if (sel->nderiv > 0 && deriv_matched) {
1320 MNEDeriv* der = deriv_matched.get();
1321 for (c = 0; c < der->deriv_data->ncol; c++) {
1322 if (der->in_use[c] > 0 &&
1323 !this_buf->ch_filtered[c]) {
1324 /*
1325 * Do not filter stimulus channels
1326 */
1327 dc_offset = 0.0;
1328 if (info->chInfo[c].kind == FIFFV_STIM_CH)
1329 filter->filter_on = FALSE;
1330 else if (dc.size() > 0)
1331 dc_offset = dc[c];
1332 if (mne_apply_filter(*filter,filter_data.get(),this_buf->vals.row(c).data(),this_buf->ns,TRUE,
1333 dc_offset,info->chInfo[c].kind) != OK) {
1334 filter->filter_on = filter_was;
1335 goto bad;
1336 }
1337 this_buf->ch_filtered[c] = TRUE;
1338 filter->filter_on = filter_was;
1339 }
1340 }
1341 }
1342 }
1343 else {
1344 /*
1345 * Simply filter all channels if there is no selection
1346 */
1347 for (c = 0; c < info->nchan; c++) {
1348 if (!this_buf->ch_filtered[c]) {
1349 /*
1350 * Do not filter stimulus channels
1351 */
1352 dc_offset = 0.0;
1353 if (info->chInfo[c].kind == FIFFV_STIM_CH)
1354 filter->filter_on = FALSE;
1355 else if (dc.size() > 0)
1356 dc_offset = dc[c];
1357 if (mne_apply_filter(*filter,filter_data.get(),this_buf->vals.row(c).data(),this_buf->ns,TRUE,
1358 dc_offset,info->chInfo[c].kind) != OK) {
1359 filter->filter_on = filter_was;
1360 goto bad;
1361 }
1362 this_buf->ch_filtered[c] = TRUE;
1363 filter->filter_on = filter_was;
1364 }
1365 }
1366 }
1367 /*
1368 * Decide the picking limits
1369 */
1370 if (firsts >= this_buf->firsts) {
1371 bs1 = firsts - this_buf->firsts;
1372 s1 = 0;
1373 }
1374 else {
1375 bs1 = 0;
1376 s1 = this_buf->firsts - firsts;
1377 }
1378 if (lasts >= this_buf->lasts) {
1379 bs2 = this_buf->ns;
1380 s2 = this_buf->lasts - lasts + ns;
1381 }
1382 else {
1383 bs2 = lasts - this_buf->lasts + this_buf->ns;
1384 s2 = ns;
1385 }
1386#ifdef DEBUG
1387 printf("buf : %d..%d %d\n",bs1,bs2,bs2-bs1);
1388 printf("dest : %d..%d %d\n",s1,s2,s2-s1);
1389#endif
1390 /*
1391 * Then pick data from all relevant channels
1392 */
1393 if (sel) {
1394 if (sel->nderiv > 0 && deriv_matched) {
1395 /*
1396 * Compute derived data if we need it
1397 */
1398 if (deriv_ns < this_buf->ns || nderiv != deriv_matched->deriv_data->nrow) {
1399 FREE_CMATRIX_36(deriv_vals);
1400 deriv_vals = ALLOC_CMATRIX_36(deriv_matched->deriv_data->nrow,this_buf->ns);
1401 nderiv = deriv_matched->deriv_data->nrow;
1402 deriv_ns = this_buf->ns;
1403 }
1404 if (mne_sparse_mat_mult2(deriv_matched->deriv_data->data.get(),this_buf->vals,this_buf->ns,deriv_vals) == FAIL)
1405 goto bad;
1406 }
1407 for (c = 0; c < sel->nchan; c++) {
1408 /*
1409 * First the ordinary channels
1410 */
1411 if (sel->pick[c] >= 0) {
1412 values = this_buf->vals.row(sel->pick[c]).data();
1413 for (s = s1, bs = bs1; s < s2; s++, bs++)
1414 picked[c][s] += values[bs];
1415 }
1416 else if (sel->pick_deriv[c] >= 0 && deriv_matched) {
1417 values = deriv_vals[sel->pick_deriv[c]];
1418 for (s = s1, bs = bs1; s < s2; s++, bs++)
1419 picked[c][s] += values[bs];
1420 }
1421 }
1422 }
1423 else {
1424 for (c = 0; c < info->nchan; c++) {
1425 values = this_buf->vals.row(c).data();
1426 for (s = s1, bs = bs1; s < s2; s++, bs++)
1427 picked[c][s] += values[bs];
1428 }
1429 }
1430 }
1431 (void)bs2; // squash compiler warning, this is unused
1432 FREE_CMATRIX_36(deriv_vals);
1433 return OK;
1434
1435bad : {
1436 FREE_CMATRIX_36(deriv_vals);
1437 return FAIL;
1438 }
1439}
1440
1441//=============================================================================================================
1442
1444 int omit_skip,
1445 int allow_maxshield,
1446 const MNEFilterDef& filter,
1447 int comp_set)
1448/*
1449 * Open a raw data file
1450 */
1451{
1452 std::unique_ptr<MNERawInfo> info;
1453 std::unique_ptr<MNERawData> data;
1454
1455 QFile file(name);
1457 // fiffFile in = NULL;
1458
1460 QList<FiffDirEntry::SPtr> dir0;
1461 // fiffTagRec tag;
1462 FiffTag::SPtr t_pTag;
1463 FiffChInfo ch;
1464 int k, b, nbuf, ndir, nnames;
1465 int current_dir0 = 0;
1466
1467 // tag.data = NULL;
1468
1469 if (MNERawInfo::load(name,allow_maxshield,info) == FAIL)
1470 goto bad;
1471
1472 for (k = 0; k < info->nchan; k++) {
1473 ch = info->chInfo.at(k);
1474 if (QString::compare(ch.ch_name,MNE_DEFAULT_TRIGGER_CH) == 0) {
1475 if (std::fabs(1.0 - ch.range) > 1e-5) {
1476 ch.range = 1.0;
1477 printf("%s range set to %f\n",MNE_DEFAULT_TRIGGER_CH,ch.range);
1478 }
1479 }
1480 /*
1481 * Take care of the nonzero unit multiplier
1482 */
1483 if (ch.unit_mul != 0) {
1484 ch.cal = pow(10.0,(double)(ch.unit_mul))*ch.cal;
1485 printf("Ch %s unit multiplier %d -> 0\n",ch.ch_name.toLatin1().data(),ch.unit_mul);
1486 ch.unit_mul = 0;
1487 }
1488 }
1489 // if ((in = fiff_open(name)) == NULL)
1490 // goto bad;
1491 if(!stream->open())
1492 goto bad;
1493
1494 data = std::make_unique<MNERawData>();
1495 data->filename = name;
1496 data->stream = stream;
1497 data->info = std::move(info);
1498 /*
1499 * Add the channel name list
1500 */
1501 mne_channel_names_to_name_list(data->info->chInfo,
1502 data->info->nchan,
1503 data->ch_names,
1504 nnames);
1505 if (nnames != data->info->nchan) {
1506 printf("Channel names were not translated correctly into a name list");
1507 goto bad;
1508 }
1509 /*
1510 * Compensation data
1511 */
1512 data->comp = MNECTFCompDataSet::read(data->filename);
1513 if (data->comp) {
1514 if (data->comp->ncomp > 0)
1515 printf("Read %d compensation data sets from %s\n",data->comp->ncomp,data->filename.toUtf8().constData());
1516 else
1517 printf("No compensation data in %s\n",data->filename.toUtf8().constData());
1518 }
1519 else
1520 qWarning() << "err_print_error()";
1521 if ((data->comp_file = MNECTFCompDataSet::get_comp(data->info->chInfo,data->info->nchan)) == FAIL)
1522 goto bad;
1523 printf("Compensation in file : %s\n",MNECTFCompDataSet::explain_comp(MNECTFCompDataSet::map_comp_kind(data->comp_file)).toUtf8().constData());
1524 if (comp_set < 0)
1525 data->comp_now = data->comp_file;
1526 else
1527 data->comp_now = comp_set;
1528
1529 if (!data->comp) {
1530 if (data->comp_now != MNE_CTFV_NOGRAD) {
1531 printf("Cannot do compensation because compensation data are missing");
1532 goto bad;
1533 }
1534 } else if (data->comp->set_compensation(data->comp_now,
1535 data->info->chInfo,
1536 data->info->nchan,
1537 QList<FIFFLIB::FiffChInfo>(),
1538 0) == FAIL)
1539 goto bad;
1540 /*
1541 * SSS data
1542 */
1543 data->sss.reset(MNESssData::read(data->filename));
1544 if (data->sss && data->sss->job != FIFFV_SSS_JOB_NOTHING && data->sss->comp_info.size() > 0) {
1545 printf("SSS data read from %s :\n",data->filename.toUtf8().constData());
1546 QTextStream errStream(stderr);
1547 data->sss->print(errStream);
1548 }
1549 else {
1550 printf("No SSS data in %s\n",data->filename.toUtf8().constData());
1551 data->sss.reset();
1552 }
1553 /*
1554 * Buffers
1555 */
1556 dir0 = data->info->rawDir;
1557 ndir = data->info->ndir;
1558 /*
1559 * Take into account the first sample
1560 */
1561 if (dir0[current_dir0]->kind == FIFF_FIRST_SAMPLE) {
1562 // if (fiff_read_this_tag(in->fd,dir0->pos,&tag) == FIFF_FAIL)
1563 // goto bad;
1564 if (!stream->read_tag(t_pTag,dir0[current_dir0]->pos))
1565 goto bad;
1566 data->first_samp = *t_pTag->toInt();
1567 current_dir0++;
1568 ndir--;
1569 }
1570 if (dir0[current_dir0]->kind == FIFF_DATA_SKIP) {
1571 int nsamp_skip;
1572 // if (fiff_read_this_tag(in->fd,dir0->pos,&tag) == FIFF_FAIL)
1573 // goto bad;
1574 if (!stream->read_tag(t_pTag,dir0[current_dir0]->pos))
1575 goto bad;
1576 nsamp_skip = data->info->buf_size*(*t_pTag->toInt());
1577 printf("Data skip of %d samples in the beginning\n",nsamp_skip);
1578 current_dir0++;
1579 ndir--;
1580 if (dir0[current_dir0]->kind == FIFF_FIRST_SAMPLE) {
1581 // if (fiff_read_this_tag(in->fd,dir0->pos,&tag) == FIFF_FAIL)
1582 // goto bad;
1583 if (!stream->read_tag(t_pTag,dir0[current_dir0]->pos))
1584 goto bad;
1585 data->first_samp += *t_pTag->toInt();
1586 current_dir0++;
1587 ndir--;
1588 }
1589 if (omit_skip) {
1590 data->omit_samp = data->first_samp + nsamp_skip;
1591 data->omit_samp_old = nsamp_skip;
1592 data->first_samp = 0;
1593 }
1594 else {
1595 data->first_samp = data->first_samp + nsamp_skip;
1596 }
1597 }
1598 else if (omit_skip) {
1599 data->omit_samp = data->first_samp;
1600 data->first_samp = 0;
1601 }
1602#ifdef DEBUG
1603 printf("data->first_samp = %d\n",data->first_samp);
1604#endif
1605 /*
1606 * Figure out the buffers
1607 */
1608 // for (k = 0, dir = dir0, nbuf = 0; k < ndir; k++, dir++)
1609 for (k = 0, nbuf = 0; k < ndir; k++)
1610 if (dir0[k]->kind == FIFF_DATA_BUFFER ||
1611 dir0[k]->kind == FIFF_DATA_SKIP)
1612 nbuf++;
1613 data->bufs.resize(nbuf);
1614
1615 // for (k = 0, nbuf = 0, dir = dir0; k < ndir; k++, dir++)
1616 for (k = 0, nbuf = 0; k < ndir; k++)
1617 if (dir0[k]->kind == FIFF_DATA_BUFFER ||
1618 dir0[k]->kind == FIFF_DATA_SKIP) {
1619 data->bufs[nbuf].ns = 0;
1620 data->bufs[nbuf].ent = dir0[k];
1621 data->bufs[nbuf].nchan = data->info->nchan;
1622 data->bufs[nbuf].is_skip = dir0[k]->kind == FIFF_DATA_SKIP;
1623 data->bufs[nbuf].valid = FALSE;
1624 data->bufs[nbuf].comp_status = data->comp_file;
1625 nbuf++;
1626 }
1627 data->nsamp = 0;
1628 for (k = 0; k < nbuf; k++) {
1629 dir = data->bufs[k].ent;
1630 if (dir->kind == FIFF_DATA_BUFFER) {
1631 if (dir->type == FIFFT_DAU_PACK16 || dir->type == FIFFT_SHORT)
1632 data->bufs[k].ns = dir->size/(data->info->nchan*sizeof(fiff_dau_pack16_t));
1633 else if (dir->type == FIFFT_FLOAT)
1634 data->bufs[k].ns = dir->size/(data->info->nchan*sizeof(fiff_float_t));
1635 else if (dir->type == FIFFT_INT)
1636 data->bufs[k].ns = dir->size/(data->info->nchan*sizeof(fiff_int_t));
1637 else {
1638 printf("We are not prepared to handle raw data type: %d",dir->type);
1639 goto bad;
1640 }
1641 }
1642 else if (dir->kind == FIFF_DATA_SKIP) {
1643 // if (fiff_read_this_tag(in->fd,dir->pos,&tag) == FIFF_FAIL)
1644 // goto bad;
1645 if (!stream->read_tag(t_pTag,dir->pos))
1646 goto bad;
1647 data->bufs[k].ns = data->info->buf_size*(*t_pTag->toInt());
1648 }
1649 data->bufs[k].firsts = k == 0 ? data->first_samp : data->bufs[k-1].lasts + 1;
1650 data->bufs[k].lasts = data->bufs[k].firsts + data->bufs[k].ns - 1;
1651 data->nsamp += data->bufs[k].ns;
1652 }
1653 // FREE_36(tag.data);
1654 /*
1655 * Set up the first sample values
1656 */
1657 data->bad = Eigen::VectorXi::Zero(data->info->nchan);
1658 data->offsets = Eigen::VectorXf::Zero(data->info->nchan);
1659 /*
1660 * Th bad channel stuff
1661 */
1662 {
1663 if (mne_read_bad_channel_list(name,data->badlist,data->nbad) == OK) {
1664 for (b = 0; b < data->nbad; b++) {
1665 for (k = 0; k < data->info->nchan; k++) {
1666 if (QString::compare(data->info->chInfo[k].ch_name,data->badlist[b],Qt::CaseInsensitive) == 0) {
1667 data->bad[k] = TRUE;
1668 break;
1669 }
1670 }
1671 }
1672 printf("%d bad channels read from %s%s",data->nbad,name.toUtf8().constData(),data->nbad > 0 ? ":\n" : "\n");
1673 if (data->nbad > 0) {
1674 printf("\t");
1675 for (k = 0; k < data->nbad; k++)
1676 printf("%s%c",data->badlist[k].toUtf8().constData(),k < data->nbad-1 ? ' ' : '\n');
1677 }
1678 }
1679 }
1680 /*
1681 * Initialize the raw data buffers
1682 */
1683 nbuf = approx_ring_buf_size/(data->info->buf_size*data->info->nchan*sizeof(float));
1684 data->ring = std::make_unique<RingBuffer>(nbuf);
1685 /*
1686 * Initialize the filter buffers
1687 */
1688 data->filter = std::make_unique<MNEFilterDef>(filter);
1689 data->setup_filter_bufs();
1690
1691 {
1692 float **vals = ALLOC_CMATRIX_36(data->info->nchan,1);
1693
1694 if (data->pick_data(NULL,data->first_samp,1,vals) == FAIL)
1695 goto bad;
1696 data->first_sample_val.resize(data->info->nchan);
1697 for (k = 0; k < data->info->nchan; k++)
1698 data->first_sample_val[k] = vals[k][0];
1699 FREE_CMATRIX_36(vals);
1700 printf("Initial dc offsets determined\n");
1701 }
1702 printf("Raw data file %s:\n",name.toUtf8().constData());
1703 printf("\tnchan = %d\n",data->info->nchan);
1704 printf("\tnsamp = %d\n",data->nsamp);
1705 printf("\tsfreq = %-8.3f Hz\n",data->info->sfreq);
1706 printf("\tlength = %-8.3f sec\n",data->nsamp/data->info->sfreq);
1707
1708 return data.release();
1709
1710bad : {
1711 return nullptr;
1712 }
1713}
1714
1715//=============================================================================================================
1716
1717MNERawData *MNERawData::open_file(const QString& name, int omit_skip, int allow_maxshield, const MNEFilterDef& filter)
1718/*
1719 * Wrapper for open_file to work as before
1720 */
1721{
1722 return open_file_comp(name,omit_skip,allow_maxshield,filter,-1);
1723}
#define M_PI
#define FIFFV_EOG_CH
#define FIFF_MNE_CH_NAME_LIST
#define FIFFV_STIM_CH
#define FIFFB_MNE_BAD_CHANNELS
#define FIFF_DATA_BUFFER
Definition fiff_file.h:556
#define FIFFTS_MC_RCS
Definition fiff_file.h:270
#define FIFFT_INT
Definition fiff_file.h:231
#define FIFFT_SHORT
Definition fiff_file.h:230
#define FIFF_FIRST_SAMPLE
Definition fiff_file.h:461
#define FIFFT_DAU_PACK16
Definition fiff_file.h:243
#define FIFFTS_MC_CCS
Definition fiff_file.h:269
#define FIFFT_FLOAT
Definition fiff_file.h:232
#define FIFFV_SSS_JOB_NOTHING
Definition fiff_file.h:538
#define FIFF_DATA_SKIP
Definition fiff_file.h:557
MNERawData class declaration.
#define MNE_DEFAULT_TRIGGER_CH
Default digital trigger channel name.
Definition mne_types.h:149
#define MNE_CTFV_NOGRAD
Definition mne_types.h:131
#define FREE_CMATRIX_36(m)
void mne_fft_syn(float *data, int np, std::vector< float > &)
void mne_string_to_name_list(const QString &s, QStringList &listp, int &nlistp)
int mne_sparse_vec_mult2(FiffSparseMatrix *mat, float *vector, float *res)
void mne_channel_names_to_name_list(const QList< FIFFLIB::FiffChInfo > &chs, int nch, QStringList &listp, int &nlistp)
QString mne_name_list_to_string(const QStringList &list)
int mne_sparse_mat_mult2(FiffSparseMatrix *mat, const MNERawBufDef::RowMajorMatrixXf &mult, int ncol, float **res)
int mne_apply_filter(const MNEFilterDef &filter, FilterData *d, float *data, int ns, int zero_pad, float dc_offset, int kind)
int mne_read_bad_channel_list(const QString &name, QStringList &listp, int &nlistp)
void mne_free_cmatrix_36(float **m)
float ** mne_cmatrix_36(int nr, int nc)
#define APPROX_RING_BUF_SIZE
QString mne_channel_names_to_string(const QList< FIFFLIB::FiffChInfo > &chs, int nch)
void mne_free_name_list_36(char **list, int nlist)
int mne_read_bad_channel_list_from_node(FiffStream::SPtr &stream, const FiffDirNode::SPtr &pNode, QStringList &listp, int &nlistp)
int mne_compare_filters(const MNEFilterDef &f1, const MNEFilterDef &f2)
#define MALLOC_36(x, t)
int mne_read_raw_buffer_t(FiffStream::SPtr &stream, const FiffDirEntry::SPtr &ent, MNERawBufDef::RowMajorMatrixXf &data, int nchan, int nsamp, const QList< FIFFLIB::FiffChInfo > &chs, int *pickno, int npick)
void mne_fft_ana(float *data, int np, std::vector< float > &)
std::unique_ptr< FilterData > mne_create_filter_response(const MNEFilterDef &filter, float sfreq, int *highpass_effective)
#define ALLOC_CMATRIX_36(x, y)
#define FREE_36(x)
#define TRUE
#define FALSE
#define OK
#define FAIL
Core MNE data structures (source spaces, source estimates, hemispheres).
MNEChSelection * mneChSelection
FIFF file I/O and data structures (raw, epochs, evoked, covariance, forward).
qint32 fiff_int_t
Definition fiff_types.h:89
float fiff_float_t
Definition fiff_types.h:93
qint16 fiff_dau_pack16_t
Definition fiff_types.h:97
qint16 fiff_short_t
Definition fiff_types.h:87
Channel info descriptor.
QSharedPointer< FiffDirEntry > SPtr
QSharedPointer< FiffDirNode > SPtr
FIFF sparse matrix storage.
FIFF File I/O routines.
static QStringList split_name_list(QString p_sNameList)
QSharedPointer< FiffStream > SPtr
QSharedPointer< FiffTag > SPtr
Definition fiff_tag.h:155
Eigen::VectorXi pick_deriv
static std::unique_ptr< MNECTFCompDataSet > read(const QString &name)
static QString explain_comp(int kind)
static int get_comp(const QList< FIFFLIB::FiffChInfo > &chs, int nch)
One item in a derivation data set.
Definition mne_deriv.h:79
std::unique_ptr< MNESparseNamedMatrix > deriv_data
Definition mne_deriv.h:99
Eigen::VectorXi in_use
Definition mne_deriv.h:100
Definition of one raw data buffer within a FIFF file.
FIFFLIB::FiffDirEntry::SPtr ent
Eigen::Matrix< float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > RowMajorMatrixXf
RowMajorMatrixXf vals
Eigen::VectorXi ch_filtered
void allocate(int nrow, int ncol, MNERawBufDef::RowMajorMatrixXf *res)
std::vector< Entry > entries
MNERawBufDef::RowMajorMatrixXf * user
Pre-computed frequency-domain filter state used for FFT-based raw data filtering.
FilterData(int resp_size)
std::vector< float > eog_freq_resp
std::vector< float > freq_resp
std::vector< float > precalc
int load_one_filt_buf(MNERawBufDef *buf)
std::unique_ptr< MNELIB::MNEProjOp > proj
std::unique_ptr< MNELIB::MNECTFCompDataSet > comp
std::unique_ptr< FilterData > filter_data
void add_filter_response(int *highpass_effective)
int compensate_buffer(MNERawBufDef *buf)
int pick_data_proj(mneChSelection sel, int firsts, int ns, float **picked)
QStringList ch_names
Eigen::VectorXi bad
std::unique_ptr< RingBuffer > filt_ring
std::unique_ptr< MNELIB::MNERawInfo > info
std::unique_ptr< MNELIB::MNEDeriv > deriv_matched
unsigned int dig_trigger_mask
QStringList badlist
std::vector< MNELIB::MNERawBufDef > filt_bufs
static MNERawData * open_file_comp(const QString &name, int omit_skip, int allow_maxshield, const MNEFilterDef &filter, int comp_set)
std::unique_ptr< MNEFilterDef > filter
int load_one_buffer(MNERawBufDef *buf)
Eigen::VectorXf first_sample_val
std::unique_ptr< MNEEventList > event_list
std::unique_ptr< MNELIB::MNEDerivSet > deriv
unsigned int max_event
std::vector< MNELIB::MNERawBufDef > bufs
int pick_data(mneChSelection sel, int firsts, int ns, float **picked)
FIFFLIB::FiffStream::SPtr stream
std::unique_ptr< MNELIB::MNESssData > sss
static MNERawData * open_file(const QString &name, int omit_skip, int allow_maxshield, const MNEFilterDef &filter)
int pick_data_filt(mneChSelection sel, int firsts, int ns, float **picked)
std::unique_ptr< RingBuffer > ring
static int load(const QString &name, int allow_maxshield, std::unique_ptr< MNERawInfo > &infop)
static MNESssData * read(const QString &name)