void maxAbsolute(const hoNDArray<T>& x, T& r, size_t& ind)
    {
        size_t N = x.get_number_of_elements();
        const T* pX = x.begin();

        ind = 0;
        if ( N == 0 ) return;

        long long n;

        typename realType<T>::Type v = abs(pX[0]);
        typename realType<T>::Type v2;

        ind = 0;
        for ( n=1; n<(long long)N; n++ )
        {
            v2 = std::abs(pX[n]);
            if ( v2 > v )
            {
                v = v2;
                ind = n;
            }
        }

        r = pX[ind];
    }
Ejemplo n.º 2
0
    void correct_time_stamp_with_fitting(hoNDArray<float>& time_stamp, size_t startE1, size_t endE1)
    {
        try
        {
            size_t E1 = time_stamp.get_size(0);
            size_t N = time_stamp.get_size(1);
            size_t rE1 = endE1 - startE1 + 1;

            size_t e1, n;

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

            GDEBUG_STREAM(" Number of acquired lines : " << num_acq_read_outs);

            float a, b; // y = a + b*x
            {
                std::vector<float> x(num_acq_read_outs), y(num_acq_read_outs);

                size_t ind = 0;
                for ( n=0; n<N; n++ )
                {
                    for ( e1=startE1; e1<=endE1; e1++ )
                    {
                        float acq_time = time_stamp(e1, n);
                        if ( acq_time > 0 )
                        {
                            x[ind] = (float)(e1-startE1 + n*rE1);
                            y[ind] = acq_time;
                            ind++;
                        }
                    }
                }

                Gadgetron::simple_line_fit(x, y, a, b);
            }

            for ( n=0; n<N; n++ )
            {
                for ( e1=startE1; e1<=endE1; e1++ )
                {
                    float x_v = (float)(e1-startE1 + n*rE1);
                    time_stamp(e1, n) = a + b*x_v;
                }
            }
        }
        catch(...)
        {
            GADGET_THROW("Exceptions happened in correct_time_stamp_with_fitting(...) ... ");
        }
    }
void grappa2d_calib_convolution_kernel(const hoNDArray<T>& acsSrc, const hoNDArray<T>& acsDst, size_t accelFactor, double thres, size_t kRO, size_t kNE1, hoNDArray<T>& convKer)
{
    size_t startRO = 0;
    size_t endRO = acsSrc.get_size(0) - 1;
    size_t startE1 = 0;
    size_t endE1 = acsSrc.get_size(1) - 1;

    grappa2d_calib_convolution_kernel(acsSrc, acsDst, accelFactor, thres, kRO, kNE1, startRO, endRO, startE1, endE1, convKer);
}
Ejemplo n.º 4
0
int CS_FOCUSS_2D::fRecon(hoNDArray<std::complex<float> >  &hacfInput, hoNDArray<std::complex<float> >  &hacfRecon){

	// input dimensions
	vtDim_ = *hacfInput.get_dimensions();

	// number of channels
	iNChannels_ = (int)vtDim_[2];

	// if Matlab is used, initialize singleton variables
	/*if (bMatlab_){
		for (int iI = 0; iI < 20; iI++){
			GlobalVar_FOCUSS::instance()->vbStatPrinc_.push_back(false);
			GlobalVar_FOCUSS::instance()->vfPrincipleComponents_.push_back(new hoNDArray<std::complex<float> > ());
		}
	}*/

	// const complex values
	const std::complex<float> cfZero(0.0);
	const std::complex<float> cfOne(1.0);

	// store incoming data in array
	hoNDArray<std::complex<float> >  hacfKSpace = hacfInput;

	// permute kSpace: x-y-c -> y-x-c
	std::vector<size_t> vtDimOrder; vtDimOrder.push_back(1); vtDimOrder.push_back(0); vtDimOrder.push_back(2);
	hacfKSpace = *permute(&hacfKSpace, &vtDimOrder,false);

	// update dim_ vector
	vtDim_.clear(); vtDim_ = *hacfKSpace.get_dimensions();

	//------------------------------------------------------------------------
	//-------------------------- sampling mask -------------------------------
	//------------------------------------------------------------------------
	hoNDArray<std::complex<float> >  hacfFullMask(hacfKSpace.get_dimensions()); hacfFullMask.fill(cfZero);
	hoNDArray<bool> habFullMask(hacfKSpace.get_dimensions()); habFullMask.fill(false);
	pcfPtr_ = hacfKSpace.get_data_ptr();
	pcfPtr2_ = hacfFullMask.get_data_ptr();
	pbPtr_ = habFullMask.get_data_ptr();
	for (int i = 0; i < hacfKSpace.get_number_of_elements(); i++)
		if (pcfPtr_[i] != cfZero){
			pcfPtr2_[i] = cfOne;
			pbPtr_[i] = true;
		}

	//-------------------------------------------------------------------------
	//---------------- iFFT x direction - x ky kz ^= v (n�) -------------------
	//-------------------------------------------------------------------------
	if (Transform_fftBA_->get_active()){
		if (!bMatlab_ && bDebug_)
			#if __GADGETRON_VERSION_HIGHER_3_6__ == 1
				GDEBUG("FFT in read direction..\n");
			#else
				GADGET_DEBUG1("FFT in read direction..\n");
			#endif
		else if(bMatlab_ && bDebug_){
			// mexPrintf("FFT in read direction..\n");mexEvalString("drawnow;");
		}
		Transform_fftBA_->FTransform(hacfKSpace);
	}
Ejemplo n.º 5
0
    void compute_phase_time_stamp(const hoNDArray<float>& time_stamp, const hoNDArray<float>& cpt_time_stamp, size_t startE1, size_t endE1, 
        hoNDArray<float>& phs_time_stamp, hoNDArray<float>& phs_cpt_time_stamp)
    {
        try
        {
            size_t E1 = time_stamp.get_size(0);
            size_t N = time_stamp.get_size(1);
            size_t rE1 = endE1 - startE1 + 1;

            size_t e1, n;

            for ( n=0; n<N; n++ )
            {
                // phase time stamp as the mean of all aquired lines
                size_t num = 0;
                float tt = 0.0f;
                for ( e1=startE1; e1<=endE1; e1++ )
                {
                    if(time_stamp(e1, n)>0)
                    {
                        tt += time_stamp(e1, n);
                        num++;
                    }
                }
                phs_time_stamp(n, 0) = tt/((num>0) ? num : 1);

                //// phase cpt time as the median of all acquired lines
                //std::vector<float> cpt_buf(rE1, 0);
                //for ( e1=startE1; e1<=endE1; e1++ )
                //{
                //    if(cpt_time_stamp(e1, n)>=0)
                //        cpt_buf[e1-startE1] = cpt_time_stamp(e1, n);
                //}

                //std::sort(cpt_buf.begin(), cpt_buf.end());
                //phs_cpt_time_stamp(n, 0) = cpt_buf[E1/2-startE1];

                // phase cpt time as the cpt time of center line
                phs_cpt_time_stamp(n, 0) = cpt_time_stamp(E1/2, n);
            }
        }
        catch(...)
        {
            GADGET_THROW("Exceptions happened in compute_phase_time_stamp(...) ... ");
        }
    }
void grappa2d_calib_convolution_kernel(const hoNDArray<T>& dataSrc, const hoNDArray<T>& dataDst, hoNDArray<unsigned short>& dataMask, size_t accelFactor, double thres, size_t kRO, size_t kNE1, hoNDArray<T>& convKer)
{
    try
    {
        bool fitItself = false;
        if (&dataSrc != &dataDst) fitItself = true;

        GADGET_CHECK_THROW(dataSrc.dimensions_equal(&dataMask));
        GADGET_CHECK_THROW(dataDst.dimensions_equal(&dataMask));

        // find the fully sampled region
        size_t RO = dataMask.get_size(0);
        size_t E1 = dataMask.get_size(1);
        size_t srcCHA = dataSrc.get_size(2);
        size_t dstCHA = dataDst.get_size(2);

        size_t startRO(0), endRO(0), startE1(0), endE1(0);

        size_t ro, e1, scha, dcha;

        for (e1 = 0; e1 < E1; e1++)
        {
            for (ro = 0; ro < RO; ro++)
            {
                if (dataMask(ro, e1)>0)
                {
                    if (ro < startRO) startRO = ro;
                    if (ro > endRO) endRO = ro;

                    if (e1 < startE1) startE1 = e1;
                    if (e1 > endE1) endE1 = e1;
                }
            }
        }

        GADGET_CHECK_THROW(endRO>startRO);
        GADGET_CHECK_THROW(endE1>startE1 + accelFactor);

        GADGET_CATCH_THROW(grappa2d_calib_convolution_kernel(dataSrc, dataDst, accelFactor, thres, kRO, kNE1, startRO, endRO, startE1, endE1, convKer));
    }
    catch (...)
    {
        GADGET_THROW("Errors in grappa2d_calib_convolution_kernel(dataMask) ... ");
    }
}
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) ... ");
    }
}
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) ... ");
    }
}
Ejemplo n.º 9
0
    hoNDArray<uint16_t>
    update_field_map(const hoNDArray<uint16_t> &field_map_index, const hoNDArray<uint16_t> &proposed_field_map_index,
                     const hoNDArray<float> &residuals_map, const hoNDArray<float> &lambda_map) {


        hoNDArray<float> residual_diff_map(field_map_index.get_dimensions());
        const auto X = field_map_index.get_size(0);
        const auto Y = field_map_index.get_size(1);
        const auto Z = field_map_index.get_size(2);

        for (size_t kz = 0; kz < Z; kz++) {
            for (size_t ky = 0; ky < Y; ky++) {
                for (size_t kx = 0; kx < X; kx++) {
                    residual_diff_map(kx, ky,kz) = residuals_map(field_map_index(kx, ky,kz), kx, ky,kz) -
                                                residuals_map(proposed_field_map_index(kx, ky,kz), kx, ky,kz);


                }
            }
        }


        std::vector<boost::default_color_type> color_map;
        if (Z == 1) {
            color_map = graph_cut<2>(field_map_index, proposed_field_map_index, lambda_map,
                                     residual_diff_map);
        } else {
            color_map = graph_cut<3>(field_map_index, proposed_field_map_index, lambda_map, residual_diff_map);
        }



        auto result = field_map_index;
        size_t updated_voxels = 0;
        for (size_t i = 0; i < field_map_index.get_number_of_elements(); i++) {
            if (color_map[i] != boost::default_color_type::black_color) {
                updated_voxels++;
                result[i] = proposed_field_map_index[i];
            }
        }

        return result;

    }
    void maxValue(const hoNDArray<T>& a, T& v)
    {
        typedef T ValueType;

        try
        {
            const ValueType* pA = a.begin();
            size_t n = a.get_number_of_elements();
            v = pA[0];

            size_t ii;
            for (ii=1; ii<n; ii++)
            {
                if (pA[ii]>v) v = pA[ii];
            }
        }
        catch(...)
        {
            GADGET_THROW("Errors in maxValue(const hoNDArray<T>& a, T& v) ... ");
        }
    }
    void sort(const hoNDArray<T>& x, hoNDArray<T>& r, bool isascending)
    {
        if ( &r != &x )
        {
            if ( r.get_number_of_elements()!=x.get_number_of_elements())
            {
                r = x;
            }
            else
            {
                memcpy(r.begin(), x.begin(), x.get_number_of_bytes());
            }
        }

        sort(x.get_number_of_elements(), x.begin(), r.begin(), isascending);
    }
