void apply_unmix_coeff_aliased_image(const hoNDArray<T>& aliasedIm, const hoNDArray<T>& unmixCoeff, hoNDArray<T>& complexIm)
{
    try
    {
        GADGET_CHECK_THROW(aliasedIm.get_size(0) == unmixCoeff.get_size(0));
        GADGET_CHECK_THROW(aliasedIm.get_size(1) == unmixCoeff.get_size(1));
        GADGET_CHECK_THROW(aliasedIm.get_size(2) == unmixCoeff.get_size(2));

        std::vector<size_t> dim;
        aliasedIm.get_dimensions(dim);
        dim[2] = 1;

        if (!complexIm.dimensions_equal(&dim))
        {
            complexIm.create(&dim);
        }

        hoNDArray<T> buffer2DT(aliasedIm);

        Gadgetron::multiply(aliasedIm, unmixCoeff, buffer2DT);
        Gadgetron::sum_over_dimension(buffer2DT, complexIm, 2);
    }
    catch (...)
    {
        GADGET_THROW("Errors in apply_unmix_coeff_aliased_image(const hoNDArray<T>& aliasedIm, const hoNDArray<T>& unmixCoeff, hoNDArray<T>& complexIm) ... ");
    }
}
void apply_unmix_coeff_kspace(const hoNDArray<T>& kspace, const hoNDArray<T>& unmixCoeff, hoNDArray<T>& complexIm)
{
    try
    {
        GADGET_CHECK_THROW(kspace.get_size(0) == unmixCoeff.get_size(0));
        GADGET_CHECK_THROW(kspace.get_size(1) == unmixCoeff.get_size(1));
        GADGET_CHECK_THROW(kspace.get_size(2) == unmixCoeff.get_size(2));

        hoNDArray<T> buffer2DT(kspace);
        GADGET_CATCH_THROW(Gadgetron::hoNDFFT<typename realType<T>::Type>::instance()->ifft2c(kspace, buffer2DT));

        std::vector<size_t> dim;
        kspace.get_dimensions(dim);
        dim[2] = 1;

        if (!complexIm.dimensions_equal(&dim))
        {
            complexIm.create(&dim);
        }

        Gadgetron::multiply(buffer2DT, unmixCoeff, buffer2DT);
        Gadgetron::sum_over_dimension(buffer2DT, complexIm, 2);
    }
    catch (...)
    {
        GADGET_THROW("Errors in apply_unmix_coeff_kspace(const hoNDArray<T>& kspace, const hoNDArray<T>& unmixCoeff, hoNDArray<T>& complexIm) ... ");
    }
}
Ejemplo n.º 3
0
void outputPlotIm(const hoNDArray<unsigned char>& im, bool trueColor, hoNDArray<float>& plotIm)
{
    size_t xsize = im.get_size(1);
    size_t ysize = im.get_size(2);

    plotIm.copyFrom(im);

    if (trueColor)
    {
        std::vector<size_t> dim_order(3);
        dim_order[0] = 1;
        dim_order[1] = 2;
        dim_order[2] = 0;

        hoNDArray<float> plotImPermuted;
        plotImPermuted.copyFrom(plotIm);

        plotIm.create(xsize, ysize, 3);

        Gadgetron::permute(plotImPermuted, plotIm, dim_order);
    }
    else
    {
        hoNDArray<float> plotIm2D;
        Gadgetron::sum_over_dimension(plotIm, plotIm2D, 0);

        plotIm2D.squeeze();

        std::vector<size_t> dim_order(2);
        dim_order[0] = 0;
        dim_order[1] = 1;

        plotIm.create(xsize, ysize);
        Gadgetron::permute(plotIm2D, plotIm, dim_order);
    }
}
    void GenericReconCartesianGrappaGadget::prepare_down_stream_coil_compression_ref_data(
            const hoNDArray<std::complex<float> > &ref_src, hoNDArray<std::complex<float> > &ref_coil_map,
            hoNDArray<std::complex<float> > &ref_dst, size_t e) {

        if (!downstream_coil_compression.value()) {
            GDEBUG_CONDITION_STREAM(verbose.value(), "Downstream coil compression is not prescribed ... ");
            ref_dst = ref_src;
            return;
        }

        if (downstream_coil_compression_thres.value() < 0 && downstream_coil_compression_num_modesKept.value() == 0) {
            GDEBUG_CONDITION_STREAM(verbose.value(),
                                    "Downstream coil compression is prescribed to use all input channels ... ");
            ref_dst = ref_src;
            return;
        }

        // determine how many channels to use
        size_t RO = ref_src.get_size(0);
        size_t E1 = ref_src.get_size(1);
        size_t E2 = ref_src.get_size(2);
        size_t CHA = ref_src.get_size(3);
        size_t N = ref_src.get_size(4);
        size_t S = ref_src.get_size(5);
        size_t SLC = ref_src.get_size(6);

        size_t recon_RO = ref_coil_map.get_size(0);
        size_t recon_E1 = ref_coil_map.get_size(1);
        size_t recon_E2 = ref_coil_map.get_size(2);

        std::complex<float> *pRef = const_cast< std::complex<float> * >(ref_src.begin());

        size_t dstCHA = CHA;
        if (downstream_coil_compression_num_modesKept.value() > 0 &&
            downstream_coil_compression_num_modesKept.value() <= CHA) {
            dstCHA = downstream_coil_compression_num_modesKept.value();
        } else {
            std::vector<float> E(CHA, 0);
            long long cha;

#pragma omp parallel default(none) private(cha) shared(RO, E1, E2, CHA, pRef, E)
            {
                hoNDArray<std::complex<float> > dataCha;
#pragma omp for
                for (cha = 0; cha < (long long) CHA; cha++) {
                    dataCha.create(RO, E1, E2, pRef + cha * RO * E1 * E2);
                    float v = Gadgetron::nrm2(dataCha);
                    E[cha] = v * v;
                }
            }

            for (cha = 1; cha < (long long) CHA; cha++) {
                if (std::abs(E[cha]) < downstream_coil_compression_thres.value() * std::abs(E[0])) {
                    break;
                }
            }

            dstCHA = cha;
        }

        GDEBUG_CONDITION_STREAM(verbose.value(),
                                "Downstream coil compression is prescribed to use " << dstCHA << " out of " << CHA
                                                                                    << " channels ...");

        if (dstCHA < CHA) {
            ref_dst.create(RO, E1, E2, dstCHA, N, S, SLC);
            hoNDArray<std::complex<float> > ref_coil_map_dst;
            ref_coil_map_dst.create(recon_RO, recon_E1, recon_E2, dstCHA, N, S, SLC);

            size_t slc, s, n;
            for (slc = 0; slc < SLC; slc++) {
                for (s = 0; s < S; s++) {
                    for (n = 0; n < N; n++) {
                        std::complex<float> *pDst = &(ref_dst(0, 0, 0, 0, n, s, slc));
                        const std::complex<float> *pSrc = &(ref_src(0, 0, 0, 0, n, s, slc));
                        memcpy(pDst, pSrc, sizeof(std::complex<float>) * RO * E1 * E2 * dstCHA);

                        pDst = &(ref_coil_map_dst(0, 0, 0, 0, n, s, slc));
                        pSrc = &(ref_coil_map(0, 0, 0, 0, n, s, slc));
                        memcpy(pDst, pSrc, sizeof(std::complex<float>) * recon_RO * recon_E1 * recon_E2 * dstCHA);
                    }
                }
            }

            ref_coil_map = ref_coil_map_dst;
        } else {
            ref_dst = ref_src;
        }

    }
