forked from MRtrix3/mrtrix3
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlabelconvert.cpp
159 lines (115 loc) · 4.67 KB
/
labelconvert.cpp
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
157
158
/* Copyright (c) 2008-2017 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/.
*
* MRtrix is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* For more details, see http://www.mrtrix.org/.
*/
#include "command.h"
#include "image.h"
#include "image_helpers.h"
#include "mrtrix.h"
#include "transform.h"
#include "algo/loop.h"
#include "file/path.h"
#include "file/utils.h"
#include "interp/nearest.h"
#include "connectome/connectome.h"
#include "connectome/lut.h"
#include <string>
#define SPINE_NODE_NAME std::string("Spinal_column")
using namespace MR;
using namespace App;
using namespace MR::Connectome;
using MR::Connectome::node_t;
void usage ()
{
AUTHOR = "Robert E. Smith ([email protected])";
SYNOPSIS = "Convert a connectome node image from one lookup table to another";
DESCRIPTION
+ "Typical usage is to convert a parcellation image provided by some other software, based on "
"the lookup table provided by that software, to conform to a new lookup table, particularly "
"one where the node indices increment from 1, in preparation for connectome construction; "
"examples of such target lookup table files are provided in share//mrtrix3//labelconvert//";
ARGUMENTS
+ Argument ("path_in", "the input image").type_image_in()
+ Argument ("lut_in", "the connectome lookup table for the input image").type_file_in()
+ Argument ("lut_out", "the target connectome lookup table for the output image").type_file_in()
+ Argument ("image_out", "the output image").type_image_out();
OPTIONS
+ Option ("spine", "provide a manually-defined segmentation of the base of the spine where the streamlines terminate, so that "
"this can become a node in the connection matrix.")
+ Argument ("image").type_image_in();
}
void run ()
{
// Open the input file
auto H = Header::open (argument[0]);
Connectome::check (H);
auto in = H.get_image<node_t>();
// Load the lookup tables
LUT lut_in (argument[1]), lut_out (argument[2]);
// Build the mapping from input to output indices
const auto mapping = get_lut_mapping (lut_in, lut_out);
// Modify the header for the output file
H.datatype() = DataType::from<node_t>();
add_line (H.keyval()["comments"], "LUT: " + Path::basename (argument[2]));
// Create the output file
auto out = Image<node_t>::create (argument[3], H);
// Fill the output image with data
bool user_warn = false;
for (auto l = Loop (in) (in, out); l; ++l) {
const node_t orig = in.value();
if (orig < mapping.size())
out.value() = mapping[orig];
else
user_warn = true;
}
if (user_warn)
WARN ("Unexpected values detected in input image; suggest checking input image thoroughly");
// Need to manually search through the output LUT to see if the
// 'Spinal_column' node is in there, and appears only once
node_t spine_index = 0;
bool duplicates = false;
for (const auto& i : lut_out) {
if (i.second.get_name() == SPINE_NODE_NAME) {
if (!spine_index)
spine_index = i.first;
else
duplicates = true;
}
}
// If the spine segment option has been provided, add this retrospectively
auto opt = get_options ("spine");
if (opt.size()) {
if (duplicates) {
WARN ("Could not add spine node: \"" + SPINE_NODE_NAME + "\" appears multiple times in output LUT");
} else {
auto in_spine = Image<bool>::open (opt[0][0]);
if (dimensions_match (in_spine, out)) {
for (auto l = Loop (in_spine) (in_spine, out); l; ++l) {
if (in_spine.value())
out.value() = spine_index;
}
} else {
WARN ("Spine node is being created from the mask image provided using -spine option using nearest-neighbour interpolation;");
WARN ("recommend using the parcellation image as the basis for this mask so that interpolation is not required");
Transform transform (out);
Interp::Nearest<decltype(in_spine)> nearest (in_spine);
for (auto l = Loop (out) (out); l; ++l) {
Eigen::Vector3 p (out.index (0), out.index (1), out.index (2));
p = transform.voxel2scanner * p;
if (nearest.scanner (p) && nearest.value())
out.value() = spine_index;
}
}
}
} else if (spine_index) {
WARN ("Config file includes \"" + SPINE_NODE_NAME + "\" node, but user has not provided the segmentation using -spine option");
}
}