Ejemplo n.º 12
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);
    }
}
Ejemplo n.º 13
0
    hoNDArray< std::complex<float> > fatwater_separation(hoNDArray< std::complex<float> >& data, FatWaterParameters p, FatWaterAlgorithm a)
    {

	//Get some data parameters
	//7D, fixed order [X, Y, Z, CHA, N, S, LOC]
        uint16_t X = data.get_size(0);
        uint16_t Y = data.get_size(1);
        uint16_t Z = data.get_size(2);
        uint16_t CHA = data.get_size(3);
        uint16_t N = data.get_size(4);
        uint16_t S = data.get_size(5);
        uint16_t LOC = data.get_size(6);

	GDEBUG("Size of my array: %d, %d, %d .\n", X,Y,Z);

	hoNDArray< std::complex<float> > out(X,Y,Z,CHA,N,2,LOC); // S dimension gets replaced by water/fat stuff

	float fieldStrength = p.fieldStrengthT_;
        std::vector<float> echoTimes = p.echoTimes_;
	bool precessionIsClockwise = p.precessionIsClockwise_;
        for (auto& te: echoTimes) {
          te = te*0.001; // Echo times in seconds rather than milliseconds
        }

	GDEBUG("In toolbox - Field Strength: %f T \n", fieldStrength);
        for (auto& te: echoTimes) {
	  GDEBUG("In toolbox - Echo time: %f seconds \n", te);
        }
	GDEBUG("In toolbox - PrecessionIsClockwise: %d \n", precessionIsClockwise);

	//Get or set some algorithm parameters
	//Gadgetron::ChemicalSpecies w = a.species_[0];
	//Gadgetron::ChemicalSpecies f = a.species_[1];

	//	GDEBUG("In toolbox - Fat peaks: %f  \n", f.ampFreq_[0].first);
	//	GDEBUG("In toolbox - Fat peaks 2: %f  \n", f.ampFreq_[0].second);

	// Set some initial parameters so we can get going
	// These will have to be specified in the XML file eventually
	std::pair<float,float> range_r2star = std::make_pair(0.0,0.0);
	uint16_t num_r2star = 1;
	std::pair<float,float> range_fm = std::make_pair(-80.0,80.0);
	uint16_t num_fm = 101;
	uint16_t num_iterations = 40;
	uint16_t subsample = 1;
	float lmap_power = 2.0;
	float lambda = 0.02;
	float lambda_extra = 0.02;

	//Check that we have reasonable data for fat-water separation


	//Calculate residual
	//
	float relAmp, freq_hz;
	uint16_t npeaks;
	uint16_t nspecies = a.species_.size();
	uint16_t nte = echoTimes.size();
	GDEBUG("In toolbox - NTE: %d \n", nte);

	hoMatrix< std::complex<float> > phiMatrix(nte,nspecies);
	for( int k1=0;k1<nte;k1++) {
	  for( int k2=0;k2<nspecies;k2++) {
	    phiMatrix(k1,k2) = 0.0;
	    npeaks = a.species_[k2].ampFreq_.size();
	    for( int k3=0;k3<npeaks;k3++) {
	      relAmp = a.species_[k2].ampFreq_[k3].first;
	      freq_hz = fieldStrength*GAMMABAR*a.species_[k2].ampFreq_[k3].second;
	      phiMatrix(k1,k2) += relAmp*std::complex<float>(cos(2*PI*echoTimes[k1]*freq_hz),sin(2*PI*echoTimes[k1]*freq_hz));
	    }
	    GDEBUG("Cur value phiMatrix = (%f,%f) \n", phiMatrix(k1,k2).real(), phiMatrix(k1,k2).imag());
	  }
	}
	//auto a_phiMatrix = as_arma_matrix(&phiMatrix);
	//auto mymat2 = mymat.t()*mymat;

	for(int ka=0;ka<phiMatrix.get_size(0);ka++) {
	  for(int kb=0;kb<phiMatrix.get_size(1);kb++) {
	    GDEBUG("Check phiMatrix(%d,%d) = %f + i %f \n", ka,kb,phiMatrix(ka,kb).real(),phiMatrix(ka,kb).imag());
	  }
	}




	hoMatrix< std::complex<float> > IdentMat(nte,nte);
	for( int k1=0;k1<nte;k1++) {
	  for( int k2=0;k2<nte;k2++) {
	    if( k1==k2 ) {
	      IdentMat(k1,k2) = std::complex<float>(1.0,0.0);
	    } else {
	      IdentMat(k1,k2) = std::complex<float>(0.0,0.0);
	    }
	  }
	}
	//	auto a_phiMatrix = as_arma_matrix(&IdentMat);

	float fm;
	std::vector<float> fms(num_fm);
	fms[0] = range_fm.first;
	for(int k1=1;k1<num_fm;k1++) {
	  fms[k1] = range_fm.first + k1*(range_fm.second-range_fm.first)/(num_fm-1);
	}

	float r2star;
    std::vector<float> r2stars(num_r2star);
	r2stars[0] = range_r2star.first;
	for(int k2=1;k2<num_r2star;k2++) {
	  r2stars[k2] = range_r2star.first + k2*(range_r2star.second-range_r2star.first)/(num_r2star-1);
	}


	std::complex<float> curModulation;
	hoMatrix< std::complex<float> > tempM1(nspecies,nspecies);
	hoMatrix< std::complex<float> > tempM2(nspecies,nte);
	hoMatrix< std::complex<float> > psiMatrix(nte,nspecies);
	hoNDArray< std::complex<float> > Ps(nte,nte,num_fm,num_r2star);
	hoMatrix< std::complex<float> > P1(nte,nte);
	hoMatrix< std::complex<float> > P(nte,nte);

	for(int k3=0;k3<num_fm;k3++) {
	  fm = fms[k3];
	  for(int k4=0;k4<num_r2star;k4++) {
	    r2star = r2stars[k4];


	    for( int k1=0;k1<nte;k1++) {
	      curModulation = exp(-r2star*echoTimes[k1])*std::complex<float>(cos(2*PI*echoTimes[k1]*fm),sin(2*PI*echoTimes[k1]*fm));
	      for( int k2=0;k2<nspecies;k2++) {
		psiMatrix(k1,k2) = phiMatrix(k1,k2)*curModulation;
	      }
	    }

	    herk( tempM1, psiMatrix, 'L', true );
	    //	    tempM1.copyLowerTriToUpper();
	    for (int ka=0;ka<tempM1.get_size(0);ka++ ) {
	      for (int kb=ka+1;kb<tempM1.get_size(1);kb++ ) {
		tempM1(ka,kb) = conj(tempM1(kb,ka));
	      }
	    }

	    if(k3==50) {
	      for(int ka=0;ka<tempM1.get_size(0);ka++) {
		for(int kb=0;kb<tempM1.get_size(1);kb++) {
		  GDEBUG(" tempM1(%d,%d) = %f + i %f \n", ka,kb,tempM1(ka,kb).real(),tempM1(ka,kb).imag());
		}
	      }
	    }


	    potri(tempM1);
	    for (int ka=0;ka<tempM1.get_size(0);ka++ ) {
	      for (int kb=ka+1;kb<tempM1.get_size(1);kb++ ) {
		tempM1(ka,kb) = conj(tempM1(kb,ka));
	      }
	    }

	    if(k3==50) {
	      for(int ka=0;ka<tempM1.get_size(0);ka++) {
		for(int kb=0;kb<tempM1.get_size(1);kb++) {
		  GDEBUG(" inv tempM1(%d,%d) = %f + i %f \n", ka,kb,tempM1(ka,kb).real(),tempM1(ka,kb).imag());
		}
	      }
	    }


	    //GDEBUG(" (%d,%d) = (%d,%d) X (%d,%d) \n", tempM2.get_size(0),tempM2.get_size(1),tempM1.get_size(0),tempM1.get_size(1),psiMatrix.get_size(1),psiMatrix.get_size(0));
	    gemm( tempM2, tempM1, false, psiMatrix, true );

	    if(k3==50) {
	      for(int ka=0;ka<tempM2.get_size(0);ka++) {
		for(int kb=0;kb<tempM2.get_size(1);kb++) {
		  GDEBUG(" tempM2(%d,%d) = %f + i %f \n", ka,kb,tempM2(ka,kb).real(),tempM2(ka,kb).imag());
		}
	      }
	    }

	    //GDEBUG(" (%d,%d) = (%d,%d) X (%d,%d) \n", P1.get_size(0),P1.get_size(1),psiMatrix.get_size(0),psiMatrix.get_size(1),tempM2.get_size(0),tempM2.get_size(1));
	    gemm( P1, psiMatrix, false, tempM2, false );

	    if(k3==50) {
	      for(int ka=0;ka<P1.get_size(0);ka++) {
		for(int kb=0;kb<P1.get_size(1);kb++) {
		  GDEBUG(" P1(%d,%d) = %f + i %f \n", ka,kb,P1(ka,kb).real(),P1(ka,kb).imag());
		}
	      }
	    }


	    subtract(IdentMat,P1,P);

	    if(k3==50) {
	      for(int ka=0;ka<P.get_size(0);ka++) {
		for(int kb=0;kb<P.get_size(1);kb++) {
		  GDEBUG(" P(%d,%d) = %f + i %f \n", ka,kb,P(ka,kb).real(),P(ka,kb).imag());
		}
	      }

	    }





	    // Keep all projector matrices together
	    for( int k1=0;k1<nte;k1++) {
	      for( int k2=0;k2<nte;k2++) {
		Ps(k1,k2,k3,k4) = P(k1,k2);
	      }
	    }
	  }
	}


	// Need to check that S = nte
	// N should be the number of contrasts (eg: for PSIR)
	hoMatrix< std::complex<float> > tempResVector(S,N);
	hoMatrix< std::complex<float> > tempSignal(S,N);
	hoNDArray<float> residual(num_fm,X,Y);
	hoNDArray<uint16_t> r2starIndex(X,Y,num_fm);
	hoNDArray<uint16_t> fmIndex(X,Y);
	float curResidual, minResidual, minResidual2;
	for( int k1=0;k1<X;k1++) {
	  for( int k2=0;k2<Y;k2++) {
	    // Get current signal
	    for( int k4=0;k4<N;k4++) {
	      for( int k5=0;k5<S;k5++) {
		tempSignal(k5,k4) = data(k1,k2,0,0,k4,k5,0);
		if (k1==107 && k2==144) {
		  tempSignal(k5,k4) = std::complex<float>(1000.0,0.0);;
		  GDEBUG(" (%d,%d) -->  %f + i %f \n",k5,k4, tempSignal(k5,k4).real(),tempSignal(k5,k4).imag());
		}

	      }
	    }

	    minResidual2 = 1.0 + nrm2(&tempSignal);

	    for(int k3=0;k3<num_fm;k3++) {

	      minResidual = 1.0 + nrm2(&tempSignal);

	      for(int k4=0;k4<num_r2star;k4++) {
		// Get current projector matrix
		for( int k5=0;k5<nte;k5++) {
		  for( int k6=0;k6<nte;k6++) {
		    P(k5,k6) = Ps(k5,k6,k3,k4);
		  }
		}

		// Apply projector
		gemm( tempResVector, P, false, tempSignal, false );

		curResidual = nrm2(&tempResVector);

		if (curResidual < minResidual) {
		  minResidual = curResidual;
		  r2starIndex(k1,k2,k3) = k4;
		}
	      }
	      residual(k3,k1,k2) = minResidual;

	      if (minResidual < minResidual2) {
		minResidual2 = minResidual;
		fmIndex(k1,k2) = k3;
	      }

	      if (k1==107 && k2==144) {
		GDEBUG(" %f -->  %f \n",fms[k3],minResidual);
	      }
	    }
	  }
	}



	//arma::Mat< std::complex<float> > arma_phiMatrix = as_arma_matrix( phiMatrix );


	//Do graph cut iterations
	using namespace boost;

	// create a typedef for the Graph type
	typedef adjacency_list<vecS, vecS, bidirectionalS> Graph;

	// Make convenient labels for the vertices
	enum { A, B, C, D, E };
	const int num_vertices = 5;
	const char* name = "ABCDE";

	// writing out the edges in the graph
	typedef std::pair<int, int> Edge;
	Edge edge_array[] =
	  { Edge(A,B), Edge(A,D), Edge(C,A), Edge(D,C),
	    Edge(C,E), Edge(B,D), Edge(D,E) };
	const int num_edges = sizeof(edge_array)/sizeof(edge_array[0]);

	// declare a graph object
	Graph g(edge_array, edge_array + sizeof(edge_array) / sizeof(Edge), num_vertices);


	/*
	property_map<Graph, edge_capacity_t>::type
	  capacity = get(edge_capacity, g);
	property_map<Graph, edge_reverse_t>::type
	  rev = get(edge_reverse, g);
	property_map<Graph, edge_residual_capacity_t>::type
	  residual_capacity = get(edge_residual_capacity, g);

	Traits::vertex_descriptor s, t;
	read_dimacs_max_flow(g, capacity, rev, s, t);

	long flow;
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
	// Use non-named parameter version
	property_map<Graph, vertex_index_t>::type
	  indexmap = get(vertex_index, g);
	flow = push_relabel_max_flow(g, s, t, capacity, residual_capacity, rev, indexmap);
#else
	flow = push_relabel_max_flow(g, s, t);
#endif

	std::cout << "c  The total flow:" << std::endl;
	std::cout << "s " << flow << std::endl << std::endl;

	std::cout << "c flow values:" << std::endl;
	graph_traits<Graph>::vertex_iterator u_iter, u_end;
	graph_traits<Graph>::out_edge_iterator ei, e_end;
	for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter)
	  for (boost::tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei)
	    if (capacity[*ei] > 0)
	      std::cout << "f " << *u_iter << " " << target(*ei, g) << " "
			<< (capacity[*ei] - residual_capacity[*ei]) << std::endl;

	*/





	//Do final calculations once the field map is done
	hoMatrix< std::complex<float> > curWaterFat(2,N);
	hoMatrix< std::complex<float> > AhA(2,2);
	// Do fat-water separation with current field map and R2* estimates
	for( int k1=0;k1<X;k1++) {
	  for( int k2=0;k2<Y;k2++) {

	    // Get current signal
	    for( int k4=0;k4<N;k4++) {
	      for( int k5=0;k5<S;k5++) {
		tempSignal(k5,k4) = data(k1,k2,0,0,k4,k5,0);
	      }
	    }
	    // Get current Psi matrix
	    fm = fms[fmIndex(k1,k2)];
	    r2star = r2stars[r2starIndex(k1,k2,fmIndex(k1,k2))];
	    for( int k3=0;k3<nte;k3++) {
	      curModulation = exp(-r2star*echoTimes[k3])*std::complex<float>(cos(2*PI*echoTimes[k3]*fm),sin(2*PI*echoTimes[k3]*fm));
	      for( int k4=0;k4<nspecies;k4++) {
		psiMatrix(k3,k4) = phiMatrix(k3,k4)*curModulation;
	      }
	    }

	    // Solve for water and fat
	    gemm( curWaterFat, psiMatrix, true, tempSignal, false );
	    herk( AhA, psiMatrix, 'L', true );
	    //	    AhA.copyLowerTriToUpper();
	    for (int ka=0;ka<AhA.get_size(0);ka++ ) {
	      for (int kb=ka+1;kb<AhA.get_size(1);kb++ ) {
		AhA(ka,kb) = conj(AhA(kb,ka));
	      }
	    }

	    hesv(AhA,curWaterFat);
	    for ( int k4=0;k4<N;k4++ ) {
	      for ( int k5=0;k5<2;k5++ ) { // 2 elements for water and fat currently
		out(k1,k2,0,0,k4,k5,0) = curWaterFat(k5,k4);
	      }
	    }

	  }
	}



	//Clean up as needed


        return out;
    }
