/* * this function tries to be a 1:1 C++ reimplementation of the Perl function * 'read_mcstas_res' of the McStas 'mcresplot' program */ Resolution calc_res(std::vector<vector<t_real>>&& Q_vec, const vector<t_real>& Q_avg, const std::vector<t_real>* pp_vec) { vector<t_real> Q_dir = tl::make_vec({Q_avg[0], Q_avg[1], Q_avg[2]}); Q_dir = Q_dir / norm_2(Q_dir); vector<t_real> Q_perp = tl::make_vec({-Q_dir[1], Q_dir[0], Q_dir[2]}); vector<t_real> vecUp = tl::cross_3(Q_dir, Q_perp); /* * transformation from the <Q_x, Q_y, Q_z, E> system * into the <Q_avg, Q_perp, Q_z, E> system, * i.e. rotate by the (ki,Q) angle */ matrix<t_real> trafo = identity_matrix<t_real>(4); tl::set_column(trafo, 0, Q_dir); tl::set_column(trafo, 1, Q_perp); tl::set_column(trafo, 2, vecUp); tl::log_info("Transformation: ", trafo); Resolution reso; reso.Q_avg_notrafo = Q_avg; reso.Q_avg = prod(trans(trafo), Q_avg); tl::log_info("Transformed average Q vector: ", reso.Q_avg); reso.res.resize(4,4,0); reso.cov.resize(4,4,0); reso.cov = tl::covariance(Q_vec, pp_vec); reso.cov = tl::transform<matrix<t_real>>(reso.cov, trafo, true); tl::log_info("Covariance matrix: ", reso.cov); if(!(reso.bHasRes = tl::inverse(reso.cov, reso.res))) tl::log_err("Covariance matrix could not be inverted!"); if(reso.bHasRes) { reso.dQ.resize(4, 0); for(int iQ=0; iQ<4; ++iQ) reso.dQ[iQ] = tl::get_SIGMA2HWHM<t_real>()/sqrt(reso.res(iQ,iQ)); tl::log_info("Resolution matrix: ", reso.res); std::ostringstream ostrVals; ostrVals << "Gaussian HWHM values: "; std::copy(reso.dQ.begin(), reso.dQ.end(), std::ostream_iterator<t_real>(ostrVals, ", ")); std::ostringstream ostrElli; ostrElli << "Ellipsoid offsets: "; std::copy(reso.Q_avg.begin(), reso.Q_avg.end(), std::ostream_iterator<t_real>(ostrElli, ", ")); reso.vecQ = std::move(Q_vec); tl::log_info(ostrVals.str()); tl::log_info(ostrElli.str()); } return reso; }