GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/unrrdu/axinfo.c Lines: 19 98 19.4 %
Date: 2017-05-26 Branches: 1 66 1.5 %

Line Branch Exec Source
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, &cent, "unknown",
66
             "centering of axis: \"cell\" or \"node\"",
67
             NULL, nrrdCenter);
68
  */
69
1
  hestOptAdd(&opt, "c,center", "center", airTypeString, 1, 1, &centerStr, "",
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);