Ejemplo n.º 14
0
    void correct_heart_beat_time_stamp_with_fitting(hoNDArray<float>& cpt_time_stamp, hoNDArray<int>& ind_hb, size_t startE1, size_t endE1, 
                                                const std::vector<size_t>& start_e1_hb, const std::vector<size_t>& end_e1_hb, 
                                                const std::vector<size_t>& start_n_hb, const 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 rE1 = endE1-startE1+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++;
                    }
                }
            }

            size_t numOfHB = start_e1_hb.size();

            std::vector<size_t> ind_HB_start(numOfHB);
            std::vector<size_t> ind_HB_end(numOfHB);

            for ( ind=0; ind<numOfHB; ind++ )
            {
                ind_HB_start[ind] = start_e1_hb[ind] + start_n_hb[ind] * E1;
                ind_HB_end[ind] = end_e1_hb[ind] + end_n_hb[ind] * E1;
            }

            // --------------------------------------------------------
            // fit a line to every heart beat
            // --------------------------------------------------------
            float a, b;
            std::vector<float> A(numOfHB, 0.0f), B(numOfHB, 0.0f);
            for ( ind=0; ind<numOfHB; ind++ )
            {
                std::vector<float> x, y;

                size_t cpt;
                for ( cpt=ind_HB_start[ind]; cpt<=ind_HB_end[ind]; cpt++ )
                {
                    size_t n = cpt / E1;
                    size_t e1 = cpt - n*E1;

                    if(e1>=startE1 && e1<=endE1)
                    {
                        if ( cpt_time_stamp[cpt] > -1 )
                        {
                            size_t x_ind = (e1-startE1) + n*rE1;
                            x.push_back( (float)x_ind );
                            y.push_back(cpt_time_stamp[cpt]);
                        }
                    }
                }

                if ( !x.empty() )
                {
                    Gadgetron::simple_line_fit(x, y, a, b);
                    A[ind] = a;
                    B[ind] = b;
                }
            }

            // --------------------------------------------------------
            // compute cpt time stamp for every line
            // --------------------------------------------------------
            size_t num = cpt_time_stamp.get_number_of_elements();
            for ( ind=0; ind<num; ind++ )
            {
                n = ind / E1;
                e1 = ind - n*E1;

                if(e1>=startE1 && e1<=endE1)
                {
                    // find to which heart beat this line belongs
                    bool foundHB = false;
                    for ( ii=0; ii<numOfHB; ii++ )
                    {
                        size_t startHB = ind_HB_start[ii];
                        size_t endHB = ind_HB_end[ii];

                        if ( ii==0 && ind<=startHB )
                        {
                            foundHB = true;
                            break;
                        }

                        if ( ii==numOfHB-1 && ind>=endHB )
                        {
                            foundHB = true;
                            break;
                        }

                        if ( ind>=startHB && ind<=endHB )
                        {
                            foundHB = true;
                            break;
                        }
                    }

                    // if cannot find a heart beat, this kspace line will not be used
                    if ( foundHB && (std::abs(B[ii])>0) )
                    {
                        ind_hb(e1, n) = ii;

                        size_t x_ind = (e1-startE1) + n*rE1;
                        cpt_time_stamp(e1, n) = (float)(A[ii] + B[ii]*x_ind);
                    }
                    else
                    {
                        ind_hb(e1, n) = -1;
                    }
                }
                else
                {
                    cpt_time_stamp(e1, n) = -1;
                    ind_hb(e1, n) = -1;
                }
            }
        }
        catch(...)
        {
            GADGET_THROW("Exceptions happened in correct_heart_beat_time_stamp_with_fitting(...) ... ");
        }
    }
 void dotu(const hoNDArray<T>& x, const hoNDArray<T>& y, T& r)
 {
     GADGET_DEBUG_CHECK_THROW(x.get_number_of_elements()==y.get_number_of_elements());
     dotu(x.get_number_of_elements(), x.begin(), y.begin(), r);
 }
 template<class T> size_t amax(const hoNDArray<T>& x)
 {
     return amax(x.get_number_of_elements(), x.begin());
 }
