Skip to content

Commit

Permalink
DWI metadata fixes
Browse files Browse the repository at this point in the history
This commit is a manual replication of the contents of #2917, but targeting 3.0.x.
  • Loading branch information
Lestropie committed Sep 19, 2024
1 parent a5a76ad commit 339ea0c
Show file tree
Hide file tree
Showing 33 changed files with 1,065 additions and 886 deletions.
4 changes: 2 additions & 2 deletions cmd/amp2sh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@

#include "command.h"
#include "image.h"
#include "phase_encoding.h"
#include "progressbar.h"
#include "algo/threaded_loop.h"
#include "dwi/gradient.h"
#include "dwi/shells.h"
#include "math/SH.h"
#include "metadata/phase_encoding.h"


using namespace MR;
Expand Down Expand Up @@ -239,7 +239,7 @@ void run ()
DWI::stash_DW_scheme (header, grad);
}
}
PhaseEncoding::clear_scheme (header);
Metadata::PhaseEncoding::clear_scheme (header.keyval());

auto sh2amp = DWI::compute_SH2amp_mapping (dirs, true, 8);

Expand Down
6 changes: 3 additions & 3 deletions cmd/dwi2adc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@

#include "command.h"
#include "image.h"
#include "phase_encoding.h"
#include "progressbar.h"
#include "algo/threaded_copy.h"
#include "math/least_squares.h"
#include "dwi/gradient.h"
#include "math/least_squares.h"
#include "metadata/phase_encoding.h"


using namespace MR;
Expand Down Expand Up @@ -99,7 +99,7 @@ void run () {
Header header (dwi);
header.datatype() = DataType::Float32;
DWI::stash_DW_scheme (header, grad);
PhaseEncoding::clear_scheme (header);
Metadata::PhaseEncoding::clear_scheme (header.keyval());
header.ndim() = 4;
header.size(3) = 2;

Expand Down
4 changes: 2 additions & 2 deletions cmd/dwi2fod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
#include "command.h"
#include "header.h"
#include "image.h"
#include "phase_encoding.h"
#include "algo/threaded_loop.h"
#include "dwi/gradient.h"
#include "dwi/shells.h"
#include "math/SH.h"
#include "metadata/phase_encoding.h"

#include "dwi/sdeconv/csd.h"
#include "dwi/sdeconv/msmt_csd.h"
Expand Down Expand Up @@ -270,7 +270,7 @@ void run ()
shared.init();

DWI::stash_DW_scheme (header_out, shared.grad);
PhaseEncoding::clear_scheme (header_out);
Metadata::PhaseEncoding::clear_scheme (header_out.keyval());

header_out.size(3) = shared.nSH();
auto fod = Image<float>::create (argument[3], header_out);
Expand Down
4 changes: 2 additions & 2 deletions cmd/dwi2tensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
*/

#include "command.h"
#include "phase_encoding.h"
#include "progressbar.h"
#include "image.h"
#include "algo/threaded_copy.h"
#include "dwi/gradient.h"
#include "dwi/tensor.h"
#include "metadata/phase_encoding.h"

using namespace MR;
using namespace App;
Expand Down Expand Up @@ -221,7 +221,7 @@ void run ()
header.datatype() = DataType::Float32;
header.ndim() = 4;
DWI::stash_DW_scheme (header, grad);
PhaseEncoding::clear_scheme (header);
Metadata::PhaseEncoding::clear_scheme (header.keyval());

Image<value_type> predict;
opt = get_options ("predicted_signal");
Expand Down
14 changes: 7 additions & 7 deletions cmd/dwiextract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@

#include "command.h"
#include "image.h"
#include "phase_encoding.h"
#include "progressbar.h"
#include "dwi/gradient.h"
#include "algo/loop.h"
#include "adapter/extract.h"
#include "algo/loop.h"
#include "dwi/gradient.h"
#include "metadata/phase_encoding.h"


using namespace MR;
Expand Down Expand Up @@ -54,8 +54,8 @@ void usage ()
+ DWI::GradImportOptions()
+ DWI::ShellsOption
+ DWI::GradExportOptions()
+ PhaseEncoding::ImportOptions
+ PhaseEncoding::SelectOptions
+ Metadata::PhaseEncoding::ImportOptions
+ Metadata::PhaseEncoding::SelectOptions
+ Stride::Options;
}

