int SimpleReconGadget::process( GadgetContainerMessage<IsmrmrdReconData>* m1) { //Iterate over all the recon bits for(std::vector<IsmrmrdReconBit>::iterator it = m1->getObjectPtr()->rbit_.begin(); it != m1->getObjectPtr()->rbit_.end(); ++it) { //Grab a reference to the buffer containing the imaging data //We are ignoring the reference data IsmrmrdDataBuffered & dbuff = it->data_; //Data 7D, fixed order [E0, E1, E2, CHA, N, S, LOC] uint16_t E0 = dbuff.data_.get_size(0); uint16_t E1 = dbuff.data_.get_size(1); uint16_t E2 = dbuff.data_.get_size(2); uint16_t CHA = dbuff.data_.get_size(3); uint16_t N = dbuff.data_.get_size(4); uint16_t S = dbuff.data_.get_size(5); uint16_t LOC = dbuff.data_.get_size(6); //Create an image array message GadgetContainerMessage<IsmrmrdImageArray>* cm1 = new GadgetContainerMessage<IsmrmrdImageArray>(); //Grab references to the image array data and headers IsmrmrdImageArray & imarray = *cm1->getObjectPtr(); //The image array data will be [E0,E1,E2,1,N,S,LOC] big //Will collapse across coils at the end std::vector<size_t> data_dims(7); data_dims[0] = E0; data_dims[1] = E1; data_dims[2] = E2; data_dims[3] = 1; data_dims[4] = N; data_dims[5] = S; data_dims[6] = LOC; imarray.data_.create(&data_dims); //ImageHeaders will be [N, S, LOC] std::vector<size_t> header_dims(3); header_dims[0] = N; header_dims[1] = S; header_dims[2] = LOC; imarray.headers_.create(&header_dims); //We will not add any meta data //so skip the meta_ part //Loop over S and N and LOC for (uint16_t loc=0; loc < LOC; loc++) { for (uint16_t s=0; s < S; s++) { for (uint16_t n=0; n < N; n++) { //Set some information into the image header //Use the middle acquisition header for some info //[E1, E2, N, S, LOC] ISMRMRD::AcquisitionHeader & acqhdr = dbuff.headers_(dbuff.sampling_.sampling_limits_[1].center_, dbuff.sampling_.sampling_limits_[2].center_, n, s, loc); imarray.headers_(n,s,loc).matrix_size[0] = E0; imarray.headers_(n,s,loc).matrix_size[1] = E1; imarray.headers_(n,s,loc).matrix_size[2] = E2; imarray.headers_(n,s,loc).field_of_view[0] = dbuff.sampling_.recon_FOV_[0]; imarray.headers_(n,s,loc).field_of_view[1] = dbuff.sampling_.recon_FOV_[1]; imarray.headers_(n,s,loc).field_of_view[2] = dbuff.sampling_.recon_FOV_[2]; imarray.headers_(n,s,loc).channels = 1; imarray.headers_(n,s,loc).average = acqhdr.idx.average; imarray.headers_(n,s,loc).slice = acqhdr.idx.slice; imarray.headers_(n,s,loc).contrast = acqhdr.idx.contrast; imarray.headers_(n,s,loc).phase = acqhdr.idx.phase; imarray.headers_(n,s,loc).repetition = acqhdr.idx.repetition; imarray.headers_(n,s,loc).set = acqhdr.idx.set; imarray.headers_(n,s,loc).acquisition_time_stamp = acqhdr.acquisition_time_stamp; imarray.headers_(n,s,loc).position[0] = acqhdr.position[0]; imarray.headers_(n,s,loc).position[1] = acqhdr.position[1]; imarray.headers_(n,s,loc).position[2] = acqhdr.position[2]; imarray.headers_(n,s,loc).read_dir[0] = acqhdr.read_dir[0]; imarray.headers_(n,s,loc).read_dir[1] = acqhdr.read_dir[1]; imarray.headers_(n,s,loc).read_dir[2] = acqhdr.read_dir[2]; imarray.headers_(n,s,loc).phase_dir[0] = acqhdr.phase_dir[0]; imarray.headers_(n,s,loc).phase_dir[1] = acqhdr.phase_dir[1]; imarray.headers_(n,s,loc).phase_dir[2] = acqhdr.phase_dir[2]; imarray.headers_(n,s,loc).slice_dir[0] = acqhdr.slice_dir[0]; imarray.headers_(n,s,loc).slice_dir[1] = acqhdr.slice_dir[1]; imarray.headers_(n,s,loc).slice_dir[2] = acqhdr.slice_dir[2]; imarray.headers_(n,s,loc).patient_table_position[0] = acqhdr.patient_table_position[0]; imarray.headers_(n,s,loc).patient_table_position[1] = acqhdr.patient_table_position[1]; imarray.headers_(n,s,loc).patient_table_position[2] = acqhdr.patient_table_position[2]; imarray.headers_(n,s,loc).data_type = ISMRMRD::ISMRMRD_CXFLOAT; imarray.headers_(n,s,loc).image_index = ++image_counter_; //Grab a wrapper around the relevant chunk of data [E0,E1,E2,CHA] for this loc, n, and s //Each chunk will be [E0,E1,E2,CHA] big std::vector<size_t> chunk_dims(4); chunk_dims[0] = E0; chunk_dims[1] = E1; chunk_dims[2] = E2; chunk_dims[3] = CHA; hoNDArray<std::complex<float> > chunk = hoNDArray<std::complex<float> >(chunk_dims, &dbuff.data_(0,0,0,0,n,s,loc)); //Do the FFTs in place hoNDFFT<float>::instance()->ifft(&chunk,0); hoNDFFT<float>::instance()->ifft(&chunk,1); if (E2>1) { hoNDFFT<float>::instance()->ifft(&chunk,2); } //Square root of the sum of squares //Each image will be [E0,E1,E2,1] big std::vector<size_t> img_dims(3); img_dims[0] = E0; img_dims[1] = E1; img_dims[2] = E2; hoNDArray<std::complex<float> > output = hoNDArray<std::complex<float> >(img_dims, &imarray.data_(0,0,0,0,n,s,loc)); //Zero out the output clear(output); //Compute d* d in place multiplyConj(chunk,chunk,chunk); //Add up for (size_t c = 0; c < CHA; c++) { output += hoNDArray<std::complex<float> >(img_dims, &chunk(0,0,0,c)); } //Take the square root in place sqrt_inplace(&output); } } } //Pass the image array down the chain if (this->next()->putq(cm1) < 0) { m1->release(); return GADGET_FAIL; } } m1->release(); return GADGET_OK; }
int NFFT2DGadget::process(GadgetContainerMessage< ISMRMRD::AcquisitionHeader > *m1, // header GadgetContainerMessage< hoNDArray< std::complex<float> > > *m2, // data GadgetContainerMessage< hoNDArray<float> > *m3 ) // traj/dcw { // Throw away any noise samples if they have been allowed to pass this far down the chain... // bool is_noise = m1->getObjectPtr()->isFlagSet(ISMRMRD::ISMRMRD_ACQ_IS_NOISE_MEASUREMENT); if (is_noise) { m1->release(); return GADGET_OK; } // First pass initialization // if (frame_readout_queue_->message_count() == 0 ) { samples_per_readout_ = m1->getObjectPtr()->number_of_samples; num_coils_ = m1->getObjectPtr()->active_channels; dimensions_.push_back(m1->getObjectPtr()->active_channels); dimensions_.push_back(repetitions_); num_trajectory_dims_ = m3->getObjectPtr()->get_size(0); // 2 for trajectories only, 3 for both trajectories + dcw } int samples = m1->getObjectPtr()->number_of_samples; int readout = m1->getObjectPtr()->idx.kspace_encode_step_1; int repetition = m1->getObjectPtr()->idx.kspace_encode_step_2; // Enqueue incoming readouts and trajectories // frame_readout_queue_->enqueue_tail(duplicate_array(m2)); frame_traj_queue_->enqueue_tail(duplicate_array(m3)); // If the last readout for a slice has arrived then perform a reconstruction // bool is_last_scan_in_repetition = m1->getObjectPtr()->isFlagSet(ISMRMRD::ISMRMRD_ACQ_LAST_IN_REPETITION); if (is_last_scan_in_repetition) { // Define the image header // GadgetContainerMessage<ISMRMRD::ImageHeader> *cm1 = new GadgetContainerMessage<ISMRMRD::ImageHeader>(); GadgetContainerMessage< hoNDArray< std::complex<float> > > *cm2 = new GadgetContainerMessage<hoNDArray< std::complex<float> > >(); cm1->getObjectPtr()->flags = 0; cm1->cont(cm2); cm1->getObjectPtr()->matrix_size[0] = dimensions_[0]; cm1->getObjectPtr()->matrix_size[1] = dimensions_[1]; cm1->getObjectPtr()->matrix_size[2] = 1; cm1->getObjectPtr()->field_of_view[0] = field_of_view_[0]; cm1->getObjectPtr()->field_of_view[1] = field_of_view_[1]; cm1->getObjectPtr()->channels = num_coils_; cm1->getObjectPtr()->repetition = m1->getObjectPtr()->idx.repetition; memcpy(cm1->getObjectPtr()->position, m1->getObjectPtr()->position, sizeof(float)*3); memcpy(cm1->getObjectPtr()->read_dir, m1->getObjectPtr()->read_dir, sizeof(float)*3); memcpy(cm1->getObjectPtr()->phase_dir, m1->getObjectPtr()->phase_dir, sizeof(float)*3); memcpy(cm1->getObjectPtr()->slice_dir, m1->getObjectPtr()->slice_dir, sizeof(float)*3); memcpy(cm1->getObjectPtr()->patient_table_position, m1->getObjectPtr()->patient_table_position, sizeof(float)*3); cm1->getObjectPtr()->data_type = ISMRMRD::ISMRMRD_CXFLOAT; cm1->getObjectPtr()->image_index = 0; cm1->getObjectPtr()->image_series_index = 0; // // Perform reconstruction of repetition // // Get samples for frame // cuNDArray<float_complext> samples( extract_samples_from_queue( frame_readout_queue_.get()).get() ); // Get trajectories/dcw for frame // boost::shared_ptr< cuNDArray<floatd2> > traj(new cuNDArray<floatd2>); boost::shared_ptr<cuNDArray<float> > dcw(new cuNDArray<float>); extract_trajectory_and_dcw_from_queue( frame_traj_queue_.get(), traj.get(), dcw.get() ); //traj = compute_radial_trajectory_golden_ratio_2d<float>(samples_per_readout_,dimensions_[1],1,0,GR_ORIGINAL); unsigned int num_profiles = samples.get_number_of_elements()/samples_per_readout_; dcw = compute_radial_dcw_golden_ratio_2d<float>(samples_per_readout_,num_profiles,1.0,1.0f/samples_per_readout_/num_profiles,0,GR_ORIGINAL); // Create output array // std::vector<size_t> img_dims(2); img_dims[0] = dimensions_[0]; img_dims[1] = dimensions_[1]; cm2->getObjectPtr()->create(&img_dims); cuNDArray<float_complext> image(&img_dims); // Initialize plan // const float kernel_width = 5.5f; cuNFFT_plan<float,2> plan( from_std_vector<size_t,2>(img_dims), from_std_vector<size_t,2>(img_dims)<<1, kernel_width ); plan.preprocess( traj.get(), cuNFFT_plan<float,2>::NFFT_PREP_NC2C ); /* if( dcw->get_number_of_elements() == 0 ){ std::vector<size_t> dcw_dims; dcw_dims.push_back(samples_per_readout_); hoNDArray<float> host_dcw( dcw_dims ); for( int i=0; i<(int)dcw_dims[0]; i++ ) host_dcw.get_data_ptr()[i]=abs(i-(int)dcw_dims[0]/2); host_dcw.get_data_ptr()[dcw_dims[0]/2] = 0.25f; // ad hoc value (we do not want a DC component of 0) dcw = expand(&host_dcw, traj->get_number_of_elements()/samples_per_readout_); } */ // Gridder // plan.compute( &samples, &image, (dcw->get_number_of_elements()>0) ? dcw.get() : 0x0, cuNFFT_plan<float,2>::NFFT_BACKWARDS_NC2C ); // Download to host // image.to_host( (hoNDArray<float_complext>*)cm2->getObjectPtr() ); // Pass on data down the gadget chain // if (this->next()->putq(cm1) < 0) { return GADGET_FAIL; } } m1->release(); return GADGET_OK; }
int NoiseCovariancePlottingGadget::close(unsigned long flags) { if (BaseClass::close(flags) != GADGET_OK) return GADGET_FAIL; // try to load the precomputed noise prewhitener if (flags == 0) return GADGET_OK; if (!full_name_stored_noise_dependency_.empty()) { if (this->loadNoiseCovariance()) { GDEBUG("Stored noise dependency is found : %s\n", full_name_stored_noise_dependency_.c_str()); if (noise_ismrmrd_header_.acquisitionSystemInformation.is_present()) { hoNDArray<float> plotIm; bool trueColor = false; size_t CHA = noise_covariance_matrixf_.get_size(0); std::vector<std::string> coilStrings(CHA, "Unknown"); for (size_t n = 0; n < CHA; n++) { int coilNum = noise_ismrmrd_header_.acquisitionSystemInformation.get().coilLabel[n].coilNumber; if (coilNum >= 0 && coilNum < CHA) { coilStrings[coilNum] = noise_ismrmrd_header_.acquisitionSystemInformation.get().coilLabel[n].coilName; } } Gadgetron::plotNoiseStandardDeviation(noise_covariance_matrixf_, coilStrings, xlabel.value(), ylabel.value(), title.value(), xsize.value(), ysize.value(), trueColor, plotIm); // send out the noise variance plot Gadgetron::GadgetContainerMessage<ISMRMRD::ImageHeader>* cm1 = new Gadgetron::GadgetContainerMessage<ISMRMRD::ImageHeader>(); Gadgetron::GadgetContainerMessage<ISMRMRD::MetaContainer>* cm3 = new Gadgetron::GadgetContainerMessage<ISMRMRD::MetaContainer>(); *cm1->getObjectPtr() = curr_image_header_; cm1->getObjectPtr()->flags = 0; cm1->getObjectPtr()->data_type = ISMRMRD::ISMRMRD_CXFLOAT; cm1->getObjectPtr()->image_type = ISMRMRD::ISMRMRD_IMTYPE_MAGNITUDE; cm1->getObjectPtr()->image_index = 1; cm1->getObjectPtr()->image_series_index = series_num.value(); Gadgetron::GadgetContainerMessage< Gadgetron::hoNDArray< std::complex<float> > >* cm2 = new Gadgetron::GadgetContainerMessage< Gadgetron::hoNDArray< std::complex<float> > >(); cm1->cont(cm2); cm2->cont(cm3); std::vector<size_t> img_dims(2); img_dims[0] = plotIm.get_size(0); img_dims[1] = plotIm.get_size(1); // set the image attributes cm3->getObjectPtr()->set(GADGETRON_IMAGECOMMENT, "Noise SD"); cm3->getObjectPtr()->set(GADGETRON_SEQUENCEDESCRIPTION, "_GT_Noise_SD_Plot"); cm3->getObjectPtr()->set(GADGETRON_IMAGEPROCESSINGHISTORY, "GT"); cm3->getObjectPtr()->set(GADGETRON_DATA_ROLE, GADGETRON_IMAGE_RECON_FIGURE); cm3->getObjectPtr()->set(GADGETRON_IMAGE_SCALE_RATIO, (double)(1)); cm3->getObjectPtr()->set(GADGETRON_IMAGE_WINDOWCENTER, (long)(200)); cm3->getObjectPtr()->set(GADGETRON_IMAGE_WINDOWWIDTH, (long)(400)); cm1->getObjectPtr()->matrix_size[0] = (uint16_t)plotIm.get_size(0); cm1->getObjectPtr()->matrix_size[1] = (uint16_t)plotIm.get_size(1); cm1->getObjectPtr()->matrix_size[2] = 1; cm1->getObjectPtr()->channels = 1; // make sure pixel is squared in size float dx = cm1->getObjectPtr()->field_of_view[0] / cm1->getObjectPtr()->matrix_size[0]; cm1->getObjectPtr()->field_of_view[1] = dx * cm1->getObjectPtr()->matrix_size[1]; try { cm2->getObjectPtr()->create(&img_dims); } catch (...) { GDEBUG("Unable to allocate new image\n"); cm1->release(); return false; } Gadgetron::real_to_complex(plotIm, *cm2->getObjectPtr()); // send out the images if (this->next()->putq(cm1) < 0) { return false; } } } else { GDEBUG("Stored noise dependency is NOT found : %s\n", full_name_stored_noise_dependency_.c_str()); } } else { GDEBUG("There is no noise stored ... \n"); } return GADGET_OK; }