Ejemplo n.º 17
0
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.º 18
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(...) ... ");
        }
    }
    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 GenericReconCartesianNonLinearSpirit2DTGadget::perform_nonlinear_spirit_unwrapping(hoNDArray< std::complex<float> >& kspace, 
        hoNDArray< std::complex<float> >& kerIm, hoNDArray< std::complex<float> >& ref2DT, hoNDArray< std::complex<float> >& coilMap2DT, hoNDArray< std::complex<float> >& res, size_t e)
    {
        try
        {
            bool print_iter = this->spirit_print_iter.value();

            size_t RO = kspace.get_size(0);
            size_t E1 = kspace.get_size(1);
            size_t E2 = kspace.get_size(2);
            size_t CHA = kspace.get_size(3);
            size_t N = kspace.get_size(4);
            size_t S = kspace.get_size(5);
            size_t SLC = kspace.get_size(6);

            size_t ref_N = kerIm.get_size(4);
            size_t ref_S = kerIm.get_size(5);

            hoNDArray< std::complex<float> > kspaceLinear(kspace);
            res = kspace;

            // detect whether random sampling is used
            bool use_random_sampling = false;
            std::vector<long long> sampled_step_size;
            long long n, e1;
            for (n=0; n<(long long)N; n++)
            {
                long long prev_sampled_line = -1;
                for (e1=0; e1<(long long)E1; e1++)
                {
                    if(std::abs(kspace(RO/2, e1, 0, 0, 0, 0, 0))>0 && std::abs(kspace(RO/2, e1, 0, CHA-1, 0, 0, 0))>0)
                    {
                        if(prev_sampled_line>0)
                        {
                            sampled_step_size.push_back(e1 - prev_sampled_line);
                        }

                        prev_sampled_line = e1;
                    }
                }
            }

            if(sampled_step_size.size()>4)
            {
                size_t s;
                for (s=2; s<sampled_step_size.size()-1; s++)
                {
                    if(sampled_step_size[s]!=sampled_step_size[s-1])
                    {
                        use_random_sampling = true;
                        break;
                    }
                }
            }

            if(use_random_sampling)
            {
                GDEBUG_STREAM("SPIRIT Non linear, random sampling is detected ... ");
            }

            Gadgetron::GadgetronTimer timer(false);

            // compute linear solution as the initialization
            if(use_random_sampling)
            {
                if (this->perform_timing.value()) timer.start("SPIRIT Non linear, perform linear spirit recon ... ");
                this->perform_spirit_unwrapping(kspace, kerIm, kspaceLinear);
                if (this->perform_timing.value()) timer.stop();
            }
            else
            {
                if (this->perform_timing.value()) timer.start("SPIRIT Non linear, perform linear recon ... ");

                size_t ref2DT_RO = ref2DT.get_size(0);
                size_t ref2DT_E1 = ref2DT.get_size(1);

                // mean over N
                hoNDArray< std::complex<float> > meanKSpace;
                Gadgetron::sum_over_dimension(ref2DT, meanKSpace, 4);

                // if (!debug_folder_full_path_.empty()) { gt_exporter_.export_array_complex(meanKSpace, debug_folder_full_path_ + "spirit_nl_2DT_meanKSpace"); }

                hoNDArray< std::complex<float> > acsSrc(ref2DT_RO, ref2DT_E1, CHA, meanKSpace.begin());
                hoNDArray< std::complex<float> > acsDst(ref2DT_RO, ref2DT_E1, CHA, meanKSpace.begin());

                double grappa_reg_lamda = 0.0005;
                size_t kRO = 5;
                size_t kE1 = 4;

                hoNDArray< std::complex<float> > convKer;
                hoNDArray< std::complex<float> > kIm(RO, E1, CHA, CHA);

                Gadgetron::grappa2d_calib_convolution_kernel(acsSrc, acsDst, (size_t)this->acceFactorE1_[e], grappa_reg_lamda, kRO, kE1, convKer);
                Gadgetron::grappa2d_image_domain_kernel(convKer, RO, E1, kIm);

                // if (!debug_folder_full_path_.empty()) gt_exporter_.export_array_complex(kIm, debug_folder_full_path_ + "spirit_nl_2DT_kIm");

                Gadgetron::hoNDFFT<float>::instance()->ifft2c(kspace, complex_im_recon_buf_);
                // if (!debug_folder_full_path_.empty()) gt_exporter_.export_array_complex(complex_im_recon_buf_, debug_folder_full_path_ + "spirit_nl_2DT_aliasedImage");

                hoNDArray< std::complex<float> > resKSpace(RO, E1, CHA, N);
                hoNDArray< std::complex<float> > aliasedImage(RO, E1, CHA, N, complex_im_recon_buf_.begin());
                Gadgetron::grappa2d_image_domain_unwrapping_aliased_image(aliasedImage, kIm, resKSpace);

                // if (!debug_folder_full_path_.empty()) gt_exporter_.export_array_complex(resKSpace, debug_folder_full_path_ + "spirit_nl_2DT_linearImage");

                Gadgetron::hoNDFFT<float>::instance()->fft2c(resKSpace);

                memcpy(kspaceLinear.begin(), resKSpace.begin(), resKSpace.get_number_of_bytes());

                if (this->perform_timing.value()) timer.stop();
            }

            // if (!debug_folder_full_path_.empty()) gt_exporter_.export_array_complex(kspaceLinear, debug_folder_full_path_ + "spirit_nl_2DT_kspaceLinear");

            // perform nonlinear reconstruction
            {
                boost::shared_ptr< hoNDArray< std::complex<float> > > coilMap;

                bool hasCoilMap = false;
                if (coilMap2DT.get_size(0) == RO && coilMap2DT.get_size(1) == E1 && coilMap2DT.get_size(3)==CHA)
                {
                    if (ref_N < N)
                    {
                        coilMap = boost::shared_ptr< hoNDArray< std::complex<float> > >(new hoNDArray< std::complex<float> >(RO, E1, CHA, coilMap2DT.begin()));
                    }
                    else
                    {
                        coilMap = boost::shared_ptr< hoNDArray< std::complex<float> > >(new hoNDArray< std::complex<float> >(RO, E1, CHA, ref_N, coilMap2DT.begin()));
                    }

                    hasCoilMap = true;
                }

                boost::shared_ptr<hoNDArray< std::complex<float> > > ker(new hoNDArray< std::complex<float> >(RO, E1, CHA, CHA, ref_N, kerIm.begin()));
                boost::shared_ptr<hoNDArray< std::complex<float> > > acq(new hoNDArray< std::complex<float> >(RO, E1, CHA, N, kspace.begin()));
                hoNDArray< std::complex<float> > kspaceInitial(RO, E1, CHA, N, kspaceLinear.begin());
                hoNDArray< std::complex<float> > res2DT(RO, E1, CHA, N, res.begin());

                if (this->spirit_data_fidelity_lamda.value() > 0)
                {
                    GDEBUG_STREAM("Start the NL SPIRIT data fidelity iteration - regularization strength : "
                                    << this->spirit_image_reg_lamda.value()
                                    << " - number of iteration : "                      << this->spirit_nl_iter_max.value()
                                    << " - proximity across cha : "                     << this->spirit_reg_proximity_across_cha.value()
                                    << " - redundant dimension weighting ratio : "      << this->spirit_reg_N_weighting_ratio.value()
                                    << " - using coil sen map : "                       << this->spirit_reg_use_coil_sen_map.value()
                                    << " - iter thres : "                               << this->spirit_nl_iter_thres.value());

                    typedef hoGdSolver< hoNDArray< std::complex<float> >, hoWavelet2DTOperator< std::complex<float> > > SolverType;
                    SolverType solver;
                    solver.iterations_ = this->spirit_nl_iter_max.value();
                    solver.set_output_mode(this->spirit_print_iter.value() ? SolverType::OUTPUT_VERBOSE : SolverType::OUTPUT_SILENT);
                    solver.grad_thres_ = this->spirit_nl_iter_thres.value();
                    solver.proximal_strength_ratio_ = this->spirit_image_reg_lamda.value();

                    boost::shared_ptr< hoNDArray< std::complex<float> > > x0 = boost::make_shared< hoNDArray< std::complex<float> > >(kspaceInitial);
                    solver.set_x0(x0);

                    // parallel imaging term
                    std::vector<size_t> dims;
                    acq->get_dimensions(dims);
                    hoSPIRIT2DTDataFidelityOperator< std::complex<float> > spirit(&dims);
                    spirit.set_forward_kernel(*ker, false);
                    spirit.set_acquired_points(*acq);

                    // image reg term
                    hoWavelet2DTOperator< std::complex<float> > wav3DOperator(&dims);
                    wav3DOperator.set_acquired_points(*acq);
                    wav3DOperator.scale_factor_first_dimension_ = this->spirit_reg_RO_weighting_ratio.value();
                    wav3DOperator.scale_factor_second_dimension_ = this->spirit_reg_E1_weighting_ratio.value();
                    wav3DOperator.scale_factor_third_dimension_ = this->spirit_reg_N_weighting_ratio.value();
                    wav3DOperator.with_approx_coeff_ = !this->spirit_reg_keep_approx_coeff.value();
                    wav3DOperator.change_coeffcients_third_dimension_boundary_ = !this->spirit_reg_keep_redundant_dimension_coeff.value();
                    wav3DOperator.proximity_across_cha_ = this->spirit_reg_proximity_across_cha.value();
                    wav3DOperator.no_null_space_ = true;
                    wav3DOperator.input_in_kspace_ = true;

                    if (this->spirit_reg_use_coil_sen_map.value() && hasCoilMap)
                    {
                        wav3DOperator.coil_map_ = *coilMap;
                    }

                    // set operators

                    solver.oper_system_ = &spirit;
                    solver.oper_reg_ = &wav3DOperator;

                    if (this->perform_timing.value()) timer.start("NonLinear SPIRIT solver for 2DT with data fidelity ... ");
                    solver.solve(*acq, res2DT);
                    if (this->perform_timing.value()) timer.stop();

                    // if (!debug_folder_full_path_.empty()) gt_exporter_.export_array_complex(res2DT, debug_folder_full_path_ + "spirit_nl_2DT_data_fidelity_res");
                }
                else
                {
                    GDEBUG_STREAM("Start the NL SPIRIT iteration with regularization strength : "
                                    << this->spirit_image_reg_lamda.value()
                                    << " - number of iteration : " << this->spirit_nl_iter_max.value()
                                    << " - proximity across cha : " << this->spirit_reg_proximity_across_cha.value()
                                    << " - redundant dimension weighting ratio : " << this->spirit_reg_N_weighting_ratio.value()
                                    << " - using coil sen map : " << this->spirit_reg_use_coil_sen_map.value()
                                    << " - iter thres : " << this->spirit_nl_iter_thres.value());

                    typedef hoGdSolver< hoNDArray< std::complex<float> >, hoWavelet2DTOperator< std::complex<float> > > SolverType;
                    SolverType solver;
                    solver.iterations_ = this->spirit_nl_iter_max.value();
                    solver.set_output_mode(this->spirit_print_iter.value() ? SolverType::OUTPUT_VERBOSE : SolverType::OUTPUT_SILENT);
                    solver.grad_thres_ = this->spirit_nl_iter_thres.value();
                    solver.proximal_strength_ratio_ = this->spirit_image_reg_lamda.value();

                    boost::shared_ptr< hoNDArray< std::complex<float> > > x0 = boost::make_shared< hoNDArray< std::complex<float> > >(kspaceInitial);
                    solver.set_x0(x0);

                    // parallel imaging term
                    std::vector<size_t> dims;
                    acq->get_dimensions(dims);

                    hoSPIRIT2DTOperator< std::complex<float> > spirit(&dims);
                    spirit.set_forward_kernel(*ker, false);
                    spirit.set_acquired_points(*acq);
                    spirit.no_null_space_ = true;
                    spirit.use_non_centered_fft_ = false;

                    // image reg term
                    std::vector<size_t> dim;
                    acq->get_dimensions(dim);

                    hoWavelet2DTOperator< std::complex<float> > wav3DOperator(&dim);
                    wav3DOperator.set_acquired_points(*acq);
                    wav3DOperator.scale_factor_first_dimension_ = this->spirit_reg_RO_weighting_ratio.value();
                    wav3DOperator.scale_factor_second_dimension_ = this->spirit_reg_E1_weighting_ratio.value();
                    wav3DOperator.scale_factor_third_dimension_ = this->spirit_reg_N_weighting_ratio.value();
                    wav3DOperator.with_approx_coeff_ = !this->spirit_reg_keep_approx_coeff.value();
                    wav3DOperator.change_coeffcients_third_dimension_boundary_ = !this->spirit_reg_keep_redundant_dimension_coeff.value();
                    wav3DOperator.proximity_across_cha_ = this->spirit_reg_proximity_across_cha.value();
                    wav3DOperator.no_null_space_ = true;
                    wav3DOperator.input_in_kspace_ = true;

                    if (this->spirit_reg_use_coil_sen_map.value() && hasCoilMap)
                    {
                        wav3DOperator.coil_map_ = *coilMap;
                    }

                    // set operators
                    solver.oper_system_ = &spirit;
                    solver.oper_reg_ = &wav3DOperator;

                    // set call back
                    solverCallBack cb;
                    cb.solver_ = &solver;
                    solver.call_back_ = &cb;

                    hoNDArray< std::complex<float> > b(kspaceInitial);
                    Gadgetron::clear(b);

                    if (this->perform_timing.value()) timer.start("NonLinear SPIRIT solver for 2DT ... ");
                    solver.solve(b, res2DT);
                    if (this->perform_timing.value()) timer.stop();

                    // if (!debug_folder_full_path_.empty()) gt_exporter_.export_array_complex(res2DT, debug_folder_full_path_ + "spirit_nl_2DT_res");

                    spirit.restore_acquired_kspace(kspace, res2DT);

                    // if (!debug_folder_full_path_.empty()) gt_exporter_.export_array_complex(res2DT, debug_folder_full_path_ + "spirit_nl_2DT_res_restored");
                }
            }
        }
        catch (...)
        {
            GADGET_THROW("Errors happened in GenericReconCartesianNonLinearSpirit2DTGadget::perform_nonlinear_spirit_unwrapping(...) ... ");
        }
    }