Expand Down Expand Up @@ -101,7 +101,7 @@ void run()
}

auto opt = get_options ("pe");
const auto pe_scheme = PhaseEncoding::get_scheme (input_image);
const auto pe_scheme = Metadata::PhaseEncoding::get_scheme (input_image);
if (opt.size()) {
if (!pe_scheme.rows())
throw Exception ("Cannot filter volumes by phase-encoding: No such information present");
Expand Down Expand Up @@ -147,7 +147,7 @@ void run()
Eigen::MatrixXd new_scheme (volumes.size(), pe_scheme.cols());
for (size_t i = 0; i != volumes.size(); ++i)
new_scheme.row(i) = pe_scheme.row (volumes[i]);
PhaseEncoding::set_scheme (header, new_scheme);
Metadata::PhaseEncoding::set_scheme (header.keyval(), new_scheme);
}

auto output_image = Image<float>::create (argument[1], header);
Expand Down
3 changes: 1 addition & 2 deletions cmd/mrcalc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,6 @@ UNARY_OP (atanh, "atanh (%1)", NORMAL, "inverse hyperbolic tangent", { return st
#include "command.h"
#include "image.h"
#include "memory.h"
#include "phase_encoding.h"
#include "math/rng.h"
#include "algo/threaded_copy.h"
#include "dwi/gradient.h"
Expand Down Expand Up @@ -731,7 +730,7 @@ void get_header (const StackEntry& entry, Header& header)
header.spacing(n) = entry.image->spacing(n);
}

header.merge_keyval (*entry.image);
header.merge_keyval (entry.image->keyval());
}


Expand Down
1 change: 0 additions & 1 deletion cmd/mrcat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#include "command.h"
#include "image.h"
#include "algo/loop.h"
#include "phase_encoding.h"
#include "progressbar.h"
#include "dwi/gradient.h"

Expand Down
58 changes: 33 additions & 25 deletions cmd/mrconvert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#include "command.h"
#include "header.h"
#include "image.h"
#include "phase_encoding.h"
#include "transform.h"
#include "types.h"
#include "algo/threaded_copy.h"
Expand All @@ -27,6 +26,7 @@
#include "file/json_utils.h"
#include "file/ofstream.h"
#include "dwi/gradient.h"
#include "metadata/phase_encoding.h"


using namespace MR;
Expand Down Expand Up @@ -224,8 +224,8 @@ void usage ()

+ DWI::GradExportOptions()

+ PhaseEncoding::ImportOptions
+ PhaseEncoding::ExportOptions;
+ Metadata::PhaseEncoding::ImportOptions
+ Metadata::PhaseEncoding::ExportOptions;
}


Expand Down Expand Up @@ -258,7 +258,7 @@ void permute_DW_scheme (Header& H, const vector<int>& axes)

void permute_PE_scheme (Header& H, const vector<int>& axes)
{
auto in = PhaseEncoding::parse_scheme (H);
auto in = Metadata::PhaseEncoding::parse_scheme (H.keyval(), H);
if (!in.rows())
return;

Expand All @@ -271,19 +271,30 @@ void permute_PE_scheme (Header& H, const vector<int>& axes)
for (int row = 0; row != in.rows(); ++row)
out.block<1,3>(row, 0) = in.block<1,3>(row, 0) * permute;

PhaseEncoding::set_scheme (H, out);
Metadata::PhaseEncoding::set_scheme (H.keyval(), out);
}



