54 QList<FIFFLIB::FiffChInfo>& megp,
56 QList<FIFFLIB::FiffChInfo>& meg_compp,
58 QList<FIFFLIB::FiffChInfo>& eegp,
70 QList<FIFFLIB::FiffChInfo> chs;
72 QList<FIFFLIB::FiffChInfo> meg;
74 QList<FIFFLIB::FiffChInfo> meg_comp;
76 QList<FIFFLIB::FiffChInfo> eeg;
78 std::unique_ptr<FiffId> id;
79 QList<FiffDirNode::SPtr> nodes;
87 if (!stream->open()) {
94 if (nodes.size() == 0) {
96 if (nodes.size() == 0) {
97 qCritical(
"Could not find the channel information.");
104 for (k = 0; k < info->nent(); k++) {
105 kind = info->dir[k]->kind;
106 pos = info->dir[k]->pos;
109 if (!stream->read_tag(t_pTag, pos)) {
113 nchan = *t_pTag->toInt();
115 for (j = 0; j < nchan; j++) {
123 if (!stream->read_tag(t_pTag, pos)) {
127 id = std::make_unique<FiffId>(*(
FiffId*)t_pTag->data());
131 if (!stream->read_tag(t_pTag, pos)) {
142 if (!stream->read_tag(t_pTag, pos)) {
147 this_ch = t_pTag->toChInfo();
149 qCritical(
"FIFF_CH_INFO : scan # out of range %d (%d)!", this_ch.
scanNo, nchan);
153 chs[this_ch.
scanNo - 1] = this_ch;
159 qCritical(
"Some of the channel information was missing.");
163 if (t.
isEmpty() && meg_head_t !=
nullptr) {
169 qCritical(
"MEG -> head coordinate transformation not found.");
177 for (k = 0; k < nchan; k++) {
182 meg_comp.append(chs[k]);
197 meg_compp = meg_comp;
199 *nmeg_compp = nmeg_comp;
207 if (idp ==
nullptr) {
211 if (meg_head_t ==
nullptr) {
234 for (k = 0; compMap[k].grad_comp >= 0; k++)
236 return compMap[k].grad_comp;
250 float maxval = dense.cwiseAbs().maxCoeff();
252 small = maxval * std::fabs(small);
254 small = std::fabs(small);
257 Eigen::SparseMatrix<float> eigenSparse = dense.sparseView(small, 1.0f);
258 eigenSparse.makeCompressed();
260 if (eigenSparse.nonZeros() <= 0) {
261 qWarning(
"No nonzero elements found.");
265 return std::make_unique<FiffSparseMatrix>(std::move(eigenSparse),
FIFFTS_MC_RCS);
275 Eigen::Map<const Eigen::VectorXf> vecIn(vector, mat->
cols());
276 Eigen::Map<Eigen::VectorXf> vecOut(res, mat->
rows());
277 vecOut = mat->
eigen() * vecIn;
302 for (int k = 0; k < set.ncomp; k++)
304 this->comps.push_back(std::make_unique<MNECTFCompData>(*set.comps[k]));
305 this->ncomp = static_cast<int>(this->comps.size());
311 this->undo = std::make_unique<MNECTFCompData>(*set.
undo);
314 this->current = std::make_unique<MNECTFCompData>(*set.
current);
333 std::unique_ptr<MNECTFCompDataSet> set;
334 QList<FiffDirNode::SPtr> nodes;
335 QList<FiffDirNode::SPtr>
comps;
339 QList<FiffChInfo>
chs;
346 QList<FiffChInfo> comp_chs, temp;
360 for (k = 0; k < ncompch; k++)
361 chs.append(comp_chs[k]);
368 if (!stream->open()) {
372 set = std::make_unique<MNECTFCompDataSet>();
377 if (nodes.size() == 0) {
382 if (
comps.size() == 0) {
395 for (k = 0; k <
ncomp; k++) {
403 kind = *t_pTag->toInt();
410 calibrated = *t_pTag->toInt();
416 auto one = std::make_unique<MNECTFCompData>();
417 one->data = std::move(mat);
420 one->calibrated = calibrated;
422 if (one->calibrate(set->chs, set->nch,
true) ==
FAIL) {
423 qWarning(
"Warning: Compensation data for '%s' omitted\n",
explain_comp(one->kind).toUtf8().constData());
425 set->comps.push_back(std::move(one));
430 qInfo(
"%d CTF compensation data sets read from %s\n", set->ncomp, name);
440 QList<FiffChInfo> compchs,
446 Eigen::VectorXi compGrades;
450 Eigen::VectorXi comp_sel;
455 std::unique_ptr<FiffSparseMatrix> presel;
456 std::unique_ptr<FiffSparseMatrix> postsel;
457 std::unique_ptr<MNENamedMatrix> data;
459 QStringList emptyList;
461 if (compchs.isEmpty()) {
465 qInfo(
"Setting up compensation data...\n");
469 compGrades.resize(nChan);
472 compGrades[k] = chList[k].chpos.coil_type >> 16;
475 first_comp = compGrades[k];
477 if (compGrades[k] != first_comp) {
478 qCritical(
"We do not support nonuniform compensation yet.");
487 if (need_comp == 0) {
488 qInfo(
"\tNo compensation set. Nothing more to do.\n");
491 qInfo(
"\t%d out of %d channels have the compensation set.\n", need_comp, nChan);
495 for (k = 0, this_comp =
nullptr; k < this->
ncomp; k++) {
496 if (this->
comps[k]->mne_kind == first_comp) {
497 this_comp = this->
comps[k].get();
502 qCritical(
"Did not find the desired compensation data : %s",
510 comp_sel.resize(this_comp->
data->ncol);
511 for (k = 0; k < this_comp->
data->ncol; k++) {
513 name = this_comp->
data->collist[k];
514 for (p = 0; p < nCompChan; p++)
515 if (QString::compare(name, compchs[p].ch_name) == 0) {
519 if (comp_sel[k] < 0) {
520 qCritical(
"Compensation channel %s not found", name.toUtf8().constData());
524 qInfo(
"\tAll compensation channels found.\n");
529 Eigen::MatrixXf sel = Eigen::MatrixXf::Zero(this_comp->
data->ncol, nCompChan);
530 for (j = 0; j < this_comp->
data->ncol; j++)
531 sel(j, comp_sel[j]) = 1.0f;
535 qInfo(
"\tPreselector created.\n");
540 for (k = 0; k < nChan; k++) {
542 names.append(chList[k].ch_name);
546 auto d = this_comp->
data->pick(names, need_comp, emptyList, 0);
551 qInfo(
"\tCompensation data matrix created.\n");
556 Eigen::MatrixXf sel = Eigen::MatrixXf::Zero(nChan, data->nrow);
557 for (j = 0, p = 0; j < nChan; j++) {
564 qInfo(
"\tPostselector created.\n");
566 current = std::make_unique<MNECTFCompData>();
569 current->data = std::move(data);
570 current->presel = std::move(presel);
571 current->postsel = std::move(postsel);
573 qInfo(
"\tCompensation set up.\n");
588 for (k = 0, nset = 0; k <
nch; k++) {
590 chs[k].chpos.coil_type = (
chs[k].chpos.coil_type & 0xFFFF) | (comp << 16);
594 qInfo(
"A new compensation value (%s) was assigned to %d MEG channels.\n",
603 return apply(do_it, data, data);
614 int ndata =
static_cast<int>(data.size());
615 int ncompdata =
static_cast<int>(compdata.size());
624 if (this_comp->
presel->cols() != ncompdata) {
625 qCritical(
"Compensation data dimension mismatch. Expected %d, got %d channels.",
626 this_comp->
presel->cols(), ncompdata);
629 }
else if (this_comp->
data->ncol != ncompdata) {
630 qCritical(
"Compensation data dimension mismatch. Expected %d, got %d channels.",
631 this_comp->
data->ncol, ncompdata);
635 if (this_comp->
postsel->rows() != ndata) {
636 qCritical(
"Data dimension mismatch. Expected %d, got %d channels.",
637 this_comp->
postsel->rows(), ndata);
640 }
else if (this_comp->
data->nrow != ndata) {
641 qCritical(
"Data dimension mismatch. Expected %d, got %d channels.",
642 this_comp->
data->nrow, ndata);
656 presel = compdata.data();
663 Eigen::Map<const Eigen::VectorXf> preselVec(presel, this_comp->
data->ncol);
664 Eigen::Map<Eigen::VectorXf> compVec(this_comp->
comp_data.data(), this_comp->
data->nrow);
665 compVec = this_comp->
data->data * preselVec;
683 Eigen::Map<const Eigen::VectorXf> compVec(comp, ndata);
699 int ndata =
static_cast<int>(data.rows());
700 int ncompdata = ndata;
709 if (this_comp->
presel->cols() != ncompdata) {
710 qCritical(
"Compensation data dimension mismatch. Expected %d, got %d channels.",
711 this_comp->
presel->cols(), ncompdata);
714 }
else if (this_comp->
data->ncol != ncompdata) {
715 qCritical(
"Compensation data dimension mismatch. Expected %d, got %d channels.",
716 this_comp->
data->ncol, ncompdata);
720 if (this_comp->
postsel->rows() != ndata) {
721 qCritical(
"Data dimension mismatch. Expected %d, got %d channels.",
722 this_comp->
postsel->rows(), ndata);
725 }
else if (this_comp->
data->nrow != ndata) {
726 qCritical(
"Data dimension mismatch. Expected %d, got %d channels.",
727 this_comp->
data->nrow, ndata);
733 Eigen::MatrixXf preselMat;
735 preselMat = this_comp->
presel->eigen() * data;
743 Eigen::MatrixXf comp = this_comp->
data->data * preselMat;
748 comp = this_comp->
postsel->eigen() * comp;
765 int first_comp, comp;
768 for (k = 0, first_comp = -1; k <
nch; k++) {
770 comp =
chs[k].chpos.coil_type >> 16;
773 else if (first_comp != comp) {
774 qCritical(
"Non uniform compensation not supported.");
793 for (k = 0; compMap[k].grad_comp >= 0; k++)
795 return compMap[k].ctf_comp;
816 if (explain[k].kind == kind)
817 return QString::fromLatin1(explain[k].expl);
818 return QString::fromLatin1(explain[k].expl);
824 QList<FiffChInfo>& chList,
826 QList<FiffChInfo> comp_chs,
836 if (comp_chs.isEmpty()) {
842 for (k = 0, have_comp_chs = 0; k < ncomp_chan; k++)
846 qWarning(
"No compensation channels in these data.");
858 qInfo(
"No further compensation necessary (comp = %s)\n",
explain_comp(
current->kind).toUtf8().constData());
864 qInfo(
"No compensation was requested.\n");
865 set_comp(chList, nchan, compensate_to);
868 if (
set_comp(chList, nchan, compensate_to) > 0) {
870 comp_was =
undo->mne_kind;
873 if (
make_comp(chList, nchan, comp_chs, ncomp_chan) ==
FAIL) {
878 qInfo(
"Compensation set up as requested (%s -> %s).\n",
constexpr auto FIFFB_MNE_PARENT_MEAS_FILE
constexpr auto FIFFV_COORD_HEAD
constexpr auto FIFFB_MNE_CTF_COMP
constexpr auto FIFF_MNE_CTF_COMP_KIND
constexpr auto FIFFV_COORD_DEVICE
constexpr auto FIFF_MNE_CTF_COMP_CALIBRATED
constexpr auto FIFF_MNE_CTF_COMP_DATA
constexpr auto FIFFB_MNE_CTF_COMP_DATA
constexpr auto FIFFV_REF_MEG_CH
4x4 affine FIFF coordinate transform (FIFF_COORD_TRANS) annotated with source/destination coordinate-...
constexpr auto FIFFTS_MC_RCS
constexpr auto FIFF_NCHAN
constexpr auto FIFF_COORD_TRANS
constexpr auto FIFF_PARENT_BLOCK_ID
constexpr auto FIFFB_MEAS_INFO
constexpr auto FIFF_CH_INFO
return FiffCoordTrans(from_frame, to_frame, R, moveVec)
Primitive scalar typedefs and forward-compatible aliases backing the FIFF type system.
Set of CTF compensation matrices plus the currently active grade.
Legacy MNE-C constants and shared typedefs used across MNELIB structures.
Single CTF reference-sensor compensation matrix labelled by kind.
std::unique_ptr< FiffSparseMatrix > mne_convert_to_sparse(const Eigen::MatrixXf &dense, int stor_type, float small)
int mne_unmap_ctf_comp_kind(int ctf_comp)
int mne_sparse_vec_mult2_32(FiffSparseMatrix *mat, float *vector, float *res)
int mne_read_meg_comp_eeg_ch_info_32(const QString &name, QList< FIFFLIB::FiffChInfo > &megp, int *nmegp, QList< FIFFLIB::FiffChInfo > &meg_compp, int *nmeg_compp, QList< FIFFLIB::FiffChInfo > &eegp, int *neegp, FiffCoordTrans *meg_head_t, fiffId *idp)
Core MNE data structures (source spaces, source estimates, hemispheres).
constexpr auto MNE_CTFV_COMP_G2BR
constexpr auto MNE_CTFV_NOGRAD
constexpr auto MNE_CTFV_GRAD2
constexpr auto MNE_CTFV_COMP_NONE
constexpr auto MNE_4DV_COMP1
constexpr auto MNE_CTFV_COMP_G1BR
constexpr auto MNE_CTFV_GRAD3
constexpr auto MNE_CTFV_COMP_G3BR
constexpr auto MNE_CTFV_COMP_UNKNOWN
constexpr auto MNE_CTFV_GRAD1
FIFF file I/O, in-memory data structures and high-level readers/writers.
FiffId * fiffId
Backward-compatible pointer typedef for the old fiffId pointer.
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.
static FiffCoordTrans readMeasTransform(const QString &name)
static FiffCoordTrans readFromTag(const std::unique_ptr< FiffTag > &tag)
QSharedPointer< FiffDirNode > SPtr
128-bit FIFF identifier: hardware machine ID plus creation time, stamped on every file and block.
Sparse FIFF matrix: CCS or RCS storage with the value / index / pointer triple as written by FiffStre...
Eigen::SparseMatrix< float > & eigen()
FIFF tag-stream reader/writer: wraps a QIODevice and exposes typed read_* / write_* methods for every...
QSharedPointer< FiffStream > SPtr
std::unique_ptr< FiffTag > UPtr
Represents a single CTF compensation data element.
std::unique_ptr< FIFFLIB::FiffSparseMatrix > postsel
std::unique_ptr< MNENamedMatrix > data
Eigen::VectorXf comp_data
std::unique_ptr< FIFFLIB::FiffSparseMatrix > presel
Eigen::VectorXf postsel_data
Eigen::VectorXf presel_data
std::vector< std::unique_ptr< MNECTFCompData > > comps
std::unique_ptr< MNECTFCompData > undo
std::unique_ptr< MNECTFCompData > current
QList< FIFFLIB::FiffChInfo > chs
static int set_comp(QList< FIFFLIB::FiffChInfo > &chs, int nch, int comp)
static std::unique_ptr< MNECTFCompDataSet > read(const QString &name)
int make_comp(const QList< FIFFLIB::FiffChInfo > &chList, int nChan, QList< FIFFLIB::FiffChInfo > compchs, int nCompChan)
int apply(bool do_it, Eigen::Ref< Eigen::VectorXf > data, Eigen::Ref< const Eigen::VectorXf > compdata)
int set_compensation(int compensate_to, QList< FIFFLIB::FiffChInfo > &chList, int nchan, QList< FIFFLIB::FiffChInfo > comp_chs, int ncomp_chan)
int apply_transpose(bool do_it, Eigen::MatrixXf &data)
static QString explain_comp(int kind)
static int get_comp(const QList< FIFFLIB::FiffChInfo > &chs, int nch)
static int map_comp_kind(int grad)
static std::unique_ptr< MNENamedMatrix > read(QSharedPointer< FIFFLIB::FiffStream > &stream, const QSharedPointer< FIFFLIB::FiffDirNode > &node, int kind)
Factory: read a named matrix from a FIFF file.