GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/pull/ccPull.c Lines: 0 123 0.0 %
Date: 2017-05-26 Branches: 0 80 0.0 %

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 "pull.h"
25
#include "privatePull.h"
26
27
/*
28
** HEY: this messes with the points' idtag, and pctx->idtagNext,
29
** even though it really shouldn't have to
30
*/
31
int
32
pullCCFind(pullContext *pctx) {
33
  static const char me[]="pullCCFind";
34
  airArray *mop, *eqvArr;
35
  unsigned int passIdx, binIdx, pointIdx, neighIdx, eqvNum,
36
    pointNum, *idmap;
37
  pullBin *bin;
38
  pullPoint *point, *her;
39
40
  if (!pctx) {
41
    biffAddf(PULL, "%s: got NULL pointer", me);
42
    return 1;
43
  }
44
  if (_pullIterate(pctx, pullProcessModeNeighLearn)) {
45
    biffAddf(PULL, "%s: trouble with %s for CC", me,
46
             airEnumStr(pullProcessMode, pullProcessModeNeighLearn));
47
    return 1;
48
  }
49
50
  mop = airMopNew();
51
  pointNum = pullPointNumber(pctx);
52
  eqvArr = airArrayNew(NULL, NULL, 2*sizeof(unsigned int), pointNum);
53
  airMopAdd(mop, eqvArr, (airMopper)airArrayNuke, airMopAlways);
54
  idmap = AIR_CAST(unsigned int *, calloc(pointNum, sizeof(unsigned int)));
55
  airMopAdd(mop, idmap, airFree, airMopAlways);
56
57
  /* to be safe, renumber all points, so that we know that the
58
     idtags are contiguous, starting at 0. HEY: this should handled
59
     by having a map from real point->idtag to a point number assigned
60
     just for the sake of doing CCs */
61
  pctx->idtagNext = 0;
62
  for (binIdx=0; binIdx<pctx->binNum; binIdx++) {
63
    bin = pctx->bin + binIdx;
64
    for (pointIdx=0; pointIdx<bin->pointNum; pointIdx++) {
65
      point = bin->point[pointIdx];
66
      point->idtag = pctx->idtagNext++;
67
    }
68
  }
69
70
  /* same stupidity copied from limn/polymod.c:limnPolyDataCCFind */
71
  eqvNum = 0;
72
  for (passIdx=0; passIdx<2; passIdx++) {
73
    if (passIdx) {
74
      airArrayLenPreSet(eqvArr, eqvNum);
75
    }
76
    for (binIdx=0; binIdx<pctx->binNum; binIdx++) {
77
      bin = pctx->bin + binIdx;
78
      for (pointIdx=0; pointIdx<bin->pointNum; pointIdx++) {
79
        point = bin->point[pointIdx];
80
        for (neighIdx=0; neighIdx<point->neighPointNum; neighIdx++) {
81
          if (0 == passIdx) {
82
            ++eqvNum;
83
          } else {
84
            her = point->neighPoint[neighIdx];
85
            airEqvAdd(eqvArr, point->idtag, her->idtag);
86
          }
87
        }
88
      }
89
    }
90
  }
91
92
  /* do the CC analysis */
93
  pctx->CCNum = airEqvMap(eqvArr, idmap, pointNum);
94
95
  /* assign idcc's */
96
  for (binIdx=0; binIdx<pctx->binNum; binIdx++) {
97
    bin = pctx->bin + binIdx;
98
    for (pointIdx=0; pointIdx<bin->pointNum; pointIdx++) {
99
      point = bin->point[pointIdx];
100
      point->idCC = idmap[point->idtag];
101
    }
102
  }
103
104
  airMopOkay(mop);
105
  return 0;
106
}
107
108
/*
109
** measure something about connected componts already found
110
**
111
** measrInfo can be 0 to say "measure # particles in CC", or
112
** it can be a scalar pullInfo
113
**
114
** rho == 0: only size, rho == 1: only measrInfo
115
*/
116
int
117
pullCCMeasure(pullContext *pctx, Nrrd *nmeasr, int measrInfo, double rho) {
118
  static const char me[]="pullCCMeasure";
119
  airArray *mop;
120
  unsigned int binIdx, pointIdx, ii;
121
  double *meas, *size;
122
  pullBin *bin;
123
  pullPoint *point;
124
125
  if (!( pctx && nmeasr )) {
126
    biffAddf(PULL, "%s: got NULL pointer", me);
127
    return 1;
128
  }
129
  if (!pctx->CCNum) {
130
    biffAddf(PULL, "%s: CCNum == 0: haven't yet learned CCs?", me);
131
    return 1;
132
  }
133
  if (measrInfo) {
134
    if (airEnumValCheck(pullInfo, measrInfo)) {
135
      biffAddf(PULL, "%s: measrInfo %d not a valid %s", me,
136
               measrInfo, pullInfo->name);
137
      return 1;
138
    }
139
    if (1 != pullInfoLen(measrInfo)) {
140
      biffAddf(PULL, "%s: measrInfo %s (%d) isn't a scalar (len %u)", me,
141
               airEnumStr(pullInfo, measrInfo), measrInfo,
142
               pullInfoLen(measrInfo));
143
      return 1;
144
    }
145
    if (!pctx->ispec[measrInfo]) {
146
      biffAddf(PULL, "%s: no ispec set for measrInfo %s (%d)", me,
147
               airEnumStr(pullInfo, measrInfo), measrInfo);
148
      return 1;
149
    }
150
  } /* else measrInfo is zero, they want to know # points */
151
  /* in any case nmeasr is allocated for doubles */
152
  if (nrrdMaybeAlloc_va(nmeasr, nrrdTypeDouble, 1,
153
                        AIR_CAST(size_t, pctx->CCNum))) {
154
    biffMovef(PULL, NRRD, "%s: couldn't alloc nmeasr", me);
155
    return 1;
156
  }
157
  meas = AIR_CAST(double *, nmeasr->data);
158
159
  mop = airMopNew();
160
  /* HEY: don't actually need to allocate and set size[],
161
     if measrInfo == 0 */
162
  if (!(size = AIR_CAST(double *,
163
                        calloc(pctx->CCNum, sizeof(double))))) {
164
    biffAddf(PULL, "%s: couldn't alloc size", me);
165
    airMopError(mop); return 1;
166
  }
167
  airMopAdd(mop, size, airFree, airMopAlways);
168
169
  /* finally, do measurement */
170
  for (binIdx=0; binIdx<pctx->binNum; binIdx++) {
171
    bin = pctx->bin + binIdx;
172
    for (pointIdx=0; pointIdx<bin->pointNum; pointIdx++) {
173
      point = bin->point[pointIdx];
174
      size[point->idCC]++;
175
      meas[point->idCC] += (measrInfo
176
                            ? pullPointScalar(pctx, point, measrInfo,
177
                                              NULL, NULL)
178
                            : 1);
179
    }
180
  }
181
  if (measrInfo) {
182
    for (ii=0; ii<pctx->CCNum; ii++) {
183
      meas[ii] /= size[ii];
184
      meas[ii] = AIR_LERP(rho, size[ii], meas[ii]);
185
    }
186
  }
187
188
  airMopOkay(mop);
189
  return 0;
190
}
191
192
typedef struct {
193
  unsigned int i;
194
  double d;
195
} ccpair;
196
197
/* we intend to sort in *descending* order */
198
static int
199
ccpairCompare(const void *_a, const void *_b) {
200
  const ccpair *a, *b;
201
202
  a = AIR_CAST(const ccpair *, _a);
203
  b = AIR_CAST(const ccpair *, _b);
204
  return (a->d < b->d
205
          ? +1
206
          : (a->d > b->d
207
             ? -1
208
             : 0));
209
}
210
211
/*
212
******** pullCCSort
213
**
214
** sort CCs in pull context
215
**
216
** measrInfo == 0: sort by size, else,
217
** sort by blend of size and measrInfo
218
** rho == 0: only size, rho == 1: only measrInfo
219
*/
220
int
221
pullCCSort(pullContext *pctx, int measrInfo, double rho) {
222
  static const char me[]="pullCCSort";
223
  ccpair *pair;
224
  Nrrd *nmeasr;
225
  airArray *mop;
226
  unsigned int ii, *revm, binIdx, pointIdx;
227
  double *measr;
228
  pullBin *bin;
229
  pullPoint *point;
230
  int E;
231
232
  if (!pctx) {
233
    biffAddf(PULL, "%s: got NULL pointer", me);
234
    return 1;
235
  }
236
  if (!pctx->CCNum) {
237
    biffAddf(PULL, "%s: haven't yet learned CCs?", me);
238
    return 1;
239
  }
240
241
#define CALLOC(T) (AIR_CAST(T *, calloc(pctx->CCNum, sizeof(T))))
242
  mop = airMopNew();
243
  if (!(nmeasr = nrrdNew())
244
      || airMopAdd(mop, nmeasr, (airMopper)nrrdNuke, airMopAlways)
245
      || !(pair = CALLOC(ccpair))
246
      || airMopAdd(mop, pair, airFree, airMopAlways)
247
      || !(revm = CALLOC(unsigned int))
248
      || airMopAdd(mop, revm, airFree, airMopAlways)) {
249
    biffAddf(PULL, "%s: couldn't allocate everything", me);
250
    airMopError(mop); return 1;
251
  }
252
#undef CALLOC
253
  if (!measrInfo) {
254
    /* sorting by size */
255
    E = pullCCMeasure(pctx, nmeasr, 0, 0.0);
256
  } else {
257
    /* sorting by some blend of size and pullInfo */
258
    E = pullCCMeasure(pctx, nmeasr, measrInfo, rho);
259
  }
260
  if (E) {
261
    biffAddf(PULL, "%s: problem measuring CCs", me);
262
    airMopError(mop); return 1;
263
  }
264
265
  measr = AIR_CAST(double *, nmeasr->data);
266
  for (ii=0; ii<pctx->CCNum; ii++) {
267
    pair[ii].i = ii;
268
    pair[ii].d = measr[ii];
269
  }
270
  qsort(pair, pctx->CCNum, sizeof(ccpair), ccpairCompare);
271
  for (ii=0; ii<pctx->CCNum; ii++) {
272
    revm[pair[ii].i] = ii;
273
  }
274
275
  for (binIdx=0; binIdx<pctx->binNum; binIdx++) {
276
    bin = pctx->bin + binIdx;
277
    for (pointIdx=0; pointIdx<bin->pointNum; pointIdx++) {
278
      point = bin->point[pointIdx];
279
      point->idCC = revm[point->idCC];
280
    }
281
  }
282
283
  airMopOkay(mop);
284
  return 0;
285
}