42static constexpr float SEG_LEN = 10.0f;
59static mneChSelection mne_ch_selection_these(
const QString& selname,
const QStringList& names,
int nch)
66 for (
int c = 0; c < nch; c++)
67 sel->chdef.append(names[c]);
92 auto info = data->
info.get();
96 name = name.trimmed();
103 for (
int c = 0; c < sel->
nchan; c++) {
104 for (
int rc = 0; rc < info->nchan; rc++) {
105 if (QString::compare(sel->
chspick[c],info->chInfo[rc].ch_name,Qt::CaseInsensitive) == 0 ||
106 QString::compare(sel->
chspick_nospace[c],info->chInfo[rc].ch_name,Qt::CaseInsensitive) == 0) {
108 sel->
ch_kind[c] = info->chInfo[rc].kind;
118 QStringList deriv_names = data->
deriv_matched->deriv_data->rowlist;
121 for (
int c = 0; c < sel->
nchan; c++) {
122 if (sel->
pick[c] == -1) {
123 for (
int d = 0; d < nderiv; d++) {
124 if (QString::compare(sel->
chspick[c],deriv_names[d],Qt::CaseInsensitive) == 0 &&
138 for (
int c = 0; c < sel->
nchan; c++) {
140 for (
int rc = 0; rc < info->nchan; rc++) {
141 QString dash = QString(info->chInfo[rc].ch_name).mid(QString(info->chInfo[rc].ch_name).indexOf(
"-")+1);
142 if (!dash.isNull()) {
143 if (QString::compare(sel->
chspick[c],info->chInfo[rc].ch_name,Qt::CaseInsensitive) == 0 ||
144 QString::compare(sel->
chspick_nospace[c],info->chInfo[rc].ch_name,Qt::CaseInsensitive) == 0) {
146 sel->
ch_kind[c] = info->chInfo[rc].kind;
154 for (
int c = 0; c < sel->
nchan; c++) {
155 if (sel->
pick[c] >= 0)
159 qInfo(
"Selection \"%s\" has %d matched derived channels.",sel->
name.toUtf8().constData(),sel->
nderiv);
168: settings(p_settings)
177 qInfo(
"---- Setting up...\n");
178 std::unique_ptr<FwdEegSphereModel> eeg_model;
179 if (settings->include_eeg) {
202 settings->include_meg,
203 settings->include_eeg));
209 fit_data->fit_mag_dipoles = settings->fit_mag_dipoles;
211 std::unique_ptr<MNERawData> raw;
212 std::unique_ptr<MNEMeasData> data;
213 std::unique_ptr<MNEChSelection> sel;
215 if (settings->is_raw) {
216 qInfo(
"\n---- Opening a raw data file...\n");
223 sel.reset(mne_ch_selection_these(
"fit",fit_data->ch_names,fit_data->nmeg+fit_data->neeg));
224 mne_ch_selection_assign_chs(sel.get(),raw.get());
225 for (
int c = 0; c < sel->nchan; c++)
226 if (sel->pick[c] < 0) {
227 qCritical(
"All desired channels were not available");
230 qInfo(
"\tChannel selection created.");
234 float t1 = raw->first_samp/raw->info->sfreq;
235 float t2 = (raw->first_samp+raw->nsamp-1)/raw->info->sfreq;
236 if (settings->tmin < t1 + settings->integ)
237 settings->tmin = t1 + settings->integ;
238 if (settings->tmax > t2 - settings->integ)
239 settings->tmax = t2 - settings->integ;
240 if (settings->tstep < 0)
241 settings->tstep = 1.0f/raw->info->sfreq;
243 qInfo(
"\tOpened raw data file %s : %d MEG and %d EEG",
244 settings->measname.toUtf8().constData(),fit_data->nmeg,fit_data->neeg);
247 qInfo(
"\n---- Reading data...\n");
253 fit_data->nmeg+fit_data->neeg));
256 if (settings->do_baseline)
257 data->adjust_baselines(settings->bmin,settings->bmax);
259 qInfo(
"\tNo baseline setting in effect.");
260 if (settings->tmin < data->current->tmin + settings->integ/2.0f)
261 settings->tmin = data->current->tmin + settings->integ/2.0f;
262 if (settings->tmax > data->current->tmin + (data->current->np-1)*data->current->tstep - settings->integ/2.0f)
263 settings->tmax = data->current->tmin + (data->current->np-1)*data->current->tstep - settings->integ/2.0f;
264 if (settings->tstep < 0)
265 settings->tstep = data->current->tstep;
267 qInfo(
"\tRead data set %d from %s : %d MEG and %d EEG",
268 settings->setno,settings->measname.toUtf8().constData(),fit_data->nmeg,fit_data->neeg);
269 if (!settings->noisename.isEmpty()) {
270 qInfo(
"Scaling the noise covariance...");
279 qInfo(
"\n---- Computing the forward solution for the guesses...\n");
280 auto guess = std::make_unique<InvGuessData>(settings->guessname,
281 settings->guess_surfname,
282 settings->guess_mindist, settings->guess_exclude, settings->guess_grid, fit_data.get());
286 qInfo(
"\n---- Fitting : %7.1f ... %7.1f ms (step: %6.1f ms integ: %6.1f ms)\n",
287 1000*settings->tmin,1000*settings->tmax,1000*settings->tstep,1000*settings->integ);
290 if (!
fit_dipoles_raw(settings->measname,raw.get(),sel.get(),fit_data.get(),guess.get(),settings->tmin,settings->tmax,settings->tstep,settings->integ,settings->verbose,set))
294 if (!
fit_dipoles(settings->measname,data.get(),fit_data.get(),guess.get(),settings->tmin,settings->tmax,settings->tstep,settings->integ,settings->verbose,set))
297 qInfo(
"%d dipoles fitted",set.
size());
306 Eigen::VectorXf one(data->
nchan);
309 constexpr int report_interval = 10;
315 for (
int s = 0; tmin + s*tstep < tmax; s++) {
316 float time = tmin + s*tstep;
318 qWarning(
"Cannot pick time: %7.1f ms",1000.0f*time);
323 qWarning(
"t = %7.1f ms : fit error",1000.0f*time);
329 if (set.
size() % report_interval == 0)
330 qInfo(
"%d..",set.
size());
342bool InvDipoleFit::fit_dipoles_raw(
const QString& dataname,
MNERawData* raw,
mneChSelection sel,
InvDipoleFitData* fit,
InvGuessData* guess,
float tmin,
float tmax,
float tstep,
float integ,
int verbose,
InvEcdSet& p_set)
344 const int nchan = sel->
nchan;
345 const float sfreq = raw->
info->sfreq;
346 const float myinteg = integ > 0.0f ? 2*integ : 0.1f;
347 const int overlap =
static_cast<int>(std::ceil(myinteg*sfreq));
348 const int length =
static_cast<int>(SEG_LEN*sfreq);
349 const int step = length - overlap;
350 const int stepo = step + overlap/2;
352 constexpr int report_interval = 10;
354 Eigen::VectorXf one(nchan);
357 std::vector<float> storage(
static_cast<std::size_t
>(nchan) * length);
358 std::vector<float*> rows(nchan);
359 for (
int i = 0; i < nchan; ++i)
360 rows[i] = storage.data() + i * length;
361 float** data = rows.data();
370 float stime = start/sfreq;
375 for (
int s = 0; tmin + s*tstep < tmax; s++) {
376 float time = tmin + s*tstep;
377 int picks = time*sfreq - start;
379 start = start + step;
382 picks = time*sfreq - start;
386 qWarning(
"Cannot pick time: %8.3f s",time);
390 qWarning(
"t = %8.3f s : fit error",time);
396 if (set.
size() % report_interval == 0)
397 qInfo(
"%d..",set.
size());
412 return fit_dipoles_raw(dataname, raw, sel, fit, guess, tmin, tmax, tstep, integ, verbose, set);
One condition / averaging slice within a legacy MNELIB::MNEMeasData.
#define MNE_CH_SELECTION_USER
Initial-guess grid for the dipole-fit optimiser, with per-guess forward fields pre-computed.
High-level driver for sequential equivalent-current-dipole (ECD) fitting at every time point of an ev...
Core MNE data structures (source spaces, source estimates, hemispheres).
MNEChSelection * mneChSelection
Inverse source estimation (MNE, dSPM, sLORETA, dipole fitting).
Forward modelling — BEM solver, spherical models, sensor/coil definitions and the lead-field assembly...
static FwdEegSphereModel::UPtr setup_eeg_sphere_model(const QString &eeg_model_file, QString eeg_model_name, float eeg_sphere_rad)
InvEcdSet calculateFit() const
static bool fit_dipoles(const QString &dataname, MNELIB::MNEMeasData *data, InvDipoleFitData *fit, InvGuessData *guess, float tmin, float tmax, float tstep, float integ, int verbose, InvEcdSet &p_set)
InvDipoleFit(InvDipoleFitSettings *p_settings)
static bool fit_dipoles_raw(const QString &dataname, MNELIB::MNERawData *raw, MNELIB::mneChSelection sel, InvDipoleFitData *fit, InvGuessData *guess, float tmin, float tmax, float tstep, float integ, int verbose, InvEcdSet &p_set)
Dipole fit workspace holding sensor geometry, forward model, noise covariance, and projection data.
static InvDipoleFitData * setup_dipole_fit_data(const QString &mriname, const QString &measname, const QString &bemname, Eigen::Vector3f *r0, FWDLIB::FwdEegSphereModel *eeg_model, int accurate_coils, const QString &badname, const QString &noisename, float grad_std, float mag_std, float eeg_std, float mag_reg, float grad_reg, float eeg_reg, int diagnoise, const QList< QString > &projnames, int include_meg, int include_eeg)
Master setup: read all inputs and build a ready-to-use fit workspace.
static int scale_noise_cov(InvDipoleFitData *f, int nave)
Scale the noise-covariance matrix for a given number of averages.
static bool fit_one(InvDipoleFitData *fit, InvGuessData *guess, float time, Eigen::Ref< Eigen::VectorXf > B, int verbose, InvEcd &res)
Fit a single dipole to the given data.
Settings for the mne_dipole_fit driver (forward model, guess grid, data, projections,...
Single equivalent current dipole with position, orientation, amplitude, and goodness-of-fit.
Holds a set of Electric Current Dipoles.
void addEcd(const InvEcd &p_ecd)
Precomputed guess point grid with forward fields for initial dipole position candidates.
Eigen::VectorXi pick_deriv
QStringList chspick_nospace
Measurement data container for MNE inverse and dipole-fit computations.
static MNEMeasData * mne_read_meas_data(const QString &name, int set, MNEInverseOperator *op, MNENamedMatrix *fwd, const QStringList &namesp, int nnamesp)
Read an evoked-response data set into a new container.
static int getValuesFromChannelData(float time, float integ, float **data, int nsamp, int nch, float tmin, float sfreq, bool use_abs, float *value)
int getValuesAtTime(float time, float integ, int nch, bool use_abs, float *value) const
A comprehensive raw data structure.
std::unique_ptr< MNELIB::MNERawInfo > info
std::unique_ptr< MNELIB::MNEDeriv > deriv_matched
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)