44constexpr float BIG = 0.5f;
50static QString readWord(QTextStream &in)
53 if (in.atEnd())
return QString();
71 if (ch.isSpace())
break;
77FwdCoil* FwdCoilSet::fwd_add_coil_to_set(
int type,
int coil_class,
int acc,
int np,
float size,
float base,
const QString& desc)
80 qWarning(
"Number of integration points should be positive (type = %d acc = %d)",type,acc);
86 qWarning(
"Illegal accuracy (type = %d acc = %d)",type,acc);
93 qWarning(
"Illegal coil class (type = %d acc = %d class = %d)",type,acc,coil_class);
97 coils.push_back(std::make_unique<FwdCoil>(np));
98 FwdCoil* def =
coils.back().get();
131 qWarning() << ch.
ch_name <<
"is not a MEG channel. Cannot create a coil definition.";
138 for (
int k = 0; k < this->
ncoil(); k++) {
140 this->coils[k]->accuracy == acc) {
141 def = this->
coils[k].get();
145 qWarning(
"Desired coil definition not found (type = %d acc = %d)",ch.
chpos.
coil_type,acc);
151 auto res = std::make_unique<FwdCoil>(def->
np);
154 if (!def->
desc.isEmpty())
155 res->desc = def->
desc;
158 res->base = def->
base;
159 res->size = def->
size;
174 res->coord_frame = t.
to;
179 for (
int p = 0; p < res->np; p++) {
180 res->w[p] = def->
w[p];
181 res->rmag.row(p) = (res->r0 + def->
rmag(p, 0)*res->ex + def->
rmag(p, 1)*res->ey + def->
rmag(p, 2)*res->ez).transpose();
182 res->cosmag.row(p) = (def->
cosmag(p, 0)*res->ex + def->
cosmag(p, 1)*res->ey + def->
cosmag(p, 2)*res->ez).transpose();
194 auto res = std::make_unique<FwdCoilSet>();
196 for (
int k = 0; k < nch; k++) {
200 res->coils.push_back(std::move(next));
203 res->coord_frame = t.
to;
213 auto res = std::make_unique<FwdCoilSet>();
215 for (
int k = 0; k < nch; k++) {
219 res->coils.push_back(std::move(next));
222 res->coord_frame = t.
to;
231 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
232 qWarning() <<
"FwdCoilSet::read_coil_defs - Cannot open" << name;
239 QTextStream fileIn(&file);
240 while (!fileIn.atEnd()) {
241 QString line = fileIn.readLine();
242 int idx = line.indexOf(
'#');
245 content += line +
'\n';
250 QTextStream in(&content);
251 in.setLocale(QLocale::c());
253 auto res = std::make_unique<FwdCoilSet>();
254 while (!in.atEnd()) {
260 if (in.status() != QTextStream::Ok)
266 in >> type >> acc >> np >> size >> base;
267 if (in.status() != QTextStream::Ok) {
268 qWarning(
"FwdCoilSet::read_coil_defs - Error reading coil header");
272 QString desc = readWord(in);
273 if (desc.isEmpty()) {
274 qWarning(
"FwdCoilSet::read_coil_defs - Missing coil description");
278 FwdCoil* def = res->fwd_add_coil_to_set(type,coil_class,acc,np,size,base,desc);
282 for (
int p = 0; p < def->
np; p++) {
287 >> def->
rmag(p, 0) >> def->
rmag(p, 1) >> def->
rmag(p, 2)
289 if (in.status() != QTextStream::Ok) {
290 qWarning(
"FwdCoilSet::read_coil_defs - Error reading integration point %d", p);
294 if (def->
pos(p).norm() >
BIG) {
295 qWarning(
"Unreasonable integration point: %f %f %f mm (coil type = %d acc = %d)", 1000*def->
rmag(p, 0),1000*def->
rmag(p, 1),1000*def->
rmag(p, 2), def->
type,def->
accuracy);
298 float cosmagNorm = def->
dir(p).norm();
299 if (cosmagNorm <= 0) {
300 qWarning(
"Unreasonable normal: %f %f %f (coil type = %d acc = %d)", def->
cosmag(p, 0),def->
cosmag(p, 1),def->
cosmag(p, 2), def->
type,def->
accuracy);
303 def->
cosmag.row(p).normalize();
307 qInfo(
"%d coil definitions read",res->ncoil());
319 qWarning(
"Coordinate frame of the transformation does not match the coil set in fwd_dup_coil_set");
323 res = std::make_unique<FwdCoilSet>();
325 res->coord_frame = t.
to;
329 res->coils.reserve(this->
ncoil());
331 for (
int k = 0; k < this->
ncoil(); k++) {
332 auto coil = std::make_unique<FwdCoil>(*(this->
coils[k]));
342 for (
int p = 0; p < coil->np; p++) {
346 coil->coord_frame = t.
to;
348 res->coils.push_back(std::move(coil));
359 for (
int k = 0; k < this->
ncoil(); k++)
360 if (this->
coils[k]->type == type)
371 for (
int k = 0; k < this->
ncoil(); k++)
372 if (this->
coils[k]->type == type)
385 for (
int k = 0; k < this->
ncoil(); k++)
386 if (this->
coils[k]->type == type)
Per-sensor projection matrix that turns BEM node potentials into MEG coil readings or EEG electrode v...
Single MEG sensor coil or EEG electrode described by a set of weighted integration points in its own ...
Container of FwdCoil instances representing either a sensor-type template database or a concrete per-...
#define FIFFV_COORD_DEVICE
#define FIFFV_COORD_UNKNOWN
FIFF channel descriptor record (FIFF_CH_INFO): per-channel logical/scanner numbers,...
FIFF file I/O, in-memory data structures and high-level readers/writers.
Forward modelling — BEM solver, spherical models, sensor/coil definitions and the lead-field assembly...
constexpr int FWD_COIL_ACCURACY_NORMAL
constexpr int FWD_COIL_ACCURACY_POINT
constexpr int FWD_COIL_ACCURACY_ACCURATE
constexpr int FWD_COILC_PLANAR_GRAD
constexpr int FWD_COILC_AXIAL_GRAD2
constexpr int FWD_COILC_AXIAL_GRAD
constexpr int FWD_COILC_MAG
Per-channel FIFF descriptor: identifiers, kind, calibration, coil type, channel-frame coil position a...
Labelled 4x4 FIFF affine: source frame, destination frame, rotation, translation and cached inverse.
Eigen::MatrixX3f apply_trans(const Eigen::MatrixX3f &rr, bool do_move=true) const
Single MEG sensor coil or EEG electrode — stores the coil-local frame and the (r_mag,...
std::unique_ptr< FwdCoil > UPtr
Eigen::Map< const Eigen::Vector3f > dir(int j) const
Eigen::Map< const Eigen::Vector3f > pos(int j) const
Eigen::Matrix< float, Eigen::Dynamic, 3, Eigen::RowMajor > cosmag
static FwdCoil::UPtr create_eeg_el(const FIFFLIB::FiffChInfo &ch, const FIFFLIB::FiffCoordTrans &t=FIFFLIB::FiffCoordTrans())
Eigen::Matrix< float, Eigen::Dynamic, 3, Eigen::RowMajor > rmag
static FwdCoilSet::UPtr read_coil_defs(const QString &name)
bool is_axial_coil_type(int type) const
bool is_magnetometer_coil_type(int type) const
bool is_planar_coil_type(int type) const
FwdCoil::UPtr create_meg_coil(const FIFFLIB::FiffChInfo &ch, int acc, const FIFFLIB::FiffCoordTrans &t=FIFFLIB::FiffCoordTrans())
bool is_eeg_electrode_type(int type) const
FwdCoilSet::UPtr create_meg_coils(const QList< FIFFLIB::FiffChInfo > &chs, int nch, int acc, const FIFFLIB::FiffCoordTrans &t=FIFFLIB::FiffCoordTrans())
static FwdCoilSet::UPtr create_eeg_els(const QList< FIFFLIB::FiffChInfo > &chs, int nch, const FIFFLIB::FiffCoordTrans &t=FIFFLIB::FiffCoordTrans())
std::unique_ptr< FwdCoilSet > UPtr
std::vector< FwdCoil::UPtr > coils
FwdCoilSet::UPtr dup_coil_set(const FIFFLIB::FiffCoordTrans &t=FIFFLIB::FiffCoordTrans()) const