Skip to content

Commit

Permalink
Add waveform stream and use ismrmrd ndarray (#1263)
Browse files Browse the repository at this point in the history
* stream out kspace as ismrmrd ND array; add stream for waveform

* update test for data stream

* fix the BucketToBufferGadget for sampling.sampling_limits

* update ismrmrd=1.14.1

* update onnxruntime to 1.18.1

* siemens_to_ismrmrd to use 1.2.12

* make bucket to buffer can be derived

* udpate cases/ismrmrd_dump_gadget_test.cfg ref data

* fix cases/ismrmrd_dump_gadget_test.cfg

* fix the ismrmrd dump test

* update image base in azure-pipeline.yml

* update build-images.sh

* further fix ismrmrd dump test

---------

Co-authored-by: Hui Xue <[email protected]>
  • Loading branch information
xueh2 and Hui Xue authored Aug 12, 2024
1 parent 9f88dcd commit 24fe05d
Show file tree
Hide file tree
Showing 13 changed files with 335 additions and 177 deletions.
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
variables:
AzureConnection: 'BiomedicalImaging-NonProd(87d8acb3-5176-4651-b457-6ab9cefd8e3d)'
imageBaseName: 'ghcr.io/gadgetron/gadgetron/gadgetron_ubuntu'
imageBaseName: 'ghcr.io/gadgetron/gadgetron/ubuntu22.04'
DOCKER_BUILDKIT: 1
isPR: $[eq(variables['Build.Reason'], 'PullRequest')]
isCI: $[or(eq(variables['Build.Reason'], 'IndividualCI'), eq(variables['Build.Reason'], 'BatchedCI'))]
Expand Down
2 changes: 1 addition & 1 deletion build-images.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ flavors=()
flavors_default=("cuda" "nocuda")

image_tag="latest"
base_name="ghcr.io/gadgetron/gadgetron/gadgetron_ubuntu"
base_name="ghcr.io/gadgetron/gadgetron/ubuntu22.04"

while [[ $# -gt 0 ]]; do
key="$1"
Expand Down
8 changes: 4 additions & 4 deletions conda/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ requirements:
- h5py=3.7.0
- hdf5=1.10.6
- howardhinnant_date=3.0.1
- ismrmrd=1.13.7
- ismrmrd=1.14.1
- ismrmrd-python=1.14.0
- libblas=*=*mkl
- libcurl=7.86.0
Expand Down Expand Up @@ -56,7 +56,7 @@ requirements:
- gadgetron-python>=1.4.1
- h5py=3.7.0
- hdf5=1.10.6
- ismrmrd=1.13.7
- ismrmrd=1.14.1
- ismrmrd-python=1.14.0
- jq=1.7.1
- libblas=*=*mkl
Expand All @@ -65,7 +65,7 @@ requirements:
- mkl>=2024.1.0
- mrd-storage-server=0.0.12
- numpy=1.26.4
- onnxruntime=1.18.0
- onnxruntime=1.18.1
- pugixml=1.12.1
- pyfftw=0.13.1
- python=3.10
Expand All @@ -74,7 +74,7 @@ requirements:

test:
requires:
- siemens_to_ismrmrd=1.2.11
- siemens_to_ismrmrd=1.2.12

about:
home: https://github.com/gadgetron/gadgetron
Expand Down
6 changes: 3 additions & 3 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ dependencies:
- h5py=3.7.0
- hdf5=1.10.6
- howardhinnant_date=3.0.1 # dev
- ismrmrd=1.13.7
- ismrmrd=1.14.1
- ismrmrd-python=1.14.0
- junitparser=3.1.2
- jupyter=1.0.0 # dev
Expand All @@ -54,7 +54,7 @@ dependencies:
- ninja=1.12.1 # dev
- nlohmann_json=3.11.3 # dev
- numpy=1.26.4
- onnxruntime=1.18.0
- onnxruntime=1.18.1
- pyyaml=6.0.1 # dev
- pip=24.0 # dev
- packaging=24.0
Expand All @@ -66,7 +66,7 @@ dependencies:
- recommonmark=0.7.1 # dev
- scipy=1.13.1
- shellcheck=0.10.0 # dev
- siemens_to_ismrmrd=1.2.11
- siemens_to_ismrmrd=1.2.12
- sphinx=7.3.7 # dev
- sphinx_rtd_theme=2.0.0 # dev
- sysroot_linux-64=2.12
Expand Down
48 changes: 32 additions & 16 deletions gadgets/mri_core/BucketToBufferGadget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ namespace Gadgetron {
}
return NLOC;
}

uint16_t BucketToBufferGadget::getNE2(
const ISMRMRD::Encoding& encoding, const AcquisitionBucketStats& stats, bool forref) const {
uint16_t NE2;
Expand Down Expand Up @@ -259,6 +260,7 @@ namespace Gadgetron {
}
return NE2;
}

uint16_t BucketToBufferGadget::getNE1(
const ISMRMRD::Encoding& encoding, const AcquisitionBucketStats& stats, bool forref) const {
uint16_t NE1;
Expand Down Expand Up @@ -290,6 +292,7 @@ namespace Gadgetron {
}
return NE1;
}

uint16_t BucketToBufferGadget::getNE0(
const ISMRMRD::AcquisitionHeader& acqhdr, const ISMRMRD::Encoding& encoding) const {
uint16_t NE0;
Expand Down Expand Up @@ -321,6 +324,35 @@ namespace Gadgetron {
sampling.recon_FOV_ = xyz_to_vector(encoding.reconSpace.fieldOfView_mm);
sampling.recon_matrix_ = xyz_to_vector(encoding.reconSpace.matrixSize);

sampling.sampling_limits_[0].min_ = 0;
sampling.sampling_limits_[0].max_ = acqhdr.number_of_samples-1;
sampling.sampling_limits_[0].center_ = acqhdr.number_of_samples/2;

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) {
GDEBUG_STREAM("Encoding space : " << acqhdr.encoding_space_ref << " - "
<< 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_ << " ]");
}

// 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;
Expand Down Expand Up @@ -391,22 +423,6 @@ namespace Gadgetron {
sampling.sampling_limits_[2].center_ = encoding.encodingLimits.kspace_encoding_step_2->center;
}

if (verbose) {
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_ << " ]");
}
return sampling;
}

Expand Down
24 changes: 11 additions & 13 deletions gadgets/mri_core/BucketToBufferGadget.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,9 @@ namespace Gadgetron {
struct BufferKey {
uint16_t average,slice,contrast,phase,repetition,set,segment;
BufferKey(const BufferKey&) = default;
BufferKey(const ISMRMRD::EncodingCounters& idx) : average{idx.average}, slice{idx.slice},contrast{idx.contrast}, phase{idx.phase},repetition{idx.repetition},set{idx.set},segment{idx.segment}{

}
BufferKey(const ISMRMRD::EncodingCounters& idx) : average{idx.average}, slice{idx.slice},contrast{idx.contrast}, phase{idx.phase},repetition{idx.repetition},set{idx.set},segment{idx.segment} {}
};

protected:
NODE_PROPERTY(N_dimension, Dimension, "N-Dimensions", Dimension::none);
NODE_PROPERTY(S_dimension, Dimension, "S-Dimensions", Dimension::none);
Expand All @@ -47,17 +46,16 @@ namespace Gadgetron {
void process(Core::InputChannel<AcquisitionBucket>& in, Core::OutputChannel& out) override;
BufferKey getKey(const ISMRMRD::EncodingCounters& idx) const;

IsmrmrdDataBuffered makeDataBuffer(const ISMRMRD::AcquisitionHeader& acqhdr, ISMRMRD::Encoding encoding, const AcquisitionBucketStats& stats, bool forref) const;

virtual SamplingDescription createSamplingDescription(const ISMRMRD::Encoding& encoding, const AcquisitionBucketStats& stats, const ISMRMRD::AcquisitionHeader& acqhdr, bool forref) const ;

void add_acquisition(IsmrmrdDataBuffered& dataBuffer, const Core::Acquisition& acq, ISMRMRD::Encoding encoding, const AcquisitionBucketStats& stats, bool forref);

IsmrmrdDataBuffered makeDataBuffer(const ISMRMRD::AcquisitionHeader& acqhdr, ISMRMRD::Encoding encoding,
const AcquisitionBucketStats& stats, bool forref) const;
SamplingDescription createSamplingDescription(const ISMRMRD::Encoding& encoding,
const AcquisitionBucketStats& stats, const ISMRMRD::AcquisitionHeader& acqhdr, bool forref) const ;
void add_acquisition(IsmrmrdDataBuffered& dataBuffer, const Core::Acquisition& acq, ISMRMRD::Encoding encoding,
const AcquisitionBucketStats& stats, bool forref);
uint16_t getNE0(const ISMRMRD::AcquisitionHeader& acqhdr, const ISMRMRD::Encoding& encoding) const;
uint16_t getNE1(const ISMRMRD::Encoding& encoding, const AcquisitionBucketStats& stats, bool forref) const;
uint16_t getNE2(const ISMRMRD::Encoding& encoding, const AcquisitionBucketStats& stats, bool forref) const;
uint16_t getNLOC(const ISMRMRD::Encoding& encoding, const AcquisitionBucketStats& stats) const;
virtual uint16_t getNE0(const ISMRMRD::AcquisitionHeader& acqhdr, const ISMRMRD::Encoding& encoding) const;
virtual uint16_t getNE1(const ISMRMRD::Encoding& encoding, const AcquisitionBucketStats& stats, bool forref) const;
virtual uint16_t getNE2(const ISMRMRD::Encoding& encoding, const AcquisitionBucketStats& stats, bool forref) const;
virtual uint16_t getNLOC(const ISMRMRD::Encoding& encoding, const AcquisitionBucketStats& stats) const;
};

void from_string(const std::string&, BucketToBufferGadget::Dimension&);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,11 @@ namespace Gadgetron {

// ---------------------------------------------------------------
// pass down waveform
if (wav) this->set_wave_form_to_image_array(*wav->getObjectPtr(), recon_obj_[e].recon_res_);
if (wav)
{
this->set_wave_form_to_image_array(*wav->getObjectPtr(), recon_obj_[e].recon_res_);
this->gt_streamer_.stream_ismrmrd_waveform(*recon_obj_[e].recon_res_.waveform_);
}
recon_obj_[e].recon_res_.acq_headers_ = recon_bit_->rbit_[e].data_.headers_;

// ---------------------------------------------------------------
Expand Down
6 changes: 3 additions & 3 deletions test/integration/cases/ismrmrd_dump_gadget_test.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ template=ismrmrd_dump_gadget_test.template.xml

[reconstruction.equals]
dataset_prefix=ismrmrd_dump_output
reference_file=simple_gre/simple_gre_in_20220831.mrd
reference_file=simple_gre/ismrmrd_dump_output_20240811.h5

[reconstruction.test]
reference_file=simple_gre/simple_gre_out_20210909_klk.mrd
reference_images=simple/image_0
reference_file=simple_gre/ref_20240810.mrd
reference_images=reconstruction.client/image_0
output_images=reconstruction.client/image_0
value_comparison_threshold=0.002
scale_comparison_threshold=0.001
Expand Down
10 changes: 9 additions & 1 deletion test/integration/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -354,5 +354,13 @@
{
"file": "cmr/RTCine/CH4/ref_20220124_173736.mrd",
"md5": "b5e9c37bbd3eb4be076d89fd7dd7db6d"
}
},
{
"file": "simple_gre/ismrmrd_dump_output_20240811.h5",
"md5": "d4dbdd40f7becc4cf5aae3e21eef26b4"
},
{
"file": "simple_gre/ref_20240810.mrd",
"md5": "152dd0ee1b259756107c9fd36965fadb"
}
]
Loading

0 comments on commit 24fe05d

Please sign in to comment.