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::stuff(std::vector<IsmrmrdAcquisitionData>::iterator it, IsmrmrdDataBuffered & dataBuffer, ISMRMRD::Encoding encoding) { // 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 size_t slice_loc; if (split_slices_) { 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.compare("cartesian") == 0) { 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 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 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; for (uint16_t cha = 0; cha < NCHA; cha++) { dataptr = & dataBuffer.data_( offset, acqhdr.idx.kspace_encode_step_1, acqhdr.idx.kspace_encode_step_2, cha, NUsed, SUsed, slice_loc); memcpy(dataptr, &acqdata(acqhdr.discard_pre, cha), sizeof(std::complex<float>)*npts_to_copy); } //Stuff the header dataBuffer.headers_(acqhdr.idx.kspace_encode_step_1, acqhdr.idx.kspace_encode_step_2, NUsed, SUsed, slice_loc) = acqhdr; //Stuff the trajectory 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, acqhdr.idx.kspace_encode_step_1, acqhdr.idx.kspace_encode_step_2, NUsed, SUsed, slice_loc); memcpy(trajptr, &acqtraj(0, acqhdr.discard_pre), sizeof(float)*npts_to_copy*acqhdr.trajectory_dimensions); } }