1 |
|
|
/* |
2 |
|
|
Teem: Tools to process and visualize scientific data and images . |
3 |
|
|
Copyright (C) 2013, 2012, 2011, 2010, 2009 University of Chicago |
4 |
|
|
Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann |
5 |
|
|
Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah |
6 |
|
|
|
7 |
|
|
This library is free software; you can redistribute it and/or |
8 |
|
|
modify it under the terms of the GNU Lesser General Public License |
9 |
|
|
(LGPL) as published by the Free Software Foundation; either |
10 |
|
|
version 2.1 of the License, or (at your option) any later version. |
11 |
|
|
The terms of redistributing and/or modifying this software also |
12 |
|
|
include exceptions to the LGPL that facilitate static linking. |
13 |
|
|
|
14 |
|
|
This library is distributed in the hope that it will be useful, |
15 |
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
17 |
|
|
Lesser General Public License for more details. |
18 |
|
|
|
19 |
|
|
You should have received a copy of the GNU Lesser General Public License |
20 |
|
|
along with this library; if not, write to Free Software Foundation, Inc., |
21 |
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
22 |
|
|
*/ |
23 |
|
|
|
24 |
|
|
#include "unrrdu.h" |
25 |
|
|
#include "privateUnrrdu.h" |
26 |
|
|
|
27 |
|
|
#define INFO "Modify attributes of one or more axes" |
28 |
|
|
static const char *_unrrdu_axinfoInfoL = |
29 |
|
|
(INFO |
30 |
|
|
". The only attributes which are set are those for which command-line " |
31 |
|
|
"options are given.\n " |
32 |
|
|
"* Uses no particular function; just sets fields in the NrrdAxisInfo"); |
33 |
|
|
|
34 |
|
|
int |
35 |
|
|
unrrdu_axinfoMain(int argc, const char **argv, const char *me, |
36 |
|
|
hestParm *hparm) { |
37 |
|
2 |
hestOpt *opt = NULL; |
38 |
|
1 |
char *out, *err, *label, *units, *centerStr, *kindStr, |
39 |
|
|
*_dirStr, *dirStr, *mmStr[2]; |
40 |
|
1 |
Nrrd *nin, *nout; |
41 |
|
|
int pret, center, kind; |
42 |
|
1 |
unsigned int *axes, axesLen, axi, mmIdx; |
43 |
|
1 |
double mm[2], spc, sdir[NRRD_SPACE_DIM_MAX]; |
44 |
|
|
airArray *mop; |
45 |
|
|
|
46 |
|
1 |
hestOptAdd(&opt, "a,axes", "ax0", airTypeUInt, 1, -1, &axes, NULL, |
47 |
|
|
"the one or more axes that should be modified", &axesLen); |
48 |
|
1 |
hestOptAdd(&opt, "l,label", "label", airTypeString, 1, 1, &label, "", |
49 |
|
|
"label to associate with axis"); |
50 |
|
1 |
hestOptAdd(&opt, "u,units", "units", airTypeString, 1, 1, &units, "", |
51 |
|
|
"units of measurement"); |
52 |
|
|
mmIdx = |
53 |
|
1 |
hestOptAdd(&opt, "mm,minmax", "min max", airTypeString, 2, 2, mmStr, "nan nan", |
54 |
|
|
"min and max values along axis"); |
55 |
|
1 |
hestOptAdd(&opt, "sp,spacing", "spacing", airTypeDouble, 1, 1, &spc, "nan", |
56 |
|
|
"spacing between samples along axis"); |
57 |
|
|
/* There used to be a complaint here about how hest doesn't allow |
58 |
|
|
you to learn whether the option was parsed from the supplied |
59 |
|
|
default versus from the command-line itself. That issue has been |
60 |
|
|
solved: opt[oi].source now takes on values from the hestSource* |
61 |
|
|
enum; axinsert.c now provides an example of this. However, |
62 |
|
|
parsing from a string here is still needed here, because here we |
63 |
|
|
need to allow the string that represents "no centering"; this |
64 |
|
|
is a current weakness of airEnumStr. |
65 |
|
|
hestOptAdd(&opt, "c,center", "center", airTypeEnum, 1, 1, ¢, "unknown", |
66 |
|
|
"centering of axis: \"cell\" or \"node\"", |
67 |
|
|
NULL, nrrdCenter); |
68 |
|
|
*/ |
69 |
|
1 |
hestOptAdd(&opt, "c,center", "center", airTypeString, 1, 1, ¢erStr, "", |
70 |
|
|
"axis centering: \"cell\" or \"node\". Not using this option " |
71 |
|
|
"leaves the centering as it is on input"); |
72 |
|
1 |
hestOptAdd(&opt, "dir,direction", "svec", airTypeString, 1, 1, &_dirStr, "", |
73 |
|
|
"(NOTE: must quote vector) The \"space direction\": the vector " |
74 |
|
|
"in space spanned by incrementing (by one) the axis index."); |
75 |
|
1 |
hestOptAdd(&opt, "k,kind", "kind", airTypeString, 1, 1, &kindStr, "", |
76 |
|
|
"axis kind. Not using this option " |
77 |
|
|
"leaves the kind as it is on input"); |
78 |
|
|
|
79 |
|
1 |
OPT_ADD_NIN(nin, "input nrrd"); |
80 |
|
1 |
OPT_ADD_NOUT(out, "output nrrd"); |
81 |
|
|
|
82 |
|
1 |
mop = airMopNew(); |
83 |
|
1 |
airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways); |
84 |
|
|
|
85 |
✓✗ |
2 |
USAGE(_unrrdu_axinfoInfoL); |
86 |
|
|
PARSE(); |
87 |
|
|
airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways); |
88 |
|
|
|
89 |
|
|
for (axi=0; axi<axesLen; axi++) { |
90 |
|
|
if (!( axes[axi] < nin->dim )) { |
91 |
|
|
fprintf(stderr, "%s: axis %u not in valid range [0,%u]\n", |
92 |
|
|
me, axes[axi], nin->dim-1); |
93 |
|
|
airMopError(mop); |
94 |
|
|
return 1; |
95 |
|
|
} |
96 |
|
|
} |
97 |
|
|
/* parse the strings given via -mm */ |
98 |
|
|
if (2 != airSingleSscanf(mmStr[0], "%lf", mm+0) |
99 |
|
|
+ airSingleSscanf(mmStr[1], "%lf", mm+1)) { |
100 |
|
|
fprintf(stderr, "%s: couldn't parse both \"%s\" and \"%s\" " |
101 |
|
|
"(from \"-mm\") as doubles\n", me, mmStr[0], mmStr[1]); |
102 |
|
|
airMopError(mop); |
103 |
|
|
return 1; |
104 |
|
|
} |
105 |
|
|
|
106 |
|
|
nout = nrrdNew(); |
107 |
|
|
airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways); |
108 |
|
|
if (nrrdCopy(nout, nin)) { |
109 |
|
|
airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); |
110 |
|
|
fprintf(stderr, "%s: error copying input:\n%s", me, err); |
111 |
|
|
airMopError(mop); |
112 |
|
|
return 1; |
113 |
|
|
} |
114 |
|
|
if (airStrlen(_dirStr)) { |
115 |
|
|
if (!nin->spaceDim) { |
116 |
|
|
fprintf(stderr, "%s: wanted to add space direction, but input " |
117 |
|
|
"doesn't have space dimension set", me); |
118 |
|
|
airMopError(mop); |
119 |
|
|
return 1; |
120 |
|
|
} |
121 |
|
|
/* mindlessly copying logic from unu make; unsure of the value */ |
122 |
|
|
if ('\"' == _dirStr[0] && '\"' == _dirStr[strlen(_dirStr)-1]) { |
123 |
|
|
_dirStr[strlen(_dirStr)-1] = 0; |
124 |
|
|
dirStr = _dirStr + 1; |
125 |
|
|
} else { |
126 |
|
|
dirStr = _dirStr; |
127 |
|
|
} |
128 |
|
|
if (nrrdSpaceVectorParse(sdir, dirStr, nin->spaceDim, AIR_TRUE)) { |
129 |
|
|
airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); |
130 |
|
|
fprintf(stderr, "%s: couldn't parse space vector:\n%s", me, err); |
131 |
|
|
airMopError(mop); |
132 |
|
|
return 1; |
133 |
|
|
} |
134 |
|
|
} else { |
135 |
|
|
dirStr = NULL; |
136 |
|
|
} |
137 |
|
|
|
138 |
|
|
for (axi=0; axi<axesLen; axi++) { |
139 |
|
|
unsigned int axis; |
140 |
|
|
axis = axes[axi]; |
141 |
|
|
if (strlen(label)) { |
142 |
|
|
nout->axis[axis].label = (char *)airFree(nout->axis[axis].label); |
143 |
|
|
nout->axis[axis].label = airStrdup(label); |
144 |
|
|
} |
145 |
|
|
if (strlen(units)) { |
146 |
|
|
nout->axis[axis].units = (char *)airFree(nout->axis[axis].units); |
147 |
|
|
nout->axis[axis].units = airStrdup(units); |
148 |
|
|
} |
149 |
|
|
if (hestSourceUser == opt[mmIdx].source) { |
150 |
|
|
/* if it came from user, set the value, even if its nan. Actually, |
151 |
|
|
especially if its nan: that is the purpose of this extra logic */ |
152 |
|
|
nout->axis[axis].min = mm[0]; |
153 |
|
|
nout->axis[axis].max = mm[1]; |
154 |
|
|
} else { |
155 |
|
|
if (AIR_EXISTS(mm[0])) { |
156 |
|
|
nout->axis[axis].min = mm[0]; |
157 |
|
|
} |
158 |
|
|
if (AIR_EXISTS(mm[1])) { |
159 |
|
|
nout->axis[axis].max = mm[1]; |
160 |
|
|
} |
161 |
|
|
} |
162 |
|
|
if (AIR_EXISTS(spc)) { |
163 |
|
|
nout->axis[axis].spacing = spc; |
164 |
|
|
} |
165 |
|
|
/* see above |
166 |
|
|
if (nrrdCenterUnknown != cent) { |
167 |
|
|
nout->axis[axis].center = cent; |
168 |
|
|
} |
169 |
|
|
*/ |
170 |
|
|
if (airStrlen(centerStr)) { |
171 |
|
|
if (!strcmp("none", centerStr) |
172 |
|
|
|| !strcmp("???", centerStr)) { |
173 |
|
|
center = nrrdCenterUnknown; |
174 |
|
|
} else { |
175 |
|
|
if (!(center = airEnumVal(nrrdCenter, centerStr))) { |
176 |
|
|
fprintf(stderr, "%s: couldn't parse \"%s\" as %s\n", me, |
177 |
|
|
centerStr, nrrdCenter->name); |
178 |
|
|
airMopError(mop); |
179 |
|
|
return 1; |
180 |
|
|
} |
181 |
|
|
} |
182 |
|
|
nout->axis[axis].center = center; |
183 |
|
|
} |
184 |
|
|
if (airStrlen(kindStr)) { |
185 |
|
|
if (!strcmp("none", kindStr) |
186 |
|
|
|| !strcmp("???", kindStr)) { |
187 |
|
|
kind = nrrdKindUnknown; |
188 |
|
|
} else { |
189 |
|
|
if (!(kind = airEnumVal(nrrdKind, kindStr))) { |
190 |
|
|
fprintf(stderr, "%s: couldn't parse \"%s\" as %s\n", me, |
191 |
|
|
kindStr, nrrdKind->name); |
192 |
|
|
airMopError(mop); |
193 |
|
|
return 1; |
194 |
|
|
} |
195 |
|
|
} |
196 |
|
|
nout->axis[axis].kind = kind; |
197 |
|
|
} |
198 |
|
|
if (dirStr) { |
199 |
|
|
nrrdSpaceVecCopy(nout->axis[axis].spaceDirection, sdir); |
200 |
|
|
} |
201 |
|
|
} |
202 |
|
|
|
203 |
|
|
SAVE(out, nout, NULL); |
204 |
|
|
|
205 |
|
|
airMopOkay(mop); |
206 |
|
|
return 0; |
207 |
|
1 |
} |
208 |
|
|
|
209 |
|
|
UNRRDU_CMD(axinfo, INFO); |