1 #include "vtkAbstractArray.h"
2 #include "vtkDoubleArray.h"
3 #include "vtkIntArray.h"
4 #include "vtkNew.h"
5 #include "vtkStringArray.h"
6 #include "vtkVariantArray.h"
7 
8 static double testTuplesDouble[] = {
9   // A simple test where every component *and* the
10   // tuples as a whole behave discretely.
11   0., 0., 1.,
12   1., 0., 3.,
13   0., 2., 7.,
14   0., 0., 9.,
15   1., 0., 1.,
16   0., 2., 8.,
17 };
18 // Bounds on the number of unique values that should be identified.
19 // For larger data, the number may not be precise
20 // as we sample subsets of the data.
21 static int numUniqueDouble[] = {
22   2, 2,
23   2, 2,
24   5, 5,
25   6, 6,
26 };
27 
28 static int testTuplesInt[] = {
29   /*
30    These next tuples repeat 16 coordinate values but are frequently not
31    identical in both components to other tuples. Thus the components
32    should have 16 discrete values reported, but the vectors as
33    a whole should not since there are 43 distinct tuples.
34    Furthermore, the array is sampled as opposed to exhastively enumerated
35    and so only 15 unique values are detected for component 1.
36    */
37   16,  1,
38    8, 14,
39   10,  3,
40   11,  4,
41    2, 13,
42    7, 12,
43    6,  5,
44   15,  9,
45   15,  6,
46    9,  7,
47   11, 16,
48    1,  5,
49    2,  3,
50   13, 12,
51    4,  8,
52   14, 10,
53    4, 14,
54   11,  9,
55    7,  3,
56    8,  2,
57   12, 13,
58    1,  6,
59   15, 10,
60   16,  5,
61    4, 10,
62   12,  3,
63    5,  8,
64   13,  1,
65   14, 11,
66    2,  6,
67   15,  9,
68    7, 16,
69    1,  2,
70    5,  3,
71   16, 13,
72   15,  9,
73   11, 12,
74    7, 14,
75    8, 10,
76    4,  6,
77    8, 13,
78   16, 14,
79   15,  2,
80   11,  1,
81    3, 10,
82    4,  6,
83    7, 12,
84    5,  9,
85 };
86 static int numUniqueInt[] = {
87   1, 16,
88   1, 16,
89   0, 0,
90 };
91 
92 static int testTuplesInt2[] = {
93   // There are no repeats in this set.
94    1,  2,  3,  4,  5,  6,  7,  8,  9, 10,
95   11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
96   21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
97   31, 32, 33,
98 };
99 static int numUniqueInt2[] = {
100   0, 0,
101 };
102 
103 static vtkStdString testTuplesString[] = {
104   /*
105    To test the log(N) sampling strategy, we must
106    have a large number of entries in the array.
107 
108    The 4 words marked "not detected" below are placed to leave them
109    intentionally undetected on at least one platform.
110    The vtkObject ModificationTime counter is used as a
111    seed for the random number generator and its count
112    will vary across platforms and compile-time options,
113    so we accept anywhere from 4 to 8 values being detected
114    when subsampling. This data is used twice: once forcing all
115    tuples to be sampled and once using subsampling.
116    */
117   "Eeny", "Meeny", "Miny", "Mo", "Miny",
118   "Eeny", "Meeny", "Miny", "Mo", "Miny",
119   "Eeny", "Meeny", "Miny", "Mo", "Miny",
120   "Eeny", "Meeny", "Miny", "Mo", "Miny",
121   "Skeenie", "Beeny", "Piny", "Po", "Po", // not detected.
122   "Eeny", "Meeny", "Miny", "Mo", "Miny",
123   "Eeny", "Meeny", "Miny", "Mo", "Miny",
124   "Eeny", "Meeny", "Miny", "Mo", "Miny",
125   "Eeny", "Meeny", "Miny", "Mo", "Miny",
126   "Eeny", "Meeny", "Miny", "Mo", "Miny",
127   "Eeny", "Meeny", "Miny", "Mo", "Miny",
128   "Eeny", "Meeny", "Miny", "Mo", "Miny",
129   "Eeny", "Meeny", "Miny", "Mo", "Miny",
130   "Eeny", "Meeny", "Miny", "Mo", "Miny",
131   "Eeny", "Meeny", "Miny", "Mo", "Miny",
132   "Eeny", "Meeny", "Miny", "Mo", "Miny",
133   "Eeny", "Meeny", "Miny", "Mo", "Miny",
134   "Eeny", "Meeny", "Miny", "Mo", "Miny",
135   "Eeny", "Meeny", "Miny", "Mo", "Miny",
136   "Eeny", "Meeny", "Miny", "Mo", "Miny",
137   "Eeny", "Meeny", "Miny", "Mo", "Miny",
138   "Eeny", "Meeny", "Miny", "Mo", "Miny",
139   "Eeny", "Meeny", "Miny", "Mo", "Miny",
140   "Eeny", "Meeny", "Miny", "Mo", "Miny",
141   "Eeny", "Meeny", "Miny", "Mo", "Miny",
142   "Eeny", "Meeny", "Miny", "Mo", "Miny",
143   "Eeny", "Meeny", "Miny", "Mo", "Miny",
144   "Eeny", "Meeny", "Miny", "Mo", "Miny",
145   "Eeny", "Meeny", "Miny", "Mo", "Miny",
146   "Eeny", "Meeny", "Miny", "Mo", "Miny",
147   "Eeny", "Meeny", "Miny", "Mo", "Miny",
148   "Eeny", "Meeny", "Miny", "Mo", "Miny",
149   "Eeny", "Meeny", "Miny", "Mo", "Miny",
150   "Eeny", "Meeny", "Miny", "Mo", "Miny",
151   "Eeny", "Meeny", "Miny", "Mo", "Miny",
152   "Eeny", "Meeny", "Miny", "Mo", "Miny",
153   "Eeny", "Meeny", "Miny", "Mo", "Miny",
154   "Eeny", "Meeny", "Miny", "Mo", "Miny",
155   "Eeny", "Meeny", "Miny", "Mo", "Miny",
156   "Eeny", "Meeny", "Miny", "Mo", "Miny",
157   "Eeny", "Meeny", "Miny", "Mo", "Miny",
158   "Eeny", "Meeny", "Miny", "Mo", "Miny",
159   "Eeny", "Meeny", "Miny", "Mo", "Miny",
160   "Eeny", "Meeny", "Miny", "Mo", "Miny",
161   "Eeny", "Meeny", "Miny", "Mo", "Miny",
162   "Eeny", "Meeny", "Miny", "Mo", "Miny",
163   "Eeny", "Meeny", "Miny", "Mo", "Miny",
164   "Eeny", "Meeny", "Miny", "Mo", "Miny",
165   "Eeny", "Meeny", "Miny", "Mo", "Miny",
166   "Eeny", "Meeny", "Miny", "Mo", "Miny",
167   "Eeny", "Meeny", "Miny", "Mo", "Miny",
168   "Eeny", "Meeny", "Miny", "Mo", "Miny",
169   "Eeny", "Meeny", "Miny", "Mo", "Miny",
170   "Eeny", "Meeny", "Miny", "Mo", "Miny",
171   "Eeny", "Meeny", "Miny", "Mo", "Miny",
172   "Eeny", "Meeny", "Miny", "Mo", "Miny",
173   "Eeny", "Meeny", "Miny", "Mo", "Miny",
174   "Eeny", "Meeny", "Miny", "Mo", "Miny",
175   "Eeny", "Meeny", "Miny", "Mo", "Miny",
176   "Eeny", "Meeny", "Miny", "Mo", "Miny",
177   "Eeny", "Meeny", "Miny", "Mo", "Miny",
178   "Eeny", "Meeny", "Miny", "Mo", "Miny",
179   "Eeny", "Meeny", "Miny", "Mo", "Miny",
180   "Eeny", "Meeny", "Miny", "Mo", "Miny",
181   "Eeny", "Meeny", "Miny", "Mo", "Miny",
182   "Eeny", "Meeny", "Miny", "Mo", "Miny",
183   "Eeny", "Meeny", "Miny", "Mo", "Miny",
184   "Eeny", "Meeny", "Miny", "Mo", "Miny",
185   "Eeny", "Meeny", "Miny", "Mo", "Miny",
186   "Eeny", "Meeny", "Miny", "Mo", "Miny",
187   "Eeny", "Meeny", "Miny", "Mo", "Miny",
188   "Eeny", "Meeny", "Miny", "Mo", "Miny",
189   "Eeny", "Meeny", "Miny", "Mo", "Miny",
190   "Eeny", "Meeny", "Miny", "Mo", "Miny",
191   "Eeny", "Meeny", "Miny", "Mo", "Miny",
192   "Eeny", "Meeny", "Miny", "Mo", "Miny",
193   "Eeny", "Meeny", "Miny", "Mo", "Miny",
194   "Eeny", "Meeny", "Miny", "Mo", "Miny",
195   "Eeny", "Meeny", "Miny", "Mo", "Miny",
196   "Eeny", "Meeny", "Miny", "Mo", "Miny",
197   "Eeny", "Meeny", "Miny", "Mo", "Miny",
198   "Eeny", "Meeny", "Miny", "Mo", "Miny",
199   "Eeny", "Meeny", "Miny", "Mo", "Miny",
200   "Eeny", "Meeny", "Miny", "Mo", "Miny",
201   "Eeny", "Meeny", "Miny", "Mo", "Miny",
202   "Eeny", "Meeny", "Miny", "Mo", "Miny",
203   "Eeny", "Meeny", "Miny", "Mo", "Miny",
204   "Eeny", "Meeny", "Miny", "Mo", "Miny",
205   "Eeny", "Meeny", "Miny", "Mo", "Miny",
206   "Eeny", "Meeny", "Miny", "Mo", "Miny",
207   "Eeny", "Meeny", "Miny", "Mo", "Miny",
208   "Eeny", "Meeny", "Miny", "Mo", "Miny",
209   "Eeny", "Meeny", "Miny", "Mo", "Miny",
210   "Eeny", "Meeny", "Miny", "Mo", "Miny",
211   "Eeny", "Meeny", "Miny", "Mo", "Miny",
212   "Eeny", "Meeny", "Miny", "Mo", "Miny",
213   "Eeny", "Meeny", "Miny", "Mo", "Miny",
214   "Eeny", "Meeny", "Miny", "Mo", "Miny",
215   "Eeny", "Meeny", "Miny", "Mo", "Miny",
216   "Eeny", "Meeny", "Miny", "Mo", "Miny",
217   "Eeny", "Meeny", "Miny", "Mo", "Miny",
218   "Eeny", "Meeny", "Miny", "Mo", "Miny",
219   "Eeny", "Meeny", "Miny", "Mo", "Miny",
220   "Eeny", "Meeny", "Miny", "Mo", "Miny",
221   "Eeny", "Meeny", "Miny", "Mo", "Miny",
222   "Eeny", "Meeny", "Miny", "Mo", "Miny",
223   "Eeny", "Meeny", "Miny", "Mo", "Miny",
224   "Eeny", "Meeny", "Miny", "Mo", "Miny",
225   "Eeny", "Meeny", "Miny", "Mo", "Miny",
226   "Eeny", "Meeny", "Miny", "Mo", "Miny",
227   "Eeny", "Meeny", "Miny", "Mo", "Miny",
228   "Eeny", "Meeny", "Miny", "Mo", "Miny",
229   "Eeny", "Meeny", "Miny", "Mo", "Miny",
230   "Eeny", "Meeny", "Miny", "Mo", "Miny",
231   "Eeny", "Meeny", "Miny", "Mo", "Miny",
232   "Eeny", "Meeny", "Miny", "Mo", "Miny",
233   "Eeny", "Meeny", "Miny", "Mo", "Miny",
234   "Eeny", "Meeny", "Miny", "Mo", "Miny",
235   "Eeny", "Meeny", "Miny", "Mo", "Miny",
236   "Eeny", "Meeny", "Miny", "Mo", "Miny",
237   "Eeny", "Meeny", "Miny", "Mo", "Miny",
238   "Eeny", "Meeny", "Miny", "Mo", "Miny",
239   "Eeny", "Meeny", "Miny", "Mo", "Miny",
240   "Eeny", "Meeny", "Miny", "Mo", "Miny",
241   "Eeny", "Meeny", "Miny", "Mo", "Miny",
242   "Eeny", "Meeny", "Miny", "Mo", "Miny",
243   "Eeny", "Meeny", "Miny", "Mo", "Miny",
244   "Eeny", "Meeny", "Miny", "Mo", "Miny",
245   "Eeny", "Meeny", "Miny", "Mo", "Miny",
246 };
247 static int numUniqueStringComplete[2] = {
248   8, 8,
249 };
250 static int numUniqueStringSubset[2] = {
251   4, 8,
252 };
253 
CheckUniques(vtkAbstractArray * arr,int * uniqueSizeBds,double uncertainty,double minProminence)254 static bool CheckUniques(
255   vtkAbstractArray* arr, int* uniqueSizeBds,
256   double uncertainty, double minProminence)
257 {
258   bool ok = true;
259   if (!arr)
260     {
261     return ok;
262     }
263 
264   cout << arr->GetName() << endl;
265 
266   int nc = arr->GetNumberOfComponents();
267   vtkNew<vtkVariantArray> uniques;
268   for (int c = 0; c < nc; ++c)
269     {
270     arr->GetProminentComponentValues(
271       c, uniques.GetPointer(), uncertainty, minProminence);
272     int numUniques = static_cast<int>(uniques->GetNumberOfTuples());
273     cout << "  comp " << c << " (" << numUniques << "): ";
274     for (int n = 0; n <= uniques->GetMaxId(); ++n)
275       {
276       cout
277         << (n > 0 ? ", " : " ")
278         << uniques->GetVariantValue(n).ToString().c_str();
279       }
280     cout << endl;
281     if (
282       uniqueSizeBds[2 * c] > numUniques ||
283       uniqueSizeBds[2 * c + 1] < numUniques)
284       {
285       cout
286         << "    ** ERROR: Expected between " << uniqueSizeBds[2 * c]
287         << " and " << uniqueSizeBds[2 * c + 1] << " values\n";
288       ok = false;
289       }
290     }
291   if (nc > 1)
292     {
293     arr->GetProminentComponentValues(
294       -1, uniques.GetPointer(), uncertainty, minProminence);
295     int numUniques = static_cast<int>(uniques->GetNumberOfTuples());
296     cout << "  tuples (" << numUniques << "): ";
297     for (int n = 0; n <= uniques->GetMaxId(); ++n)
298       {
299       cout
300         << (n > 0 && n % nc == 0 ? ", " : " ")
301         << uniques->GetVariantValue(n).ToString().c_str();
302       }
303     cout << endl;
304     if (
305       uniqueSizeBds[2 * nc] > numUniques ||
306       uniqueSizeBds[2 * nc + 1] < numUniques)
307       {
308       cout
309         << "    ** ERROR: Expected between " << uniqueSizeBds[2 * nc]
310         << " and " << uniqueSizeBds[2 * nc + 1] << " values\n";
311       ok = false;
312       }
313     }
314   return ok;
315 }
316 
TestArrayUniqueValueDetection(int vtkNotUsed (argc),char * vtkNotUsed (argv)[])317 int TestArrayUniqueValueDetection(int vtkNotUsed(argc), char* vtkNotUsed(argv)[])
318 {
319   bool ok = true;
320   vtkNew<vtkDoubleArray> darr;
321   vtkNew<vtkIntArray> iarr;
322   vtkNew<vtkStringArray> sarr;
323 
324   darr->SetNumberOfComponents(3);
325   darr->SetArray(testTuplesDouble,
326     sizeof(testTuplesDouble)/sizeof(testTuplesDouble[0]), 1);
327   darr->SetName("Some3DPoints - Show off distinct tuple detection");
328   ok &= CheckUniques(darr.GetPointer(), numUniqueDouble, 0., 0.);
329 
330   iarr->SetNumberOfComponents(2);
331   iarr->SetArray(testTuplesInt,
332     sizeof(testTuplesInt)/sizeof(testTuplesInt[0]), 1);
333   iarr->SetName("Some2DPoints - Show off tuple non-detection");
334   ok &= CheckUniques(iarr.GetPointer(), numUniqueInt, 0., 0.);
335 
336   iarr->SetNumberOfComponents(1);
337   iarr->SetArray(testTuplesInt2,
338     sizeof(testTuplesInt2)/sizeof(testTuplesInt2[0]), 1);
339   //iarr->Modified(); // required since we have changed the tuples?
340   iarr->SetName("Some1DPoints - Show off component non-detection");
341   ok &= CheckUniques(iarr.GetPointer(), numUniqueInt2, 0., 0.);
342 
343   sarr->SetNumberOfComponents(1);
344   sarr->SetArray(testTuplesString,
345     sizeof(testTuplesString)/sizeof(testTuplesString[0]), 1);
346   sarr->SetName("SomeNonWords - Show off string value detection");
347   ok &= CheckUniques(sarr.GetPointer(), numUniqueStringComplete, 0.0, 0.0);
348 
349   sarr->Modified(); // Verify that modifying the array causes a re-compute
350   sarr->SetName("SomeNonWords - Show off non-exhaustive search");
351   ok &= CheckUniques(sarr.GetPointer(), numUniqueStringSubset, 0.5, 0.1);
352 
353   return ok ? 0 : 1;
354 }
355