1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
/* 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
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Covered Software is provided under this License on an "as is"
* basis, without warranty of any kind, either expressed, implied, or
* statutory, including, without limitation, warranties that the
* Covered Software is free of defects, merchantable, fit for a
* particular purpose or non-infringing.
* See the Mozilla Public License v. 2.0 for more details.
*
* For more details, see http://www.mrtrix.org/.
*/
#include <iomanip>
#include "command.h"
#include "datatype.h"
#include "image.h"
#include "image_helpers.h"
#include "memory.h"
#include "stats.h"
#include "types.h"
#include "algo/histogram.h"
#include "algo/loop.h"
#include "file/ofstream.h"
using namespace MR;
using namespace App;
void usage ()
{
AUTHOR = "J-Donald Tournier (jdtournier@gmail.com)";
SYNOPSIS = "Compute images statistics";
ARGUMENTS
+ Argument ("image",
"the input image from which statistics will be computed.")
.type_image_in ();
OPTIONS
+ Stats::Options
+ OptionGroup ("Additional options for mrstats")
+ Option ("allvolumes", "generate statistics across all image volumes, rather than one set of statistics per image volume");
}
using value_type = Stats::value_type;
using complex_type = Stats::complex_type;
class Volume_loop
{ NOMEMALIGN
public:
Volume_loop (Image<complex_type>& in) :
image (in),
is_4D (in.ndim() == 4),
status (true)
{
if (is_4D)
image.index(3) = 0;
}
void operator++ ()
{
if (is_4D) {
image.index(3)++;
} else {
assert (status);
status = false;
}
}
operator bool() const
{
if (is_4D)
return (image.index(3) >= 0 && image.index(3) < image.size(3));
else
return status;
}
private:
Image<complex_type>& image;
const bool is_4D;
bool status;
};
void run_volume (Stats::Stats& stats, Image<complex_type>& data, Image<bool>& mask)
{
if (mask.valid()) {
for (auto l = Loop(0,3) (data, mask); l; ++l) {
if (mask.value())
stats (data.value());
}
} else {
for (auto l = Loop(0,3) (data); l; ++l)
stats (data.value());
}
}
void run ()
{
auto header = Header::open (argument[0]);
if (header.ndim() > 4)
throw Exception ("mrstats is not designed to handle images greater than 4D");
const bool is_complex = header.datatype().is_complex();
auto data = header.get_image<complex_type>();
const bool ignorezero = get_options("ignorezero").size();
auto opt = get_options ("mask");
Image<bool> mask;
if (opt.size()) {
mask = Image<bool>::open (opt[0][0]);
check_dimensions (mask, header, 0, 3);
}
vector<std::string> fields;
opt = get_options ("output");
for (size_t n = 0; n < opt.size(); ++n)
fields.push_back (opt[n][0]);
if (App::log_level && fields.empty())
Stats::print_header (is_complex);
if (get_options ("allvolumes").size()) {
Stats::Stats stats (is_complex, ignorezero);
for (auto i = Volume_loop (data); i; ++i)
run_volume (stats, data, mask);
stats.print (data, fields);
} else {
for (auto i = Volume_loop (data); i; ++i) {
Stats::Stats stats (is_complex, ignorezero);
run_volume (stats, data, mask);
stats.print (data, fields);
}
}
}
|