v2.0.0
Loading...
Searching...
No Matches
rt_filter.cpp
Go to the documentation of this file.
1//=============================================================================================================
12
13//=============================================================================================================
14// INCLUDES
15//=============================================================================================================
16
17#include "rt_filter.h"
18
19#include <fiff/fiff_raw_data.h>
20#include <fiff/fiff_file.h>
21#include <mne/mne_epoch_data.h>
23
24//=============================================================================================================
25// QT INCLUDES
26//=============================================================================================================
27
28#include <QDebug>
29
30//=============================================================================================================
31// EIGEN INCLUDES
32//=============================================================================================================
33
34#include <Eigen/Dense>
35#include <Eigen/Core>
36
37#include <cmath>
38
39//=============================================================================================================
40// USED NAMESPACES
41//=============================================================================================================
42
43using namespace RTPROCESSINGLIB;
44using namespace Eigen;
45using namespace FIFFLIB;
46using namespace UTILSLIB;
47using namespace MNELIB;
48
49//=============================================================================================================
50// DEFINE GLOBAL RTPROCESSINGLIB METHODS
51//=============================================================================================================
52
53bool RTPROCESSINGLIB::filterFile(QIODevice& pIODevice,
54 QSharedPointer<FiffRawData> pFiffRawData,
55 int type,
56 double dCenterfreq,
57 double bandwidth,
58 double dTransition,
59 double dSFreq,
60 int iOrder,
61 int designMethod,
62 const RowVectorXi& vecPicks,
63 bool bUseThreads)
64{
65 // Normalize cut off frequencies to nyquist
66 dCenterfreq = dCenterfreq / (dSFreq / 2.0);
67 bandwidth = bandwidth / (dSFreq / 2.0);
68 dTransition = dTransition / (dSFreq / 2.0);
69
70 // create filter
71 FilterKernel filter = FilterKernel("filter_kernel",
72 type,
73 iOrder,
74 dCenterfreq,
75 bandwidth,
76 dTransition,
77 dSFreq,
78 designMethod);
79
80 return filterFile(pIODevice,
81 pFiffRawData,
82 filter,
83 vecPicks,
84 bUseThreads);
85}
86
87//=============================================================================================================
88
89bool RTPROCESSINGLIB::filterFile(QIODevice& pIODevice,
90 QSharedPointer<FiffRawData> pFiffRawData,
91 const FilterKernel& filterKernel,
92 const RowVectorXi& vecPicks,
93 bool bUseThreads)
94{
95 int iOrder = filterKernel.getFilterOrder();
96
97 RowVectorXd cals;
98 SparseMatrix<double> mult;
99 RowVectorXi sel;
100 FiffStream::SPtr outfid = FiffStream::start_writing_raw(pIODevice, pFiffRawData->info, cals);
101 if (!outfid) {
102 return false;
103 }
104
105 //Setup reading parameters
106 fiff_int_t from = pFiffRawData->first_samp;
107 fiff_int_t to = pFiffRawData->last_samp;
108
109 // slice input data into data junks with proper length so that the slices are always >= the filter order
110 float fFactor = 2.0f;
111 int iSize = fFactor * iOrder;
112 int residual = (to - from) % iSize;
113 while (residual < iOrder) {
114 fFactor = fFactor - 0.1f;
115 iSize = fFactor * iOrder;
116 residual = (to - from) % iSize;
117
118 if ((iSize < iOrder)) {
119 qInfo() << "[Filter::filterData] Sliced data block size is too small. Filtering whole block at once.";
120 iSize = to - from;
121 break;
122 }
123 }
124
125 float quantum_sec = iSize / pFiffRawData->info.sfreq;
126 fiff_int_t quantum = ceil(static_cast<double>(quantum_sec) * pFiffRawData->info.sfreq);
127
128 // Read, filter and write the data
129 bool first_buffer = true;
130
131 fiff_int_t first, last;
132 MatrixXd matData, matDataOverlap;
133 MatrixXd times;
134
135 for (first = from; first < to; first += quantum) {
136 last = first + quantum - 1;
137 if (last > to) {
138 last = to;
139 }
140
141 if (!pFiffRawData->read_raw_segment(matData, times, mult, first, last, sel)) {
142 qWarning("[Filter::filterData] Error during read_raw_segment\n");
143 return false;
144 }
145
146 qInfo() << "Filtering and writing block" << first << "to" << last;
147
148 if (first_buffer) {
149 if (first > 0) {
150 outfid->write_int(FIFF_FIRST_SAMPLE, &first);
151 }
152 first_buffer = false;
153 }
154
155 matData = filterDataBlock(matData,
156 vecPicks,
157 filterKernel,
158 bUseThreads);
159
160 // Output column c holds sample first + c - iOrder / 2; the last iOrder columns still get the next block's head
161 const bool lastBlock = last == to;
162 const int writeFrom = first == from ? iOrder / 2 : 0;
163 const int writeTo = lastBlock ? matData.cols() - iOrder / 2 : matData.cols() - iOrder;
164 if (first != from) {
165 matData.block(0, 0, matData.rows(), iOrder) += matDataOverlap;
166 }
167 outfid->write_raw_buffer(matData.block(0, writeFrom, matData.rows(), writeTo - writeFrom), cals);
168
169 matDataOverlap = matData.block(0, matData.cols() - iOrder, matData.rows(), iOrder);
170 }
171
172 outfid->finish_writing_raw();
173
174 return true;
175}
176
177//=============================================================================================================
178
179MatrixXd RTPROCESSINGLIB::filterData(const MatrixXd& matData,
180 int type,
181 double dCenterfreq,
182 double bandwidth,
183 double dTransition,
184 double dSFreq,
185 int iOrder,
186 int designMethod,
187 const RowVectorXi& vecPicks,
188 bool bUseThreads,
189 bool bKeepOverhead)
190{
191 // Check for size of data
192 if (matData.cols() < iOrder) {
193 qWarning() << QString("[Filter::filterData] Filter length/order is bigger than data length. Returning.");
194 return matData;
195 }
196
197 // Normalize cut off frequencies to nyquist
198 dCenterfreq = dCenterfreq / (dSFreq / 2.0);
199 bandwidth = bandwidth / (dSFreq / 2.0);
200 dTransition = dTransition / (dSFreq / 2.0);
201
202 // create filter
203 FilterKernel filter = FilterKernel("filter_kernel",
204 type,
205 iOrder,
206 dCenterfreq,
207 bandwidth,
208 dTransition,
209 dSFreq,
210 designMethod);
211
212 return filterData(matData,
213 filter,
214 vecPicks,
215 bUseThreads,
216 bKeepOverhead);
217}
218
219//=============================================================================================================
220
221MatrixXd RTPROCESSINGLIB::filterData(const MatrixXd& matData,
222 const FilterKernel& filterKernel,
223 const RowVectorXi& vecPicks,
224 bool bUseThreads,
225 bool bKeepOverhead)
226{
227 int iOrder = filterKernel.getFilterOrder();
228
229 // Check for size of data
230 if (matData.cols() < iOrder) {
231 qWarning() << "[Filter::filterData] Filter length/order is bigger than data length. Returning.";
232 return matData;
233 }
234
235 // Create output matrix with size of input matrix
236 MatrixXd matDataOut(matData.rows(), matData.cols() + iOrder);
237 matDataOut.setZero();
238 MatrixXd sliceFiltered;
239
240 // slice input data into data junks with proper length so that the slices are always >= the filter order
241 float fFactor = 2.0f;
242 int iSize = fFactor * iOrder;
243 int residual = matData.cols() % iSize;
244 while (residual < iOrder) {
245 fFactor = fFactor - 0.1f;
246 iSize = fFactor * iOrder;
247 residual = matData.cols() % iSize;
248
249 if (iSize < iOrder) {
250 iSize = matData.cols();
251 break;
252 }
253 }
254
255 if (matData.cols() > iSize) {
256 int from = 0;
257 int numSlices = ceil(static_cast<float>(matData.cols()) / static_cast<float>(iSize)); //calculate number of data slices
258
259 for (int i = 0; i < numSlices; i++) {
260 if (i == numSlices - 1) {
261 //catch the last one that might be shorter than the other blocks
262 iSize = matData.cols() - (iSize * (numSlices - 1));
263 }
264
265 // Filter the data block. This will return data with a fitler delay of iOrder/2 in front and back
266 sliceFiltered = filterDataBlock(matData.block(0, from, matData.rows(), iSize),
267 vecPicks,
268 filterKernel,
269 bUseThreads);
270
271 // Perform overlap add
272 if (i == 0) {
273 matDataOut.block(0, 0, matData.rows(), sliceFiltered.cols()) += sliceFiltered;
274 } else {
275 matDataOut.block(0, from, matData.rows(), sliceFiltered.cols()) += sliceFiltered;
276 }
277
278 from += iSize;
279 }
280 } else {
281 matDataOut = filterDataBlock(matData,
282 vecPicks,
283 filterKernel,
284 bUseThreads);
285 }
286
287 if (bKeepOverhead) {
288 return matDataOut;
289 } else {
290 return matDataOut.block(0, iOrder / 2, matDataOut.rows(), matData.cols());
291 }
292}
293
294//=============================================================================================================
295
296MatrixXd RTPROCESSINGLIB::filterDataBlock(const MatrixXd& matData,
297 const RowVectorXi& vecPicks,
298 const FilterKernel& filterKernel,
299 bool bUseThreads)
300{
301 int iOrder = filterKernel.getFilterOrder();
302
303 // Check for size of data
304 if (matData.cols() < iOrder) {
305 qWarning() << QString("[Filter::filterDataBlock] Filter length/order is bigger than data length. Returning.");
306 return matData;
307 }
308
309 // Setup filters to the correct length, so we do not have to do this everytime we call the FFT filter function
310 FilterKernel filterKernelSetup = filterKernel;
311 filterKernelSetup.prepareFilter(matData.cols());
312
313 // Do the concurrent filtering
314 RowVectorXi vecPicksNew = vecPicks;
315 if (vecPicksNew.cols() == 0) {
316 vecPicksNew = RowVectorXi::LinSpaced(matData.rows(), 0, matData.rows() - 1);
317 }
318
319 // Generate QList structure which can be handled by the QConcurrent framework
320 QList<FilterObject> timeData;
321
322 // Only select channels specified in vecPicksNew
323 FilterObject data;
324 for (qint32 i = 0; i < vecPicksNew.cols(); ++i) {
325 data.filterKernel = filterKernelSetup;
326 data.iRow = vecPicksNew[i];
327 data.vecData = matData.row(vecPicksNew[i]);
328 timeData.append(data);
329 }
330
331 // Copy in data from last data block. This is necessary in order to also delay channels which are not filtered
332 MatrixXd matDataOut(matData.rows(), matData.cols() + iOrder);
333 matDataOut.setZero();
334 matDataOut.block(0, iOrder / 2, matData.rows(), matData.cols()) = matData;
335
336 if (bUseThreads) {
337 QFuture<void> future = QtConcurrent::map(timeData,
339 future.waitForFinished();
340 } else {
341 for (int i = 0; i < timeData.size(); ++i) {
342 filterChannel(timeData[i]);
343 }
344 }
345
346 // Do the overlap add method and store in matDataOut
347 RowVectorXd tempData;
348
349 for (int r = 0; r < timeData.size(); r++) {
350 // Write the newly calculated filtered data to the filter data matrix. This data has a delay of iOrder/2 in front and back
351 matDataOut.row(timeData.at(r).iRow) = timeData.at(r).vecData;
352 }
353
354 return matDataOut;
355}
356
357//=============================================================================================================
358
360{
361 //channelDataTime.vecData = channelDataTime.first.at(i).applyConvFilter(channelDataTime.vecData, true);
362 channelDataTime.filterKernel.applyFftFilter(channelDataTime.vecData, true); //FFT Convolution for rt is not suitable. FFT make the signal filtering non causal.
363}
364
365//=============================================================================================================
366// DEFINE MEMBER METHODS
367//=============================================================================================================
368
369MatrixXd FilterOverlapAdd::calculate(const MatrixXd& matData,
370 int type,
371 double dCenterfreq,
372 double bandwidth,
373 double dTransition,
374 double dSFreq,
375 int iOrder,
376 int designMethod,
377 const RowVectorXi& vecPicks,
378 bool bFilterEnd,
379 bool bUseThreads,
380 bool bKeepOverhead)
381{
382 // Check for size of data
383 if (matData.cols() < iOrder) {
384 qWarning() << QString("[Filter::filterData] Filter length/order is bigger than data length. Returning.");
385 return matData;
386 }
387
388 // Normalize cut off frequencies to nyquist
389 dCenterfreq = dCenterfreq / (dSFreq / 2.0);
390 bandwidth = bandwidth / (dSFreq / 2.0);
391 dTransition = dTransition / (dSFreq / 2.0);
392
393 // create filter
394 FilterKernel filter = FilterKernel("filter_kernel",
395 type,
396 iOrder,
397 dCenterfreq,
398 bandwidth,
399 dTransition,
400 dSFreq,
401 designMethod);
402
403 return calculate(matData,
404 filter,
405 vecPicks,
406 bFilterEnd,
407 bUseThreads,
408 bKeepOverhead);
409}
410
411//=============================================================================================================
412
413MatrixXd FilterOverlapAdd::calculate(const MatrixXd& matData,
414 const FilterKernel& filterKernel,
415 const RowVectorXi& vecPicks,
416 bool bFilterEnd,
417 bool bUseThreads,
418 bool bKeepOverhead)
419{
420 int iOrder = filterKernel.getFilterOrder();
421
422 // Check for size of data
423 if (matData.cols() < iOrder) {
424 qWarning() << "[Filter::filterData] Filter length/order is bigger than data length. Returning.";
425 return matData;
426 }
427
428 // Init overlaps from last block
429 if (m_matOverlapBack.cols() != iOrder || m_matOverlapBack.rows() < matData.rows()) {
430 m_matOverlapBack.resize(matData.rows(), iOrder);
431 m_matOverlapBack.setZero();
432 }
433
434 if (m_matOverlapFront.cols() != iOrder || m_matOverlapFront.rows() < matData.rows()) {
435 m_matOverlapFront.resize(matData.rows(), iOrder);
436 m_matOverlapFront.setZero();
437 }
438
439 // Create output matrix with size of input matrix
440 MatrixXd matDataOut(matData.rows(), matData.cols() + iOrder);
441 matDataOut.setZero();
442 MatrixXd sliceFiltered;
443
444 // slice input data into data junks with proper length so that the slices are always >= the filter order
445 float fFactor = 2.0f;
446 int iSize = fFactor * iOrder;
447 int residual = matData.cols() % iSize;
448 while (residual < iOrder) {
449 fFactor = fFactor - 0.1f;
450 iSize = fFactor * iOrder;
451 residual = matData.cols() % iSize;
452
453 if (iSize < iOrder) {
454 iSize = matData.cols();
455 break;
456 }
457 }
458
459 if (matData.cols() > iSize) {
460 int from = 0;
461 int numSlices = ceil(static_cast<float>(matData.cols()) / static_cast<float>(iSize)); //calculate number of data slices
462
463 for (int i = 0; i < numSlices; i++) {
464 if (i == numSlices - 1) {
465 //catch the last one that might be shorter than the other blocks
466 iSize = matData.cols() - (iSize * (numSlices - 1));
467 }
468
469 // Filter the data block. This will return data with a fitler delay of iOrder/2 in front and back
470 sliceFiltered = filterDataBlock(matData.block(0, from, matData.rows(), iSize),
471 vecPicks,
472 filterKernel,
473 bUseThreads);
474
475 if (i == 0) {
476 matDataOut.block(0, 0, matData.rows(), sliceFiltered.cols()) += sliceFiltered;
477 } else {
478 matDataOut.block(0, from, matData.rows(), sliceFiltered.cols()) += sliceFiltered;
479 }
480
481 if (bFilterEnd && (i == 0)) {
482 matDataOut.block(0, 0, matDataOut.rows(), iOrder) += m_matOverlapBack;
483 } else if (!bFilterEnd && (i == numSlices - 1)) {
484 matDataOut.block(0, matDataOut.cols() - iOrder, matDataOut.rows(), iOrder) += m_matOverlapFront;
485 }
486
487 from += iSize;
488 }
489 } else {
490 matDataOut = filterDataBlock(matData,
491 vecPicks,
492 filterKernel,
493 bUseThreads);
494
495 if (bFilterEnd) {
496 matDataOut.block(0, 0, matDataOut.rows(), iOrder) += m_matOverlapBack;
497 } else {
498 matDataOut.block(0, matDataOut.cols() - iOrder, matDataOut.rows(), iOrder) += m_matOverlapFront;
499 }
500 }
501
502 // Refresh the overlap matrix with the new calculated filtered data
503 m_matOverlapBack = matDataOut.block(0, matDataOut.cols() - iOrder, matDataOut.rows(), iOrder);
504 m_matOverlapFront = matDataOut.block(0, 0, matDataOut.rows(), iOrder);
505
506 if (bKeepOverhead) {
507 return matDataOut;
508 } else {
509 return matDataOut.block(0, 0, matDataOut.rows(), matData.cols());
510 }
511}
512
513//=============================================================================================================
514
516{
517 m_matOverlapBack.resize(0, 0);
518 m_matOverlapFront.resize(0, 0);
519}
520
521//=============================================================================================================
522
524 const MatrixXi& matEvents,
525 float fTMinS,
526 float fTMaxS,
527 qint32 eventType,
528 bool bApplyBaseline,
529 float fTBaselineFromS,
530 float fTBaselineToS,
531 const QMap<QString, double>& mapReject,
532 const FilterKernel& filterKernel,
533 const QStringList& lExcludeChs,
534 const RowVectorXi& picks)
535{
536 MNEEpochDataList lstEpochDataList;
537
538 // Select the desired events
539 qint32 count = 0;
540 qint32 p;
541 MatrixXi selected = MatrixXi::Zero(1, matEvents.rows());
542 for (p = 0; p < matEvents.rows(); ++p) {
543 if (matEvents(p, 1) == 0 && matEvents(p, 2) == eventType) {
544 selected(0, count) = p;
545 ++count;
546 }
547 }
548 selected.conservativeResize(1, count);
549 if (count > 0) {
550 qInfo("[RTPROCESSINGLIB::computeFilteredAverage] %d matching events found", count);
551 }
552
553 // If picks are empty, pick all
554 RowVectorXi picksNew = picks;
555 if (picks.cols() <= 0) {
556 picksNew.resize(raw.info.chs.size());
557 for (int i = 0; i < raw.info.chs.size(); ++i) {
558 picksNew(i) = i;
559 }
560 }
561
562 fiff_int_t event_samp, from, to;
563 fiff_int_t dropCount = 0;
564 MatrixXd timesDummy;
565 MatrixXd times;
566
567 std::unique_ptr<MNEEpochData> epoch;
568 int iFilterDelay = filterKernel.getFilterOrder() / 2;
569
570 for (p = 0; p < count; ++p) {
571 // Read a data segment
572 event_samp = matEvents(selected(p), 0);
573 // Like mne.Epochs: both ends rounded to the nearest sample
574 from = event_samp + static_cast<fiff_int_t>(std::lround(fTMinS * raw.info.sfreq));
575 to = event_samp + static_cast<fiff_int_t>(std::lround(fTMaxS * raw.info.sfreq));
576
577 epoch = std::make_unique<MNEEpochData>();
578
579 if (raw.read_raw_segment(epoch->epoch, timesDummy, from - iFilterDelay, to + iFilterDelay, picksNew)) {
580 // Filter the data
581 epoch->epoch = RTPROCESSINGLIB::filterData(epoch->epoch, filterKernel).block(0, iFilterDelay, epoch->epoch.rows(), to - from + 1);
582
583 if (p == 0) {
584 times.resize(1, to - from + 1);
585 for (qint32 i = 0; i < times.cols(); ++i)
586 times(0, i) = (static_cast<float>(from - event_samp + i)) / raw.info.sfreq;
587 }
588
589 epoch->event = eventType;
590 epoch->eventSample = event_samp;
591 epoch->tmin = fTMinS;
592 epoch->tmax = fTMaxS;
593
594 epoch->bReject = MNEEpochDataList::checkForArtifact(epoch->epoch,
595 raw.info,
596 mapReject,
597 lExcludeChs);
598
599 if (epoch->bReject) {
600 dropCount++;
601 }
602
603 //Check if data block has the same size as the previous one
604 if (!lstEpochDataList.isEmpty()) {
605 if (epoch->epoch.size() == lstEpochDataList.last()->epoch.size()) {
606 lstEpochDataList.append(MNEEpochData::SPtr(epoch.release()));
607 }
608 } else {
609 lstEpochDataList.append(MNEEpochData::SPtr(epoch.release()));
610 }
611 } else {
612 qWarning("[MNEEpochDataList::readEpochs] Can't read the event data segments.");
613 }
614 }
615
616 qInfo().noquote() << "[MNEEpochDataList::readEpochs] Read a total of" << lstEpochDataList.size() << "epochs of type" << eventType << "and marked" << dropCount << "for rejection.";
617
618 if (bApplyBaseline) {
619 QPair<float, float> baselinePair(fTBaselineFromS, fTBaselineToS);
620 lstEpochDataList.applyBaselineCorrection(baselinePair);
621 }
622
623 if (!mapReject.isEmpty()) {
624 lstEpochDataList.dropRejected();
625 }
626
627 if (lstEpochDataList.isEmpty())
628 return FiffEvoked();
629
630 const fiff_int_t first = static_cast<fiff_int_t>(std::lround(fTMinS * raw.info.sfreq));
631 FiffEvoked evoked = lstEpochDataList.average(raw.info,
632 first,
633 first + static_cast<fiff_int_t>(lstEpochDataList.first()->epoch.cols()) - 1);
634 evoked.baseline = bApplyBaseline ? QPair<float, float>(fTBaselineFromS, fTBaselineToS)
635 : QPair<float, float>(0.0f, 0.0f);
636 return evoked;
637}
FIFF tag-kind, block-kind and type-code numerical definitions, authoritative for FIFFLIB.
constexpr auto FIFF_FIRST_SAMPLE
Definition fiff_file.h:452
FIFF continuous raw recording: FiffInfo plus a directory of FIFF_DATA_BUFFER tags for random-access s...
Real-time FIR / IIR filtering of streaming MEG / EEG data blocks.
Single epoch (one trial slice of preprocessed sensor data) with timing and rejection metadata.
Ordered list of MNELIB::MNEEpochData objects sharing a common FIFFLIB::FiffInfo.
Core MNE data structures (source spaces, source estimates, hemispheres).
FIFF file I/O, in-memory data structures and high-level readers/writers.
qint32 fiff_int_t
Definition fiff_types.h:86
DSPSHARED_EXPORT FIFFLIB::FiffEvoked computeFilteredAverage(const FIFFLIB::FiffRawData &raw, const Eigen::MatrixXi &matEvents, float fTMinS, float fTMaxS, qint32 eventType, bool bApplyBaseline, float fTBaselineFromS, float fTBaselineToS, const QMap< QString, double > &mapReject, const UTILSLIB::FilterKernel &filterKernel, const QStringList &lExcludeChs=QStringList(), const Eigen::RowVectorXi &vecPicks=Eigen::RowVectorXi())
DSPSHARED_EXPORT Eigen::MatrixXd filterData(const Eigen::MatrixXd &matData, int type, double dCenterfreq, double dBandwidth, double dTransition, double dSFreq, int iOrder=1024, int designMethod=UTILSLIB::FilterKernel::m_designMethods.indexOf(UTILSLIB::FilterParameter("Cosine")), const Eigen::RowVectorXi &vecPicks=Eigen::RowVectorXi(), bool bUseThreads=true, bool bKeepOverhead=false)
DSPSHARED_EXPORT Eigen::MatrixXd filterDataBlock(const Eigen::MatrixXd &matData, const Eigen::RowVectorXi &vecPicks, const UTILSLIB::FilterKernel &filterKernel, bool bUseThreads=true)
DSPSHARED_EXPORT void filterChannel(FilterObject &channelDataTime)
DSPSHARED_EXPORT bool filterFile(QIODevice &pIODevice, QSharedPointer< FIFFLIB::FiffRawData > pFiffRawData, int type, double dCenterfreq, double dBandwidth, double dTransition, double dSFreq, int iOrder=4096, int designMethod=UTILSLIB::FilterKernel::m_designMethods.indexOf(UTILSLIB::FilterParameter("Cosine")), const Eigen::RowVectorXi &vecPicks=Eigen::RowVectorXi(), bool bUseThreads=true)
Shared utilities (I/O helpers, spectral analysis, layout management, warp algorithms).
The FilterKernel class provides methods to create/design a FIR filter kernel.
void applyFftFilter(Eigen::RowVectorXd &vecData, bool bKeepOverhead=false)
void prepareFilter(int iDataSize)
Lightweight filter configuration holding kernel coefficients and overlap-add state for one channel.
Definition rt_filter.h:75
UTILSLIB::FilterKernel filterKernel
Definition rt_filter.h:76
Eigen::RowVectorXd vecData
Definition rt_filter.h:78
Eigen::MatrixXd calculate(const Eigen::MatrixXd &matData, int type, double dCenterfreq, double dBandwidth, double dTransition, double dSFreq, int iOrder=1024, int designMethod=UTILSLIB::FilterKernel::m_designMethods.indexOf(UTILSLIB::FilterParameter("Cosine")), const Eigen::RowVectorXi &vecPicks=Eigen::RowVectorXi(), bool bFilterEnd=true, bool bUseThreads=true, bool bKeepOverhead=false)
Single averaged evoked response: time axis, data, baseline, channel info and averaging metadata.
Definition fiff_evoked.h:77
QPair< float, float > baseline
QList< FiffChInfo > chs
Continuous FIFF raw recording: FiffInfo plus a random-access directory of FIFF_DATA_BUFFER tags.
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
QSharedPointer< FiffStream > SPtr
static FiffStream::SPtr start_writing_raw(QIODevice &p_IODevice, const FiffInfo &info, Eigen::RowVectorXd &cals, Eigen::MatrixXi sel=defaultMatrixXi, bool bResetRange=true)
QSharedPointer< MNEEpochData > SPtr
Ordered list of MNEEpochData objects sharing a common measurement info.
FIFFLIB::FiffEvoked average(const FIFFLIB::FiffInfo &p_info, FIFFLIB::fiff_int_t first, FIFFLIB::fiff_int_t last, Eigen::VectorXi sel=FIFFLIB::defaultVectorXi, bool proj=false) const
void applyBaselineCorrection(const QPair< float, float > &baseline)
static bool checkForArtifact(const Eigen::MatrixXd &data, const FIFFLIB::FiffInfo &pFiffInfo, const QMap< QString, double > &mapReject, const QStringList &lExcludeChs=QStringList())