Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions cpp/mrd-tools/converters.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1107,6 +1107,16 @@ int convert(ArrayComplexFloat&) {
return 0;
}

// Convert mrd::Gradient - no equivalent in ISMRMRD::
int convert(Gradient&) {
return 0;
}

// Convert mrd::Pulse - no equivalent in ISMRMRD::
int convert(Pulse&) {
return 0;
}

yardl::Date date_from_string(const std::string& s) {
std::stringstream ss{s};

Expand Down
4 changes: 3 additions & 1 deletion cpp/mrd-tools/converters.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

#include "mrd/types.h"

#include <ismrmrd/xml.h>
#include <ismrmrd/waveform.h>
#include <ismrmrd/xml.h>

namespace mrd::converters {

Expand All @@ -22,6 +22,8 @@ int convert(AcquisitionBucket&);
int convert(ReconData&);
int convert(ImageArray&);
int convert(ArrayComplexFloat&);
int convert(Gradient&);
int convert(Pulse&);

Header convert(ISMRMRD::IsmrmrdHeader& hdr);
Acquisition convert(ISMRMRD::Acquisition& acq);
Expand Down
2 changes: 2 additions & 0 deletions cpp/mrd-tools/mrd_to_ismrmrd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ int main(int argc, char** argv) {

mrd::StreamItem item;
while (r.ReadData(item)) {
// if item type is mrd::Pulse or mrd::Gradient, skip from visit serailizer
// as the ISMRMRD format does not support these types
std::visit([&serializer](auto&& arg) { serializer.serialize(convert(arg)); },
item);
}
Expand Down
248 changes: 242 additions & 6 deletions cpp/mrd/binary/protocols.cc

Large diffs are not rendered by default.

259 changes: 217 additions & 42 deletions cpp/mrd/hdf5/protocols.cc

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions cpp/mrd/hdf5/protocols.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class MrdWriter : public mrd::MrdWriterBase, public yardl::hdf5::Hdf5Writer {
void Flush() override;

private:
std::unique_ptr<yardl::hdf5::UnionDatasetWriter<14>> data_dataset_state_;
std::unique_ptr<yardl::hdf5::UnionDatasetWriter<16>> data_dataset_state_;
};

// HDF5 reader for the Mrd protocol.
Expand All @@ -42,7 +42,7 @@ class MrdReader : public mrd::MrdReaderBase, public yardl::hdf5::Hdf5Reader {
bool ReadDataImpl(mrd::StreamItem& value) override;

private:
std::unique_ptr<yardl::hdf5::UnionDatasetReader<14>> data_dataset_state_;
std::unique_ptr<yardl::hdf5::UnionDatasetReader<16>> data_dataset_state_;
};

// HDF5 writer for the MrdNoiseCovariance protocol.
Expand Down
210 changes: 195 additions & 15 deletions cpp/mrd/ndjson/protocols.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ void from_json(ordered_json const& j, mrd::AcquisitionHeader& value);
void to_json(ordered_json& j, mrd::Acquisition const& value);
void from_json(ordered_json const& j, mrd::Acquisition& value);

void to_json(ordered_json& j, mrd::GradientDirection const& value);
void from_json(ordered_json const& j, mrd::GradientDirection& value);

void to_json(ordered_json& j, mrd::GradientHeader const& value);
void from_json(ordered_json const& j, mrd::GradientHeader& value);

void to_json(ordered_json& j, mrd::Gradient const& value);
void from_json(ordered_json const& j, mrd::Gradient& value);

void to_json(ordered_json& j, mrd::PatientGender const& value);
void from_json(ordered_json const& j, mrd::PatientGender& value);

Expand Down Expand Up @@ -175,6 +184,12 @@ void from_json(ordered_json const& j, mrd::ReconData& value);
void to_json(ordered_json& j, mrd::ImageArray const& value);
void from_json(ordered_json const& j, mrd::ImageArray& value);

void to_json(ordered_json& j, mrd::PulseHeader const& value);
void from_json(ordered_json const& j, mrd::PulseHeader& value);

void to_json(ordered_json& j, mrd::Pulse const& value);
void from_json(ordered_json const& j, mrd::Pulse& value);

} // namespace mrd

NLOHMANN_JSON_NAMESPACE_BEGIN
Expand Down Expand Up @@ -287,63 +302,77 @@ struct adl_serializer<std::variant<mrd::Image<uint16_t>, mrd::Image<int16_t>, mr
};

template <>
struct adl_serializer<std::variant<mrd::Acquisition, mrd::Waveform<uint32_t>, mrd::Image<uint16_t>, mrd::Image<int16_t>, mrd::Image<uint32_t>, mrd::Image<int32_t>, mrd::Image<float>, mrd::Image<double>, mrd::Image<std::complex<float>>, mrd::Image<std::complex<double>>, mrd::AcquisitionBucket, mrd::ReconData, yardl::DynamicNDArray<std::complex<float>>, mrd::ImageArray>> {
static void to_json(ordered_json& j, std::variant<mrd::Acquisition, mrd::Waveform<uint32_t>, mrd::Image<uint16_t>, mrd::Image<int16_t>, mrd::Image<uint32_t>, mrd::Image<int32_t>, mrd::Image<float>, mrd::Image<double>, mrd::Image<std::complex<float>>, mrd::Image<std::complex<double>>, mrd::AcquisitionBucket, mrd::ReconData, yardl::DynamicNDArray<std::complex<float>>, mrd::ImageArray> const& value) {
struct adl_serializer<std::variant<mrd::Acquisition, mrd::Pulse, mrd::Gradient, mrd::Waveform<uint32_t>, mrd::Image<uint16_t>, mrd::Image<int16_t>, mrd::Image<uint32_t>, mrd::Image<int32_t>, mrd::Image<float>, mrd::Image<double>, mrd::Image<std::complex<float>>, mrd::Image<std::complex<double>>, mrd::AcquisitionBucket, mrd::ReconData, yardl::DynamicNDArray<std::complex<float>>, mrd::ImageArray>> {
static void to_json(ordered_json& j, std::variant<mrd::Acquisition, mrd::Pulse, mrd::Gradient, mrd::Waveform<uint32_t>, mrd::Image<uint16_t>, mrd::Image<int16_t>, mrd::Image<uint32_t>, mrd::Image<int32_t>, mrd::Image<float>, mrd::Image<double>, mrd::Image<std::complex<float>>, mrd::Image<std::complex<double>>, mrd::AcquisitionBucket, mrd::ReconData, yardl::DynamicNDArray<std::complex<float>>, mrd::ImageArray> const& value) {
switch (value.index()) {
case 0:
j = ordered_json{ {"Acquisition", std::get<mrd::Acquisition>(value)} };
break;
case 1:
j = ordered_json{ {"WaveformUint32", std::get<mrd::Waveform<uint32_t>>(value)} };
j = ordered_json{ {"Pulse", std::get<mrd::Pulse>(value)} };
break;
case 2:
j = ordered_json{ {"ImageUint16", std::get<mrd::Image<uint16_t>>(value)} };
j = ordered_json{ {"Gradient", std::get<mrd::Gradient>(value)} };
break;
case 3:
j = ordered_json{ {"ImageInt16", std::get<mrd::Image<int16_t>>(value)} };
j = ordered_json{ {"WaveformUint32", std::get<mrd::Waveform<uint32_t>>(value)} };
break;
case 4:
j = ordered_json{ {"ImageUint32", std::get<mrd::Image<uint32_t>>(value)} };
j = ordered_json{ {"ImageUint16", std::get<mrd::Image<uint16_t>>(value)} };
break;
case 5:
j = ordered_json{ {"ImageInt32", std::get<mrd::Image<int32_t>>(value)} };
j = ordered_json{ {"ImageInt16", std::get<mrd::Image<int16_t>>(value)} };
break;
case 6:
j = ordered_json{ {"ImageFloat", std::get<mrd::Image<float>>(value)} };
j = ordered_json{ {"ImageUint32", std::get<mrd::Image<uint32_t>>(value)} };
break;
case 7:
j = ordered_json{ {"ImageDouble", std::get<mrd::Image<double>>(value)} };
j = ordered_json{ {"ImageInt32", std::get<mrd::Image<int32_t>>(value)} };
break;
case 8:
j = ordered_json{ {"ImageComplexFloat", std::get<mrd::Image<std::complex<float>>>(value)} };
j = ordered_json{ {"ImageFloat", std::get<mrd::Image<float>>(value)} };
break;
case 9:
j = ordered_json{ {"ImageComplexDouble", std::get<mrd::Image<std::complex<double>>>(value)} };
j = ordered_json{ {"ImageDouble", std::get<mrd::Image<double>>(value)} };
break;
case 10:
j = ordered_json{ {"AcquisitionBucket", std::get<mrd::AcquisitionBucket>(value)} };
j = ordered_json{ {"ImageComplexFloat", std::get<mrd::Image<std::complex<float>>>(value)} };
break;
case 11:
j = ordered_json{ {"ReconData", std::get<mrd::ReconData>(value)} };
j = ordered_json{ {"ImageComplexDouble", std::get<mrd::Image<std::complex<double>>>(value)} };
break;
case 12:
j = ordered_json{ {"ArrayComplexFloat", std::get<yardl::DynamicNDArray<std::complex<float>>>(value)} };
j = ordered_json{ {"AcquisitionBucket", std::get<mrd::AcquisitionBucket>(value)} };
break;
case 13:
j = ordered_json{ {"ReconData", std::get<mrd::ReconData>(value)} };
break;
case 14:
j = ordered_json{ {"ArrayComplexFloat", std::get<yardl::DynamicNDArray<std::complex<float>>>(value)} };
break;
case 15:
j = ordered_json{ {"ImageArray", std::get<mrd::ImageArray>(value)} };
break;
default:
throw std::runtime_error("Invalid union value");
}
}

static void from_json(ordered_json const& j, std::variant<mrd::Acquisition, mrd::Waveform<uint32_t>, mrd::Image<uint16_t>, mrd::Image<int16_t>, mrd::Image<uint32_t>, mrd::Image<int32_t>, mrd::Image<float>, mrd::Image<double>, mrd::Image<std::complex<float>>, mrd::Image<std::complex<double>>, mrd::AcquisitionBucket, mrd::ReconData, yardl::DynamicNDArray<std::complex<float>>, mrd::ImageArray>& value) {
static void from_json(ordered_json const& j, std::variant<mrd::Acquisition, mrd::Pulse, mrd::Gradient, mrd::Waveform<uint32_t>, mrd::Image<uint16_t>, mrd::Image<int16_t>, mrd::Image<uint32_t>, mrd::Image<int32_t>, mrd::Image<float>, mrd::Image<double>, mrd::Image<std::complex<float>>, mrd::Image<std::complex<double>>, mrd::AcquisitionBucket, mrd::ReconData, yardl::DynamicNDArray<std::complex<float>>, mrd::ImageArray>& value) {
auto it = j.begin();
std::string tag = it.key();
if (tag == "Acquisition") {
value = it.value().get<mrd::Acquisition>();
return;
}
if (tag == "Pulse") {
value = it.value().get<mrd::Pulse>();
return;
}
if (tag == "Gradient") {
value = it.value().get<mrd::Gradient>();
return;
}
if (tag == "WaveformUint32") {
value = it.value().get<mrd::Waveform<uint32_t>>();
return;
Expand Down Expand Up @@ -928,6 +957,95 @@ void from_json(ordered_json const& j, mrd::Acquisition& value) {
}
}

namespace {
std::unordered_map<std::string, mrd::GradientDirection> const __GradientDirection_values = {
{"z", mrd::GradientDirection::kZ},
{"y", mrd::GradientDirection::kY},
{"x", mrd::GradientDirection::kX},
};
} //namespace

void to_json(ordered_json& j, mrd::GradientDirection const& value) {
switch (value) {
case mrd::GradientDirection::kZ:
j = "z";
break;
case mrd::GradientDirection::kY:
j = "y";
break;
case mrd::GradientDirection::kX:
j = "x";
break;
default:
using underlying_type = typename std::underlying_type<mrd::GradientDirection>::type;
j = static_cast<underlying_type>(value);
break;
}
}

void from_json(ordered_json const& j, mrd::GradientDirection& value) {
if (j.is_string()) {
auto symbol = j.get<std::string>();
if (auto res = __GradientDirection_values.find(symbol); res != __GradientDirection_values.end()) {
value = res->second;
return;
}
throw std::runtime_error("Invalid enum value '" + symbol + "' for enum mrd::GradientDirection");
}
using underlying_type = typename std::underlying_type<mrd::GradientDirection>::type;
value = static_cast<mrd::GradientDirection>(j.get<underlying_type>());
}

void to_json(ordered_json& j, mrd::GradientHeader const& value) {
j = ordered_json::object();
if (yardl::ndjson::ShouldSerializeFieldValue(value.gradient_time_stamp_ns)) {
j.push_back({"gradientTimeStampNs", value.gradient_time_stamp_ns});
}
if (yardl::ndjson::ShouldSerializeFieldValue(value.gradient_sample_time_ns)) {
j.push_back({"gradientSampleTimeNs", value.gradient_sample_time_ns});
}
if (yardl::ndjson::ShouldSerializeFieldValue(value.pulse_calibration)) {
j.push_back({"pulseCalibration", value.pulse_calibration});
}
if (yardl::ndjson::ShouldSerializeFieldValue(value.gradient_direction)) {
j.push_back({"gradientDirection", value.gradient_direction});
}
}

void from_json(ordered_json const& j, mrd::GradientHeader& value) {
if (auto it = j.find("gradientTimeStampNs"); it != j.end()) {
it->get_to(value.gradient_time_stamp_ns);
}
if (auto it = j.find("gradientSampleTimeNs"); it != j.end()) {
it->get_to(value.gradient_sample_time_ns);
}
if (auto it = j.find("pulseCalibration"); it != j.end()) {
it->get_to(value.pulse_calibration);
}
if (auto it = j.find("gradientDirection"); it != j.end()) {
it->get_to(value.gradient_direction);
}
}

void to_json(ordered_json& j, mrd::Gradient const& value) {
j = ordered_json::object();
if (yardl::ndjson::ShouldSerializeFieldValue(value.head)) {
j.push_back({"head", value.head});
}
if (yardl::ndjson::ShouldSerializeFieldValue(value.data)) {
j.push_back({"data", value.data});
}
}

void from_json(ordered_json const& j, mrd::Gradient& value) {
if (auto it = j.find("head"); it != j.end()) {
it->get_to(value.head);
}
if (auto it = j.find("data"); it != j.end()) {
it->get_to(value.data);
}
}

namespace {
std::unordered_map<std::string, mrd::PatientGender> const __PatientGender_values = {
{"m", mrd::PatientGender::kM},
Expand Down Expand Up @@ -3029,6 +3147,68 @@ void from_json(ordered_json const& j, mrd::ImageArray& value) {
}
}

void to_json(ordered_json& j, mrd::PulseHeader const& value) {
j = ordered_json::object();
if (yardl::ndjson::ShouldSerializeFieldValue(value.pulse_time_stamp_ns)) {
j.push_back({"pulseTimeStampNs", value.pulse_time_stamp_ns});
}
if (yardl::ndjson::ShouldSerializeFieldValue(value.channel_order)) {
j.push_back({"channelOrder", value.channel_order});
}
if (yardl::ndjson::ShouldSerializeFieldValue(value.sample_time_ns)) {
j.push_back({"sampleTimeNs", value.sample_time_ns});
}
if (yardl::ndjson::ShouldSerializeFieldValue(value.pulse_calibration)) {
j.push_back({"pulseCalibration", value.pulse_calibration});
}
}

void from_json(ordered_json const& j, mrd::PulseHeader& value) {
if (auto it = j.find("pulseTimeStampNs"); it != j.end()) {
it->get_to(value.pulse_time_stamp_ns);
}
if (auto it = j.find("channelOrder"); it != j.end()) {
it->get_to(value.channel_order);
}
if (auto it = j.find("sampleTimeNs"); it != j.end()) {
it->get_to(value.sample_time_ns);
}
if (auto it = j.find("pulseCalibration"); it != j.end()) {
it->get_to(value.pulse_calibration);
}
}

void to_json(ordered_json& j, mrd::Pulse const& value) {
j = ordered_json::object();
if (yardl::ndjson::ShouldSerializeFieldValue(value.head)) {
j.push_back({"head", value.head});
}
if (yardl::ndjson::ShouldSerializeFieldValue(value.amplitude)) {
j.push_back({"amplitude", value.amplitude});
}
if (yardl::ndjson::ShouldSerializeFieldValue(value.phase)) {
j.push_back({"phase", value.phase});
}
if (yardl::ndjson::ShouldSerializeFieldValue(value.phase_offset)) {
j.push_back({"phaseOffset", value.phase_offset});
}
}

void from_json(ordered_json const& j, mrd::Pulse& value) {
if (auto it = j.find("head"); it != j.end()) {
it->get_to(value.head);
}
if (auto it = j.find("amplitude"); it != j.end()) {
it->get_to(value.amplitude);
}
if (auto it = j.find("phase"); it != j.end()) {
it->get_to(value.phase);
}
if (auto it = j.find("phaseOffset"); it != j.end()) {
it->get_to(value.phase_offset);
}
}

} // namespace mrd

namespace mrd::ndjson {
Expand Down
2 changes: 1 addition & 1 deletion cpp/mrd/protocols.cc

Large diffs are not rendered by default.

Loading
Loading