1 /*
2  * Copyright 2008 Sandia Corporation.
3  * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
4  * license for use of this work by or on behalf of the
5  * U.S. Government. Redistribution and use in source and binary forms, with
6  * or without modification, are permitted provided that this Notice and any
7  * statement of authorship are reproduced on all copies.
8  */
9 // .SECTION Thanks
10 // Thanks to Philippe Pebay and David Thompson from Sandia National Laboratories
11 // for implementing this test.
12 
13 #include "vtkDoubleArray.h"
14 #include "vtkMultiBlockDataSet.h"
15 #include "vtkStringArray.h"
16 #include "vtkTable.h"
17 #include "vtkMultiCorrelativeStatistics.h"
18 
19 //=============================================================================
TestMultiCorrelativeStatistics(int,char * [])20 int TestMultiCorrelativeStatistics( int, char *[] )
21 {
22   int testStatus = 0;
23 
24   /* */
25   double mingledData[] =
26     {
27     46, 45,
28     47, 49,
29     46, 47,
30     46, 46,
31     47, 46,
32     47, 49,
33     49, 49,
34     47, 45,
35     50, 50,
36     46, 46,
37     51, 50,
38     48, 48,
39     52, 54,
40     48, 47,
41     52, 52,
42     49, 49,
43     53, 54,
44     50, 50,
45     53, 54,
46     50, 52,
47     53, 53,
48     50, 51,
49     54, 54,
50     49, 49,
51     52, 52,
52     50, 51,
53     52, 52,
54     49, 47,
55     48, 48,
56     48, 50,
57     46, 48,
58     47, 47
59     };
60   int nVals = 32;
61 
62   const char m0Name[] = "M0";
63   vtkDoubleArray* dataset1Arr = vtkDoubleArray::New();
64   dataset1Arr->SetNumberOfComponents( 1 );
65   dataset1Arr->SetName( m0Name );
66 
67   const char m1Name[] = "M1";
68   vtkDoubleArray* dataset2Arr = vtkDoubleArray::New();
69   dataset2Arr->SetNumberOfComponents( 1 );
70   dataset2Arr->SetName( m1Name );
71 
72   const char m2Name[] = "M2";
73   vtkDoubleArray* dataset3Arr = vtkDoubleArray::New();
74   dataset3Arr->SetNumberOfComponents( 1 );
75   dataset3Arr->SetName( m2Name );
76 
77   for ( int i = 0; i < nVals; ++ i )
78     {
79     int ti = i << 1;
80     dataset1Arr->InsertNextValue( mingledData[ti] );
81     dataset2Arr->InsertNextValue( mingledData[ti + 1] );
82     dataset3Arr->InsertNextValue( i != 12 ? -1. : -1.001 );
83     }
84 
85   vtkTable* datasetTable = vtkTable::New();
86   datasetTable->AddColumn( dataset1Arr );
87   dataset1Arr->Delete();
88   datasetTable->AddColumn( dataset2Arr );
89   dataset2Arr->Delete();
90   datasetTable->AddColumn( dataset3Arr );
91   dataset3Arr->Delete();
92 
93   // Set multi-correlative statistics algorithm and its input data port
94   vtkMultiCorrelativeStatistics* mcs = vtkMultiCorrelativeStatistics::New();
95 
96   // First verify that absence of input does not cause trouble
97   cout << "## Verifying that absence of input does not cause trouble... ";
98   mcs->Update();
99   cout << "done.\n";
100 
101   // Prepare first test with data
102   mcs->SetInputData( vtkStatisticsAlgorithm::INPUT_DATA, datasetTable );
103 
104   datasetTable->Delete();
105 
106   // Select Column Pairs of Interest ( Learn Mode )
107   mcs->SetColumnStatus( m0Name, 1 );
108   mcs->SetColumnStatus( m1Name, 1 );
109   mcs->RequestSelectedColumns();
110   mcs->ResetAllColumnStates();
111   mcs->SetColumnStatus( m0Name, 1 );
112   mcs->SetColumnStatus( m1Name, 1 );
113   mcs->SetColumnStatus( m2Name, 1 );
114   mcs->SetColumnStatus( m2Name, 0 );
115   mcs->SetColumnStatus( m2Name, 1 );
116   mcs->RequestSelectedColumns();
117   mcs->RequestSelectedColumns(); // Try a duplicate entry. This should have no effect.
118   mcs->SetColumnStatus( m0Name, 0 );
119   mcs->SetColumnStatus( m2Name, 0 );
120   mcs->SetColumnStatus( "Metric 3", 1 ); // An invalid name. This should result in a request for metric 1's self-correlation.
121   // mcs->RequestSelectedColumns(); will get called in RequestData()
122 
123   // Test Learn Mode
124   mcs->SetLearnOption( true );
125   mcs->SetDeriveOption( true );
126   mcs->SetAssessOption( false );
127 
128   mcs->Update();
129   vtkMultiBlockDataSet* outputMetaDS = vtkMultiBlockDataSet::SafeDownCast( mcs->GetOutputDataObject( vtkStatisticsAlgorithm::OUTPUT_MODEL ) );
130 
131   cout << "## Calculated the following statistics for data set:\n";
132   for ( unsigned int b = 0; b < outputMetaDS->GetNumberOfBlocks(); ++ b )
133     {
134     vtkTable* outputMeta = vtkTable::SafeDownCast( outputMetaDS->GetBlock( b ) );
135 
136     if ( b == 0 )
137       {
138       cout << "Primary Statistics\n";
139       }
140     else
141       {
142       cout << "Derived Statistics " << ( b - 1 ) << "\n";
143       }
144 
145     outputMeta->Dump();
146     }
147 
148   // Test Assess Mode
149   vtkMultiBlockDataSet* paramsTables = vtkMultiBlockDataSet::New();
150   paramsTables->ShallowCopy( outputMetaDS );
151 
152   mcs->SetInputData( vtkStatisticsAlgorithm::INPUT_MODEL, paramsTables );
153   paramsTables->Delete();
154 
155   // Test Assess only (Do not recalculate nor rederive a model)
156   mcs->SetLearnOption( false );
157   mcs->SetDeriveOption( false );
158   mcs->SetAssessOption( true );
159   mcs->Update();
160 
161   vtkTable* outputData = mcs->GetOutput();
162   outputData->Dump();
163 
164   // Threshold for outlier detection
165   double threshold = 4.;
166   int nOutliers = 0;
167   int tableIdx[] = { 0, 1, 3 };
168 
169   cout << "## Searching for outliers such that "
170        << outputData->GetColumnName( tableIdx[2] )
171        << " > "
172        << threshold
173        << "\n";
174 
175   cout << "   Found the following outliers:\n";
176   for ( int i = 0; i < 3; ++ i )
177     {
178     cout << "   "
179          << outputData->GetColumnName( tableIdx[i] );
180     }
181   cout << "\n";
182 
183   for ( vtkIdType r = 0; r < outputData->GetNumberOfRows(); ++ r )
184     {
185     if ( outputData->GetValue( r, tableIdx[2] ).ToDouble() > threshold )
186       {
187       ++ nOutliers;
188 
189       for ( int i = 0; i < 3; ++ i )
190         {
191         cout << "     "
192              << outputData->GetValue( r,  tableIdx[i] ).ToString()
193              << "    ";
194         }
195       cout << "\n";
196       }
197     }
198 
199   if ( nOutliers != 3 )
200     {
201     vtkGenericWarningMacro("Expected 3 outliers, found " << nOutliers << ".");
202     testStatus = 1;
203     }
204 
205   mcs->Delete();
206 
207   return testStatus;
208 }
209 
210