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) ... "); } }
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; }
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) ... "); } }