void permute_slice_direction (Header& H, const vector<int>& axes)
{
auto it = H.keyval().find ("SliceEncodingDirection");
if (it == H.keyval().end())
using Metadata::BIDS::axis_vector_type;
auto slice_encoding_it = H.keyval().find("SliceEncodingDirection");
auto slice_timing_it = H.keyval().find("SliceTiming");
if (slice_encoding_it == H.keyval().end() && slice_timing_it == H.keyval().end())
return;
const Eigen::Vector3d orig_dir = Axes::id2dir (it->second);
const Eigen::Vector3d new_dir (orig_dir[axes[0]], orig_dir[axes[1]], orig_dir[axes[2]]);
it->second = Axes::dir2id (new_dir);
if (slice_encoding_it == H.keyval().end()) {
const axis_vector_type orig_dir({0, 0, 1});
const axis_vector_type new_dir(orig_dir[axes[0]], orig_dir[axes[1]], orig_dir[axes[2]]);
slice_encoding_it->second = Metadata::BIDS::vector2axisid(new_dir);
WARN("Header field \"SliceEncodingDirection\" inferred to be \"k\" in input image"
" and then transformed according to axis permutation"
" in order to preserve validity of existing header field \"SliceTiming\"");
return;
}
const axis_vector_type orig_dir = Metadata::BIDS::axisid2vector(slice_encoding_it->second);
const axis_vector_type new_dir(orig_dir[axes[0]], orig_dir[axes[1]], orig_dir[axes[2]]);
slice_encoding_it->second = Metadata::BIDS::vector2axisid(new_dir);
}


Expand Down Expand Up @@ -352,7 +363,7 @@ void copy_permute (const InputType& in, Header& header_out, const std::string& o
const auto axes = set_header (header_out, in);
auto out = Image<T>::create (output_filename, header_out, add_to_command_history);
DWI::export_grad_commandline (out);
PhaseEncoding::export_commandline (out);
Metadata::PhaseEncoding::export_commandline (out);
auto perm = Adapter::make <Adapter::PermuteAxes> (in, axes);
threaded_copy_with_progress (perm, out, 0, std::numeric_limits<size_t>::max(), 2);
}
Expand Down Expand Up @@ -396,21 +407,17 @@ void run ()
e.display (2);
}

auto opt = get_options("json_import");
if (!opt.empty())
File::JSON::load(header_in, opt[0][0]);
if (!get_options("import_pe_table").empty() || !get_options("import_pe_eddy").empty())
Metadata::PhaseEncoding::set_scheme(header_in.keyval(), Metadata::PhaseEncoding::get_scheme(header_in));

Header header_out (header_in);
header_out.datatype() = DataType::from_command_line (header_out.datatype());

if (header_in.datatype().is_complex() && !header_out.datatype().is_complex())
WARN ("requested datatype is real but input datatype is complex - imaginary component will be ignored");

if (get_options ("import_pe_table").size() || get_options ("import_pe_eddy").size())
PhaseEncoding::set_scheme (header_out, PhaseEncoding::get_scheme (header_in));

auto opt = get_options ("json_import");
if (opt.size())
File::JSON::load (header_out, opt[0][0]);