Ejemplo n.º 21
0
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) ... ");
    }
}
Ejemplo n.º 22
0
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;
}
 template<class T> void asum(const hoNDArray<T>& x, typename realType<T>::Type& r)
 {
     asum(x.get_number_of_elements(), x.begin(), r);
 }
Ejemplo n.º 24
0
bool plotNoiseStandardDeviation(const hoNDArray< std::complex<T> >& m, const std::vector<std::string>& coilStrings,
                    const std::string& xlabel, const std::string& ylabel, const std::string& title,
                    size_t xsize, size_t ysize, bool trueColor,
                    hoNDArray<float>& plotIm)
{
    try
    {
        size_t CHA = m.get_size(0);
        GADGET_CHECK_RETURN_FALSE(coilStrings.size() == CHA);

        hoNDArray<double> xd, yd, yd2;

        xd.create(CHA);
        yd.create(CHA);

        size_t c;
        for (c = 0; c < CHA; c++)
        {
            xd(c) = c+1;
            yd(c) = std::sqrt( std::abs(m(c, c)) );
        }

        double maxY = Gadgetron::max(&yd);

        yd2 = yd;
        std::sort(yd2.begin(), yd2.end());
        double medY = yd2(CHA / 2);

        // increase dot line to be 1 sigma ~= 33%
        double medRange = 0.33;

        if (maxY < medY*(1 + medRange))
        {
            maxY = medY*(1 + medRange);
        }

        hoNDArray<unsigned char> im;
        im.create(3, xsize, ysize);
        Gadgetron::clear(im);

        plsdev("mem");

        plsmem(im.get_size(1), im.get_size(2), im.begin());

        plinit();
        plfont(2);
        pladv(0);
        plvpor(0.15, 0.75, 0.1, 0.8);

        plwind(0, CHA+1, 0, maxY*1.05);

        plcol0(15);
        plbox("bcnst", 0.0, 0, "bcnstv", 0.0, 0);

        std::string gly;
        getPlotGlyph(0, gly); // circle
        plstring(CHA, xd.begin(), yd.begin(), gly.c_str());

        // draw the median line
        pllsty(1);

        double px[2], py[2];

        px[0] = 0;
        px[1] = CHA+1;

        py[0] = medY;
        py[1] = medY;

        plline(2, px, py);

        pllsty(2);

        py[0] = medY*(1 - medRange);
        py[1] = medY*(1 - medRange);

        plline(2, px, py);

        py[0] = medY*(1 + medRange);
        py[1] = medY*(1 + medRange);

        plline(2, px, py);

        plmtex("b", 3.2, 0.5, 0.5, xlabel.c_str());
        plmtex("t", 2.0, 0.5, 0.5, title.c_str());
        plmtex("l", 5.0, 0.5, 0.5, ylabel.c_str());

        // draw the legend
        std::vector<PLINT> opt_array(CHA), text_colors(CHA), line_colors(CHA), line_styles(CHA), symbol_numbers(CHA), symbol_colors(CHA);
        std::vector<PLFLT> symbol_scales(CHA), line_widths(CHA), box_scales(CHA, 1);

        std::vector<const char*> symbols(CHA);
        PLFLT legend_width, legend_height;

        std::vector<const char*> legend_text(CHA);

        std::vector<std::string> legends(CHA);

        size_t n;
        for (n = 0; n < CHA; n++)
        {
            opt_array[n] = PL_LEGEND_SYMBOL;
            text_colors[n] = 15;
            line_colors[n] = 15;
            line_styles[n] = (n % 8 + 1);
            line_widths[n] = 0.2;
            symbol_colors[n] = 15;
            symbol_scales[n] = 0.75;
            symbol_numbers[n] = 1;
            symbols[n] = gly.c_str();

            std::ostringstream ostr;
            ostr << n+1 << ":" << coilStrings[n];

            legends[n] = ostr.str();

            legend_text[n] = legends[n].c_str();
        }

        pllegend(&legend_width,
            &legend_height,
            PL_LEGEND_BACKGROUND,
            PL_POSITION_OUTSIDE | PL_POSITION_RIGHT,
            0.02,                                       // x
            0.0,                                        // y
            0.05,                                       // plot_width
            0,                                          // bg_color
            15,                                         // bb_color
            1,                                          // bb_style
            0,                                          // nrow
            0,                                          // ncolumn
            CHA,                                        // nlegend
            &opt_array[0],
            0.05,                                       // text_offset
            0.5,                                        // text_scale
            1.0,                                        // text_spacing
            0.5,                                        // text_justification
            &text_colors[0],
            (const char **)(&legend_text[0]),
            NULL,                                       // box_colors
            NULL,                                       // box_patterns
            &box_scales[0],                             // box_scales
            NULL,                                       // box_line_widths
            &line_colors[0],
            &line_styles[0],
            &line_widths[0],
            &symbol_colors[0],
            &symbol_scales[0],
            &symbol_numbers[0],
            (const char **)(&symbols[0])
            );

        plend();

        outputPlotIm(im, trueColor, plotIm);
    }
    catch (...)
    {
        GERROR_STREAM("Errors happened in plotNoiseStandardDeviation(...) ... ");
        return false;
    }

    return true;
}
 void norm2(const hoNDArray<T>& x, typename realType<T>::Type& r)
 {
     norm2(x.get_number_of_elements(), x.begin(), r);
 }
    void GenericReconCartesianNonLinearSpirit2DTGadget::perform_nonlinear_spirit_unwrapping(hoNDArray< std::complex<float> >& kspace, 
        hoNDArray< std::complex<float> >& kerIm, hoNDArray< std::complex<float> >& ref2DT, hoNDArray< std::complex<float> >& coilMap2DT, hoNDArray< std::complex<float> >& res, size_t e)
    {
        try
        {
            bool print_iter = this->spirit_print_iter.value();

            size_t RO = kspace.get_size(0);
            size_t E1 = kspace.get_size(1);
            size_t E2 = kspace.get_size(2);
            size_t CHA = kspace.get_size(3);
            size_t N = kspace.get_size(4);
            size_t S = kspace.get_size(5);
            size_t SLC = kspace.get_size(6);

            size_t ref_N = kerIm.get_size(4);
            size_t ref_S = kerIm.get_size(5);

            hoNDArray< std::complex<float> > kspaceLinear(kspace);
            res = kspace;

            // detect whether random sampling is used
            bool use_random_sampling = false;
            std::vector<long long> sampled_step_size;
            long long n, e1;
            for (n=0; n<(long long)N; n++)
            {
                long long prev_sampled_line = -1;
                for (e1=0; e1<(long long)E1; e1++)
                {
                    if(std::abs(kspace(RO/2, e1, 0, 0, 0, 0, 0))>0 && std::abs(kspace(RO/2, e1, 0, CHA-1, 0, 0, 0))>0)
                    {
                        if(prev_sampled_line>0)
                        {
                            sampled_step_size.push_back(e1 - prev_sampled_line);
                        }

                        prev_sampled_line = e1;
                    }
                }
            }

            if(sampled_step_size.size()>4)
            {
                size_t s;
                for (s=2; s<sampled_step_size.size()-1; s++)
                {
                    if(sampled_step_size[s]!=sampled_step_size[s-1])
                    {
                        use_random_sampling = true;
                        break;
                    }
                }
            }

            if(use_random_sampling)
            {
                GDEBUG_STREAM("SPIRIT Non linear, random sampling is detected ... ");
            }

            Gadgetron::GadgetronTimer timer(false);

            boost::shared_ptr< hoNDArray< std::complex<float> > > coilMap;

            bool hasCoilMap = false;
            if (coilMap2DT.get_size(0) == RO && coilMap2DT.get_size(1) == E1 && coilMap2DT.get_size(3)==CHA)
            {
                if (ref_N < N)
                {
                    coilMap = boost::shared_ptr< hoNDArray< std::complex<float> > >(new hoNDArray< std::complex<float> >(RO, E1, CHA, coilMap2DT.begin()));
                }
                else
                {
                    coilMap = boost::shared_ptr< hoNDArray< std::complex<float> > >(new hoNDArray< std::complex<float> >(RO, E1, CHA, ref_N, coilMap2DT.begin()));
                }

                hasCoilMap = true;
            }

            hoNDArray<float> gFactor;
            float gfactorMedian = 0;

            float smallest_eigen_value(0);

            // -----------------------------------------------------
            // estimate gfactor
            // -----------------------------------------------------

            // mean over N
            hoNDArray< std::complex<float> > meanKSpace;

            if(calib_mode_[e]==ISMRMRD_interleaved)
            {
                Gadgetron::compute_averaged_data_N_S(kspace, true, true, true, meanKSpace);
            }
            else
            {
                Gadgetron::compute_averaged_data_N_S(ref2DT, true, true, true, meanKSpace);
            }

            if (!debug_folder_full_path_.empty()) { gt_exporter_.export_array_complex(meanKSpace, debug_folder_full_path_ + "spirit_nl_2DT_meanKSpace"); }

            hoNDArray< std::complex<float> > acsSrc(meanKSpace.get_size(0), meanKSpace.get_size(1), CHA, meanKSpace.begin());
            hoNDArray< std::complex<float> > acsDst(meanKSpace.get_size(0), meanKSpace.get_size(1), CHA, meanKSpace.begin());

            double grappa_reg_lamda = 0.0005;
            size_t kRO = 5;
            size_t kE1 = 4;

            hoNDArray< std::complex<float> > convKer;
            hoNDArray< std::complex<float> > kIm(RO, E1, CHA, CHA);

            Gadgetron::grappa2d_calib_convolution_kernel(acsSrc, acsDst, (size_t)this->acceFactorE1_[e], grappa_reg_lamda, kRO, kE1, convKer);
            Gadgetron::grappa2d_image_domain_kernel(convKer, RO, E1, kIm);

            hoNDArray< std::complex<float> > unmixC;

            if(hasCoilMap)
            {
                Gadgetron::grappa2d_unmixing_coeff(kIm, *coilMap, (size_t)acceFactorE1_[e], unmixC, gFactor);

                if (!debug_folder_full_path_.empty()) gt_exporter_.export_array(gFactor, debug_folder_full_path_ + "spirit_nl_2DT_gFactor");

                hoNDArray<float> gfactorSorted(gFactor);
                std::sort(gfactorSorted.begin(), gfactorSorted.begin()+RO*E1);
                gfactorMedian = gFactor((RO*E1 / 2));

                GDEBUG_STREAM("SPIRIT Non linear, the median gfactor is found to be : " << gfactorMedian);
            }

            if (!debug_folder_full_path_.empty()) gt_exporter_.export_array_complex(kIm, debug_folder_full_path_ + "spirit_nl_2DT_kIm");

            hoNDArray< std::complex<float> > complexIm;

            // compute linear solution as the initialization
            if(use_random_sampling)
            {
                if (this->perform_timing.value()) timer.start("SPIRIT Non linear, perform linear spirit recon ... ");
                this->perform_spirit_unwrapping(kspace, kerIm, kspaceLinear);
                if (this->perform_timing.value()) timer.stop();
            }
            else
            {
                if (this->perform_timing.value()) timer.start("SPIRIT Non linear, perform linear recon ... ");

                //size_t ref2DT_RO = ref2DT.get_size(0);
                //size_t ref2DT_E1 = ref2DT.get_size(1);

                //// mean over N
                //hoNDArray< std::complex<float> > meanKSpace;
                //Gadgetron::sum_over_dimension(ref2DT, meanKSpace, 4);

                //if (!debug_folder_full_path_.empty()) { gt_exporter_.export_array_complex(meanKSpace, debug_folder_full_path_ + "spirit_nl_2DT_meanKSpace"); }

                //hoNDArray< std::complex<float> > acsSrc(ref2DT_RO, ref2DT_E1, CHA, meanKSpace.begin());
                //hoNDArray< std::complex<float> > acsDst(ref2DT_RO, ref2DT_E1, CHA, meanKSpace.begin());

                //double grappa_reg_lamda = 0.0005;
                //size_t kRO = 5;
                //size_t kE1 = 4;

                //hoNDArray< std::complex<float> > convKer;
                //hoNDArray< std::complex<float> > kIm(RO, E1, CHA, CHA);

                //Gadgetron::grappa2d_calib_convolution_kernel(acsSrc, acsDst, (size_t)this->acceFactorE1_[e], grappa_reg_lamda, kRO, kE1, convKer);
                //Gadgetron::grappa2d_image_domain_kernel(convKer, RO, E1, kIm);

                //if (!debug_folder_full_path_.empty()) gt_exporter_.export_array_complex(kIm, debug_folder_full_path_ + "spirit_nl_2DT_kIm");

                Gadgetron::hoNDFFT<float>::instance()->ifft2c(kspace, complex_im_recon_buf_);
                if (!debug_folder_full_path_.empty()) gt_exporter_.export_array_complex(complex_im_recon_buf_, debug_folder_full_path_ + "spirit_nl_2DT_aliasedImage");

                hoNDArray< std::complex<float> > resKSpace(RO, E1, CHA, N);
                hoNDArray< std::complex<float> > aliasedImage(RO, E1, CHA, N, complex_im_recon_buf_.begin());
                Gadgetron::grappa2d_image_domain_unwrapping_aliased_image(aliasedImage, kIm, resKSpace);

                if (!debug_folder_full_path_.empty()) gt_exporter_.export_array_complex(resKSpace, debug_folder_full_path_ + "spirit_nl_2DT_linearImage");

                Gadgetron::hoNDFFT<float>::instance()->fft2c(resKSpace);

                memcpy(kspaceLinear.begin(), resKSpace.begin(), resKSpace.get_number_of_bytes());

                Gadgetron::apply_unmix_coeff_aliased_image(aliasedImage, unmixC, complexIm);

                if (this->perform_timing.value()) timer.stop();
            }

            if (!debug_folder_full_path_.empty()) gt_exporter_.export_array_complex(kspaceLinear, debug_folder_full_path_ + "spirit_nl_2DT_kspaceLinear");

            if(hasCoilMap)
            {
                if(N>=spirit_reg_minimal_num_images_for_noise_floor.value())
                {
                    // estimate the noise level

                    if(use_random_sampling)
                    {
                        Gadgetron::hoNDFFT<float>::instance()->ifft2c(kspaceLinear, complex_im_recon_buf_);

                        hoNDArray< std::complex<float> > complexLinearImage(RO, E1, CHA, N, complex_im_recon_buf_.begin());

                        Gadgetron::coil_combine(complexLinearImage, *coilMap, 2, complexIm);
                    }

                    if (!debug_folder_full_path_.empty()) gt_exporter_.export_array_complex(complexIm, debug_folder_full_path_ + "spirit_nl_2DT_linearImage_complexIm");

                    // if N is sufficiently large, we can estimate the noise floor by the smallest eigen value
                    hoMatrix< std::complex<float> > data;
                    data.createMatrix(RO*E1, N, complexIm.begin(), false);

                    hoNDArray< std::complex<float> > eigenVectors, eigenValues, eigenVectorsPruned;

                    // compute eigen
                    hoNDKLT< std::complex<float> > klt;
                    klt.prepare(data, (size_t)1, (size_t)0);
                    klt.eigen_value(eigenValues);

                    if (this->verbose.value())
                    {
                        GDEBUG_STREAM("SPIRIT Non linear, computes eigen values for all 2D kspaces ... ");
                        eigenValues.print(std::cout);

                        for (size_t i = 0; i<eigenValues.get_size(0); i++)
                        {
                            GDEBUG_STREAM(i << " = " << eigenValues(i));
                        }
                    }

                    smallest_eigen_value = std::sqrt( std::abs(eigenValues(N - 1).real()) / (RO*E1) );
                    GDEBUG_STREAM("SPIRIT Non linear, the smallest eigen value is : " << smallest_eigen_value);
                }
            }

            // perform nonlinear reconstruction
            {
                boost::shared_ptr<hoNDArray< std::complex<float> > > ker(new hoNDArray< std::complex<float> >(RO, E1, CHA, CHA, ref_N, kerIm.begin()));
                boost::shared_ptr<hoNDArray< std::complex<float> > > acq(new hoNDArray< std::complex<float> >(RO, E1, CHA, N, kspace.begin()));
                hoNDArray< std::complex<float> > kspaceInitial(RO, E1, CHA, N, kspaceLinear.begin());
                hoNDArray< std::complex<float> > res2DT(RO, E1, CHA, N, res.begin());

                if (this->spirit_data_fidelity_lamda.value() > 0)
                {
                    GDEBUG_STREAM("Start the NL SPIRIT data fidelity iteration - regularization strength : " << this->spirit_image_reg_lamda.value()
                                    << " - number of iteration : "                      << this->spirit_nl_iter_max.value()
                                    << " - proximity across cha : "                     << this->spirit_reg_proximity_across_cha.value()
                                    << " - redundant dimension weighting ratio : "      << this->spirit_reg_N_weighting_ratio.value()
                                    << " - using coil sen map : "                       << this->spirit_reg_use_coil_sen_map.value()
                                    << " - iter thres : "                               << this->spirit_nl_iter_thres.value()
                                    << " - wavelet name : "                             << this->spirit_reg_name.value()
                                    );

                    typedef hoGdSolver< hoNDArray< std::complex<float> >, hoWavelet2DTOperator< std::complex<float> > > SolverType;
                    SolverType solver;
                    solver.iterations_ = this->spirit_nl_iter_max.value();
                    solver.set_output_mode(this->spirit_print_iter.value() ? SolverType::OUTPUT_VERBOSE : SolverType::OUTPUT_SILENT);
                    solver.grad_thres_ = this->spirit_nl_iter_thres.value();

                    if(spirit_reg_estimate_noise_floor.value() && std::abs(smallest_eigen_value)>0)
                    {
                        solver.scale_factor_ = smallest_eigen_value;
                        solver.proximal_strength_ratio_ = this->spirit_image_reg_lamda.value() * gfactorMedian;

                        GDEBUG_STREAM("SPIRIT Non linear, eigen value is used to derive the regularization strength : " << solver.proximal_strength_ratio_ << " - smallest eigen value : " << solver.scale_factor_);
                    }
                    else
                    {
                        solver.proximal_strength_ratio_ = this->spirit_image_reg_lamda.value();
                    }

                    boost::shared_ptr< hoNDArray< std::complex<float> > > x0 = boost::make_shared< hoNDArray< std::complex<float> > >(kspaceInitial);
                    solver.set_x0(x0);

                    // parallel imaging term
                    std::vector<size_t> dims;
                    acq->get_dimensions(dims);
                    hoSPIRIT2DTDataFidelityOperator< std::complex<float> > spirit(&dims);
                    spirit.set_forward_kernel(*ker, false);
                    spirit.set_acquired_points(*acq);

                    // image reg term
                    hoWavelet2DTOperator< std::complex<float> > wav3DOperator(&dims);
                    wav3DOperator.set_acquired_points(*acq);
                    wav3DOperator.scale_factor_first_dimension_ = this->spirit_reg_RO_weighting_ratio.value();
                    wav3DOperator.scale_factor_second_dimension_ = this->spirit_reg_E1_weighting_ratio.value();
                    wav3DOperator.scale_factor_third_dimension_ = this->spirit_reg_N_weighting_ratio.value();
                    wav3DOperator.with_approx_coeff_ = !this->spirit_reg_keep_approx_coeff.value();
                    wav3DOperator.change_coeffcients_third_dimension_boundary_ = !this->spirit_reg_keep_redundant_dimension_coeff.value();
                    wav3DOperator.proximity_across_cha_ = this->spirit_reg_proximity_across_cha.value();
                    wav3DOperator.no_null_space_ = true;
                    wav3DOperator.input_in_kspace_ = true;
                    wav3DOperator.select_wavelet(this->spirit_reg_name.value());

                    if (this->spirit_reg_use_coil_sen_map.value() && hasCoilMap)
                    {
                        wav3DOperator.coil_map_ = *coilMap;
                    }

                    // set operators

                    solver.oper_system_ = &spirit;
                    solver.oper_reg_ = &wav3DOperator;

                    if (this->perform_timing.value()) timer.start("NonLinear SPIRIT solver for 2DT with data fidelity ... ");
                    solver.solve(*acq, res2DT);
                    if (this->perform_timing.value()) timer.stop();

                    if (!debug_folder_full_path_.empty()) gt_exporter_.export_array_complex(res2DT, debug_folder_full_path_ + "spirit_nl_2DT_data_fidelity_res");
                }
                else
                {
                    GDEBUG_STREAM("Start the NL SPIRIT iteration with regularization strength : "<< this->spirit_image_reg_lamda.value()
                                    << " - number of iteration : " << this->spirit_nl_iter_max.value()
                                    << " - proximity across cha : " << this->spirit_reg_proximity_across_cha.value()
                                    << " - redundant dimension weighting ratio : " << this->spirit_reg_N_weighting_ratio.value()
                                    << " - using coil sen map : " << this->spirit_reg_use_coil_sen_map.value()
                                    << " - iter thres : " << this->spirit_nl_iter_thres.value()
                                    << " - wavelet name : " << this->spirit_reg_name.value()
                                    );

                    typedef hoGdSolver< hoNDArray< std::complex<float> >, hoWavelet2DTOperator< std::complex<float> > > SolverType;
                    SolverType solver;
                    solver.iterations_ = this->spirit_nl_iter_max.value();
                    solver.set_output_mode(this->spirit_print_iter.value() ? SolverType::OUTPUT_VERBOSE : SolverType::OUTPUT_SILENT);
                    solver.grad_thres_ = this->spirit_nl_iter_thres.value();

                    if(spirit_reg_estimate_noise_floor.value() && std::abs(smallest_eigen_value)>0)
                    {
                        solver.scale_factor_ = smallest_eigen_value;
                        solver.proximal_strength_ratio_ = this->spirit_image_reg_lamda.value() * gfactorMedian;

                        GDEBUG_STREAM("SPIRIT Non linear, eigen value is used to derive the regularization strength : " << solver.proximal_strength_ratio_ << " - smallest eigen value : " << solver.scale_factor_);
                    }
                    else
                    {
                        solver.proximal_strength_ratio_ = this->spirit_image_reg_lamda.value();
                    }

                    boost::shared_ptr< hoNDArray< std::complex<float> > > x0 = boost::make_shared< hoNDArray< std::complex<float> > >(kspaceInitial);
                    solver.set_x0(x0);

                    // parallel imaging term
                    std::vector<size_t> dims;
                    acq->get_dimensions(dims);

                    hoSPIRIT2DTOperator< std::complex<float> > spirit(&dims);
                    spirit.set_forward_kernel(*ker, false);
                    spirit.set_acquired_points(*acq);
                    spirit.no_null_space_ = true;
                    spirit.use_non_centered_fft_ = false;

                    // image reg term
                    std::vector<size_t> dim;
                    acq->get_dimensions(dim);

                    hoWavelet2DTOperator< std::complex<float> > wav3DOperator(&dim);
                    wav3DOperator.set_acquired_points(*acq);
                    wav3DOperator.scale_factor_first_dimension_ = this->spirit_reg_RO_weighting_ratio.value();
                    wav3DOperator.scale_factor_second_dimension_ = this->spirit_reg_E1_weighting_ratio.value();
                    wav3DOperator.scale_factor_third_dimension_ = this->spirit_reg_N_weighting_ratio.value();
                    wav3DOperator.with_approx_coeff_ = !this->spirit_reg_keep_approx_coeff.value();
                    wav3DOperator.change_coeffcients_third_dimension_boundary_ = !this->spirit_reg_keep_redundant_dimension_coeff.value();
                    wav3DOperator.proximity_across_cha_ = this->spirit_reg_proximity_across_cha.value();
                    wav3DOperator.no_null_space_ = true;
                    wav3DOperator.input_in_kspace_ = true;
                    wav3DOperator.select_wavelet(this->spirit_reg_name.value());

                    if (this->spirit_reg_use_coil_sen_map.value() && hasCoilMap)
                    {
                        wav3DOperator.coil_map_ = *coilMap;
                    }

                    // set operators
                    solver.oper_system_ = &spirit;
                    solver.oper_reg_ = &wav3DOperator;

                    // set call back
                    solverCallBack cb;
                    cb.solver_ = &solver;
                    solver.call_back_ = &cb;

                    hoNDArray< std::complex<float> > b(kspaceInitial);
                    Gadgetron::clear(b);

                    if (this->perform_timing.value()) timer.start("NonLinear SPIRIT solver for 2DT ... ");
                    solver.solve(b, res2DT);
                    if (this->perform_timing.value()) timer.stop();

                    if (!debug_folder_full_path_.empty()) gt_exporter_.export_array_complex(res2DT, debug_folder_full_path_ + "spirit_nl_2DT_res");

                    spirit.restore_acquired_kspace(kspace, res2DT);

                    if (!debug_folder_full_path_.empty()) gt_exporter_.export_array_complex(res2DT, debug_folder_full_path_ + "spirit_nl_2DT_res_restored");
                }
            }
        }
        catch (...)
        {
            GADGET_THROW("Errors happened in GenericReconCartesianNonLinearSpirit2DTGadget::perform_nonlinear_spirit_unwrapping(...) ... ");
        }
    }
Ejemplo n.º 27
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;
}