74 QList<FIFFLIB::FiffChInfo>& megp,
76 QList<FIFFLIB::FiffChInfo>& meg_compp,
78 QList<FIFFLIB::FiffChInfo>& eegp,
90 QList<FIFFLIB::FiffChInfo> chs;
92 QList<FIFFLIB::FiffChInfo> meg;
94 QList<FIFFLIB::FiffChInfo> meg_comp;
96 QList<FIFFLIB::FiffChInfo> eeg;
98 std::unique_ptr<FiffId> id;
99 QList<FiffDirNode::SPtr> nodes;
107 if(!stream->open()) {
113 if (nodes.size() == 0) {
115 if (nodes.size() == 0) {
116 qCritical (
"Could not find the channel information.");
122 for (k = 0; k < info->nent(); k++) {
123 kind = info->dir[k]->kind;
124 pos = info->dir[k]->pos;
127 if (!stream->read_tag(t_pTag,pos)) {
130 nchan = *t_pTag->toInt();
132 for (j = 0; j < nchan; j++) {
140 if(!stream->read_tag(t_pTag, pos)) {
143 id = std::make_unique<FiffId>(*(
FiffId*)t_pTag->data());
147 if(!stream->read_tag(t_pTag, pos)) {
157 if(!stream->read_tag(t_pTag, pos)) {
161 this_ch = t_pTag->toChInfo();
163 qCritical (
"FIFF_CH_INFO : scan # out of range %d (%d)!",this_ch.
scanNo,nchan);
167 chs[this_ch.
scanNo-1] = this_ch;
173 qCritical(
"Some of the channel information was missing.");
176 if (t.
isEmpty() && meg_head_t !=
nullptr) {
182 qCritical(
"MEG -> head coordinate transformation not found.");
189 for (k = 0; k < nchan; k++) {
194 meg_comp.append(chs[k]);
209 meg_compp = meg_comp;
211 *nmeg_compp = nmeg_comp;
219 if (idp ==
nullptr) {
224 if (meg_head_t ==
nullptr) {
232#define MNE_CTFV_COMP_UNKNOWN -1
233#define MNE_CTFV_COMP_NONE 0
234#define MNE_CTFV_COMP_G1BR 0x47314252
235#define MNE_CTFV_COMP_G2BR 0x47324252
236#define MNE_CTFV_COMP_G3BR 0x47334252
237#define MNE_CTFV_COMP_G2OI 0x47324f49
238#define MNE_CTFV_COMP_G3OI 0x47334f49
255 for (k = 0; compMap[k].grad_comp >= 0; k++)
257 return compMap[k].grad_comp;
271 float maxval = dense.cwiseAbs().maxCoeff();
273 small = maxval*std::fabs(small);
275 small = std::fabs(small);
278 Eigen::SparseMatrix<float> eigenSparse = dense.sparseView(small, 1.0f);
279 eigenSparse.makeCompressed();
281 if (eigenSparse.nonZeros() <= 0) {
282 qWarning(
"No nonzero elements found.");
286 return std::make_unique<FiffSparseMatrix>(std::move(eigenSparse),
FIFFTS_MC_RCS);
296 Eigen::Map<const Eigen::VectorXf> vecIn(vector, mat->
cols());
297 Eigen::Map<Eigen::VectorXf> vecOut(res, mat->
rows());
298 vecOut = mat->
eigen() * vecIn;
323 for (int k = 0; k < set.ncomp; k++)
325 this->comps.push_back(std::make_unique<MNECTFCompData>(*set.comps[k]));
326 this->ncomp = this->comps.size();
332 this->undo = std::make_unique<MNECTFCompData>(*set.
undo);
335 this->current = std::make_unique<MNECTFCompData>(*set.
current);
354 std::unique_ptr<MNECTFCompDataSet> set;
355 QList<FiffDirNode::SPtr> nodes;
356 QList<FiffDirNode::SPtr>
comps;
360 QList<FiffChInfo>
chs;
367 QList<FiffChInfo> comp_chs, temp;
381 for (k = 0; k < ncompch; k++)
382 chs.append(comp_chs[k]);
389 if(!stream->open()) {
390 stream->close();
return nullptr;
392 set = std::make_unique<MNECTFCompDataSet>();
397 if (nodes.size() == 0) {
398 stream->close();
return set;
401 if (
comps.size() == 0) {
402 stream->close();
return set;
413 for (k = 0; k <
ncomp; k++) {
416 stream->close();
return nullptr;
420 kind = *t_pTag->toInt();
423 stream->close();
return nullptr;
427 calibrated = *t_pTag->toInt();
434 auto one = std::make_unique<MNECTFCompData>();
435 one->data = std::move(mat);
438 one->calibrated = calibrated;
440 if (one->calibrate(set->chs,set->nch,
true) ==
FAIL) {
441 qWarning(
"Warning: Compensation data for '%s' omitted\n",
explain_comp(one->kind).toUtf8().constData());
444 set->comps.push_back(std::move(one));
449 qInfo(
"%d CTF compensation data sets read from %s\n",set->ncomp,name);
459 QList<FiffChInfo> compchs,
465 Eigen::VectorXi
comps;
469 Eigen::VectorXi comp_sel;
474 std::unique_ptr<FiffSparseMatrix> presel;
475 std::unique_ptr<FiffSparseMatrix> postsel;
476 std::unique_ptr<MNENamedMatrix> data;
478 QStringList emptyList;
480 if (compchs.isEmpty()) {
484 qInfo(
"Setting up compensation data...\n");
491 comps[k] =
chs[k].chpos.coil_type >> 16;
494 first_comp =
comps[k];
496 if (
comps[k] != first_comp) {
497 qCritical(
"We do not support nonuniform compensation yet.");
507 if (need_comp == 0) {
508 qInfo(
"\tNo compensation set. Nothing more to do.\n");
511 qInfo(
"\t%d out of %d channels have the compensation set.\n",need_comp,
nch);
515 for (k = 0, this_comp =
nullptr; k < this->ncomp; k++) {
516 if (this->comps[k]->mne_kind == first_comp) {
517 this_comp = this->comps[k].get();
522 qCritical(
"Did not find the desired compensation data : %s",
530 comp_sel.resize(this_comp->
data->ncol);
531 for (k = 0; k < this_comp->
data->ncol; k++) {
533 name = this_comp->
data->collist[k];
534 for (p = 0; p <
ncomp; p++)
535 if (QString::compare(name,compchs[p].ch_name) == 0) {
539 if (comp_sel[k] < 0) {
540 qCritical(
"Compensation channel %s not found",name.toUtf8().constData());
544 qInfo(
"\tAll compensation channels found.\n");
549 Eigen::MatrixXf sel = Eigen::MatrixXf::Zero(this_comp->
data->ncol,
ncomp);
550 for (j = 0; j < this_comp->
data->ncol; j++)
551 sel(j, comp_sel[j]) = 1.0f;
555 qInfo(
"\tPreselector created.\n");
560 for (k = 0; k <
nch; k++) {
562 names.append(
chs[k].ch_name);
566 auto d = this_comp->
data->pick(names, need_comp, emptyList, 0);
571 qInfo(
"\tCompensation data matrix created.\n");
576 Eigen::MatrixXf sel = Eigen::MatrixXf::Zero(
nch, data->nrow);
577 for (j = 0, p = 0; j <
nch; j++) {
584 qInfo(
"\tPostselector created.\n");
586 current = std::make_unique<MNECTFCompData>();
589 current->data = std::move(data);
590 current->presel = std::move(presel);
591 current->postsel = std::move(postsel);
593 qInfo(
"\tCompensation set up.\n");
608 for (k = 0, nset = 0; k <
nch; k++) {
610 chs[k].chpos.coil_type = (
chs[k].chpos.coil_type & 0xFFFF) | (comp << 16);
614 qInfo(
"A new compensation value (%s) was assigned to %d MEG channels.\n",
623 return apply(do_it, data, data);
634 int ndata =
static_cast<int>(data.size());
635 int ncompdata =
static_cast<int>(compdata.size());
644 if (this_comp->
presel->cols() != ncompdata) {
645 qCritical(
"Compensation data dimension mismatch. Expected %d, got %d channels.",
646 this_comp->
presel->cols(),ncompdata);
650 else if (this_comp->
data->ncol != ncompdata) {
651 qCritical(
"Compensation data dimension mismatch. Expected %d, got %d channels.",
652 this_comp->
data->ncol,ncompdata);
656 if (this_comp->
postsel->rows() != ndata) {
657 qCritical(
"Data dimension mismatch. Expected %d, got %d channels.",
658 this_comp->
postsel->rows(),ndata);
662 else if (this_comp->
data->nrow != ndata) {
663 qCritical(
"Data dimension mismatch. Expected %d, got %d channels.",
664 this_comp->
data->nrow,ndata);
679 presel = compdata.data();
686 Eigen::Map<const Eigen::VectorXf> preselVec(presel, this_comp->
data->ncol);
687 Eigen::Map<Eigen::VectorXf> compVec(this_comp->
comp_data.data(), this_comp->
data->nrow);
688 compVec = this_comp->
data->data * preselVec;
706 Eigen::Map<const Eigen::VectorXf> compVec(comp, ndata);
721 using RowMatrixXf = Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
724 int ndata =
static_cast<int>(data.rows());
725 int ns =
static_cast<int>(data.cols());
726 int ncompdata = ndata;
735 if (this_comp->
presel->cols() != ncompdata) {
736 qCritical(
"Compensation data dimension mismatch. Expected %d, got %d channels.",
737 this_comp->
presel->cols(),ncompdata);
741 else if (this_comp->
data->ncol != ncompdata) {
742 qCritical(
"Compensation data dimension mismatch. Expected %d, got %d channels.",
743 this_comp->
data->ncol,ncompdata);
747 if (this_comp->
postsel->rows() != ndata) {
748 qCritical(
"Data dimension mismatch. Expected %d, got %d channels.",
749 this_comp->
postsel->rows(),ndata);
753 else if (this_comp->
data->nrow != ndata) {
754 qCritical(
"Data dimension mismatch. Expected %d, got %d channels.",
755 this_comp->
data->nrow,ndata);
761 Eigen::MatrixXf preselMat;
763 preselMat = this_comp->
presel->eigen() * data;
772 Eigen::MatrixXf comp = this_comp->
data->data * preselMat;
777 comp = this_comp->
postsel->eigen() * comp;
797 for (k = 0, first_comp = -1; k <
nch; k++) {
799 comp =
chs[k].chpos.coil_type >> 16;
802 else if (first_comp != comp) {
803 qCritical(
"Non uniform compensation not supported.");
822 for (k = 0; compMap[k].grad_comp >= 0; k++)
824 return compMap[k].ctf_comp;
832 static const struct {
844 if (explain[k].kind == kind)
845 return QString::fromLatin1(explain[k].expl);
846 return QString::fromLatin1(explain[k].expl);
852 QList<FiffChInfo>&
chs,
854 QList<FiffChInfo> comp_chs,
864 if (comp_chs.isEmpty()) {
870 for (k = 0, have_comp_chs = 0; k < ncomp_chan; k++)
874 qWarning(
"No compensation channels in these data.");
886 qInfo(
"No further compensation necessary (comp = %s)\n",
explain_comp(
current->kind).toUtf8().constData());
892 qInfo(
"No compensation was requested.\n");
898 comp_was =
undo->mne_kind;
906 qInfo(
"Compensation set up as requested (%s -> %s).\n",
Old fiff_type declarations - replace them.
FiffCoordTrans class declaration.
#define FIFF_PARENT_BLOCK_ID
#define FIFF_MNE_CTF_COMP_KIND
#define FIFFV_COORD_DEVICE
#define FIFFB_MNE_CTF_COMP_DATA
#define FIFF_MNE_CTF_COMP_CALIBRATED
#define FIFF_MNE_CTF_COMP_DATA
#define FIFFB_MNE_CTF_COMP
#define FIFFB_MNE_PARENT_MEAS_FILE
MNECTFCompData class declaration.
Legacy MNE-C constants and common typedefs.
#define MNE_CTFV_COMP_G2BR
#define MNE_CTFV_COMP_NONE
#define MNE_CTFV_COMP_UNKNOWN
#define MNE_CTFV_COMP_G3BR
#define MNE_CTFV_COMP_G1BR
MNECTFCompDataSet class declaration.
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).
FIFF file I/O and data structures (raw, epochs, evoked, covariance, forward).
FiffId * fiffId
Backward-compatible pointer typedef for the old fiffId pointer.
Coordinate transformation description.
QSharedPointer< FiffDirNode > SPtr
Universally unique identifier.
FIFF sparse matrix storage backed by Eigen.
Eigen::SparseMatrix< float > & eigen()
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
int make_comp(const QList< FIFFLIB::FiffChInfo > &chs, int nch, QList< FIFFLIB::FiffChInfo > compchs, int ncomp)
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 apply(bool do_it, Eigen::Ref< Eigen::VectorXf > data, Eigen::Ref< const Eigen::VectorXf > compdata)
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)
int set_compensation(int compensate_to, QList< FIFFLIB::FiffChInfo > &chs, int nchan, QList< FIFFLIB::FiffChInfo > comp_chs, int ncomp_chan)
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.
static FiffCoordTrans readMeasTransform(const QString &name)
static FiffCoordTrans readFromTag(const std::unique_ptr< FiffTag > &tag)