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;  

}
예제 #2
0
  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;
}