GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/unrrdu/aabplot.c Lines: 17 103 16.5 %
Date: 2017-05-26 Branches: 1 56 1.8 %

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 "Draws ASCII-art box plots"
28
static const char *_unrrdu_aabplotInfoL =
29
  (INFO
30
   ".  Because why not.\n "
31
   "* (uses nrrd, but no Nrrd implements this functionality)");
32
33
int
34
unrrdu_aabplotMain(int argc, const char **argv, const char *me,
35
                   hestParm *hparm) {
36
  /* these are stock for unrrdu */
37
2
  hestOpt *opt = NULL;
38
  airArray *mop;
39
  int pret;
40
1
  char *err;
41
  /* these are specific to this command */
42
1
  int medshow, rshow;
43
1
  Nrrd *_nin, *nin, *_nsingle, *nsingle;
44
1
  unsigned int plen;
45
1
  double vrange[2], *single;
46
47
1
  hestOptAdd(&opt, "l", "len", airTypeUInt, 1, 1, &plen, "78",
48
             "number of characters in box plot");
49
1
  hestOptAdd(&opt, "r", "min max", airTypeDouble, 2, 2, vrange, "0 100",
50
             "values to use as absolute min and max (unfortunately "
51
             "has to be same for all scanlines (rows).");
52
1
  hestOptAdd(&opt, "rs", "show", airTypeBool, 1, 1, &rshow, "false",
53
             "show range above plots");
54
1
  hestOptAdd(&opt, "ms", "show", airTypeBool, 1, 1, &medshow, "false",
55
             "print the median value");
56
1
  OPT_ADD_NIN(_nin, "input nrrd");
57
1
  hestOptAdd(&opt, "s", "single", airTypeOther, 1, 1, &_nsingle, "",
58
             "if given a 1D nrrd here that matches the number of "
59
             "rows in the \"-i\" input, interpret it as a list of values "
60
             "that should be indicated with \"X\"s in the plots.",
61
1
             NULL, NULL, nrrdHestNrrd);
62
63
1
  mop = airMopNew();
64
1
  airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);
65
2
  USAGE(_unrrdu_aabplotInfoL);
66
  PARSE();
67
  airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);
68
69
  if (!( 2 == _nin->dim || 1 == _nin->dim )) {
70
    fprintf(stderr, "%s: need 1-D or 2-D array\n", me);
71
    airMopError(mop);
72
    return 1;
73
  }
74
  nin = nrrdNew();
75
  airMopAdd(mop, nin, (airMopper)nrrdNuke, airMopAlways);
76
  if (nrrdConvert(nin, _nin, nrrdTypeDouble)) {
77
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
78
    fprintf(stderr, "%s: error converting \"-s\" input:\n%s", me, err);
79
    airMopError(mop);
80
    return 1;
81
  }
82
  if (1 == nin->dim) {
83
    if (nrrdAxesInsert(nin, nin, 1)) {
84
      airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
85
      fprintf(stderr, "%s: error making 2-D from 1-D:\n%s", me, err);
86
      airMopError(mop);
87
      return 1;
88
    }
89
  }
90
  if (_nsingle) {
91
    if (nrrdElementNumber(_nsingle) != nin->axis[1].size) {
92
      fprintf(stderr, "%s: \"-s\" input doesn't match size of \"-i\" input",
93
              me);
94
      airMopError(mop);
95
      return 1;
96
    }
97
    nsingle = nrrdNew();
98
    airMopAdd(mop, nsingle, (airMopper)nrrdNuke, airMopAlways);
99
    if (nrrdConvert(nsingle, _nsingle, nrrdTypeDouble)) {
100
      airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
101
      fprintf(stderr, "%s: error converting \"-s\" input:\n%s", me, err);
102
      airMopError(mop);
103
      return 1;
104
    }
105
    single = (double*)nsingle->data;
106
  } else {
107
    nsingle = NULL;
108
    single = NULL;
109
  }
