/* * @brief Create new vector * and copy the data into the new vector. If the target * is bigger, the remaining space is set 0. If it is * smaller data is truncted. * * @param M The matrix to resize * @param sz New length * @return Resized vector */ template <class T> inline static Matrix<T> resize (const Matrix<T>& M, const size_t& s0, const size_t& s1, const size_t& s2, const size_t& s3, const size_t& s4) { assert (numel(M)==s0*s1*s2*s3*s4); Matrix<T> res (s0,s1,s2,s3,s4); res.Container() = M.Container(); return res; }
/** * @brief FLip up down * * @param M Matrix * @return Flipped matrix */ template <class T> inline static Matrix<T> flipud (const Matrix<T>& M) { size_t scol = size(M,0), ncol = numel(M)/scol; Matrix<T> res = M; if (scol == 1) // trivial return res; typedef typename Vector<T>::iterator VI; for (VI i = res.Container().begin(); i < res.Container().end(); i += scol) std::reverse(i, i+scol); return res; }
/** * @brief Elementwise multiplication with scalar (lhs) * * @param s Scalar lhs * @param m Matrix rhs * @return m * s */ inline friend Matrix<T,P> operator/ (const T s, const Matrix<T,P> &m) { Matrix<T,P> res = m; #ifdef USE_VALARRAY res.Container() = s / res.Container(); #else #ifdef EW_OMP #pragma omp parallel for #endif for (size_t i = 0; i < m.Size(); ++i) res[i] = s / res[i]; #endif return res; }
/** * @brief FFT shift * * @param m TO be shifted * @return Shifted */ template <class T> inline Matrix<T> fftshift (const Matrix<T>& m, const bool& fw = true) { assert (isvec(m) || is2d(m) || is3d(m)); Matrix<size_t> tmp = resize(size(m),ndims(m),1); for (size_t i = 0; i<ndims(m); i++) if (tmp[i] == 0) tmp[i] = 1; container<size_t> d = tmp.Container(); // data side lengths container<size_t> c = floor(tmp/2).Container(); // center coords Matrix<T> res (vsize(m)); size_t oi[3]; size_t si[3]; for (oi[0] = 0; oi[0] < d[0]; oi[0]++) { si[0] = (oi[0] + c[0]) % d[0]; for (oi[1] = 0; oi[1] < d[1]; oi[1]++) { si[1] = (oi[1] + c[1]) % d[1]; for (oi[2] = 0; oi[2] < d[2]; oi[2]++) { si[2] = (oi[2] + c[2]) % d[2]; if (fw) res(si[0],si[1],si[2]) = m(oi[0],oi[1],oi[2]); else res(oi[0],oi[1],oi[2]) = m(si[0],si[1],si[2]); } } } return res; }
/** * @brief Construct FFTW plans for forward and backward FT with credentials * * @param sl Matrix of side length of the FT range * @param mask K-Space mask (if left empty no mask is applied) * @param pc Phase correction (or target phase) * @param b0 Field distortion */ explicit DFT (const Matrix<size_t>& sl, const Matrix<T>& mask = Matrix<T>(1), const Matrix<CT>& pc = Matrix<CT>(1), const Matrix<T>& b0 = Matrix<T>(1)) : m_N(1), m_have_mask (false), m_have_pc (false) { size_t rank = numel(sl); container<int> n (rank); if (numel(mask) > 1) { m_have_mask = true; m_mask = mask; } if (numel(pc) > 1) { m_have_pc = true; m_pc = pc; m_cpc = conj(pc); } for (int i = 0; i < rank; i++) n[i] = (int) sl [rank-1-i]; m_N = std::accumulate(n.begin(), n.end(), 1, std::multiplies<int>()); Matrix<size_t> tmp = resize(sl,3,1); for (size_t i = 0; i < 3; ++i) tmp[i] = (tmp[i] > 0) ? tmp[i] : 1; d = tmp.Container(); // data side lengths c = (floor(tmp/2)).Container(); // center coords Allocate (rank, &n[0]); m_initialised = true; }
/** * @brief Construct NFFT plans for forward and backward FT with credentials * * @param imsize Matrix of side length of the image space * @param nk # k-space points * @param m Spatial cut-off of FT * @param alpha Oversampling factor * @param b0 Off-resonance maps if available * @param pc Phase correction applied before forward or after adjoint transforms (default: empty) * @param eps Convergence criterium for inverse transform (default: 1.0e-7) * @param maxit Maximum # NFFT iterations (default: 3) */ NFFT (const Matrix<size_t>& imsize, const size_t& nk, const size_t m = 1, const T alpha = 1.0, const Matrix<T> b0 = Matrix<T>(1), const Matrix< std::complex<T> > pc = Matrix< std::complex<T> >(1), const T eps = 7.0e-4, const size_t maxit = 1) : m_prepared (false) { m_M = nk; m_imgsz = 1; m_m = m; m_N = imsize.Container(); m_n = m_N;//ceil (alpha*m_N); m_rank = numel(imsize); m_imgsz = prod(m_N); m_epsilon = eps; m_maxit = maxit; NFFTTraits<double>::Init (m_N, m_M, m_n, m_m, m_fplan, m_iplan); m_y = m_iplan.y; m_f = m_iplan.f_hat_iter; if (pc.Size() > 1) m_have_pc = true; m_pc = pc; m_cpc = conj(pc); m_initialised = true; }
/** * @brief Uniformly random matrix * * @param sz Size vector * @return Rand matrix * */ template <class T> inline static Matrix<T> randn (const Matrix<size_t>& sz) { Matrix<T> res (sz.Container()); Random<T>::Normal(res); return res; }
/** * @brief Which elements are Inf * * @param M Matrix * @return Matrix of booleans true where inf */ template <class T> inline static Matrix<cbool> isnan (const Matrix<T>& M) { Matrix<cbool> res (M.Dim()); for (size_t i = 0; i < res.Size(); ++i) res.Container()[i] = (is_nan(TypeTraits<T>::Imag(M[i]))||is_nan(TypeTraits<T>::Imag(M[i]))); return res; }
template <class T> Matrix<T> Read (const std::string& uri = "") const { int dt; size_t ns, n; std::vector<size_t> dim; std::vector<float> res; char* name; Matrix<T> M; T t; // Read type if (!mread (&dt, 1, m_file, "data type")) return M; // Matrix and data type must fit as of now. if (CODTraits<T>::dt == dt) { if (!mread (&n, 1, m_file, "dimensions")) return M; dim = std::vector<size_t>(n,1); res = std::vector<float>(n,1.0); // Read dimensions and allocate matrix if (!mread (dim, m_file, "dimensions")) return M; //Read resolutions and assign if (!mread (res, m_file, "resolutions")) return M; M = Matrix<T>(dim,res); n = numel(M); // Name if (!mread (&n, 1, m_file, "name length")) return M; name = new char [n+1]; if (!mread (name, n, m_file, "name")) return M; name[n] = '\0'; M.SetClassName(name); // Read data if (!mread (M.Container(), m_file, "data")) return M; //Close and clean up; delete name; } return M; }
template <class T> bool Write (const Matrix<T>& M, const std::string& uri = "") { assert (m_file != NULL); dtype dt = CODTraits<T>::dt; size_t n, l; // Dump type if (!mwrite(&dt, 1, m_file, "data type")) return false; n = M.NDim(); if (!mwrite(&n, 1, m_file, "data dimensions")) return false; // Dump dimensions if (!mwrite(M.Dim(), m_file, "dimensions")) return false; // Dump resolutions if (!mwrite(M.Res(), m_file, "resolutions")) return false; // Size of name and name n = uri.size(); if (!mwrite(&n, 1, m_file, "name length")) return false; // Dump name if (!mwrite(uri.c_str(), n, m_file, "name")) return false; // Dump data if (!mwrite(M.Container(), m_file, "data")) return false; if (!mwrite(delim.c_str(), delim.length(), m_file, "delimiter")) return false; return true; }
/** * @brief Construct FFTW plans for forward and backward FT with credentials for FT with identical side lengths * * @param rank Rank (i.e. # FT directions) * @param sl Side length of the slice, volume ... * @param mask K-Space mask (if left empty no mask is applied) * @param pc Phase correction (or target phase) * @param b0 Static field distortion */ DFT (const size_t rank, const size_t sl, const Matrix<T>& mask = Matrix<T>(), const Matrix<CT>& pc = Matrix<CT>(), const Matrix<T>& b0 = Matrix<T>()) : m_have_mask (false), m_have_pc (false) { std::vector<int> n (rank); size_t i; if (numel(mask) > 1) { m_have_mask = true; m_mask = mask; } if (pc.Size() > 1) { m_have_pc = true; m_pc = pc; m_cpc = conj(pc); } for (i = 0; i < rank; i++) { n[i] = sl; m_N *= n[i]; } Matrix<size_t> tmp (3,1); for (i = 0; i < rank; ++i) tmp[i] = sl; for ( ; i < 3; ++i) tmp[i] = 1; d = tmp.Container(); // data side lengths c = (floor(tmp/2)).Container(); // center coords Allocate (rank, &n[0]); m_initialised = true; }
/** * @brief Create new vector * and copy the data into the new vector. If the target * is bigger, the remaining space is set 0. If it is * smaller data is truncted. * * @param M The matrix to resize * @param sc New height * @param sl New width * @return Resized vector */ template <class T> inline static Matrix<T> resize (const Matrix<T>& M, size_t sc, size_t sl) { assert(sl*sc==numel(M)); Matrix<T> ret(sc,sl); ret.Container() = M.Container(); return ret; }
/** * @brief Zero matrix * * @param sz Size vector * @return Zero matrix * */ template <class T> inline static Matrix<T> zeros (const Matrix<size_t>& sz) { return Matrix<T> (sz.Container()); }