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) ... ");
    }
}
Exemplo n.º 3
0
void hoSPIRITOperator<T>::restore_acquired_kspace(const ARRAY_TYPE& acquired, ARRAY_TYPE& y)
{
    try
    {
        GADGET_CHECK_THROW(acquired.get_number_of_elements() == y.get_number_of_elements());

        size_t N = acquired.get_number_of_elements();

        const T* pA = acquired.get_data_ptr();
        T* pY = y.get_data_ptr();

        int n(0);
#pragma omp parallel for default(none) private(n) shared(N, pA, pY)
        for (n = 0; n<(int)N; n++)
        {
            if (std::abs(pA[n]) > 0)
            {
                pY[n] = pA[n];
            }
        }
    }
    catch (...)
    {
        GADGET_THROW("Errors happened in hoSPIRITOperator<T>::restore_acquired_kspace(...) ... ");
    }
}
    void GenericReconCartesianGrappaGadget::compute_snr_map(ReconObjType &recon_obj,
                                                            hoNDArray<std::complex<float> > &snr_map) {

        typedef std::complex<float> T;

        snr_map = recon_obj.recon_res_.data_;

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

        size_t gN = recon_obj.gfactor_.get_size(4);
        size_t gS = recon_obj.gfactor_.get_size(5);

        GADGET_CHECK_THROW(recon_obj.gfactor_.get_size(0) == RO);
        GADGET_CHECK_THROW(recon_obj.gfactor_.get_size(1) == E1);
        GADGET_CHECK_THROW(recon_obj.gfactor_.get_size(2) == E2);
        GADGET_CHECK_THROW(recon_obj.gfactor_.get_size(3) == CHA);
        GADGET_CHECK_THROW(recon_obj.gfactor_.get_size(6) == SLC);

        size_t n, s, slc;
        for (slc = 0; slc < SLC; slc++) {
            for (s = 0; s < S; s++) {
                size_t usedS = s;
                if (usedS >= gS) usedS = gS - 1;

                for (n = 0; n < N; n++) {
                    size_t usedN = n;
                    if (usedN >= gN) usedN = gN - 1;

                    float *pG = &(recon_obj.gfactor_(0, 0, 0, 0, usedN, usedS, slc));
                    T *pIm = &(recon_obj.recon_res_.data_(0, 0, 0, 0, n, s, slc));
                    T *pSNR = &(snr_map(0, 0, 0, 0, n, s, slc));

                    for (size_t ii = 0; ii < RO * E1 * E2 * CHA; ii++) {
                        pSNR[ii] = pIm[ii] / pG[ii];
                    }
                }
            }
        }

    }
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 BucketToBufferGadget::stuff(std::vector<IsmrmrdAcquisitionData>::iterator it, IsmrmrdDataBuffered & dataBuffer, ISMRMRD::Encoding encoding, IsmrmrdAcquisitionBucketStats & stats, bool forref)
  {

    // The acquisition header and data
    ISMRMRD::AcquisitionHeader & acqhdr = *it->head_->getObjectPtr();
    hoNDArray< std::complex<float> > & acqdata = *it->data_->getObjectPtr();
    // we make one for the trajectory down below if we need it

    uint16_t NE0  = (uint16_t)dataBuffer.data_.get_size(0);
    uint16_t NE1  = (uint16_t)dataBuffer.data_.get_size(1);
    uint16_t NE2  = (uint16_t)dataBuffer.data_.get_size(2);
    uint16_t NCHA = (uint16_t)dataBuffer.data_.get_size(3);
    uint16_t NN   = (uint16_t)dataBuffer.data_.get_size(4);
    uint16_t NS   = (uint16_t)dataBuffer.data_.get_size(5);
    uint16_t NLOC = (uint16_t)dataBuffer.data_.get_size(6);

    size_t slice_loc;
    if (split_slices_ || NLOC==1)
      {
        slice_loc = 0;
      }
    else
      {
        slice_loc = acqhdr.idx.slice;
      }

    //Stuff the data
    uint16_t npts_to_copy = acqhdr.number_of_samples - acqhdr.discard_pre - acqhdr.discard_post;
    long long offset;
    if (encoding.trajectory == ISMRMRD::TrajectoryType::CARTESIAN || encoding.trajectory == ISMRMRD::TrajectoryType::EPI) {
        if ((acqhdr.number_of_samples == dataBuffer.data_.get_size(0)) && (acqhdr.center_sample == acqhdr.number_of_samples/2)) // acq has been corrected for center , e.g. by asymmetric handling
        {
            offset = acqhdr.discard_pre;
        }
        else
        {
            offset = (long long)dataBuffer.sampling_.sampling_limits_[0].center_ - (long long)acqhdr.center_sample;
        }
    } else {
        //TODO what about EPI with asymmetric readouts?
        //TODO any other sort of trajectory?
        offset = 0;
    }
    long long roffset = (long long) dataBuffer.data_.get_size(0) - npts_to_copy - offset;

    //GDEBUG_STREAM("Num_samp: "<< acqhdr.number_of_samples << ", pre: " << acqhdr.discard_pre << ", post" << acqhdr.discard_post << std::endl);
    //std::cout << "Sampling limits: "
    //    << "  min: " << dataBuffer.sampling_.sampling_limits_[0].min_
    //    << "  max: " << dataBuffer.sampling_.sampling_limits_[0].max_
    //    << "  center: " << dataBuffer.sampling_.sampling_limits_[0].center_
    //    << std::endl;
    //GDEBUG_STREAM("npts_to_copy = " << npts_to_copy  << std::endl);
    //GDEBUG_STREAM("offset = " << offset  << std::endl);
    //GDEBUG_STREAM("loffset = " << roffset << std::endl);

    if ((offset < 0) | (roffset < 0) )
      {
        throw std::runtime_error("Acquired reference data does not fit into the reference data buffer.\n");
      }

    std::complex<float> *dataptr;

    uint16_t NUsed = (uint16_t)getN(acqhdr.idx);
    if (NUsed >= NN) NUsed = NN - 1;

    uint16_t SUsed = (uint16_t)getS(acqhdr.idx);
    if (SUsed >= NS) SUsed = NS - 1;

    int16_t e1 = (int16_t)acqhdr.idx.kspace_encode_step_1;
    int16_t e2 = (int16_t)acqhdr.idx.kspace_encode_step_2;

    bool is_cartesian_sampling = (encoding.trajectory == ISMRMRD::TrajectoryType::CARTESIAN);
    bool is_epi_sampling = (encoding.trajectory == ISMRMRD::TrajectoryType::EPI);
    if(is_cartesian_sampling || is_epi_sampling)
    {
        if (!forref || (forref && (encoding.parallelImaging.get().calibrationMode.get() == "embedded")))
        {
            // compute the center offset for E1 and E2
            int16_t space_matrix_offset_E1 = 0;
            if (encoding.encodingLimits.kspace_encoding_step_1.is_present())
            {
                space_matrix_offset_E1 = (int16_t)encoding.encodedSpace.matrixSize.y / 2 - (int16_t)encoding.encodingLimits.kspace_encoding_step_1->center;
            }

            int16_t space_matrix_offset_E2 = 0;
            if (encoding.encodingLimits.kspace_encoding_step_2.is_present() && encoding.encodedSpace.matrixSize.z > 1)
            {
                space_matrix_offset_E2 = (int16_t)encoding.encodedSpace.matrixSize.z / 2 - (int16_t)encoding.encodingLimits.kspace_encoding_step_2->center;
            }

            // compute the used e1 and e2 indices and make sure they are in the valid range
            e1 = (int16_t)acqhdr.idx.kspace_encode_step_1 + space_matrix_offset_E1;
            e2 = (int16_t)acqhdr.idx.kspace_encode_step_2 + space_matrix_offset_E2;
        }

        // for external or separate mode, it is possible the starting numbers of ref lines are not zero, therefore it is needed to subtract the staring ref line number
        // because the ref array size is set up by the actual number of lines acquired
        // only assumption for external or separate ref line mode is that all ref lines are numbered sequentially
        // the acquisition order of ref line can be arbitrary
        if (forref && ( (encoding.parallelImaging.get().calibrationMode.get() == "separate") || (encoding.parallelImaging.get().calibrationMode.get() == "external") ) )
        {
            if(*stats.kspace_encode_step_1.begin()>0)
            {
                e1 = acqhdr.idx.kspace_encode_step_1 - *stats.kspace_encode_step_1.begin();
            }

            if(*stats.kspace_encode_step_2.begin()>0)
            {
                e2 = acqhdr.idx.kspace_encode_step_2 - *stats.kspace_encode_step_2.begin();
            }
        }

        if (e1 < 0 || e1 >= (int16_t)NE1)
        {
            // if the incoming line is outside the encoding limits, something is wrong
            GADGET_CHECK_THROW(acqhdr.idx.kspace_encode_step_1>=encoding.encodingLimits.kspace_encoding_step_1->minimum && acqhdr.idx.kspace_encode_step_1 <= encoding.encodingLimits.kspace_encoding_step_1->maximum);

            // if the incoming line is inside encoding limits but outside the encoded matrix, do not include the data
            GWARN_STREAM("incoming readout " << acqhdr.scan_counter << " is inside the encoding limits, but outside the encoded matrix for kspace_encode_step_1 : " << e1 << " out of " << NE1);
            return;
        }

        if (e2 < 0 || e2 >= (int16_t)NE2)
        {
            GADGET_CHECK_THROW(acqhdr.idx.kspace_encode_step_2 >= encoding.encodingLimits.kspace_encoding_step_2->minimum && acqhdr.idx.kspace_encode_step_2 <= encoding.encodingLimits.kspace_encoding_step_2->maximum);

            GWARN_STREAM("incoming readout " << acqhdr.scan_counter << " is inside the encoding limits, but outside the encoded matrix for kspace_encode_step_2 : " << e2 << " out of " << NE2);
            return;
        }
    }

    std::complex<float>* pData = &dataBuffer.data_(offset, e1, e2, 0, NUsed, SUsed, slice_loc);

    for (uint16_t cha = 0; cha < NCHA; cha++)
    {
        dataptr = pData + cha*NE0*NE1*NE2;
        memcpy(dataptr, &acqdata(acqhdr.discard_pre, cha), sizeof(std::complex<float>)*npts_to_copy);
    }

    dataBuffer.headers_(e1, e2, NUsed, SUsed, slice_loc) = acqhdr;

    if (acqhdr.trajectory_dimensions > 0)
    {

        hoNDArray< float > & acqtraj = *it->traj_->getObjectPtr();  // TODO do we need to check this?

        float * trajptr;

        trajptr = &(*dataBuffer.trajectory_)(0, offset, e1, e2, NUsed, SUsed, slice_loc);

        memcpy(trajptr, &acqtraj(0, acqhdr.discard_pre), sizeof(float)*npts_to_copy*acqhdr.trajectory_dimensions);

    }
  }
  void BucketToBufferGadget::fillSamplingDescription(SamplingDescription & sampling, ISMRMRD::Encoding & encoding, IsmrmrdAcquisitionBucketStats & stats, ISMRMRD::AcquisitionHeader& acqhdr, bool forref)
  {
    // For cartesian trajectories, assume that any oversampling has been removed.
    if (encoding.trajectory == ISMRMRD::TrajectoryType::CARTESIAN) {
        sampling.encoded_FOV_[0] = encoding.reconSpace.fieldOfView_mm.x;
        sampling.encoded_matrix_[0] = encoding.reconSpace.matrixSize.x;
    } else {
        sampling.encoded_FOV_[0] = encoding.encodedSpace.fieldOfView_mm.x;
        sampling.encoded_matrix_[0] = encoding.encodedSpace.matrixSize.x;
    }

    sampling.encoded_FOV_[1] = encoding.encodedSpace.fieldOfView_mm.y;
    sampling.encoded_FOV_[2] = encoding.encodedSpace.fieldOfView_mm.z;

    sampling.encoded_matrix_[1] = encoding.encodedSpace.matrixSize.y;
    sampling.encoded_matrix_[2] = encoding.encodedSpace.matrixSize.z;

    sampling.recon_FOV_[0] = encoding.reconSpace.fieldOfView_mm.x;
    sampling.recon_FOV_[1] = encoding.reconSpace.fieldOfView_mm.y;
    sampling.recon_FOV_[2] = encoding.reconSpace.fieldOfView_mm.z;

    sampling.recon_matrix_[0] = encoding.reconSpace.matrixSize.x;
    sampling.recon_matrix_[1] = encoding.reconSpace.matrixSize.y;
    sampling.recon_matrix_[2] = encoding.reconSpace.matrixSize.z;

    // For cartesian trajectories, assume that any oversampling has been removed.
    if ( ((encoding.trajectory == ISMRMRD::TrajectoryType::CARTESIAN)) || (encoding.trajectory == ISMRMRD::TrajectoryType::EPI) )
    {
        sampling.sampling_limits_[0].min_ = acqhdr.discard_pre;
        sampling.sampling_limits_[0].max_ = acqhdr.number_of_samples - acqhdr.discard_post - 1;
        sampling.sampling_limits_[0].center_ = acqhdr.number_of_samples / 2;
    } else {
        sampling.sampling_limits_[0].min_ = 0;
        sampling.sampling_limits_[0].max_ = encoding.encodedSpace.matrixSize.x - 1;
        sampling.sampling_limits_[0].center_ = encoding.encodedSpace.matrixSize.x / 2;
    }

    // if the scan is cartesian  
        if ( ( (encoding.trajectory == ISMRMRD::TrajectoryType::CARTESIAN) && (!forref || (forref && (encoding.parallelImaging.get().calibrationMode.get() == "embedded"))) )
        || ( (encoding.trajectory == ISMRMRD::TrajectoryType::EPI) && !forref) )
    {
        int16_t space_matrix_offset_E1 = 0;
        if (encoding.encodingLimits.kspace_encoding_step_1.is_present())
        {
            space_matrix_offset_E1 = (int16_t)encoding.encodedSpace.matrixSize.y / 2 - (int16_t)encoding.encodingLimits.kspace_encoding_step_1->center;
        }

        int16_t space_matrix_offset_E2 = 0;
        if (encoding.encodingLimits.kspace_encoding_step_2.is_present() && encoding.encodedSpace.matrixSize.z > 1)
        {
            space_matrix_offset_E2 = (int16_t)encoding.encodedSpace.matrixSize.z / 2 - (int16_t)encoding.encodingLimits.kspace_encoding_step_2->center;
        }

        // E1
        sampling.sampling_limits_[1].min_ = encoding.encodingLimits.kspace_encoding_step_1->minimum + space_matrix_offset_E1;
        sampling.sampling_limits_[1].max_ = encoding.encodingLimits.kspace_encoding_step_1->maximum + space_matrix_offset_E1;
        sampling.sampling_limits_[1].center_ = sampling.encoded_matrix_[1] / 2;

        GADGET_CHECK_THROW(sampling.sampling_limits_[1].min_ < encoding.encodedSpace.matrixSize.y);
        GADGET_CHECK_THROW(sampling.sampling_limits_[1].max_ >= sampling.sampling_limits_[1].min_);
        GADGET_CHECK_THROW(sampling.sampling_limits_[1].center_ >= sampling.sampling_limits_[1].min_);
        GADGET_CHECK_THROW(sampling.sampling_limits_[1].center_ <= sampling.sampling_limits_[1].max_);

        // E2
        sampling.sampling_limits_[2].min_ = encoding.encodingLimits.kspace_encoding_step_2->minimum + space_matrix_offset_E2;
        sampling.sampling_limits_[2].max_ = encoding.encodingLimits.kspace_encoding_step_2->maximum + space_matrix_offset_E2;
        sampling.sampling_limits_[2].center_ = sampling.encoded_matrix_[2] / 2;

        GADGET_CHECK_THROW(sampling.sampling_limits_[2].min_ < encoding.encodedSpace.matrixSize.y);
        GADGET_CHECK_THROW(sampling.sampling_limits_[2].max_ >= sampling.sampling_limits_[2].min_);
        GADGET_CHECK_THROW(sampling.sampling_limits_[2].center_ >= sampling.sampling_limits_[2].min_);
        GADGET_CHECK_THROW(sampling.sampling_limits_[2].center_ <= sampling.sampling_limits_[2].max_);
    }
    else
    {
        sampling.sampling_limits_[1].min_ = encoding.encodingLimits.kspace_encoding_step_1->minimum;
        sampling.sampling_limits_[1].max_ = encoding.encodingLimits.kspace_encoding_step_1->maximum;
        sampling.sampling_limits_[1].center_ = encoding.encodingLimits.kspace_encoding_step_1->center;

        sampling.sampling_limits_[2].min_ = encoding.encodingLimits.kspace_encoding_step_2->minimum;
        sampling.sampling_limits_[2].max_ = encoding.encodingLimits.kspace_encoding_step_2->maximum;
        sampling.sampling_limits_[2].center_ = encoding.encodingLimits.kspace_encoding_step_2->center;
    }

    if (verbose.value())
    {
        GDEBUG_STREAM("Encoding space : " << int(encoding.trajectory)
            << " - FOV : [ " << encoding.encodedSpace.fieldOfView_mm.x << " " << encoding.encodedSpace.fieldOfView_mm.y << " " << encoding.encodedSpace.fieldOfView_mm.z << " ] "
            << " - Matris size : [ " << encoding.encodedSpace.matrixSize.x << " " << encoding.encodedSpace.matrixSize.y << " " << encoding.encodedSpace.matrixSize.z << " ] ");

        GDEBUG_STREAM("Sampling limits : "
                << "- RO : [ " << sampling.sampling_limits_[0].min_ << " " << sampling.sampling_limits_[0].center_ << " " << sampling.sampling_limits_[0].max_
                << " ] - E1 : [ " << sampling.sampling_limits_[1].min_ << " " << sampling.sampling_limits_[1].center_ << " " << sampling.sampling_limits_[1].max_
                << " ] - E2 : [ " << sampling.sampling_limits_[2].min_ << " " << sampling.sampling_limits_[2].center_ << " " << sampling.sampling_limits_[2].max_ << " ]");
    }
  }
    void MultiChannelCartesianGrappaReconGadget::compute_image_header(IsmrmrdReconBit& recon_bit, ReconObjType& recon_obj, size_t e)
    {
        try
        {
            size_t RO = recon_obj.recon_res_.data_.get_size(0);
            size_t E1 = recon_obj.recon_res_.data_.get_size(1);
            size_t E2 = recon_obj.recon_res_.data_.get_size(2);
            size_t CHA = recon_obj.recon_res_.data_.get_size(3);
            size_t N = recon_obj.recon_res_.data_.get_size(4);
            size_t S = recon_obj.recon_res_.data_.get_size(5);
            size_t SLC = recon_obj.recon_res_.data_.get_size(6);

            GADGET_CHECK_THROW(N == recon_bit.data_.headers_.get_size(2));
            GADGET_CHECK_THROW(S == recon_bit.data_.headers_.get_size(3));

            recon_obj.recon_res_.headers_.create(N, S, SLC);
            recon_obj.recon_res_.meta_.resize(N*S*SLC);

            size_t n, s, slc;

            for (slc = 0; slc < SLC; slc++)
            {
                for (s = 0; s < S; s++)
                {
                    for (n = 0; n < N; n++)
                    {
                        size_t header_E1 = recon_bit.data_.headers_.get_size(0);
                        size_t header_E2 = recon_bit.data_.headers_.get_size(1);

                        // for every kspace, find the recorded header which is closest to the kspace center [E1/2 E2/2]
                        ISMRMRD::AcquisitionHeader acq_header;

                        long long bestE1 = E1 + 1;
                        long long bestE2 = E2 + 1;

                        size_t e1, e2;
                        for (e2 = 0; e2 < header_E2; e2++)
                        {
                            for (e1 = 0; e1 < header_E1; e1++)
                            {
                                ISMRMRD::AcquisitionHeader& curr_header = recon_bit.data_.headers_(e1, e2, n, s, slc);

                                // if (curr_header.measurement_uid != 0) // a valid header
                                {
                                    if (E2 > 1)
                                    {
                                        if (std::abs((long long)curr_header.idx.kspace_encode_step_1 - (long long)(E1 / 2)) < bestE1
                                            && std::abs((long long)curr_header.idx.kspace_encode_step_2 - (long long)(E2 / 2)) < bestE2)
                                        {
                                            bestE1 = std::abs((long long)curr_header.idx.kspace_encode_step_1 - (long long)E1 / 2);
                                            bestE2 = std::abs((long long)curr_header.idx.kspace_encode_step_2 - (long long)E2 / 2);

                                            acq_header = curr_header;
                                        }
                                    }
                                    else
                                    {
                                        if (std::abs((long long)curr_header.idx.kspace_encode_step_1 - (long long)(E1 / 2)) < bestE1)
                                        {
                                            bestE1 = std::abs((long long)curr_header.idx.kspace_encode_step_1 - (long long)E1 / 2);

                                            acq_header = curr_header;
                                        }
                                    }
                                }
                            }
                        }

                        //if (acq_header.measurement_uid == 0)
                        //{
                        //    std::ostringstream ostr;
                        //    ostr << "Cannot create valid image header : n = " << n << ", s = " << s << ", slc = " << slc;
                        //    GADGET_THROW(ostr.str());
                        //}
                        //else
                        //{
                            ISMRMRD::ImageHeader& im_header = recon_obj.recon_res_.headers_(n, s, slc);
                            ISMRMRD::MetaContainer& meta = recon_obj.recon_res_.meta_[n + s*N + slc*N*S];

                            im_header.version = acq_header.version;
                            im_header.data_type = ISMRMRD::ISMRMRD_CXFLOAT;
                            im_header.flags = acq_header.flags;
                            im_header.measurement_uid = acq_header.measurement_uid;

                            im_header.matrix_size[0] = (uint16_t)RO;
                            im_header.matrix_size[1] = (uint16_t)E1;
                            im_header.matrix_size[2] = (uint16_t)E2;

                            im_header.field_of_view[0] = recon_bit.data_.sampling_.recon_FOV_[0];
                            im_header.field_of_view[1] = recon_bit.data_.sampling_.recon_FOV_[1];
                            im_header.field_of_view[2] = recon_bit.data_.sampling_.recon_FOV_[2];

                            im_header.channels = (uint16_t)CHA;

                            im_header.position[0] = acq_header.position[0];
                            im_header.position[1] = acq_header.position[1];
                            im_header.position[2] = acq_header.position[2];

                            im_header.read_dir[0] = acq_header.read_dir[0];
                            im_header.read_dir[1] = acq_header.read_dir[1];
                            im_header.read_dir[2] = acq_header.read_dir[2];

                            im_header.phase_dir[0] = acq_header.phase_dir[0];
                            im_header.phase_dir[1] = acq_header.phase_dir[1];
                            im_header.phase_dir[2] = acq_header.phase_dir[2];

                            im_header.slice_dir[0] = acq_header.slice_dir[0];
                            im_header.slice_dir[1] = acq_header.slice_dir[1];
                            im_header.slice_dir[2] = acq_header.slice_dir[2];

                            im_header.patient_table_position[0] = acq_header.patient_table_position[0];
                            im_header.patient_table_position[1] = acq_header.patient_table_position[1];
                            im_header.patient_table_position[2] = acq_header.patient_table_position[2];

                            im_header.average = acq_header.idx.average;
                            im_header.slice = acq_header.idx.slice;
                            im_header.contrast = acq_header.idx.contrast;
                            im_header.phase = acq_header.idx.phase;
                            im_header.repetition = acq_header.idx.repetition;
                            im_header.set = acq_header.idx.set;

                            im_header.acquisition_time_stamp = acq_header.acquisition_time_stamp;

                            im_header.physiology_time_stamp[0] = acq_header.physiology_time_stamp[0];
                            im_header.physiology_time_stamp[1] = acq_header.physiology_time_stamp[1];
                            im_header.physiology_time_stamp[2] = acq_header.physiology_time_stamp[2];

                            im_header.image_type = ISMRMRD::ISMRMRD_IMTYPE_MAGNITUDE;
                            im_header.image_index = (uint16_t)(n + s*N + slc*N*S);
                            im_header.image_series_index = 0;

                            memcpy(im_header.user_int, acq_header.user_int, sizeof(int32_t)*ISMRMRD::ISMRMRD_USER_INTS);
                            memcpy(im_header.user_float, acq_header.user_float, sizeof(float)*ISMRMRD::ISMRMRD_USER_FLOATS);

                            im_header.attribute_string_len = 0;

                            meta.set("encoding", (long)e);

                            meta.set("encoding_FOV", recon_bit.data_.sampling_.encoded_FOV_[0]);
                            meta.append("encoding_FOV", recon_bit.data_.sampling_.encoded_FOV_[1]);
                            meta.append("encoding_FOV", recon_bit.data_.sampling_.encoded_FOV_[2]);

                            meta.set("recon_FOV", recon_bit.data_.sampling_.recon_FOV_[0]);
                            meta.append("recon_FOV", recon_bit.data_.sampling_.recon_FOV_[1]);
                            meta.append("recon_FOV", recon_bit.data_.sampling_.recon_FOV_[2]);

                            meta.set("encoded_matrix", (long)recon_bit.data_.sampling_.encoded_matrix_[0]);
                            meta.append("encoded_matrix", (long)recon_bit.data_.sampling_.encoded_matrix_[1]);
                            meta.append("encoded_matrix", (long)recon_bit.data_.sampling_.encoded_matrix_[2]);

                            meta.set("recon_matrix", (long)recon_bit.data_.sampling_.recon_matrix_[0]);
                            meta.append("recon_matrix", (long)recon_bit.data_.sampling_.recon_matrix_[1]);
                            meta.append("recon_matrix", (long)recon_bit.data_.sampling_.recon_matrix_[2]);

                            meta.set("sampling_limits_RO", (long)recon_bit.data_.sampling_.sampling_limits_[0].min_);
                            meta.append("sampling_limits_RO", (long)recon_bit.data_.sampling_.sampling_limits_[0].center_);
                            meta.append("sampling_limits_RO", (long)recon_bit.data_.sampling_.sampling_limits_[0].max_);

                            meta.set("sampling_limits_E1", (long)recon_bit.data_.sampling_.sampling_limits_[1].min_);
                            meta.append("sampling_limits_E1", (long)recon_bit.data_.sampling_.sampling_limits_[1].center_);
                            meta.append("sampling_limits_E1", (long)recon_bit.data_.sampling_.sampling_limits_[1].max_);

                            meta.set("sampling_limits_E2", (long)recon_bit.data_.sampling_.sampling_limits_[2].min_);
                            meta.append("sampling_limits_E2", (long)recon_bit.data_.sampling_.sampling_limits_[2].center_);
                            meta.append("sampling_limits_E2", (long)recon_bit.data_.sampling_.sampling_limits_[2].max_);
                        //}
                    }
                }
            }
        }
        catch (...)
        {
            GADGET_THROW("Errors happened in MultiChannelCartesianGrappaReconGadget::compute_image_header(...) ... ");
        }
    }
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;
}
Exemplo n.º 10
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) ... ");
    }
}