1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: TestXMLWriteRead.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15
16 #include "vtkArrayDispatch.h"
17 #include "vtkFloatArray.h"
18 #include "vtkHDFReader.h"
19 #include "vtkImageData.h"
20 #include "vtkMathUtilities.h"
21 #include "vtkNew.h"
22 #include "vtkPointData.h"
23 #include "vtkTesting.h"
24 #include "vtkUnstructuredGrid.h"
25 #include "vtkXMLImageDataReader.h"
26 #include "vtkXMLPUnstructuredGridReader.h"
27 #include "vtkXMLUnstructuredGridReader.h"
28
29 #include <iterator>
30 #include <string>
31
32 struct CompareVectorWorker
33 {
CompareVectorWorkerCompareVectorWorker34 CompareVectorWorker()
35 : ExitValue(EXIT_SUCCESS)
36 {
37 }
38 template <typename ArrayT, typename ExpectedArrayT>
operator ()CompareVectorWorker39 void operator()(ArrayT* array, ExpectedArrayT* expectedArray)
40 {
41 const auto range = vtk::DataArrayTupleRange(array);
42 const auto expectedRange = vtk::DataArrayTupleRange(expectedArray);
43
44 const vtk::TupleIdType numTuples = range.size();
45 const vtk::ComponentIdType numComps = range.GetTupleSize();
46
47 std::cout << "Compare " << array->GetName() << std::endl;
48 this->ExitValue = EXIT_SUCCESS;
49 for (vtk::TupleIdType tupleId = 0; tupleId < numTuples; ++tupleId)
50 {
51 const auto tuple = range[tupleId];
52 auto expectedTuple = expectedRange[tupleId];
53
54 for (vtk::ComponentIdType compId = 0; compId < numComps; ++compId)
55 {
56 if (tuple[compId] != expectedTuple[compId])
57 {
58 std::cerr << "Expecting " << expectedTuple[compId] << " for tuple/component: " << tupleId
59 << "/" << compId << " but got: " << tuple[compId] << std::endl;
60 this->ExitValue = EXIT_FAILURE;
61 break;
62 }
63 }
64 }
65 }
66 int ExitValue;
67 };
68
CompareVectors(vtkDataArray * array,vtkDataArray * expectedArray)69 int CompareVectors(vtkDataArray* array, vtkDataArray* expectedArray)
70 {
71 using Dispatcher = vtkArrayDispatch::Dispatch2BySameValueType<vtkArrayDispatch::AllTypes>;
72
73 // Create the functor:
74 CompareVectorWorker worker;
75
76 if (!Dispatcher::Execute(array, expectedArray, worker))
77 {
78 // If Execute(...) fails, the arrays don't match the constraints.
79 // Run the algorithm using the slower vtkDataArray double API instead:
80 worker(array, expectedArray);
81 }
82 return worker.ExitValue;
83 }
84
ReadImageData(const std::string & fileName)85 vtkSmartPointer<vtkImageData> ReadImageData(const std::string& fileName)
86 {
87 vtkNew<vtkXMLImageDataReader> reader;
88 reader->SetFileName(fileName.c_str());
89 reader->Update();
90 vtkSmartPointer<vtkImageData> data = vtkImageData::SafeDownCast(reader->GetOutput());
91 return data;
92 }
93
TestDataSet(vtkDataSet * data,vtkDataSet * expectedData)94 int TestDataSet(vtkDataSet* data, vtkDataSet* expectedData)
95 {
96 if (data == nullptr || expectedData == nullptr)
97 {
98 std::cerr << "Error: Data not in the format expected." << std::endl;
99 return EXIT_FAILURE;
100 }
101
102 if (data->GetNumberOfPoints() != expectedData->GetNumberOfPoints())
103 {
104 std::cerr << "Expecting " << expectedData->GetNumberOfPoints()
105 << " points but got: " << data->GetNumberOfPoints() << std::endl;
106 return EXIT_FAILURE;
107 }
108
109 if (data->GetNumberOfCells() != expectedData->GetNumberOfCells())
110 {
111 std::cerr << "Expecting " << expectedData->GetNumberOfCells()
112 << " cells but got: " << data->GetNumberOfCells() << std::endl;
113 return EXIT_FAILURE;
114 }
115 for (int attributeType = 0; attributeType < vtkDataObject::FIELD; ++attributeType)
116 {
117 int numberRead = data->GetAttributesAsFieldData(attributeType)->GetNumberOfArrays();
118 int numberExpected = expectedData->GetAttributesAsFieldData(attributeType)->GetNumberOfArrays();
119 if (numberRead != numberExpected)
120 {
121 std::cerr << "Expecting " << numberExpected << " arrays of type " << attributeType
122 << " but got " << numberRead << std::endl;
123 return EXIT_FAILURE;
124 }
125 vtkFieldData* fieldData = data->GetAttributesAsFieldData(attributeType);
126 vtkFieldData* expectedFieldData = expectedData->GetAttributesAsFieldData(attributeType);
127 for (int i = 0; i < numberRead; ++i)
128 {
129 // the arrays are not in the same order because listing arrays in creation
130 // order fails. See vtkHDFReader::Implementation::GetArrayNames
131 vtkAbstractArray* expectedArray = expectedFieldData->GetAbstractArray(i);
132 vtkAbstractArray* array = fieldData->GetAbstractArray(expectedArray->GetName());
133 if (std::string(expectedArray->GetClassName()) != array->GetClassName() &&
134 // long long == long
135 !(std::string(expectedArray->GetClassName()) == "vtkLongLongArray" &&
136 std::string(array->GetClassName()) == "vtkLongArray" &&
137 sizeof(long long) == sizeof(long)) &&
138 // unsigned long long == unsigned long
139 !(std::string(expectedArray->GetClassName()) == "vtkUnsignedLongLongArray" &&
140 std::string(array->GetClassName()) == "vtkUnsignedLongArray" &&
141 sizeof(unsigned long long) == sizeof(unsigned long)) &&
142 // vtkIdType == long
143 !(std::string(expectedArray->GetClassName()) == "vtkIdTypeArray" &&
144 std::string(array->GetClassName()) == "vtkLongArray" &&
145 sizeof(vtkIdType) == sizeof(long)) &&
146 // vtkIdType == long long
147 !(std::string(expectedArray->GetClassName()) == "vtkIdTypeArray" &&
148 std::string(array->GetClassName()) == "vtkLongLongArray" &&
149 sizeof(vtkIdType) == sizeof(long long)))
150 {
151 std::cerr << "Different array type: " << array->GetClassName() << " from expected "
152 << expectedArray->GetClassName() << " for array: " << expectedArray->GetName()
153 << std::endl
154 << "sizeof(long long): " << sizeof(long long) << std::endl
155 << "sizeof(long): " << sizeof(long) << std::endl;
156 return EXIT_FAILURE;
157 }
158
159 if (array->GetNumberOfTuples() != expectedArray->GetNumberOfTuples() ||
160 array->GetNumberOfComponents() != expectedArray->GetNumberOfComponents())
161 {
162 std::cerr << "Array " << array->GetName() << " has a different number of "
163 << "tuples/components: " << array->GetNumberOfTuples() << "/"
164 << array->GetNumberOfComponents()
165 << " than expected: " << expectedArray->GetNumberOfTuples() << "/"
166 << expectedArray->GetNumberOfComponents() << std::endl;
167 return EXIT_FAILURE;
168 }
169 vtkDataArray* a = vtkDataArray::SafeDownCast(array);
170 vtkDataArray* ea = vtkDataArray::SafeDownCast(expectedArray);
171 if (a)
172 {
173 if (CompareVectors(a, ea))
174 {
175 return EXIT_FAILURE;
176 }
177 }
178 };
179 }
180 return EXIT_SUCCESS;
181 }
182
TestImageData(const std::string & dataRoot)183 int TestImageData(const std::string& dataRoot)
184 {
185 // ImageData file
186 // ------------------------------------------------------------
187 std::string fileName = dataRoot + "/Data/mandelbrot-vti.hdf";
188 std::cout << "Testing: " << fileName << std::endl;
189 vtkNew<vtkHDFReader> reader;
190 if (!reader->CanReadFile(fileName.c_str()))
191 {
192 return EXIT_FAILURE;
193 }
194 reader->SetFileName(fileName.c_str());
195 reader->Update();
196 vtkImageData* data = vtkImageData::SafeDownCast(reader->GetOutput());
197 vtkSmartPointer<vtkImageData> expectedData = ReadImageData(dataRoot + "/Data/mandelbrot.vti");
198
199 int* dims = data->GetDimensions();
200 int* edims = expectedData->GetDimensions();
201 if (dims[0] != edims[0] || dims[1] != edims[1] || dims[2] != edims[2])
202 {
203 std::cerr << "Error: vtkImageData with wrong dimensions: "
204 << "expecting "
205 << "[" << edims[0] << ", " << edims[1] << ", " << edims[2] << "]"
206 << " got "
207 << "[" << dims[0] << ", " << dims[1] << ", " << dims[2] << "]" << std::endl;
208 return EXIT_FAILURE;
209 }
210
211 return TestDataSet(data, expectedData);
212 }
213
214 template <bool parallel>
TestUnstructuredGrid(const std::string & dataRoot)215 int TestUnstructuredGrid(const std::string& dataRoot)
216 {
217 std::string fileName, expectedName;
218 vtkNew<vtkHDFReader> reader;
219 vtkNew<vtkXMLUnstructuredGridReader> expectedReader;
220 vtkNew<vtkXMLPUnstructuredGridReader> expectedPReader;
221 vtkXMLReader* oreader;
222 if (parallel)
223 {
224 fileName = dataRoot + "/Data/can-pvtu.hdf";
225 expectedName = dataRoot + "/Data/can.pvtu";
226 oreader = expectedPReader;
227 }
228 else
229 {
230 fileName = dataRoot + "/Data/can-vtu.hdf";
231 expectedName = dataRoot + "/Data/can.vtu";
232 oreader = expectedReader;
233 }
234 std::cout << "Testing: " << fileName << std::endl;
235 if (!reader->CanReadFile(fileName.c_str()))
236 {
237 return EXIT_FAILURE;
238 }
239 reader->SetFileName(fileName.c_str());
240 reader->Update();
241 vtkUnstructuredGrid* data = vtkUnstructuredGrid::SafeDownCast(reader->GetOutputAsDataSet());
242
243 oreader->SetFileName(expectedName.c_str());
244 oreader->Update();
245 vtkUnstructuredGrid* expectedData =
246 vtkUnstructuredGrid::SafeDownCast(oreader->GetOutputAsDataSet());
247 return TestDataSet(data, expectedData);
248 }
249
TestHDFReader(int argc,char * argv[])250 int TestHDFReader(int argc, char* argv[])
251 {
252 vtkNew<vtkTesting> testHelper;
253 testHelper->AddArguments(argc, argv);
254 if (!testHelper->IsFlagSpecified("-D"))
255 {
256 std::cerr << "Error: -D /path/to/data was not specified.";
257 return EXIT_FAILURE;
258 }
259
260 std::string dataRoot = testHelper->GetDataRoot();
261 if (TestImageData(dataRoot))
262 {
263 return EXIT_FAILURE;
264 }
265
266 if (TestUnstructuredGrid<false /*parallel*/>(dataRoot))
267 {
268 return EXIT_FAILURE;
269 }
270 if (TestUnstructuredGrid<true /*parallel*/>(dataRoot))
271 {
272 return EXIT_FAILURE;
273 }
274 return EXIT_SUCCESS;
275 }
276