45constexpr float BIG = 0.5f;
51static QString readWord(QTextStream& in)
81FwdCoil* FwdCoilSet::fwd_add_coil_to_set(
int type,
int coil_class,
int acc,
int np,
float size,
float base,
const QString& desc)
84 qWarning(
"Number of integration points should be positive (type = %d acc = %d)", type, acc);
90 qWarning(
"Illegal accuracy (type = %d acc = %d)", type, acc);
97 qWarning(
"Illegal coil class (type = %d acc = %d class = %d)", type, acc, coil_class);
101 coils.push_back(std::make_unique<FwdCoil>(np));
102 FwdCoil* def =
coils.back().get();
135 qWarning() << ch.
ch_name <<
"is not a MEG channel. Cannot create a coil definition.";
142 for (
int k = 0; k < this->
ncoil(); k++) {
144 this->coils[k]->accuracy == acc) {
145 def = this->
coils[k].get();
149 qWarning(
"Desired coil definition not found (type = %d acc = %d)", ch.
chpos.
coil_type, acc);
155 auto res = std::make_unique<FwdCoil>(def->
np);
158 if (!def->
desc.isEmpty())
159 res->desc = def->
desc;
162 res->base = def->
base;
163 res->size = def->
size;
178 res->coord_frame = t.
to;
182 for (
int p = 0; p < res->np; p++) {
183 res->w[p] = def->
w[p];
184 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();
185 res->cosmag.row(p) = (def->
cosmag(p, 0) * res->ex + def->
cosmag(p, 1) * res->ey + def->
cosmag(p, 2) * res->ez).transpose();
197 auto res = std::make_unique<FwdCoilSet>();
199 for (
int k = 0; k < nch; k++) {
203 res->coils.push_back(std::move(next));
206 res->coord_frame = t.
to;
216 auto res = std::make_unique<FwdCoilSet>();
218 for (
int k = 0; k < nch; k++) {
222 res->coils.push_back(std::move(next));
225 res->coord_frame = t.
to;
234 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
235 qWarning() <<
"FwdCoilSet::read_coil_defs - Cannot open" << name;
242 QTextStream fileIn(&file);
243 while (!fileIn.atEnd()) {
244 QString line = fileIn.readLine();
245 int idx = line.indexOf(
'#');
248 content += line +
'\n';
253 QTextStream in(&content);
254 in.setLocale(QLocale::c());
256 auto res = std::make_unique<FwdCoilSet>();
257 while (!in.atEnd()) {
263 if (in.status() != QTextStream::Ok)
269 in >> type >> acc >> np >> size >> base;
270 if (in.status() != QTextStream::Ok) {
271 qWarning(
"FwdCoilSet::read_coil_defs - Error reading coil header");
275 QString desc = readWord(in);
276 if (desc.isEmpty()) {
277 qWarning(
"FwdCoilSet::read_coil_defs - Missing coil description");
281 FwdCoil* def = res->fwd_add_coil_to_set(type, coil_class, acc, np, size, base, desc);
285 for (
int p = 0; p < def->
np; p++) {
290 if (in.status() != QTextStream::Ok) {
291 qWarning(
"FwdCoilSet::read_coil_defs - Error reading integration point %d", p);
295 if (def->
pos(p).norm() >
BIG) {
296 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);
299 float cosmagNorm = def->
dir(p).norm();
300 if (cosmagNorm <= 0) {
301 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);
304 def->
cosmag.row(p).normalize();
308 qInfo(
"%d coil definitions read", res->ncoil());
320 qWarning(
"Coordinate frame of the transformation does not match the coil set in fwd_dup_coil_set");
324 res = std::make_unique<FwdCoilSet>();
326 res->coord_frame = t.
to;
330 res->coils.reserve(this->
ncoil());
332 for (
int k = 0; k < this->
ncoil(); k++) {
333 auto coil = std::make_unique<FwdCoil>(*(this->
coils[k]));
343 for (
int p = 0; p < coil->np; p++) {
347 coil->coord_frame = t.
to;
349 res->coils.push_back(std::move(coil));
360 for (
int k = 0; k < this->
ncoil(); k++)
361 if (this->
coils[k]->type == type)
372 for (
int k = 0; k < this->
ncoil(); k++)
373 if (this->
coils[k]->type == type)
386 for (
int k = 0; k < this->
ncoil(); k++)
387 if (this->
coils[k]->type == type)
FIFF channel descriptor record (FIFF_CH_INFO): per-channel logical/scanner numbers,...
#define FIFFV_COORD_DEVICE
#define FIFFV_COORD_UNKNOWN
Container of FwdCoil instances representing either a sensor-type template database or a concrete per-...
Single MEG sensor coil or EEG electrode described by a set of weighted integration points in its own ...
Per-sensor projection matrix that turns BEM node potentials into MEG coil readings or EEG electrode v...
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