void grappa2d_calib(const hoNDArray<T>& acsSrc, const hoNDArray<T>& acsDst, double thres, size_t kRO, const std::vector<int>& kE1, const std::vector<int>& oE1, size_t startRO, size_t endRO, size_t startE1, size_t endE1, hoNDArray<T>& ker)
{
    try
    {
        GADGET_CHECK_THROW(acsSrc.get_size(0)==acsDst.get_size(0));
        GADGET_CHECK_THROW(acsSrc.get_size(1)==acsDst.get_size(1));
        GADGET_CHECK_THROW(acsSrc.get_size(2)>=acsDst.get_size(2));

        size_t RO = acsSrc.get_size(0);
        size_t E1 = acsSrc.get_size(1);
        size_t srcCHA = acsSrc.get_size(2);
        size_t dstCHA = acsDst.get_size(2);

        const T* pSrc = acsSrc.begin();
        const T* pDst = acsDst.begin();

        long long kROhalf = kRO/2;
        if ( 2*kROhalf == kRO )
        {
            GWARN_STREAM("grappa<T>::calib(...) - 2*kROhalf == kRO " << kRO);
        }
        kRO = 2*kROhalf + 1;

        size_t kNE1 = kE1.size();
        size_t oNE1 = oE1.size();

        /// allocate kernel
        ker.create(kRO, kNE1, srcCHA, dstCHA, oNE1);

        /// loop over the calibration region and assemble the equation
        /// Ax = b

        size_t sRO = startRO + kROhalf;
        size_t eRO = endRO - kROhalf;
        size_t sE1 = std::abs(kE1[0]) + startE1;
        size_t eE1 = endE1 - kE1[kNE1-1];

        size_t lenRO = eRO - sRO + 1;

        size_t rowA = (eE1-sE1+1)*lenRO;
        size_t colA = kRO*kNE1*srcCHA;
        size_t colB = dstCHA*oNE1;

        hoMatrix<T> A;
        hoMatrix<T> B;
        hoMatrix<T> x( colA, colB );

        hoNDArray<T> A_mem(rowA, colA);
        A.createMatrix( rowA, colA, A_mem.begin() );
        T* pA = A.begin();

        hoNDArray<T> B_mem(rowA, colB);
        B.createMatrix( A.rows(), colB, B_mem.begin() );
        T* pB = B.begin();

        long long e1;
        for ( e1=(long long)sE1; e1<=(long long)eE1; e1++ )
        {
            for ( long long ro=sRO; ro<=(long long)eRO; ro++ )
            {
                long long rInd = (e1-sE1)*lenRO+ro-kROhalf;

                size_t src, dst, ke1, oe1;
                long long kro;

                /// fill matrix A
                size_t col = 0;
                size_t offset = 0;
                for ( src=0; src<srcCHA; src++ )
                {
                    for ( ke1=0; ke1<kNE1; ke1++ )
                    {
                        offset = src*RO*E1 + (e1+kE1[ke1])*RO;
                        for ( kro=-kROhalf; kro<=kROhalf; kro++ )
                        {
                            /// A(rInd, col++) = acsSrc(ro+kro, e1+kE1[ke1], src);
                            pA[rInd + col*rowA] = pSrc[ro+kro+offset];
                            col++;
                        }
                    }
                }

                /// fill matrix B
                col = 0;
                for ( oe1=0; oe1<oNE1; oe1++ )
                {
                    for ( dst=0; dst<dstCHA; dst++ )
                    {
                        B(rInd, col++) = acsDst(ro, e1+oE1[oe1], dst);
                    }
                }
            }
        }

        SolveLinearSystem_Tikhonov(A, B, x, thres);
        memcpy(ker.begin(), x.begin(), ker.get_number_of_bytes());
    }
    catch(...)
    {
        GADGET_THROW("Errors in grappa2d_calib(...) ... ");
    }

    return;
}
void grappa2d_unmixing_coeff(const hoNDArray<T>& kerIm, const hoNDArray<T>& coilMap, size_t acceFactorE1, hoNDArray<T>& unmixCoeff, hoNDArray< typename realType<T>::Type >& gFactor)
{
    try
    {
        typedef typename realType<T>::Type value_type;

        size_t RO = kerIm.get_size(0);
        size_t E1 = kerIm.get_size(1);
        size_t srcCHA = kerIm.get_size(2);
        size_t dstCHA = kerIm.get_size(3);

        GADGET_CHECK_THROW(acceFactorE1 >= 1);

        GADGET_CHECK_THROW(coilMap.get_size(0) == RO);
        GADGET_CHECK_THROW(coilMap.get_size(1) == E1);
        GADGET_CHECK_THROW(coilMap.get_size(2) == dstCHA);

        std::vector<size_t> dimUnmixing(3);
        dimUnmixing[0] = RO; dimUnmixing[1] = E1; dimUnmixing[2] = srcCHA;
        if (!unmixCoeff.dimensions_equal(&dimUnmixing))
        {
            unmixCoeff.create(RO, E1, srcCHA);
        }
        Gadgetron::clear(&unmixCoeff);

        std::vector<size_t> dimGFactor(2);
        dimGFactor[0] = RO; dimGFactor[1] = E1;
        if (!gFactor.dimensions_equal(&dimGFactor))
        {
            gFactor.create(RO, E1);
        }
        Gadgetron::clear(&gFactor);

        int src;

        T* pKerIm = const_cast<T*>(kerIm.begin());
        T* pCoilMap = const_cast<T*>(coilMap.begin());
        T* pCoeff = unmixCoeff.begin();

        std::vector<size_t> dim(2);
        dim[0] = RO;
        dim[1] = E1;

#pragma omp parallel default(none) private(src) shared(RO, E1, srcCHA, dstCHA, pKerIm, pCoilMap, pCoeff, dim)
        {
            hoNDArray<T> coeff2D, coeffTmp(&dim);
            hoNDArray<T> coilMap2D;
            hoNDArray<T> kerIm2D;

#pragma omp for
            for (src = 0; src<(int)srcCHA; src++)
            {
                coeff2D.create(&dim, pCoeff + src*RO*E1);

                for (size_t dst = 0; dst<dstCHA; dst++)
                {
                    kerIm2D.create(&dim, pKerIm + src*RO*E1 + dst*RO*E1*srcCHA);
                    coilMap2D.create(&dim, pCoilMap + dst*RO*E1);
                    Gadgetron::multiplyConj(kerIm2D, coilMap2D, coeffTmp);
                    Gadgetron::add(coeff2D, coeffTmp, coeff2D);
                }
            }
        }

        hoNDArray<T> conjUnmixCoeff(unmixCoeff);
        Gadgetron::multiplyConj(unmixCoeff, conjUnmixCoeff, conjUnmixCoeff);
        // Gadgetron::sumOverLastDimension(conjUnmixCoeff, gFactor);

        hoNDArray<T> gFactorBuf(RO, E1, 1);
        Gadgetron::sum_over_dimension(conjUnmixCoeff, gFactorBuf, 2);
        Gadgetron::sqrt(gFactorBuf, gFactorBuf);
        Gadgetron::scal((value_type)(1.0 / acceFactorE1), gFactorBuf);

        Gadgetron::complex_to_real(gFactorBuf, gFactor);
    }
    catch (...)
    {
        GADGET_THROW("Errors in grappa2d_unmixing_coeff(const hoNDArray<T>& kerIm, const hoNDArray<T>& coilMap, hoNDArray<T>& unmixCoeff, hoNDArray<T>& gFactor) ... ");
    }
}
void grappa2d_convert_to_convolution_kernel(const hoNDArray<T>& ker, size_t kRO, const std::vector<int>& kE1, const std::vector<int>& oE1, hoNDArray<T>& convKer)
{
    try
    {
        long long srcCHA = (long long)(ker.get_size(2));
        long long dstCHA = (long long)(ker.get_size(3));
        long long kNE1 = (long long)(kE1.size());
        long long oNE1 = (long long)(oE1.size());

        long long kROhalf = kRO / 2;
        if (2 * kROhalf == kRO)
        {
            GWARN_STREAM("grappa2d_convert_to_convolution_kernel - 2*kROhalf == kRO " << kRO);
        }
        kRO = 2 * kROhalf + 1;

        //// fill the convolution kernels
        long long convKRO = 2 * kRO + 3;

        long long maxKE1 = std::abs(kE1[0]);
        if (std::abs(kE1[kNE1 - 1]) > maxKE1)
        {
            maxKE1 = std::abs(kE1[kNE1 - 1]);
        }
        long long convKE1 = 2 * maxKE1 + 1;

        //// allocate the convolution kernel
        convKer.create(convKRO, convKE1, srcCHA, dstCHA);
        Gadgetron::clear(&convKer);

        //// index
        long long oe1, kro, ke1, src, dst;

        //// fill the convolution kernel and sum up multiple kernels
        for (oe1 = 0; oe1<oNE1; oe1++)
        {
            for (ke1 = 0; ke1<kNE1; ke1++)
            {
                for (kro = -kROhalf; kro <= kROhalf; kro++)
                {
                    for (dst = 0; dst<dstCHA; dst++)
                    {
                        for (src = 0; src<srcCHA; src++)
                        {
                            convKer(-kro + kRO + 1, oE1[oe1] - kE1[ke1] + maxKE1, src, dst) = ker(kro + kROhalf, ke1, src, dst, oe1);
                        }
                    }

                }
            }
        }

        if (oE1[0] != 0)
        {
            for (dst = 0; dst<dstCHA; dst++)
            {
                convKer(kRO + 1, maxKE1, dst, dst) = 1.0;
            }
        }
    }
    catch (...)
    {
        GADGET_THROW("Errors in grappa2d_convert_to_convolution_kernel(...) ... ");
    }

    return;
}
Ejemplo n.º 8
0
    void detect_heart_beat_with_time_stamp(hoNDArray<float>& cpt_time_stamp, hoNDArray<int>& ind_hb, 
                                        std::vector<size_t>& start_e1_hb, std::vector<size_t>& end_e1_hb, 
                                        std::vector<size_t>& start_n_hb, std::vector<size_t>& end_n_hb )
    {
        try
        {
            size_t E1 = cpt_time_stamp.get_size(0);
            size_t N = cpt_time_stamp.get_size(1);

            size_t e1, n, ind, ii;

            size_t num_acq_read_outs = 0;
            for ( n=0; n<N; n++ )
            {
                for ( e1=0; e1<E1; e1++ )
                {
                    if ( cpt_time_stamp(e1, n) >= 0 )
                    {
                        num_acq_read_outs++;
                    }
                }
            }

            ind_hb.create(E1, N);
            Gadgetron::clear(ind_hb);

            // --------------------------------------------------------
            // cpt time stamps
            // --------------------------------------------------------

            std::vector<float> acquired_cpt(num_acq_read_outs);
            std::vector<size_t> ind_acquired_cpt(num_acq_read_outs);

            ind = 0;
            for ( n=0; n<N; n++ )
            {
                for ( e1=0; e1<E1; e1++ )
                {
                    if ( cpt_time_stamp(e1, n) > -1 )
                    {
                        acquired_cpt[ind] = cpt_time_stamp(e1, n);
                        ind_acquired_cpt[ind] = e1 + n*E1;
                        ind++;
                    }
                }
            }

            // --------------------------------------------------------
            // find the number of heart beats
            // --------------------------------------------------------
            size_t numOfHB = 0;

            // store the line indexes for every heart beat
            std::vector<size_t> ind_HB_start, ind_HB_end;
            ind_HB_start.push_back(0);

            for ( ind=1; ind<num_acq_read_outs; ind++ )
            {
                if ( acquired_cpt[ind] < acquired_cpt[ind-1] )
                {
                    // find a new heart beat
                    numOfHB++;

                    size_t end_ind_prev_HB = ind_acquired_cpt[ind-1];
                    size_t start_ind_curr_HB = ind_acquired_cpt[ind];

                    // if there is a gap between end and start ind, fill the gap
                    if ( end_ind_prev_HB+1 != start_ind_curr_HB )
                    {
                        long long gap = start_ind_curr_HB - end_ind_prev_HB - 1;
                        if ( gap % 2 == 0 )
                        {
                            end_ind_prev_HB += gap;
                        }
                        else
                        {
                            end_ind_prev_HB += gap;
                        }

                        if ( end_ind_prev_HB+1 != start_ind_curr_HB )
                        {
                            GWARN_STREAM("end_ind_prev_HB+1 ~= start_ind_curr_HB : " << end_ind_prev_HB << " " << start_ind_curr_HB);
                        }
                    }

                    ind_HB_end.push_back( end_ind_prev_HB );
                    ind_HB_start.push_back( start_ind_curr_HB );
                }
            }

            ind_HB_end.push_back( E1*N-1 );
            numOfHB = ind_HB_end.size();

            // --------------------------------------------------------
            // fill the start and end indexes
            // --------------------------------------------------------
            start_e1_hb.resize(numOfHB, 0);
            end_e1_hb.resize(numOfHB, 0);

            start_n_hb.resize(numOfHB, 0);
            end_n_hb.resize(numOfHB, 0);

            std::vector<size_t> start, end;
            for ( ii=0; ii<numOfHB; ii++ )
            {
                start_n_hb[ii] = ind_HB_start[ii] / E1;
                start_e1_hb[ii] = ind_HB_start[ii] - start_n_hb[ii] * E1;

                end_n_hb[ii] = ind_HB_end[ii] / E1;
                end_e1_hb[ii] = ind_HB_end[ii] - end_n_hb[ii]*E1;

                for (ind=ind_HB_start[ii]; ind<=ind_HB_end[ii]; ind++)
                {
                    ind_hb(ind) = ii;
                }
            }
        }
        catch(...)
        {
            GADGET_THROW("Exceptions happened in detect_heart_beat_with_time_stamp(...) ... ");
        }
    }