110
111
  {
112
#define PTNUM 5
113
    double *in, *buff, ptile[PTNUM]={5,25,50,75,95};
114
    unsigned int xi, yi, pi, ti, sx, sy, pti[PTNUM];
115
    char *line, rbuff[128];
116
    Nrrd *nbuff;
117
118
    sx = AIR_CAST(unsigned int, nin->axis[0].size);
119
    sy = AIR_CAST(unsigned int, nin->axis[1].size);
120
    nbuff = nrrdNew();
121
    airMopAdd(mop, nbuff, (airMopper)nrrdNuke, airMopAlways);
122
    if (nrrdSlice(nbuff, nin, 1, 0)) {
123
      airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
124
      fprintf(stderr, "%s: error making buffer:\n%s", me, err);
125
      airMopError(mop);
126
      return 1;
127
    }
128
    line = calloc(plen+1, sizeof(char));
129
    in = (double*)nin->data;
130
    buff = (double*)nbuff->data;
131
132
    if (rshow) {
133
      for (pi=0; pi<plen; pi++) {
134
        line[pi] = ' ';
135
      }
136
      sprintf(rbuff, "|<-- %g", vrange[0]);
137
      memcpy(line, rbuff, strlen(rbuff));
138
      sprintf(rbuff, "%g -->|", vrange[1]);
139
      memcpy(line + plen - strlen(rbuff), rbuff, strlen(rbuff));
140
      printf("%s", line);
141
      if (medshow) {
142
        printf(" median:");
143
      }
144
      printf("\n");
145
    }
146
    for (yi=0; yi<sy; yi++) {
147
      for (xi=0; xi<sx; xi++) {
148
        buff[xi] = in[xi + sx*yi];
149
      }
150
      qsort(buff, sx, sizeof(double), nrrdValCompare[nrrdTypeDouble]);
151
      for (ti=0; ti<PTNUM; ti++) {
152
        pti[ti] = airIndexClamp(vrange[0],
153
                                buff[airIndexClamp(0, ptile[ti], 100, sx)],
154
                                vrange[1], plen);
155
        /*
156
        fprintf(stderr, "ti %u (%g) -> buff[%u] = %g -> %u\n", ti,
157
                ptile[ti], airIndexClamp(0, ptile[ti], 100, sx),
158
                buff[airIndexClamp(0, ptile[ti], 100, sx)], pti[ti]);
159
        */
160
      }
161
      for (pi=0; pi<plen; pi++) {
162
        line[pi] = pi % 2 ? ' ' : '.';
163
      }
164
      for (pi=pti[0]; pi<=pti[4]; pi++) {
165
        line[pi] = '-';
166
      }
167
      for (pi=pti[1]; pi<=pti[3]; pi++) {
168
        line[pi] = '=';
169
      }
170
      line[pti[2]]='m';
171
      if (pti[2] > 0) {
172
        line[pti[2]-1]='<';
173
      }
174
      if (pti[2] < plen-1) {
175
        line[pti[2]+1]='>';
176
      }
177
      if (single) {
178
        line[airIndexClamp(vrange[0], single[yi], vrange[1], plen)]='X';
179
      }
180
      printf("%s", line);
181
      if (medshow) {
182
        printf(" %g", buff[airIndexClamp(0, 50, 100, sx)]);
183
      }
184
      printf("\n");
185
#if 0
186
      unsigned int ltt = (unsigned int)(-1);
187
      /* printf("["); */
188
      for (pi=0; pi<plen; pi++) {
189
        for (tt=0; tt<PTNUM && pti[tt] < pi; tt++) {
190
          /*
191
          fprintf(stderr, "(pi %u < pti[%u]==%u)", pi, tt, pti[tt]);
192
          */
193
        }
194
        /* fprintf(stderr, " --> tt=%u\n", tt); */
195
        if (2 == ltt && 3 == tt) {
196
          printf("M");
197
        } else {
198
          printf("%c", cc[tt]);
199
        }
200
        ltt = tt;
201
      }
202
      /* printf("]\n"); */
203
      printf("\n");
204
#endif
205
    }
206
  }
207
  airMopOkay(mop);
208
  return 0;
209
1
}
210
211
UNRRDU_CMD_HIDE(aabplot, INFO);