From ee6f06009cca9774d5f43f4b24e6f762144e15e0 Mon Sep 17 00:00:00 2001 From: Robert Smith Date: Wed, 15 Jan 2025 22:47:41 +1100 Subject: [PATCH] Resolution of merge of master to dev Resolution of content merged to dev initially omitted from #3061. - #2693 (completely omitted) - #3005 (partial propagation / independent address of some common issues on both branches) - #3001 (completely omitted) - #2908 (completely omitted) - #2955 (completely omitted) - #2600 (completely omitted) - #2962 (completely omitted) - #2935 (completely omitted) - #2923 (completely omitted) - #2910 (completely omitted) - #2638 (completely omitted) - #2698 (completely omitted) - #2721 (completely omitted) - #2794 (completely omitted) - #2768 (completely omitted; required modification to conform to other dev changes) - #2713 (residual compilation errors following adf8fdd9b2403d181d4016439c3b6dd3db8c0767, including resolution against changes in #2437 on dev. --- .github/workflows/checks.yml | 2 +- cpp/cmd/dwi2tensor.cpp | 2 +- cpp/cmd/mrcalc.cpp | 2 ++ cpp/cmd/mrdegibbs.cpp | 16 ++++++++++---- cpp/cmd/mrgrid.cpp | 2 +- cpp/cmd/mrinfo.cpp | 2 +- cpp/core/adapter/reslice.h | 20 ++++++++++++----- cpp/core/app.cpp | 5 +++++ cpp/core/dwi/fmls.cpp | 2 +- cpp/core/file/dicom/select_cmdline.cpp | 6 ++--- cpp/core/file/mmap.cpp | 3 ++- cpp/core/file/png.cpp | 1 - cpp/core/file/png.h | 8 ++++--- cpp/core/formats/pipe.cpp | 3 ++- cpp/core/formats/png.cpp | 3 --- cpp/core/progressbar.cpp | 2 +- docs/reference/commands/dirrotate.rst | 2 +- docs/reference/commands/dwi2mask.rst | 22 +++++++++---------- docs/reference/commands/dwibiascorrect.rst | 2 +- docs/reference/commands/dwibiasnormmask.rst | 2 +- docs/reference/commands/dwinormalise.rst | 2 +- docs/reference/commands/mask2glass.rst | 2 +- docs/reference/commands/mrdegibbs.rst | 2 +- python/mrtrix3/commands/for_each.py | 12 ++++++++-- .../commands/population_template/input.py | 2 +- .../commands/population_template/utils.py | 19 ++++++++-------- 26 files changed, 89 insertions(+), 57 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 01dd92195c..bf272d3063 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -29,7 +29,7 @@ jobs: - name: install dependencies run: | sudo apt-get update - sudo apt-get install clang qt6-base-dev libglvnd-dev zlib1g-dev libfftw3-dev ninja-build python3-distutils python3-numpy libpng-dev + sudo apt-get install clang qt6-base-dev libglvnd-dev zlib1g-dev libfftw3-dev ninja-build python3-numpy libpng-dev - name: Run sccache-cache uses: mozilla-actions/sccache-action@v0.0.4 diff --git a/cpp/cmd/dwi2tensor.cpp b/cpp/cmd/dwi2tensor.cpp index 6822a9d80f..e52af511a7 100644 --- a/cpp/cmd/dwi2tensor.cpp +++ b/cpp/cmd/dwi2tensor.cpp @@ -295,7 +295,6 @@ void run() { Header header(dwi); header.datatype() = DataType::Float32; header.ndim() = 4; - DWI::stash_DW_scheme(header, grad); PhaseEncoding::clear_scheme(header); Image predict; @@ -303,6 +302,7 @@ void run() { if (!opt.empty()) predict = Image::create(opt[0][0], header); + DWI::stash_DW_scheme(header, grad); header.size(3) = 6; auto dt = Image::create(argument[1], header); diff --git a/cpp/cmd/mrcalc.cpp b/cpp/cmd/mrcalc.cpp index 5d3292d6c2..3bc55892a4 100644 --- a/cpp/cmd/mrcalc.cpp +++ b/cpp/cmd/mrcalc.cpp @@ -992,6 +992,8 @@ void run() { ++n; else if (opt->is("force") || opt->is("info") || opt->is("debug") || opt->is("quiet")) continue; + else if (opt->is("config")) + n+=2; #define SECTION 3 #include "mrcalc.cpp" diff --git a/cpp/cmd/mrdegibbs.cpp b/cpp/cmd/mrdegibbs.cpp index 17b5ac14e8..3fd59ae481 100644 --- a/cpp/cmd/mrdegibbs.cpp +++ b/cpp/cmd/mrdegibbs.cpp @@ -51,11 +51,19 @@ void usage() { " you should run denoising before this command to not alter the noise structure," " which would impact on dwidenoise's performance." + + "For best results, any form of filtering performed by the scanner should be disabled," + " whether performed in the image domain or k-space." + " This includes elliptic filtering and other filters " + " that are often applied to reduce Gibbs ringing artifacts." + " While this method can still safely be applied to such data," + " some residual ringing artefacts may still be present in the output." + + "Note that this method is designed to work on images acquired with full k-space coverage." - " Running this method on partial Fourier ('half-scan')" - " or filtered data may not remove all ringing artefacts." - " Users are encouraged to acquired full-Fourier data where possible," - " and disable any form of filtering on the scanner."; + " If this method is executed on data acquired with partial Fourier (eg. \"half-scan\") acceleration," + " it may not fully remove all ringing artifacts," + " and you may observe residuals of the original artifact in the partial Fourier direction." + " Nonetheless, application of the method is still considered safe and worthwhile." + " Users are however encouraged to acquired full-Fourier data where possible."; ARGUMENTS diff --git a/cpp/cmd/mrgrid.cpp b/cpp/cmd/mrgrid.cpp index be9cc5653b..cb81738900 100644 --- a/cpp/cmd/mrgrid.cpp +++ b/cpp/cmd/mrgrid.cpp @@ -150,7 +150,7 @@ void usage() { " to match the specified reference image grid." " This operation ignores differences in image transformation" " between input and reference image.") - + Argument ("reference image").type_image_in() + + Argument ("reference_image").type_image_in() + Option ("uniform", "pad or crop the input image" " by a uniform number of voxels on all sides") diff --git a/cpp/cmd/mrinfo.cpp b/cpp/cmd/mrinfo.cpp index dad1b62fad..155811a9b6 100644 --- a/cpp/cmd/mrinfo.cpp +++ b/cpp/cmd/mrinfo.cpp @@ -51,7 +51,7 @@ const OptionGroup FieldExportOptions = OptionGroup ("Options for exporting image void usage() { - AUTHOR = "J-Donald Tournier (d.tournier@brain.org.au)" + AUTHOR = "J-Donald Tournier (jdtournier@gmail.com)" " and Robert E. Smith (robert.smith@florey.edu.au)"; SYNOPSIS = "Display image header information," diff --git a/cpp/core/adapter/reslice.h b/cpp/core/adapter/reslice.h index 8e200c9a08..a5ca68c788 100644 --- a/cpp/core/adapter/reslice.h +++ b/cpp/core/adapter/reslice.h @@ -42,11 +42,21 @@ typename std::enable_if::value && std::is_integr return value_type(std::round(sum * norm)); } -template -typename std::enable_if::value, value_type>::type inline normalise( - const default_type sum, const default_type norm) { - return (sum * norm); +// Standard implementation for floating point (either real or complex) +template +typename std::enable_if::value && !std::is_integral::value, value_type>::type +inline normalise (const summing_type sum, const default_type norm) { + return value_type (sum * norm); } + +// If summing complex numbers, use double precision complex; +// otherwise, use double precision real +template struct summing_type { + using type = double; +}; +template struct summing_type> { + using type = std::complex; +}; } // namespace extern const transform_type NoTransform; @@ -175,7 +185,7 @@ class Reslice : public ImageBase, typename Imag using namespace Eigen; if (oversampling) { Vector3d d(x[0] + from[0], x[1] + from[1], x[2] + from[2]); - default_type sum(0.0); + typename summing_type::type sum(0); Vector3d s; for (uint32_t z = 0; z < OS[2]; ++z) { s[2] = d[2] + z * inc[2]; diff --git a/cpp/core/app.cpp b/cpp/core/app.cpp index 94eab5c739..96268007fe 100644 --- a/cpp/core/app.cpp +++ b/cpp/core/app.cpp @@ -187,6 +187,8 @@ std::string underline(const std::string &text, bool ignore_whitespace = false) { const char *argtype_description(ArgType type) { switch (type) { + case Boolean: + return ("boolean"); case Integer: return ("integer"); case Float: @@ -450,6 +452,9 @@ std::string Argument::usage() const { case Undefined: assert(0); break; + case Boolean: + stream << "BOOL"; + break; case Integer: { const auto int_range = std::get(limits); stream << "INT " << int_range.min << " " << int_range.max; diff --git a/cpp/core/dwi/fmls.cpp b/cpp/core/dwi/fmls.cpp index bd495aab1e..c5d5fcb17c 100644 --- a/cpp/core/dwi/fmls.cpp +++ b/cpp/core/dwi/fmls.cpp @@ -78,7 +78,7 @@ void load_fmls_thresholds(Segmenter &segmenter) { } } - opt = get_options("fmls_merge_ratio"); + opt = get_options("fmls_lobe_merge_ratio"); if (!opt.empty()) segmenter.set_lobe_merge_ratio(default_type(opt[0][0])); } diff --git a/cpp/core/file/dicom/select_cmdline.cpp b/cpp/core/file/dicom/select_cmdline.cpp index 48905d2bc3..6274e1914a 100644 --- a/cpp/core/file/dicom/select_cmdline.cpp +++ b/cpp/core/file/dicom/select_cmdline.cpp @@ -100,7 +100,7 @@ std::vector> select_cmdline(const Tree &tree) { } std::cerr << "? "; std::cin >> buf; - if (buf[0] == 'q' || buf[0] == 'Q') + if (!std::cin || buf[0] == 'q' || buf[0] == 'Q') throw CancelException(); if (isdigit(buf[0])) { int n = to(buf) - 1; @@ -138,7 +138,7 @@ std::vector> select_cmdline(const Tree &tree) { } std::cerr << "? "; std::cin >> buf; - if (buf[0] == 'q' || buf[0] == 'Q') + if (!std::cin || buf[0] == 'q' || buf[0] == 'Q') throw CancelException(); if (isdigit(buf[0])) { int n = to(buf) - 1; @@ -179,7 +179,7 @@ std::vector> select_cmdline(const Tree &tree) { } std::cerr << "? "; std::cin >> buf; - if (buf[0] == 'q' || buf[0] == 'Q') + if (!std::cin || buf[0] == 'q' || buf[0] == 'Q') throw CancelException(); if (isdigit(buf[0])) { std::vector seq; diff --git a/cpp/core/file/mmap.cpp b/cpp/core/file/mmap.cpp index 087f4eef13..34597c4e79 100644 --- a/cpp/core/file/mmap.cpp +++ b/cpp/core/file/mmap.cpp @@ -109,7 +109,8 @@ MMap::MMap(const Entry &entry, bool readwrite, bool preload, int64_t mapped_size if (fsbuf.f_type == 0xff534d42 /* CIFS */ || fsbuf.f_type == 0x6969 /* NFS */ || fsbuf.f_type == 0x65735546 /* FUSE */ || fsbuf.f_type == 0x517b /* SMB */ || - fsbuf.f_type == 0x47504653 /* GPFS */ || fsbuf.f_type == 0xbd00bd0 /* LUSTRE */ + fsbuf.f_type == 0x47504653 /* GPFS */ || fsbuf.f_type == 0xbd00bd0 /* LUSTRE */ || + fsbuf.f_type == 0x1021997 /* 9P (WSL) */ #ifdef MRTRIX_MACOSX || fsbuf.f_type == 0x0017 /* OSXFUSE */ diff --git a/cpp/core/file/png.cpp b/cpp/core/file/png.cpp index c696f0a42d..061232f051 100644 --- a/cpp/core/file/png.cpp +++ b/cpp/core/file/png.cpp @@ -309,7 +309,6 @@ void Writer::save(uint8_t *data) { row_pointers[row] = to_write + row * row_bytes; png_write_image(png_ptr, row_pointers.get()); png_write_end(png_ptr, info_ptr); - delete [] row_pointers; }; if (data_type == DataType::UInt8 || data_type == DataType::UInt16BE) { diff --git a/cpp/core/file/png.h b/cpp/core/file/png.h index 3c711e0a93..9766c6a518 100644 --- a/cpp/core/file/png.h +++ b/cpp/core/file/png.h @@ -87,9 +87,11 @@ template void Writer::fill(uint8_t *in_ptr, uint8_t *out_ptr, const DataType data_type, const size_t num_elements) { auto fetch_func = __set_fetch_function(data_type); for (size_t i = 0; i != num_elements; ++i) - Raw::store_BE (std::min (default_type(std::numeric_limits::max()), // - std::max (0.0, std::round(multiplier * fetch_func (in_ptr, i, 0.0, 1.0)))), // - out_ptr, i); // + Raw::store_BE (std::min (default_type(std::numeric_limits::max()), // + std::max (0.0, std::round(multiplier * fetch_func (in_ptr, 0)))), // + out_ptr, i); // + in_ptr += data_type.bytes(); + out_ptr += sizeof(T); }; } // namespace MR::File::PNG diff --git a/cpp/core/formats/pipe.cpp b/cpp/core/formats/pipe.cpp index 41c8aacd01..aaade85860 100644 --- a/cpp/core/formats/pipe.cpp +++ b/cpp/core/formats/pipe.cpp @@ -54,7 +54,8 @@ bool Pipe::check(Header &H, size_t num_axes) const { return false; if (isatty(STDOUT_FILENO)) - throw Exception("attempt to pipe image to standard output (this will leave temporary files behind)"); + throw Exception ("cannot create output piped image: " // + "no command connected at other end of pipe to receive that image"); // H.name() = File::create_tempfile(0, "mif"); diff --git a/cpp/core/formats/png.cpp b/cpp/core/formats/png.cpp index 71146b25ba..d26a50c8df 100644 --- a/cpp/core/formats/png.cpp +++ b/cpp/core/formats/png.cpp @@ -160,7 +160,6 @@ bool PNG::check(Header &H, size_t num_axes) const { axis_to_zero = 1; } else if (H.size(0) == 1) { axis_to_zero = 0; - width_axis = 1; } else { // If image is 3D, and all three axes have size greater than one, and we // haven't used the square-bracket notation, we can't export genuine 3D data @@ -184,8 +183,6 @@ bool PNG::check(Header &H, size_t num_axes) const { if (axis < 0) throw Exception("Cannot export 4D image to PNG format if all three spatial axes have size greater than 1 and " "square-bracket notation is not used"); - if (!axis_to_zero) - width_axis = 1; break; default: throw Exception("Cannot generate PNG file(s) from image with more than 4 axes"); diff --git a/cpp/core/progressbar.cpp b/cpp/core/progressbar.cpp index 700c5160b9..bc26c74e93 100644 --- a/cpp/core/progressbar.cpp +++ b/cpp/core/progressbar.cpp @@ -155,7 +155,7 @@ bool ProgressBar::set_update_method() { // unable to determine nature of stderr; assuming socket stderr_to_file = false; else - stderr_to_file = S_ISREG(buf.st_mode); + stderr_to_file = S_ISREG(buf.st_mode) || S_ISFIFO(buf.st_mode); if (stderr_to_file) { ProgressBar::display_func = display_func_redirect; diff --git a/docs/reference/commands/dirrotate.rst b/docs/reference/commands/dirrotate.rst index 99ab692a0d..0f2d3df038 100644 --- a/docs/reference/commands/dirrotate.rst +++ b/docs/reference/commands/dirrotate.rst @@ -60,7 +60,7 @@ Tournier, J.-D.; Smith, R. E.; Raffelt, D.; Tabbara, R.; Dhollander, T.; Pietsch **Author:** Robert E. Smith (robert.smith@florey.edu.au) -**Copyright:** Copyright (c) 2008-2024 the MRtrix3 contributors. +**Copyright:** Copyright (c) 2008-2025 the MRtrix3 contributors. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/docs/reference/commands/dwi2mask.rst b/docs/reference/commands/dwi2mask.rst index 4457f42bb4..a4ea9e84a9 100644 --- a/docs/reference/commands/dwi2mask.rst +++ b/docs/reference/commands/dwi2mask.rst @@ -185,7 +185,7 @@ Tournier, J.-D.; Smith, R. E.; Raffelt, D.; Tabbara, R.; Dhollander, T.; Pietsch **Author:** Ricardo Rios (ricardo.rios@cimat.mx) -**Copyright:** Copyright (c) 2008-2024 the MRtrix3 contributors. +**Copyright:** Copyright (c) 2008-2025 the MRtrix3 contributors. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this @@ -276,7 +276,7 @@ Tournier, J.-D.; Smith, R. E.; Raffelt, D.; Tabbara, R.; Dhollander, T.; Pietsch **Author:** Robert E. Smith (robert.smith@florey.edu.au) -**Copyright:** Copyright (c) 2008-2024 the MRtrix3 contributors. +**Copyright:** Copyright (c) 2008-2025 the MRtrix3 contributors. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this @@ -390,7 +390,7 @@ Tournier, J.-D.; Smith, R. E.; Raffelt, D.; Tabbara, R.; Dhollander, T.; Pietsch **Author:** Robert E. Smith (robert.smith@florey.edu.au) -**Copyright:** Copyright (c) 2008-2024 the MRtrix3 contributors. +**Copyright:** Copyright (c) 2008-2025 the MRtrix3 contributors. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this @@ -485,7 +485,7 @@ Tournier, J.-D.; Smith, R. E.; Raffelt, D.; Tabbara, R.; Dhollander, T.; Pietsch **Author:** Robert E. Smith (robert.smith@florey.edu.au) -**Copyright:** Copyright (c) 2008-2024 the MRtrix3 contributors. +**Copyright:** Copyright (c) 2008-2025 the MRtrix3 contributors. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this @@ -584,7 +584,7 @@ Tournier, J.-D.; Smith, R. E.; Raffelt, D.; Tabbara, R.; Dhollander, T.; Pietsch **Author:** Warda Syeda (wtsyeda@unimelb.edu.au) and Robert E. Smith (robert.smith@florey.edu.au) -**Copyright:** Copyright (c) 2008-2024 the MRtrix3 contributors. +**Copyright:** Copyright (c) 2008-2025 the MRtrix3 contributors. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this @@ -675,7 +675,7 @@ Tournier, J.-D.; Smith, R. E.; Raffelt, D.; Tabbara, R.; Dhollander, T.; Pietsch **Author:** Robert E. Smith (robert.smith@florey.edu.au) -**Copyright:** Copyright (c) 2008-2024 the MRtrix3 contributors. +**Copyright:** Copyright (c) 2008-2025 the MRtrix3 contributors. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this @@ -761,7 +761,7 @@ Tournier, J.-D.; Smith, R. E.; Raffelt, D.; Tabbara, R.; Dhollander, T.; Pietsch **Author:** Robert E. Smith (robert.smith@florey.edu.au) -**Copyright:** Copyright (c) 2008-2024 the MRtrix3 contributors. +**Copyright:** Copyright (c) 2008-2025 the MRtrix3 contributors. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this @@ -852,7 +852,7 @@ Tournier, J.-D.; Smith, R. E.; Raffelt, D.; Tabbara, R.; Dhollander, T.; Pietsch **Author:** Warda Syeda (wtsyeda@unimelb.edu.au) -**Copyright:** Copyright (c) 2008-2024 the MRtrix3 contributors. +**Copyright:** Copyright (c) 2008-2025 the MRtrix3 contributors. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this @@ -960,7 +960,7 @@ Tournier, J.-D.; Smith, R. E.; Raffelt, D.; Tabbara, R.; Dhollander, T.; Pietsch **Author:** Robert E. Smith (robert.smith@florey.edu.au) and Arshiya Sangchooli (asangchooli@student.unimelb.edu.au) -**Copyright:** Copyright (c) 2008-2024 the MRtrix3 contributors. +**Copyright:** Copyright (c) 2008-2025 the MRtrix3 contributors. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this @@ -1064,7 +1064,7 @@ Tournier, J.-D.; Smith, R. E.; Raffelt, D.; Tabbara, R.; Dhollander, T.; Pietsch **Author:** Ruobing Chen (chrc@student.unimelb.edu.au) -**Copyright:** Copyright (c) 2008-2024 the MRtrix3 contributors. +**Copyright:** Copyright (c) 2008-2025 the MRtrix3 contributors. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this @@ -1162,7 +1162,7 @@ Tournier, J.-D.; Smith, R. E.; Raffelt, D.; Tabbara, R.; Dhollander, T.; Pietsch **Author:** Warda Syeda (wtsyeda@unimelb.edu.au) and Robert E. Smith (robert.smith@florey.edu.au) -**Copyright:** Copyright (c) 2008-2024 the MRtrix3 contributors. +**Copyright:** Copyright (c) 2008-2025 the MRtrix3 contributors. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/docs/reference/commands/dwibiascorrect.rst b/docs/reference/commands/dwibiascorrect.rst index d85fd5dbbf..badacebdf9 100644 --- a/docs/reference/commands/dwibiascorrect.rst +++ b/docs/reference/commands/dwibiascorrect.rst @@ -392,7 +392,7 @@ Tournier, J.-D.; Smith, R. E.; Raffelt, D.; Tabbara, R.; Dhollander, T.; Pietsch **Author:** Robert E. Smith (robert.smith@florey.edu.au) and Arshiya Sangchooli (asangchooli@student.unimelb.edu.au) -**Copyright:** Copyright (c) 2008-2024 the MRtrix3 contributors. +**Copyright:** Copyright (c) 2008-2025 the MRtrix3 contributors. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/docs/reference/commands/dwibiasnormmask.rst b/docs/reference/commands/dwibiasnormmask.rst index 2a8de8f063..eadd774cc2 100644 --- a/docs/reference/commands/dwibiasnormmask.rst +++ b/docs/reference/commands/dwibiasnormmask.rst @@ -115,7 +115,7 @@ Tournier, J.-D.; Smith, R. E.; Raffelt, D.; Tabbara, R.; Dhollander, T.; Pietsch **Author:** Robert E. Smith (robert.smith@florey.edu.au) and Arshiya Sangchooli (asangchooli@student.unimelb.edu.au) -**Copyright:** Copyright (c) 2008-2024 the MRtrix3 contributors. +**Copyright:** Copyright (c) 2008-2025 the MRtrix3 contributors. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/docs/reference/commands/dwinormalise.rst b/docs/reference/commands/dwinormalise.rst index 800a74daac..a1175fe791 100644 --- a/docs/reference/commands/dwinormalise.rst +++ b/docs/reference/commands/dwinormalise.rst @@ -354,7 +354,7 @@ Tournier, J.-D.; Smith, R. E.; Raffelt, D.; Tabbara, R.; Dhollander, T.; Pietsch **Author:** Robert E. Smith (robert.smith@florey.edu.au) and Arshiya Sangchooli (asangchooli@student.unimelb.edu.au) -**Copyright:** Copyright (c) 2008-2024 the MRtrix3 contributors. +**Copyright:** Copyright (c) 2008-2025 the MRtrix3 contributors. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/docs/reference/commands/mask2glass.rst b/docs/reference/commands/mask2glass.rst index cf6acc068c..7222ffd4c8 100644 --- a/docs/reference/commands/mask2glass.rst +++ b/docs/reference/commands/mask2glass.rst @@ -73,7 +73,7 @@ Tournier, J.-D.; Smith, R. E.; Raffelt, D.; Tabbara, R.; Dhollander, T.; Pietsch **Author:** Remika Mito (remika.mito@florey.edu.au) and Robert E. Smith (robert.smith@florey.edu.au) -**Copyright:** Copyright (c) 2008-2024 the MRtrix3 contributors. +**Copyright:** Copyright (c) 2008-2025 the MRtrix3 contributors. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/docs/reference/commands/mrdegibbs.rst b/docs/reference/commands/mrdegibbs.rst index eeadc3100c..8a4881efe6 100644 --- a/docs/reference/commands/mrdegibbs.rst +++ b/docs/reference/commands/mrdegibbs.rst @@ -27,7 +27,7 @@ By default, the original 2D slice-wise version is used. If the -mode 3d option i This command is designed to run on data directly after it has been reconstructed by the scanner, before any interpolation of any kind has taken place. You should not run this command after any form of motion correction (e.g. not after dwifslpreproc). Similarly, if you intend running dwidenoise, you should run denoising before this command to not alter the noise structure, which would impact on dwidenoise's performance. -For best results, any form of filtering performed by the scanner should be disabled, whether performed in the image domain or k-space. This includes elliptic filtering and other filters that are often applied to reduce Gibbs ringing artifacts. While this method can still safely be applied to such data, some residual ringing artefacts may still be present in the output. +For best results, any form of filtering performed by the scanner should be disabled, whether performed in the image domain or k-space. This includes elliptic filtering and other filters that are often applied to reduce Gibbs ringing artifacts. While this method can still safely be applied to such data, some residual ringing artefacts may still be present in the output. Note that this method is designed to work on images acquired with full k-space coverage. If this method is executed on data acquired with partial Fourier (eg. "half-scan") acceleration, it may not fully remove all ringing artifacts, and you may observe residuals of the original artifact in the partial Fourier direction. Nonetheless, application of the method is still considered safe and worthwhile. Users are however encouraged to acquired full-Fourier data where possible. diff --git a/python/mrtrix3/commands/for_each.py b/python/mrtrix3/commands/for_each.py index 56b099a18b..18289c3190 100644 --- a/python/mrtrix3/commands/for_each.py +++ b/python/mrtrix3/commands/for_each.py @@ -119,6 +119,14 @@ def usage(cmdline): #pylint: disable=unused-variable ' but will not actually execute those commands.' ' It can therefore be used to verify that the script is receiving the intended set of inputs,' ' and that the text substitutions on those inputs lead to the intended command strings.') + cmdline.add_example_usage('Utilising shell operators within the command substitution', + 'for_each * : tensor2metric IN/dwi.mif - "|" tensor2metric - -fa IN/fa.mif', + 'In this example, if the double-quotes were NOT placed around the pipe operator,' + ' then the shell would take the sum total output of the for_each script' + ' and pipe that to a single invocation of the tensor2metric command.' + ' Since in this example it is instead desired for the pipe operator to be' + ' a part of the command string that is executed multiple times by the for_each script,' + ' it must be escaped using double-quotes.') cmdline.add_argument('inputs', nargs='+', help='Each of the inputs for which processing should be run') @@ -297,7 +305,7 @@ def __init__(self, input_text): def progress_string(): success_count = sum(1 if job.returncode is not None else 0 for job in jobs) - fail_count = sum(1 if job.returncode else 0 for job in jobs) + fail_count = sum(bool(job.returncode) for job in jobs) threading_message = f'across {app.NUM_THREADS} threads' if parallel else 'sequentially' fail_message = f' ({fail_count} errors)' if fail_count else '' return f'{success_count}/{len(jobs)} jobs completed {threading_message}{fail_message}' @@ -348,7 +356,7 @@ def execute_parallel(): progress.done() assert all(job.returncode is not None for job in jobs) - fail_count = sum(1 if job.returncode else 0 for job in jobs) + fail_count = sum(bool(job.returncode) for job in jobs) if fail_count: app.warn(f'{fail_count} of {len(jobs)} jobs did not complete successfully') if fail_count > 1: diff --git a/python/mrtrix3/commands/population_template/input.py b/python/mrtrix3/commands/population_template/input.py index 362506659f..4a41db9768 100644 --- a/python/mrtrix3/commands/population_template/input.py +++ b/python/mrtrix3/commands/population_template/input.py @@ -63,7 +63,7 @@ class Input: # pylint: disable=unused-variable copy files into folders in current working directory. modifies _local_ims and _local_msk """ - def __init__(self, uid, filenames, directories, contrasts, mask_filename='', mask_directory=''): # pylint: disable=too-many-positional-arguments + def __init__(self, uid, filenames, directories, contrasts, mask_filename='', mask_directory=''): # pylint: disable=too-many-arguments self.contrasts = contrasts self.uid = uid diff --git a/python/mrtrix3/commands/population_template/utils.py b/python/mrtrix3/commands/population_template/utils.py index 46d06a3f3e..c9f303bd88 100644 --- a/python/mrtrix3/commands/population_template/utils.py +++ b/python/mrtrix3/commands/population_template/utils.py @@ -41,7 +41,7 @@ def copy(src, dst, follow_symlinks=True): # pylint: disable=unused-variable -def check_linear_transformation(transformation, cmd, max_scaling=0.5, max_shear=0.2, max_rot=None, pause_on_warn=True): # pylint: disable=unused-variable,too-many-positional-arguments +def check_linear_transformation(transformation, cmd, max_scaling=0.5, max_shear=0.2, max_rot=None, pause_on_warn=True): # pylint: disable=unused-variable, too-many-arguments if max_rot is None: max_rot = 2 * math.pi @@ -53,8 +53,9 @@ def check_linear_transformation(transformation, cmd, max_scaling=0.5, max_shear= data = utils.load_keyval(f'{transformation}decomp') run.function(os.remove, f'{transformation}decomp') scaling = [float(value) for value in data['scaling']] - if any(a < 0 for a in scaling) or any(a > (1 + max_scaling) for a in scaling) or any( - a < (1 - max_scaling) for a in scaling): + if any(a < 0 for a in scaling) or \ + any(a > (1 + max_scaling) for a in scaling) or \ + any(a < (1 - max_scaling) for a in scaling): app.warn(f'large scaling ({scaling})) in {transformation}') good = False shear = [float(value) for value in data['shear']] @@ -115,10 +116,10 @@ def aggregate(inputs, output, contrast_idx, mode, force=True): # pylint: disable elif mode == 'weighted_mean': weights = [inp.aggregation_weight for inp in inputs] assert not any(w is None for w in weights), weights - wsum = sum(float(w) for w in weights) - cmd = ['mrcalc'] + wsum = sum(map(float, weights)) if wsum <= 0: raise MRtrixError('the sum of aggregetion weights has to be positive') + cmd = ['mrcalc'] for weight, imagepath in zip(weights, images): if float(weight) != 0: cmd += [imagepath, weight, '-mult'] + (['-add'] if len(cmd) > 1 else []) @@ -273,16 +274,14 @@ def paths_to_file_uids(paths, prefix, postfix): if f_agg_weight: try: with open(f_agg_weight, 'r', encoding='utf-8') as fweights: - agg_weights = dict((row[0].lstrip().rstrip(), row[1]) for row in csv.reader(fweights, delimiter=',', quotechar='#')) + agg_weights = dict((row[0].strip(), row[1].strip()) for row in csv.reader(fweights, delimiter=',', quotechar='#')) except UnicodeDecodeError: with open(f_agg_weight, 'r', encoding='utf-8') as fweights: reader = csv.reader(fweights.read().decode('utf-8', errors='replace'), delimiter=',', quotechar='#') - agg_weights = dict((row[0].lstrip().rstrip(), row[1]) for row in reader) + agg_weights = dict((row[0].strip(), row[1].strip()) for row in reader) pref = '^' + re.escape(get_common_prefix(list(agg_weights.keys()))) suff = re.escape(get_common_postfix(list(agg_weights.keys()))) + '$' - for key in agg_weights.keys(): - agg_weights[re.sub(suff, '', re.sub(pref, '', key))] = agg_weights.pop(key).strip() - + agg_weights = {re.sub(suff, '', re.sub(pref, '', item[0])):item[1] for item in agg_weights.items()} for inp in inputs: if inp.uid not in agg_weights: raise MRtrixError(f'aggregation weight not found for {inp.uid}')