48bool parseFloat(
const char* arg,
float& value)
51 const float parsed = QString::fromUtf8(arg).toFloat(&bOk);
68bool parseInt(
const char* arg,
int& value)
71 const int parsed = QString::fromUtf8(arg).toInt(&bOk);
88bool parseTriplet(
const char* arg, Eigen::Vector3f& values)
90 const QStringList parts = QString::fromUtf8(arg).split(
':');
91 if (parts.size() != 3) {
95 Eigen::Vector3f parsed;
96 for (
int i = 0; i < 3; ++i) {
98 parsed[i] = parts.at(i).toFloat(&bOk);
126 if (!check_args(argc, argv))
140void InvDipoleFitSettings::initMembers()
143 r0 << 0.0f, 0.0f, 0.04f;
202 qCritical(
"Data file name missing. Please specify one using the --meas option.");
207 qCritical(
"Please specify the MRI/head coordinate transformation with the --mri option");
212 qCritical(
"Specify one or both of the --eeg and --meg options");
220 qInfo(
"BEM : %s",
bemname.toUtf8().data());
222 qInfo(
"Sphere model : origin at (% 7.2f % 7.2f % 7.2f) mm",
223 1000 *
r0[0], 1000 *
r0[1], 1000 *
r0[2]);
225 qInfo(
"Using %s MEG coil definitions.",
accurate ?
"accurate" :
"standard");
227 qInfo(
"MRI transform : %s",
mriname.toUtf8().data());
229 qInfo(
"Guesses : %s",
guessname.toUtf8().data());
232 qInfo(
"Guess space bounded by %s",
guess_surfname.toUtf8().data());
234 qInfo(
"Spherical guess space, rad = %.1f mm", 1000 *
guess_rad);
235 qInfo(
"Guess grid : %6.1f mm", 1000 *
guess_grid);
241 qInfo(
"Data : %s",
measname.toUtf8().data());
243 qInfo(
"SSP sources :");
244 for (
int k = 0; k <
projnames.size(); k++)
245 qInfo(
"\t%s",
projnames[k].toUtf8().data());
248 qInfo(
"Bad channels : %s",
badname.toUtf8().data());
250 qInfo(
"Baseline : %10.2f ... %10.2f ms", 1000 *
bmin, 1000 *
bmax);
252 qInfo(
"Noise covariance : %s",
noisename.toUtf8().data());
255 qInfo(
"\tNoise-covariance regularization (mag) : %-5.2f",
mag_reg);
257 qInfo(
"\tNoise-covariance regularization (grad) : %-5.2f",
grad_reg);
260 qInfo(
"\tNoise-covariance regularization (EEG) : %-5.2f",
eeg_reg);
263 qInfo(
"Fit data with magnetic dipoles");
265 qInfo(
"dip output : %s",
dipname.toUtf8().data());
267 qInfo(
"bdip output : %s",
bdipname.toUtf8().data());
273void InvDipoleFitSettings::usage(
const char* name)
275 qInfo(
"usage: %s [options]", name);
276 qInfo(
"This is a program for sequential single dipole fitting.");
277 qInfo(
"\nInput data:\n");
278 qInfo(
"\t--meas name specify an evoked-response data file");
279 qInfo(
"\t--set no evoked data set number to use (default: 1)");
280 qInfo(
"\t--bad name take bad channel list from here");
282 qInfo(
"\nModality selection:\n");
283 qInfo(
"\t--meg employ MEG data in fitting");
284 qInfo(
"\t--eeg employ EEG data in fitting");
286 qInfo(
"\nTime scale selection:\n");
287 qInfo(
"\t--tmin time/ms specify the starting analysis time");
288 qInfo(
"\t--tmax time/ms specify the ending analysis time");
289 qInfo(
"\t--tstep time/ms specify the time step between frames (default 1/(sampling frequency))");
290 qInfo(
"\t--integ time/ms specify the time integration for each frame (default 0)");
292 qInfo(
"\nPreprocessing:\n");
293 qInfo(
"\t--bmin time/ms specify the baseline starting time (evoked data only)");
294 qInfo(
"\t--bmax time/ms specify the baseline ending time (evoked data only)");
295 qInfo(
"\t--proj name Load the linear projection from here");
296 qInfo(
"\t Multiple projections can be specified.");
297 qInfo(
"\t The data file will be automatically included, unless --noproj is present.");
298 qInfo(
"\t--noproj Do not load the projection from the data file, just those given with the --proj option.");
299 qInfo(
"\n\tFiltering (raw data only):\n");
300 qInfo(
"\t--filtersize size desired filter length (default = %d)",
filter.
size);
301 qInfo(
"\t--highpass val/Hz highpass corner (default = %6.1f Hz)",
filter.
highpass);
302 qInfo(
"\t--lowpass val/Hz lowpass corner (default = %6.1f Hz)",
filter.
lowpass);
303 qInfo(
"\t--lowpassw val/Hz lowpass transition width (default = %6.1f Hz)",
filter.
lowpass_width);
304 qInfo(
"\t--filteroff do not filter the data");
306 qInfo(
"\nNoise specification:\n");
307 qInfo(
"\t--noise name take the noise-covariance matrix from here");
308 qInfo(
"\t--gradnoise val specify a gradiometer noise value in fT/cm");
309 qInfo(
"\t--magnoise val specify a magnetometer noise value in fT");
310 qInfo(
"\t--eegnoise val specify an EEG value in uV");
311 qInfo(
"\t NOTE: The above will be used only if --noise is missing");
312 qInfo(
"\t--diagnoise omit off-diagonal terms from the noise-covariance matrix");
313 qInfo(
"\t--reg amount Apply regularization to the noise-covariance matrix (same fraction for all channels).");
314 qInfo(
"\t--gradreg amount Apply regularization to the MEG noise-covariance matrix (planar gradiometers, default = %6.2f).",
grad_reg);
315 qInfo(
"\t--magreg amount Apply regularization to the MEG noise-covariance matrix (axial gradiometers and magnetometers, default = %6.2f).",
mag_reg);
316 qInfo(
"\t--eegreg amount Apply regularization to the EEG noise-covariance matrix (default = %6.2f).",
eeg_reg);
318 qInfo(
"\nForward model:\n");
319 qInfo(
"\t--mri name take head/MRI coordinate transform from here (Neuromag MRI description file)");
320 qInfo(
"\t--bem name BEM model name");
321 qInfo(
"\t--origin x:y:z/mm use a sphere model with this origin (head coordinates/mm)");
322 qInfo(
"\t--eegscalp scale the electrode locations to the surface of the scalp when using a sphere model");
323 qInfo(
"\t--eegmodels name read EEG sphere model specifications from here.");
324 qInfo(
"\t--eegmodel name name of the EEG sphere model to use (default : Default)");
325 qInfo(
"\t--eegrad val radius of the scalp surface to use in EEG sphere model (default : %7.1f mm)", 1000 *
eeg_sphere_rad);
326 qInfo(
"\t--accurate use accurate coil definitions in MEG forward computation");
328 qInfo(
"\nFitting parameters:\n");
329 qInfo(
"\t--guess name The source space of initial guesses.");
330 qInfo(
"\t If not present, the values below are used to generate the guess grid.");
331 qInfo(
"\t--guesssurf name Read the inner skull surface from this fif file to generate the guesses.");
332 qInfo(
"\t--guessrad value Radius of a spherical guess volume if neither of the above is present (default : %.1f mm)", 1000 *
guess_rad);
333 qInfo(
"\t--exclude dist/mm Exclude points which are closer than this distance from the CM of the inner skull surface (default = %6.1f mm).", 1000 *
guess_exclude);
334 qInfo(
"\t--mindist dist/mm Exclude points which are closer than this distance from the inner skull surface (default = %6.1f mm).", 1000 *
guess_mindist);
335 qInfo(
"\t--grid dist/mm Source space grid size (default = %6.1f mm).", 1000 *
guess_grid);
336 qInfo(
"\t--magdip Fit magnetic dipoles instead of current dipoles.");
337 qInfo(
"\nOutput:\n");
338 qInfo(
"\t--dip name xfit dip format output file name");
339 qInfo(
"\t--bdip name xfit bdip format output file name");
340 qInfo(
"\nGeneral:\n");
341 qInfo(
"\t--gui Enables the gui.");
342 qInfo(
"\t--help print this info.");
343 qInfo(
"\t--version print version info.");
348bool InvDipoleFitSettings::check_unrecognized_args(
int argc,
char** argv)
352 for (
int k = 1; k < argc; k++)
353 args += QString(argv[k]) +
" ";
354 qCritical(
"Unrecognized arguments : %s", args.trimmed().toUtf8().data());
362bool InvDipoleFitSettings::check_args(
int* argc,
char** argv)
366 int ival, filter_size;
368 for (
int k = 0; k < *argc; k++) {
370 if (strcmp(argv[k],
"--gui") == 0) {
373 }
else if (strcmp(argv[k],
"--version") == 0) {
374 qInfo(
"%s compiled at %s %s",
375 argv[0], __DATE__, __TIME__);
377 }
else if (strcmp(argv[k],
"--help") == 0) {
380 }
else if (strcmp(argv[k],
"--guess") == 0) {
382 if (k == *argc - 1) {
383 qCritical(
"--guess: argument required.");
387 }
else if (strcmp(argv[k],
"--gsurf") == 0) {
389 if (k == *argc - 1) {
390 qCritical(
"--gsurf: argument required.");
394 }
else if (strcmp(argv[k],
"--guesssurf") == 0) {
396 if (k == *argc - 1) {
397 qCritical(
"--guesssurf: argument required.");
401 }
else if (strcmp(argv[k],
"--guessrad") == 0) {
403 if (k == *argc - 1) {
404 qCritical(
"--guessrad: argument required.");
407 if (!parseFloat(argv[k + 1], fval)) {
408 qCritical(
"Could not interpret the radius.");
412 qCritical(
"Radius should be positive");
416 }
else if (strcmp(argv[k],
"--mindist") == 0) {
418 if (k == *argc - 1) {
419 qCritical(
"--mindist: argument required.");
422 if (!parseFloat(argv[k + 1], fval)) {
423 qCritical(
"Could not interpret the distance.");
429 }
else if (strcmp(argv[k],
"--exclude") == 0) {
431 if (k == *argc - 1) {
432 qCritical(
"--exclude: argument required.");
435 if (!parseFloat(argv[k + 1], fval)) {
436 qCritical(
"Could not interpret the distance.");
442 }
else if (strcmp(argv[k],
"--grid") == 0) {
444 if (k == *argc - 1) {
445 qCritical(
"--grid: argument required.");
448 if (!parseFloat(argv[k + 1], fval)) {
449 qCritical(
"Could not interpret the distance.");
453 qCritical(
"Grid spacing should be positive");
458 }
else if (strcmp(argv[k],
"--mri") == 0) {
460 if (k == *argc - 1) {
461 qCritical(
"--mri: argument required.");
464 mriname = QString(argv[k + 1]);
465 }
else if (strcmp(argv[k],
"--bem") == 0) {
467 if (k == *argc - 1) {
468 qCritical(
"--bem: argument required.");
471 bemname = QString(argv[k + 1]);
472 }
else if (strcmp(argv[k],
"--accurate") == 0) {
475 }
else if (strcmp(argv[k],
"--meg") == 0) {
478 }
else if (strcmp(argv[k],
"--eeg") == 0) {
481 }
else if (strcmp(argv[k],
"--origin") == 0) {
483 if (k == *argc - 1) {
484 qCritical(
"--origin: argument required.");
487 if (!parseTriplet(argv[k + 1],
r0)) {
488 qCritical(
"Could not interpret the origin.");
491 r0[0] =
r0[0] / 1000.0f;
492 r0[1] =
r0[1] / 1000.0f;
493 r0[2] =
r0[2] / 1000.0f;
494 }
else if (strcmp(argv[k],
"--eegrad") == 0) {
496 if (k == *argc - 1) {
497 qCritical(
"--eegrad: argument required.");
501 qCritical() <<
"Incomprehensible radius:" << argv[k + 1];
505 qCritical(
"Radius must be positive");
509 }
else if (strcmp(argv[k],
"--eegmodels") == 0) {
511 if (k == *argc - 1) {
512 qCritical(
"--eegmodels: argument required.");
516 }
else if (strcmp(argv[k],
"--eegmodel") == 0) {
518 if (k == *argc - 1) {
519 qCritical(
"--eegmodel: argument required.");
523 }
else if (strcmp(argv[k],
"--eegscalp") == 0) {
526 }
else if (strcmp(argv[k],
"--meas") == 0) {
528 if (k == *argc - 1) {
529 qCritical(
"--meas: argument required.");
534 }
else if (strcmp(argv[k],
"--raw") == 0) {
536 if (k == *argc - 1) {
537 qCritical(
"--raw: argument required.");
542 }
else if (strcmp(argv[k],
"--proj") == 0) {
544 if (k == *argc - 1) {
545 qCritical(
"--proj: argument required.");
549 }
else if (strcmp(argv[k],
"--noproj") == 0) {
552 }
else if (strcmp(argv[k],
"--bad") == 0) {
554 if (k == *argc - 1) {
555 qCritical(
"--bad: argument required.");
558 badname = QString(argv[k + 1]);
559 }
else if (strcmp(argv[k],
"--noise") == 0) {
561 if (k == *argc - 1) {
562 qCritical(
"--noise: argument required.");
566 }
else if (strcmp(argv[k],
"--gradnoise") == 0) {
568 if (k == *argc - 1) {
569 qCritical(
"--gradnoise: argument required.");
572 if (!parseFloat(argv[k + 1], fval)) {
573 qCritical() <<
"Incomprehensible value:" << argv[k + 1];
577 qCritical(
"Value should be positive");
581 }
else if (strcmp(argv[k],
"--magnoise") == 0) {
583 if (k == *argc - 1) {
584 qCritical(
"--magnoise: argument required.");
587 if (!parseFloat(argv[k + 1], fval)) {
588 qCritical() <<
"Incomprehensible value:" << argv[k + 1];
592 qCritical(
"Value should be positive");
596 }
else if (strcmp(argv[k],
"--eegnoise") == 0) {
598 if (k == *argc - 1) {
599 qCritical(
"--eegnoise: argument required.");
602 if (!parseFloat(argv[k + 1], fval)) {
603 qCritical() <<
"Incomprehensible value:" << argv[k + 1];
607 qCritical(
"Value should be positive");
611 }
else if (strcmp(argv[k],
"--diagnoise") == 0) {
614 }
else if (strcmp(argv[k],
"--eegreg") == 0) {
616 if (k == *argc - 1) {
617 qCritical(
"--eegreg: argument required.");
620 if (!parseFloat(argv[k + 1], fval)) {
621 qCritical() <<
"Incomprehensible value:" << argv[k + 1];
624 if (fval < 0 || fval > 1) {
625 qCritical(
"Regularization value should be positive and smaller than one.");
629 }
else if (strcmp(argv[k],
"--magreg") == 0) {
631 if (k == *argc - 1) {
632 qCritical(
"--magreg: argument required.");
635 if (!parseFloat(argv[k + 1], fval)) {
636 qCritical() <<
"Incomprehensible value:" << argv[k + 1];
639 if (fval < 0 || fval > 1) {
640 qCritical(
"Regularization value should be positive and smaller than one.");
644 }
else if (strcmp(argv[k],
"--gradreg") == 0) {
646 if (k == *argc - 1) {
647 qCritical(
"--gradreg: argument required.");
650 if (!parseFloat(argv[k + 1], fval)) {
651 qCritical() <<
"Incomprehensible value:" << argv[k + 1];
654 if (fval < 0 || fval > 1) {
655 qCritical(
"Regularization value should be positive and smaller than one.");
659 }
else if (strcmp(argv[k],
"--reg") == 0) {
661 if (k == *argc - 1) {
662 qCritical(
"--reg: argument required.");
665 if (!parseFloat(argv[k + 1], fval)) {
666 qCritical() <<
"Incomprehensible value:" << argv[k + 1];
669 if (fval < 0 || fval > 1) {
670 qCritical(
"Regularization value should be positive and smaller than one.");
676 }
else if (strcmp(argv[k],
"--tstep") == 0) {
678 if (k == *argc - 1) {
679 qCritical(
"--tstep: argument required.");
682 if (!parseFloat(argv[k + 1], fval)) {
683 qCritical() <<
"Incomprehensible tstep:" << argv[k + 1];
687 qCritical(
"Time step should be positive");
690 tstep = fval / 1000.0;
691 }
else if (strcmp(argv[k],
"--integ") == 0) {
693 if (k == *argc - 1) {
694 qCritical(
"--integ: argument required.");
697 if (!parseFloat(argv[k + 1], fval)) {
698 qCritical() <<
"Incomprehensible integration time:" << argv[k + 1];
702 qCritical(
"Integration time should be positive.");
705 integ = fval / 1000.0f;
706 }
else if (strcmp(argv[k],
"--tmin") == 0) {
708 if (k == *argc - 1) {
709 qCritical(
"--tmin: argument required.");
712 if (!parseFloat(argv[k + 1], fval)) {
713 qCritical() <<
"Incomprehensible tmin:" << argv[k + 1];
716 tmin = fval / 1000.0f;
717 }
else if (strcmp(argv[k],
"--tmax") == 0) {
719 if (k == *argc - 1) {
720 qCritical(
"--tmax: argument required.");
723 if (!parseFloat(argv[k + 1], fval)) {
724 qCritical() <<
"Incomprehensible tmax:" << argv[k + 1];
727 tmax = fval / 1000.0;
728 }
else if (strcmp(argv[k],
"--bmin") == 0) {
730 if (k == *argc - 1) {
731 qCritical(
"--bmin: argument required.");
734 if (!parseFloat(argv[k + 1], fval)) {
735 qCritical() <<
"Incomprehensible bmin:" << argv[k + 1];
738 bmin = fval / 1000.0f;
739 }
else if (strcmp(argv[k],
"--bmax") == 0) {
741 if (k == *argc - 1) {
742 qCritical(
"--bmax: argument required.");
745 if (!parseFloat(argv[k + 1], fval)) {
746 qCritical() <<
"Incomprehensible bmax:" << argv[k + 1];
749 bmax = fval / 1000.0f;
750 }
else if (strcmp(argv[k],
"--set") == 0) {
752 if (k == *argc - 1) {
753 qCritical(
"--set: argument required.");
756 if (!parseInt(argv[k + 1],
setno)) {
757 qCritical() <<
"Incomprehensible data set number:" << argv[k + 1];
761 qCritical(
"Data set number must be > 0");
764 }
else if (strcmp(argv[k],
"--filteroff") == 0) {
767 }
else if (strcmp(argv[k],
"--lowpass") == 0) {
769 if (k == *argc - 1) {
770 qCritical(
"--lowpass: argument required.");
773 if (!parseFloat(argv[k + 1], fval)) {
774 qCritical() <<
"Illegal number:" << argv[k + 1];
778 qCritical(
"Lowpass corner must be positive");
782 }
else if (strcmp(argv[k],
"--lowpassw") == 0) {
784 if (k == *argc - 1) {
785 qCritical(
"--lowpassw: argument required.");
788 if (!parseFloat(argv[k + 1], fval)) {
789 qCritical() <<
"Illegal number:" << argv[k + 1];
793 qCritical(
"Lowpass width must be positive");
796 filter.lowpass_width = fval;
797 }
else if (strcmp(argv[k],
"--highpass") == 0) {
799 if (k == *argc - 1) {
800 qCritical(
"--highpass: argument required.");
803 if (!parseFloat(argv[k + 1], fval)) {
804 qCritical() <<
"Illegal number:" << argv[k + 1];
808 qCritical(
"Highpass corner must be positive");
812 }
else if (strcmp(argv[k],
"--filtersize") == 0) {
814 if (k == *argc - 1) {
815 qCritical(
"--filtersize: argument required.");
818 if (!parseInt(argv[k + 1], ival)) {
819 qCritical() <<
"Illegal number:" << argv[k + 1];
823 qCritical(
"Filtersize should be at least 1024.");
826 for (filter_size = 1024; filter_size < ival; filter_size = 2 * filter_size)
828 filter.size = filter_size;
829 filter.taper_size = filter_size / 2;
830 }
else if (strcmp(argv[k],
"--magdip") == 0) {
833 }
else if (strcmp(argv[k],
"--dip") == 0) {
835 if (k == *argc - 1) {
836 qCritical(
"--dip: argument required.");
839 dipname = QString(argv[k + 1]);
840 }
else if (strcmp(argv[k],
"--bdip") == 0) {
842 if (k == *argc - 1) {
843 qCritical(
"--bdip: argument required.");
847 }
else if (strcmp(argv[k],
"--verbose") == 0) {
852 for (
int p = k; p < *argc - found; p++)
853 argv[p] = argv[p + found];
854 *argc = *argc - found;
858 return check_unrecognized_args(*argc, argv);
Command-line and programmatic settings struct for the mne_dipole_fit driver.
Inverse source estimation (MNE, dSPM, sLORETA, dipole fitting).
constexpr double BIG_TIME
MNELIB::MNEFilterDef filter
virtual ~InvDipoleFitSettings()