Ejemplo n.º 9
0
// C = A*B
bool GeneralMatrixProduct(hoNDArray<float>& C, const hoNDArray<float>& A, bool transA, const hoNDArray<float>& B, bool transB)
{
    try
    {
        typedef float T;

        size_t M = A.get_size(0);
        size_t K = A.get_size(1);
        if ( transA )
        { 
            M = A.get_size(1);
            K = A.get_size(0);
        }

        size_t K2 = B.get_size(0);
        size_t N = B.get_size(1);
        if ( transB )
        {
            K2 = B.get_size(1);
            N = B.get_size(0);
        }

        GADGET_CHECK_RETURN_FALSE(K==K2);
        if ( (C.get_size(0)!=M) || (C.get_size(1)!=N) )
        {
            C.create(M, N);
        }

        const T* pA = A.begin();
        const T* pB = B.begin();
        T* pC = C.begin();

        size_t m, n, k;

        if ( !transA && !transB )
        {
            for ( m=0; m<M; m++ )
            {
                for ( n=0; n<N; n++ )
                {
                    pC[m+n*M] = 0;
                    for ( k=0; k<K; k++ )
                    {
                        pC[m+n*M] += pA[m+k*M]*pB[k+n*K];
                    }
                }
            }
        }

        if ( transA && !transB )
        {
            for ( m=0; m<M; m++ )
            {
                for ( n=0; n<N; n++ )
                {
                    pC[m+n*M] = 0;
                    for ( k=0; k<K; k++ )
                    {
                        pC[m+n*M] += pA[k+m*K]*pB[k+n*K];
                    }
                }
            }
        }

        if ( !transA && transB )
        {
            for ( m=0; m<M; m++ )
            {
                for ( n=0; n<N; n++ )
                {
                    pC[m+n*M] = 0;
                    for ( k=0; k<K; k++ )
                    {
                        pC[m+n*M] += pA[m+k*M]*pB[n+k*K];
                    }
                }
            }
        }

        if ( transA && transB )
        {
            for ( m=0; m<M; m++ )
            {
                for ( n=0; n<N; n++ )
                {
                    pC[m+n*M] = 0;
                    for ( k=0; k<K; k++ )
                    {
                        pC[m+n*M] += pA[k+m*K]*pB[n+k*K];
                    }
                }
            }
        }
    }
    catch(...)
    {
        GERROR_STREAM("Errors in GeneralMatrixProduct(hoNDArray<float>& C, const hoNDArray<float>& A, bool transA, const hoNDArray<float>& B, bool transB) ...");
        return false;
    }
    return true;
}