61static constexpr float SEG_LEN = 10.0f;
78static mneChSelection mne_ch_selection_these(
const QString& selname,
const QStringList& names,
int nch)
85 for (
int c = 0; c < nch; c++)
86 sel->chdef.append(names[c]);
111 auto info = data->
info.get();
115 name = name.trimmed();
122 for (
int c = 0; c < sel->
nchan; c++) {
123 for (
int rc = 0; rc < info->nchan; rc++) {
124 if (QString::compare(sel->
chspick[c],info->chInfo[rc].ch_name,Qt::CaseInsensitive) == 0 ||
125 QString::compare(sel->
chspick_nospace[c],info->chInfo[rc].ch_name,Qt::CaseInsensitive) == 0) {
127 sel->
ch_kind[c] = info->chInfo[rc].kind;
137 QStringList deriv_names = data->
deriv_matched->deriv_data->rowlist;
140 for (
int c = 0; c < sel->
nchan; c++) {
141 if (sel->
pick[c] == -1) {
142 for (
int d = 0; d < nderiv; d++) {
143 if (QString::compare(sel->
chspick[c],deriv_names[d],Qt::CaseInsensitive) == 0 &&
157 for (
int c = 0; c < sel->
nchan; c++) {
159 for (
int rc = 0; rc < info->nchan; rc++) {
160 QString dash = QString(info->chInfo[rc].ch_name).mid(QString(info->chInfo[rc].ch_name).indexOf(
"-")+1);
161 if (!dash.isNull()) {
162 if (QString::compare(sel->
chspick[c],info->chInfo[rc].ch_name,Qt::CaseInsensitive) == 0 ||
163 QString::compare(sel->
chspick_nospace[c],info->chInfo[rc].ch_name,Qt::CaseInsensitive) == 0) {
165 sel->
ch_kind[c] = info->chInfo[rc].kind;
173 for (
int c = 0; c < sel->
nchan; c++) {
174 if (sel->
pick[c] >= 0)
178 qInfo(
"Selection \"%s\" has %d matched derived channels.",sel->
name.toUtf8().constData(),sel->
nderiv);
187: settings(p_settings)
196 qInfo(
"---- Setting up...\n");
197 std::unique_ptr<FwdEegSphereModel> eeg_model;
198 if (settings->include_eeg) {
221 settings->include_meg,
222 settings->include_eeg));
228 fit_data->fit_mag_dipoles = settings->fit_mag_dipoles;
230 std::unique_ptr<MNERawData> raw;
231 std::unique_ptr<MNEMeasData> data;
232 std::unique_ptr<MNEChSelection> sel;
234 if (settings->is_raw) {
235 qInfo(
"\n---- Opening a raw data file...\n");
242 sel.reset(mne_ch_selection_these(
"fit",fit_data->ch_names,fit_data->nmeg+fit_data->neeg));
243 mne_ch_selection_assign_chs(sel.get(),raw.get());
244 for (
int c = 0; c < sel->nchan; c++)
245 if (sel->pick[c] < 0) {
246 qCritical(
"All desired channels were not available");
249 qInfo(
"\tChannel selection created.");
253 float t1 = raw->first_samp/raw->info->sfreq;
254 float t2 = (raw->first_samp+raw->nsamp-1)/raw->info->sfreq;
255 if (settings->tmin < t1 + settings->integ)
256 settings->tmin = t1 + settings->integ;
257 if (settings->tmax > t2 - settings->integ)
258 settings->tmax = t2 - settings->integ;
259 if (settings->tstep < 0)
260 settings->tstep = 1.0f/raw->info->sfreq;
262 qInfo(
"\tOpened raw data file %s : %d MEG and %d EEG",
263 settings->measname.toUtf8().constData(),fit_data->nmeg,fit_data->neeg);
266 qInfo(
"\n---- Reading data...\n");
272 fit_data->nmeg+fit_data->neeg));
275 if (settings->do_baseline)
276 data->adjust_baselines(settings->bmin,settings->bmax);
278 qInfo(
"\tNo baseline setting in effect.");
279 if (settings->tmin < data->current->tmin + settings->integ/2.0f)
280 settings->tmin = data->current->tmin + settings->integ/2.0f;
281 if (settings->tmax > data->current->tmin + (data->current->np-1)*data->current->tstep - settings->integ/2.0f)
282 settings->tmax = data->current->tmin + (data->current->np-1)*data->current->tstep - settings->integ/2.0f;
283 if (settings->tstep < 0)
284 settings->tstep = data->current->tstep;
286 qInfo(
"\tRead data set %d from %s : %d MEG and %d EEG",
287 settings->setno,settings->measname.toUtf8().constData(),fit_data->nmeg,fit_data->neeg);
288 if (!settings->noisename.isEmpty()) {
289 qInfo(
"Scaling the noise covariance...");
298 qInfo(
"\n---- Computing the forward solution for the guesses...\n");
299 auto guess = std::make_unique<InvGuessData>(settings->guessname,
300 settings->guess_surfname,
301 settings->guess_mindist, settings->guess_exclude, settings->guess_grid, fit_data.get());
305 qInfo(
"\n---- Fitting : %7.1f ... %7.1f ms (step: %6.1f ms integ: %6.1f ms)\n",
306 1000*settings->tmin,1000*settings->tmax,1000*settings->tstep,1000*settings->integ);
309 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))
313 if (!
fit_dipoles(settings->measname,data.get(),fit_data.get(),guess.get(),settings->tmin,settings->tmax,settings->tstep,settings->integ,settings->verbose,set))
316 qInfo(
"%d dipoles fitted",set.
size());
325 Eigen::VectorXf one(data->
nchan);
328 constexpr int report_interval = 10;
334 for (
int s = 0; tmin + s*tstep < tmax; s++) {
335 float time = tmin + s*tstep;
337 qWarning(
"Cannot pick time: %7.1f ms",1000.0f*time);
342 qWarning(
"t = %7.1f ms : fit error",1000.0f*time);
348 if (set.
size() % report_interval == 0)
349 qInfo(
"%d..",set.
size());
361bool 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)
363 const int nchan = sel->
nchan;
364 const float sfreq = raw->
info->sfreq;
365 const float myinteg = integ > 0.0f ? 2*integ : 0.1f;
366 const int overlap =
static_cast<int>(std::ceil(myinteg*sfreq));
367 const int length =
static_cast<int>(SEG_LEN*sfreq);
368 const int step = length - overlap;
369 const int stepo = step + overlap/2;
371 constexpr int report_interval = 10;
373 Eigen::VectorXf one(nchan);
376 std::vector<float> storage(nchan * length);
377 std::vector<float*> rows(nchan);
378 for (
int i = 0; i < nchan; ++i)
379 rows[i] = storage.data() + i * length;
380 float** data = rows.data();
389 float stime = start/sfreq;
394 for (
int s = 0; tmin + s*tstep < tmax; s++) {
395 float time = tmin + s*tstep;
396 int picks = time*sfreq - start;
398 start = start + step;
401 picks = time*sfreq - start;
405 qWarning(
"Cannot pick time: %8.3f s",time);
409 qWarning(
"t = %8.3f s : fit error",time);
415 if (set.
size() % report_interval == 0)
416 qInfo(
"%d..",set.
size());
431 return fit_dipoles_raw(dataname, raw, sel, fit, guess, tmin, tmax, tstep, integ, verbose, set);
InvGuessData class declaration.
Dipole Fit class declaration.
#define MNE_CH_SELECTION_USER
MNEMeasDataSet class declaration.
Core MNE data structures (source spaces, source estimates, hemispheres).
MNEChSelection * mneChSelection
Inverse source estimation (MNE, dSPM, sLORETA, dipole fitting).
Forward modelling (BEM, MEG/EEG lead fields).
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.
Dipole Fit setting implementation.
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)