opt = get_options ("copy_properties");
if (opt.size()) {
header_out.keyval().clear();
Expand Down Expand Up @@ -494,16 +501,17 @@ void run ()
}
Eigen::MatrixXd pe_scheme;
try {
pe_scheme = PhaseEncoding::get_scheme (header_in);
pe_scheme = Metadata::PhaseEncoding::get_scheme (header_in);
if (pe_scheme.rows()) {
Eigen::MatrixXd extract_scheme (pos[3].size(), pe_scheme.cols());
for (size_t vol = 0; vol != pos[3].size(); ++vol)
extract_scheme.row (vol) = pe_scheme.row (pos[3][vol]);
PhaseEncoding::set_scheme (header_out, extract_scheme);
Metadata::PhaseEncoding::set_scheme (header_out.keyval(), extract_scheme);
}
} catch (...) {
WARN ("Phase encoding scheme of input file does not match number of image volumes; omitting information from output image");
PhaseEncoding::set_scheme (header_out, Eigen::MatrixXd());
WARN ("Phase encoding scheme of input file does not match number of image volumes;"
" omitting information from output image");
Metadata::PhaseEncoding::clear_scheme(header_out.keyval());
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion cmd/mrdegibbs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "image.h"
#include "progressbar.h"
#include "algo/threaded_loop.h"
#include "metadata/bids.h"
#include <numeric>

using namespace MR;
Expand Down Expand Up @@ -331,7 +332,7 @@ void run ()
auto slice_encoding_it = header.keyval().find ("SliceEncodingDirection");
if (slice_encoding_it != header.keyval().end()) {
try {
const Eigen::Vector3d slice_encoding_axis_onehot = Axes::id2dir (slice_encoding_it->second);
const Metadata::BIDS::axis_vector_type slice_encoding_axis_onehot = Metadata::BIDS::axisid2vector (slice_encoding_it->second);
vector<size_t> auto_slice_axes = { 0, 0 };
if (slice_encoding_axis_onehot[0])
auto_slice_axes = { 1, 2 };
Expand Down
10 changes: 5 additions & 5 deletions cmd/mrinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@

#include "command.h"
#include "header.h"
#include "phase_encoding.h"
#include "types.h"
#include "file/json.h"
#include "file/json_utils.h"
#include "dwi/gradient.h"
#include "image_io/pipe.h"
#include "metadata/phase_encoding.h"


using namespace MR;
Expand Down Expand Up @@ -106,7 +106,7 @@ void usage ()
+ Option ("shell_sizes", "list the number of volumes in each shell")
+ Option ("shell_indices", "list the image volumes attributed to each b-value shell")

+ PhaseEncoding::ExportOptions
+ Metadata::PhaseEncoding::ExportOptions
+ Option ("petable", "print the phase encoding table")

+ OptionGroup ("Handling of piped images")
Expand Down Expand Up @@ -251,7 +251,7 @@ void run ()
ImageIO::Pipe::delete_piped_images = false;

const bool export_grad = check_option_group (GradExportOptions);
const bool export_pe = check_option_group (PhaseEncoding::ExportOptions);
const bool export_pe = check_option_group (Metadata::PhaseEncoding::ExportOptions);

if (export_grad && argument.size() > 1)
throw Exception ("can only export DW gradient table to file if a single input image is provided");
Expand Down Expand Up @@ -300,7 +300,7 @@ void run ()
if (offset) std::cout << header.intensity_offset() << "\n";
if (multiplier) std::cout << header.intensity_scale() << "\n";
if (transform) print_transform (header);
if (petable) std::cout << PhaseEncoding::get_scheme (header) << "\n";
if (petable) std::cout << Metadata::PhaseEncoding::get_scheme (header) << "\n";

for (size_t n = 0; n < properties.size(); ++n)
print_properties (header, properties[n][0]);
Expand All @@ -319,7 +319,7 @@ void run ()
}

DWI::export_grad_commandline (header);
PhaseEncoding::export_commandline (header);
Metadata::PhaseEncoding::export_commandline (header);

if (json_keyval)
File::JSON::write (header, *json_keyval, (argument.size() > 1 ? std::string("") : std::string(argument[0])));
Expand Down
8 changes: 4 additions & 4 deletions cmd/mrmath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
#include "command.h"
#include "image.h"
#include "memory.h"
#include "phase_encoding.h"
#include "progressbar.h"
#include "algo/threaded_loop.h"
#include "dwi/gradient.h"
#include "math/math.h"
#include "math/median.h"
#include "dwi/gradient.h"
#include "metadata/phase_encoding.h"

#include <limits>

Expand Down Expand Up @@ -381,7 +381,7 @@ void run ()
DWI::stash_DW_scheme (header_out, DW_scheme);
} catch (...) { }
DWI::clear_DW_scheme (header_out);
PhaseEncoding::clear_scheme (header_out);
Metadata::PhaseEncoding::clear_scheme (header_out.keyval());
}

header_out.datatype() = DataType::from_command_line (DataType::Float32);
Expand Down Expand Up @@ -443,7 +443,7 @@ void run ()
if (temp.size(axis) != 1)
throw Exception ("Image " + path + " has axis with non-unary dimension beyond first input image " + header.name());
}
header.merge_keyval (temp);
header.merge_keyval (temp.keyval());
}

// Instantiate a kernel depending on the operation requested
Expand Down
Loading

0 comments on commit 339ea0c

Please sign in to comment.