53 QList<FiffEpochData> epochs;
55 if (matData.size() == 0 || dSFreq <= 0.0 || dDuration <= 0.0) {
56 qWarning() <<
"[FiffEpochs::makeFixedLengthEpochs] Invalid input parameters.";
60 if (dOverlap >= dDuration) {
61 qWarning() <<
"[FiffEpochs::makeFixedLengthEpochs] Overlap must be less than duration.";
65 const int nCh =
static_cast<int>(matData.rows());
66 const int nTimes =
static_cast<int>(matData.cols());
67 const int epochSamples =
static_cast<int>(std::round(dDuration * dSFreq));
68 const int stepSamples =
static_cast<int>(std::round((dDuration - dOverlap) * dSFreq));
70 if (epochSamples <= 0 || stepSamples <= 0)
74 while (start + epochSamples <= nTimes) {
76 epoch.
data = matData.block(0, start, nCh, epochSamples);
77 epoch.
tmin =
static_cast<double>(start) / dSFreq;
78 epoch.
tmax =
static_cast<double>(start + epochSamples - 1) / dSFreq;
84 if (!bDropLast && start < nTimes) {
85 int remaining = nTimes - start;
87 epoch.
data = matData.block(0, start, nCh, remaining);
88 epoch.
tmin =
static_cast<double>(start) / dSFreq;
89 epoch.
tmax =
static_cast<double>(nTimes - 1) / dSFreq;
100 QList<FiffEpochData> result;
102 for (
const auto& epochSet : epochSets)
103 result.append(epochSet);
112 const QString& comment)
116 if (epochs.isEmpty()) {
117 qWarning() <<
"[FiffEpochs::averageEpochs] Empty epoch list.";
121 const int nCh =
static_cast<int>(epochs[0].data.rows());
122 const int nTimes =
static_cast<int>(epochs[0].data.cols());
123 const int nEpochs = epochs.size();
125 MatrixXd avg = MatrixXd::Zero(nCh, nTimes);
127 for (
const auto& epoch : epochs) {
128 if (epoch.data.rows() != nCh || epoch.data.cols() != nTimes) {
129 qWarning() <<
"[FiffEpochs::averageEpochs] Inconsistent epoch dimensions; skipping.";
135 avg /=
static_cast<double>(nEpochs);
139 evoked.
nave = nEpochs;
144 const double tmin = epochs[0].tmin;
145 evoked.
first =
static_cast<fiff_int_t
>(std::round(tmin * dSFreq));
148 RowVectorXf times(nTimes);
149 for (
int i = 0; i < nTimes; ++i)
150 times(i) =
static_cast<float>(tmin +
static_cast<double>(i) / dSFreq);
151 evoked.
times = times;
160 QList<MatrixXd> result;
161 result.reserve(epochs.size());
163 for (
const auto& epoch : epochs)
164 result.append(epoch.data);
Static epoching utilities: cut a FiffRawData stream into fixed-length, event-aligned epochs.
#define FIFFV_ASPECT_AVERAGE
Single averaged evoked response: time axis, samples, baseline, channel info and processing history.
FIFF file I/O, in-memory data structures and high-level readers/writers.
static QList< FiffEpochData > makeFixedLengthEpochs(const Eigen::MatrixXd &matData, double dSFreq, double dDuration, double dOverlap=0.0, bool bDropLast=true)
Create fixed-length epochs from continuous data.
static QList< FiffEpochData > concatenateEpochs(const QList< QList< FiffEpochData > > &epochSets)
Concatenate multiple epoch sets into a single list.
static QList< Eigen::MatrixXd > toMatrixList(const QList< FiffEpochData > &epochs)
Extract data matrices from epoch structures.
static FiffEvoked averageEpochs(const QList< FiffEpochData > &epochs, double dSFreq, const QString &comment="Average")
Compute the average (evoked response) across epochs.
Single averaged evoked response: time axis, data, baseline, channel info and averaging metadata.