53#define _USE_MATH_DEFINES
94#define VEC_DOT_17(x,y) ((x)[X_17]*(y)[X_17] + (x)[Y_17]*(y)[Y_17] + (x)[Z_17]*(y)[Z_17])
96#define VEC_LEN_17(x) sqrt(VEC_DOT_17(x,x))
98#define VEC_DIFF_17(from,to,diff) {\
99 (diff)[X_17] = (to)[X_17] - (from)[X_17];\
100 (diff)[Y_17] = (to)[Y_17] - (from)[Y_17];\
101 (diff)[Z_17] = (to)[Z_17] - (from)[Z_17];\
104#define VEC_COPY_17(to,from) {\
105 (to)[X_17] = (from)[X_17];\
106 (to)[Y_17] = (from)[Y_17];\
107 (to)[Z_17] = (from)[Z_17];\
110#define CROSS_PRODUCT_17(x,y,xy) {\
111 (xy)[X_17] = (x)[Y_17]*(y)[Z_17]-(y)[Y_17]*(x)[Z_17];\
112 (xy)[Y_17] = -((x)[X_17]*(y)[Z_17]-(y)[X_17]*(x)[Z_17]);\
113 (xy)[Z_17] = (x)[X_17]*(y)[Y_17]-(y)[X_17]*(x)[Y_17];\
116#define MALLOC_17(x,t) (t *)malloc((x)*sizeof(t))
118#define ALLOC_CMATRIX_17(x,y) mne_cmatrix_ds_17((x),(y))
120static void matrix_error_ds_17(
int kind,
int nr,
int nc)
123 printf(
"Failed to allocate memory pointers for a %d x %d matrix\n",nr,nc);
125 printf(
"Failed to allocate memory for a %d x %d matrix\n",nr,nc);
127 printf(
"Allocation error for a %d x %d matrix\n",nr,nc);
128 if (
sizeof(
void *) == 4) {
129 printf(
"This is probably because you seem to be using a computer with 32-bit architecture.\n");
130 printf(
"Please consider moving to a 64-bit platform.");
132 printf(
"Cannot continue. Sorry.\n");
136static float** mne_cmatrix_ds_17(
int numPoints,
int numDim)
142 if (!m) matrix_error_ds_17(1, numPoints, numDim);
144 whole =
MALLOC_17(numPoints * numDim,
float);
145 if (!whole) matrix_error_ds_17(2, numPoints, numDim);
147 for(
int i = 0; i < numPoints; ++i)
148 m[i] = &whole[ i * numDim ];
153#define FREE_17(x) if ((char *)(x) != NULL) free((char *)(x))
155#define FREE_CMATRIX_17(m) mne_free_cmatrix_ds_17((m))
157static void mne_free_cmatrix_ds_17(
float **m)
188 Eigen::Vector3f& scales)
191 using FidMatrix = Eigen::Matrix<float, 3, 3, Eigen::RowMajor>;
192 FidMatrix head_fid, mri_fid;
193 bool head_fid_found[3] = {
false,
false,
false};
194 bool mri_fid_found[3] = {
false,
false,
false};
197 float nasion_weight = 5.0;
199 for (j = 0; j < 2; j++) {
201 FidMatrix& fid = (j == 0) ? head_fid : mri_fid;
202 bool* found = (j == 0) ? head_fid_found : mri_fid_found;
204 for (k = 0; k < d.
npoint; k++) {
208 fid.row(0) = Eigen::Map<const Eigen::RowVector3f>(d.
points[k].r);
212 fid.row(1) = Eigen::Map<const Eigen::RowVector3f>(d.
points[k].r);
216 fid.row(2) = Eigen::Map<const Eigen::RowVector3f>(d.
points[k].r);
223 for (k = 0; k < 3; k++) {
224 if (!head_fid_found[k]) {
225 qCritical(
"Some of the MEG fiducials were missing");
229 if (!mri_fid_found[k]) {
230 qCritical(
"Some of the MRI fiducials were missing");
237 printf(
"xscale = %.3f yscale = %.3f zscale = %.3f\n",scales[0],scales[1],scales[2]);
239 for (j = 0; j < 3; j++)
240 for (k = 0; k < 3; k++)
241 mri_fid(j,k) = mri_fid(j,k)*scales[k];
248 mri_fid.row(0).data(),mri_fid.row(1).data(),mri_fid.row(2).data()));
254 for (k = 0; k < head_dig.
nfids(); k++)
257 printf(
"After simple alignment : \n");
264 for (k = 0; k < niter; k++) {
265 if (
iterate_alignment_once(head_dig,nasion_weight,Eigen::Vector3f(mri_fid.row(1).transpose()),k == niter-1 && niter > 1) ==
FAIL)
269 printf(
"%d / %d iterations done. RMS dist = %7.1f mm\n",k,niter,
271 printf(
"After refinement :\n");
285 const Eigen::Matrix<float, 3, 3, Eigen::RowMajor>& mri_fid,
286 Eigen::Vector3f& scales)
288 float **dig_rr = NULL;
289 float **head_rr = NULL;
291 float simplex_size = 2e-2;
292 float r0[3],Rdig,Rscalp;
293 float LR[3],LN[3],len,norm[3],diff[3];
295 scales[0] = scales[1] = scales[2] = 1.0;
301 for (k = 0, ndig = 0; k < dig.
npoint; k++) {
303 dig_rr[ndig++] = dig.
points[k].r;
311 printf(
"Polhemus : (%.1f %.1f %.1f) mm R = %.1f mm\n",1000*r0[
X_17],1000*r0[
Y_17],1000*r0[
Z_17],1000*Rdig);
314 VEC_DIFF_17(mri_fid.row(0).data(),mri_fid.row(2).data(),LR);
315 VEC_DIFF_17(mri_fid.row(0).data(),mri_fid.row(1).data(),LN);
318 norm[0] = norm[0]/len;
319 norm[1] = norm[1]/len;
320 norm[2] = norm[2]/len;
322 for (k = 0, nhead = 0; k <
np; k++) {
325 head_rr[nhead++] = &
rr(k,0);
333 printf(
"Scalp : (%.1f %.1f %.1f) mm R = %.1f mm\n",1000*r0[
X_17],1000*r0[
Y_17],1000*r0[
Z_17],1000*Rscalp);
335 scales[0] = scales[1] = scales[2] = Rdig/Rscalp;
355 d.dist_valid =
false;
357 for (k = 0; k < d.npoint; k++) {
362 if (std::fabs(d.dist(k)) > maxdist &&
369 printf(
"%d points discarded (maxdist = %6.1f mm).\n",discarded,1000*maxdist);
377 int do_all,
int do_approx)
const
384 Q_ASSERT(dig.head_mri_t);
385 const FiffCoordTrans& t = (dig.head_mri_t_adj && !dig.head_mri_t_adj->isEmpty()) ? *dig.head_mri_t_adj : *dig.head_mri_t;
393 dig.dist.conservativeResize(dig.npoint);
394 if (dig.closest.size() == 0) {
398 dig.closest = Eigen::VectorXi::Constant(dig.npoint, -1);
401 dig.closest_point.setZero(dig.npoint,3);
402 Eigen::VectorXi closest(dig.npoint);
403 Eigen::VectorXf dists(dig.npoint);
405 for (k = 0, nactive = 0; k < dig.npoint; k++) {
406 if ((dig.active[k] && !dig.discard[k]) || do_all) {
407 point = dig.points.at(k);
408 rr.row(nactive) = Eigen::Map<const Eigen::RowVector3f>(point.
r);
411 closest[nactive] = dig.closest(k);
412 if (closest[nactive] < 0)
416 closest[nactive] = -1;
426 printf(
"Inside or outside for %d points...",nactive);
427 for (k = 0, nactive = 0; k < dig.npoint; k++) {
428 if ((dig.active[k] && !dig.discard[k]) || do_all) {
429 dig.dist(k) = dists[nactive];
430 dig.closest(k) = closest[nactive];
432 Eigen::Vector3f pt = Eigen::Map<const Eigen::Vector3f>(
rr.row(nactive).data());
434 dig.closest_point.row(k) = proj.transpose();
440 if (!do_approx &&
false) {
441 Eigen::Vector3f pt = Eigen::Map<const Eigen::Vector3f>(
rr.row(nactive).data());
443 dig.dist(k) = - std::fabs(dig.dist(k));
445 dig.dist(k) = std::fabs(dig.dist(k));
454 dig.dist_valid =
true;
463 const std::optional<Eigen::Vector3f>& nasion_mri,
470 float **rr_head = NULL;
471 float **rr_mri = NULL;
476 float max_diff = 40e-3;
478 if (!dig.head_mri_t_adj) {
479 qCritical()<<
"Not adjusting the transformation";
494 for (k = 0, nactive = 0; k < dig.npoint; k++) {
495 if (dig.active[k] && !dig.discard[k]) {
496 point = dig.points.at(k);
498 VEC_COPY_17(rr_mri[nactive],dig.closest_point.row(k).data());
504 w[nactive] = nasion_weight;
508 Q_ASSERT(dig.head_mri_t || dig.head_mri_t_adj);
510 dig.head_mri_t_adj ? *dig.head_mri_t_adj : *dig.head_mri_t,
520 qCritical() <<
"Not enough points to do the alignment";
524 rr_head, rr_mri, w, nactive, max_diff)).isEmpty())
527 if (dig.head_mri_t_adj)
528 dig.head_mri_t_adj = std::make_unique<FiffCoordTrans>(t);
532 dig.dist_valid =
false;
554 for (k = 0, rms = 0.0, nactive = 0; k < dig.
npoint; k++)
556 rms = rms + dig.
dist(k)*dig.
dist(k);
560 rms = rms/(nactive-1);
573 for (k = 0; k < 3; k++) {
577 for (j = 0; j <
np; j++)
578 for (k = 0; k < 3; k++)
579 rr(j,k) =
rr(j,k)*scales[k];
587 Eigen::Vector3f mn =
rr.row(0).transpose();
588 Eigen::Vector3f mx = mn;
590 for (
int k = 1; k <
np; k++) {
591 Eigen::Vector3f r =
rr.row(k).transpose();
597 printf(
"%s:\n",tag.toUtf8().constData());
598 printf(
"\tx = %f ... %f mm\n",1000*mn[0],1000*mx[0]);
599 printf(
"\ty = %f ... %f mm\n",1000*mn[1],1000*mx[1]);
600 printf(
"\tz = %f ... %f mm\n",1000*mn[2],1000*mx[2]);
603 fov = std::max(mn.cwiseAbs().maxCoeff(), mx.cwiseAbs().maxCoeff());
614 if (name.startsWith(
"inflated") || name.startsWith(
"sphere") || name.startsWith(
"white"))
629 const int totalSize = ncolor *
np;
634 float curv_sum = 0.0f;
636 for (
int k = 0; k <
np; k++) {
637 const int base = k * ncolor;
638 curv_sum += std::fabs(
curv[k]);
640 for (
int j = 0; j < 3; j++)
647 for (
int k = 0; k <
np; k++) {
648 const int base = k * ncolor;
649 curv_sum += std::fabs(
curv[k]);
650 for (
int j = 0; j < 3; j++)
657 printf(
"Average curvature : %f\n",curv_sum/
np);
#define FIFFV_POINT_CARDINAL
#define FIFFV_POINT_NASION
FiffStream class declaration.
FiffDigitizerData class declaration.
FiffCoordTrans class declaration.
FiffDigPoint class declaration.
Sphere class declaration.
MNEMshPicked class declaration.
MNESurface class declaration.
#define VEC_COPY_17(to, from)
constexpr float NEG_CURV_COLOR
#define CROSS_PRODUCT_17(x, y, xy)
#define FREE_CMATRIX_17(m)
constexpr float POS_CURV_COLOR
#define VEC_DIFF_17(from, to, diff)
#define ALLOC_CMATRIX_17(x, y)
constexpr float EVEN_CURV_COLOR
MNEMshColorScaleDef class declaration.
MNEMshDisplaySurface class declaration.
MNEMorphMap class declaration.
#define SHOW_CURVATURE_NONE
#define SHOW_CURVATURE_OVERLAY
#define SHOW_OVERLAY_HEAT
Core MNE data structures (source spaces, source estimates, hemispheres).
FIFF file I/O and data structures (raw, epochs, evoked, covariance, forward).
Coordinate transformation description.
static FiffCoordTrans fromCardinalPoints(int from, int to, const float *rL, const float *rN, const float *rR)
Digitization point description.
Digitization points container and description.
QList< FIFFLIB::FiffDigPoint > points
std::unique_ptr< FiffCoordTrans > head_mri_t_adj
QList< FIFFLIB::FiffDigPoint > mri_fids
void pickCardinalFiducials()
void get_head_scale(FIFFLIB::FiffDigitizerData &dig, const Eigen::Matrix< float, 3, 3, Eigen::RowMajor > &mri_fid, Eigen::Vector3f &scales)
float rms_digitizer_distance(FIFFLIB::FiffDigitizerData &dig) const
void decide_surface_extent(const QString &tag)
void calculate_digitizer_distances(FIFFLIB::FiffDigitizerData &dig, int do_all, int do_approx) const
mneUserFreeFunc user_data_free
void scale(const Eigen::Vector3f &scales)
int align_fiducials(FIFFLIB::FiffDigitizerData &head_dig, const FIFFLIB::FiffDigitizerData &mri_dig, int niter, int scale_head, float omit_dist, Eigen::Vector3f &scales)
void setup_curvature_colors()
Eigen::VectorXf vertex_colors
int discard_outlier_digitizer_points(FIFFLIB::FiffDigitizerData &d, float maxdist) const
int iterate_alignment_once(FIFFLIB::FiffDigitizerData &dig, int nasion_weight, const std::optional< Eigen::Vector3f > &nasion_mri, int last_step) const
void decide_curv_display(const QString &name)
double sum_solids(const Eigen::Vector3f &from) const
void find_closest_on_surface_approx(const PointsT &r, int np, Eigen::VectorXi &nearest_tri, Eigen::VectorXf &dist, int nstep) const
Eigen::Vector3f project_to_triangle(int tri, float p, float q) const
Eigen::Matrix< float, Eigen::Dynamic, 3, Eigen::RowMajor > PointsT
static bool fit_sphere_to_points(const Eigen::MatrixXf &rr, float simplex_size, Eigen::VectorXf &r0, float &R)
static FiffCoordTrans procrustesAlign(int from_frame, int to_frame, float **fromp, float **top, float *w, int np, float max_diff)
Eigen::MatrixX3f apply_inverse_trans(const Eigen::MatrixX3f &rr, bool do_move=true) const
Eigen::MatrixX3f apply_trans(const Eigen::MatrixX3f &rr, bool do_move=true) const