File: vtkHDFWriterImplementation.h

package info (click to toggle)
vtk9 9.5.2%2Bdfsg3-4
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 205,916 kB
  • sloc: cpp: 2,336,565; ansic: 327,116; python: 111,200; yacc: 4,104; java: 3,977; sh: 3,032; xml: 2,771; perl: 2,189; lex: 1,787; makefile: 178; javascript: 165; objc: 153; tcl: 59
file content (382 lines) | stat: -rw-r--r-- 13,891 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
// SPDX-License-Identifier: BSD-3-Clause
/**
 * @class   vtkHDFWriterImplementation
 * @brief   Implementation class for vtkHDFWriter
 *
 * Opens, closes and writes information to a VTK HDF file.
 */

#ifndef vtkHDFWriterImplementation_h
#define vtkHDFWriterImplementation_h

#include "vtkAbstractArray.h"
#include "vtkCellArray.h"
#include "vtkHDF5ScopedHandle.h"
#include "vtkHDFUtilities.h"
#include "vtkHDFWriter.h"
#include "vtkType.h"

#include <array>
#include <string>

VTK_ABI_NAMESPACE_BEGIN

class vtkHDFWriter::Implementation
{
public:
  hid_t GetRoot() { return this->Root; }
  hid_t GetFile() { return this->File; }
  hid_t GetStepsGroup(hid_t currentGroup);

  /**
   * Write version and type attributes to the root group
   * A root must be open for the operation to succeed
   * Returns whether the operation was successful
   * If the operation fails, some attributes may have been written
   */
  bool WriteHeader(hid_t group, const char* hdfType);

  /**
   * Create the file from the filename and create the root VTKHDF group.
   * This file is closed on object destruction.
   * Overwrite the file if it exists by default
   * Returns true if the operation was successful
   * If the operation fails, the file may have been created
   */
  bool CreateFile(bool overwrite, const std::string& filename);

  /**
   * Open existing VTKHDF file and set Root and File members.
   * This file is closed on object destruction.
   */
  bool OpenFile();

  /**
   * Close currently handled file, open using CreateFile or OpenFile.
   * This does only need to be called when we want to close the file early; the file and open groups
   * are closed automatically on object destruction.
   */
  void CloseFile();

  /**
   * Open subfile where data has already been written, and needs to be referenced by the main file
   * using virtual datasets.
   * Return false if the subfile cannot be opened.
   */
  bool OpenSubfile(const std::string& filename);

  ///@{
  /**
   * Inform the implementation that all the data has been written in subfiles,
   * and that the virtual datasets can now be created from them.
   * This mechanism is used when writing a meta-file for temporal and/or multi-piece data.
   */
  void SetSubFilesReady(bool status) { this->SubFilesReady = status; }
  bool GetSubFilesReady() { return this->SubFilesReady; }
  ///@}

  /**
   * Create the steps group in the given group. It can be retrieved later using `GetStepsGroup`
   */
  bool CreateStepsGroup(hid_t group);

  /**
   * @struct PolyDataTopos
   * @brief Stores a group name and the corresponding cell array.
   *
   * Use this structure to avoid maintaining two arrays which is error prone (AOS instead of SOA)
   */
  typedef struct
  {
    const char* hdfGroupName;
    vtkCellArray* cellArray;
  } PolyDataTopos;

  /**
   * Get the cell array for the POLY_DATA_TOPOS
   */
  std::vector<PolyDataTopos> GetCellArraysForTopos(vtkPolyData* polydata);

  // Creation utility functions

  /**
   * Create a dataset in the given group with the given parameters and write data to it
   * Returned scoped handle may be invalid
   */
  vtkHDF::ScopedH5DHandle CreateAndWriteHdfDataset(hid_t group, hid_t type, hid_t source_type,
    const char* name, int rank, std::vector<hsize_t> dimensions, const void* data);

  /**
   * Create a HDF dataspace
   * It is simple (not scalar or null) which means that it is an array of elements
   * Returned scoped handle may be invalid
   */
  vtkHDF::ScopedH5SHandle CreateSimpleDataspace(int rank, const hsize_t dimensions[]);

  /**
   * Create a scalar integer attribute in the given group.
   * Noop if the attribute already exists.
   */
  vtkHDF::ScopedH5AHandle CreateScalarAttribute(hid_t group, const char* name, int value);

  /**
   * Create an unlimited HDF dataspace with a dimension of `0 * numCols`.
   * This dataspace can be attached to a chunked dataset and extended afterwards.
   * Returned scoped handle may be invalid
   */
  vtkHDF::ScopedH5SHandle CreateUnlimitedSimpleDataspace(hsize_t numCols);

  /**
   * Create a group in the given group from a dataspace.
   * Returned scoped handle may be invalid.
   */
  vtkHDF::ScopedH5GHandle CreateHdfGroup(hid_t group, const char* name);

  /**
   * Create a group that keeps track of link creation order
   * Returned scoped handle may be invalid.
   */
  vtkHDF::ScopedH5GHandle CreateHdfGroupWithLinkOrder(hid_t group, const char* name);

  /**
   * Create a soft link to the real group containing the block dataset.
   * Return true if the operation succeeded.
   */
  bool CreateSoftLink(hid_t group, const char* groupName, const char* targetLink);

  /**
   * Create an external link to the real group containing the block dataset.
   * Return true if the operation succeeded.
   */
  bool CreateExternalLink(
    hid_t group, const char* filename, const char* source, const char* targetLink);

  /**
   * Open and return an existing group thanks to id and a relative or absolute path to this group.
   */
  vtkHDF::ScopedH5GHandle OpenExistingGroup(hid_t group, const char* name);

  /**
   * Open and return an existing dataset using its group id and dataset name.
   */
  vtkHDF::ScopedH5DHandle OpenDataset(hid_t group, const char* name);

  /**
   * Return the name of a group given its id
   */
  std::string GetGroupName(hid_t group);

  /**
   * Create a dataset in the given group from a dataspace
   * Returned scoped handle may be invalid
   */
  vtkHDF::ScopedH5DHandle CreateHdfDataset(
    hid_t group, const char* name, hid_t type, hid_t dataspace);

  /**
   * Create a dataset in the given group
   * It internally creates a dataspace from a rank and dimensions
   * Returned scoped handle may be invalid
   */
  vtkHDF::ScopedH5DHandle CreateHdfDataset(
    hid_t group, const char* name, hid_t type, int rank, const hsize_t dimensions[]);

  /**
   * Create a virtual dataset from all the subfiles that have been added.
   * This virtual dataset references the datasets with the same name in subfiles,
   * and its first dimension is the sum of all subfiles datasets'.
   * the number of components must be the same in every subfile.
   * Return true iff the operation completed successfully
   */
  bool CreateVirtualDataset(hid_t group, const char* name, hid_t type, int numComp);

  ///@{
  /**
   * For temporal multi-piece meta-files, write the dataset `name` in group `group`,
   * which must be the "steps" group or a child of it as the running sum of all registered sub-files
   * datasets in the same location.
   * The `PolyData` version does the same operation in 2 dimensions, for offsets array of size
   * nbTimeSteps*nbPrimitives.
   */
  bool WriteSumSteps(hid_t group, const char* name);
  bool WriteSumStepsPolyData(hid_t group, const char* name);
  ///@}

  /**
   * Create a chunked dataset in the given group from a dataspace.
   * Chunked datasets are used to append data iteratively
   * Returned scoped handle may be invalid
   */
  vtkHDF::ScopedH5DHandle CreateChunkedHdfDataset(hid_t group, const char* name, hid_t type,
    hid_t dataspace, hsize_t numCols, hsize_t chunkSize[], int compressionLevel = 0);

  /**
   * Creates a dataspace to the exact array dimensions
   * Returned scoped handle may be invalid
   */
  vtkHDF::ScopedH5SHandle CreateDataspaceFromArray(vtkAbstractArray* dataArray);

  /**
   * Creates a dataset in the given group from a dataArray and write data to it
   * Returned scoped handle may be invalid
   */
  vtkHDF::ScopedH5DHandle CreateDatasetFromDataArray(
    hid_t group, const char* name, hid_t type, vtkAbstractArray* dataArray);

  ///@{
  /**
   * Creates a dataset and write a value to it.
   * Returned scoped handle may be invalid
   */
  vtkHDF::ScopedH5DHandle CreateSingleValueDataset(hid_t group, const char* name, vtkIdType value);
  ///@}

  /**
   * Create a chunked dataset with an empty extendable dataspace using chunking and set the desired
   * level of compression.
   * Return true if the operation was successful.
   */
  bool InitDynamicDataset(hid_t group, const char* name, hid_t type, hsize_t cols,
    hsize_t chunkSize[], int compressionLevel = 0);

  /**
   * Add a single value of integer type to an existing dataspace.
   * The trim parameter allows to overwrite the last data instead
   * of appending it to the dataset.
   * Return true if the write operation was successful.
   */
  bool AddSingleValueToDataset(hid_t dataset, vtkIdType value, bool offset, bool trim = false);

  /**
   * Add a 2D value of integer type to an existing dataspace which represents the FieldDataSize.
   * Return true if the write operation was successful.
   */
  bool AddFieldDataSizeValueToDataset(hid_t dataset, vtkIdType* value, vtkIdType size, bool offset);

  /**
   * Append a full data array at the end of an existing infinite dataspace.
   * It can also overwrite the last elements using the `trim` parameter.
   * When `trim` is positive, it will overwrite the number of array defined
   * by the parameter starting from the end of the dataset. When `trim` is non positive
   * it appends data array at the end of the dataset.
   * Return true if the write operation was successful.
   */
  bool AddArrayToDataset(hid_t dataset, vtkAbstractArray* dataArray, int trim = 0);

  /**
   * Append the given array to the dataset with the given `name`, creating it if it does not exist
   * yet. If the dataset/dataspace already exists, array types much match.
   * Return true if the operation was successful.
   */
  bool AddOrCreateDataset(hid_t group, const char* name, hid_t type, vtkAbstractArray* dataArray);

  /**
   * Append a single integer value to the dataset with name `name` in `group` group.
   * Create the dataset and dataspace if it does not exist yet.
   * When offset is true, the value written to the dataset is offset by the previous value of the
   * dataspace.
   * Return true if the operation is successful.
   */
  bool AddOrCreateSingleValueDataset(
    hid_t group, const char* name, vtkIdType value, bool offset = false, bool trim = false);

  /**
   * Append a 2D integer value to the dataset with name `FieldDataSize`.
   * Create the dataset and dataspace if it does not exist yet.
   * When offset is true, the value written to the dataset is offset by the previous value of the
   * dataspace.
   * Return true if the operation is successful.
   */
  bool AddOrCreateFieldDataSizeValueDataset(
    hid_t group, const char* name, vtkIdType* value, vtkIdType size, bool offset = false);

  /**
   * Find the first non null part for the given path in all subfiles.
   */
  vtkHDF::ScopedH5GHandle GetSubfileNonNullPart(const std::string& blockPath, int& type);

  /**
   * Initialize empty data object array structures from a base group.
   * Used to get meta information for composite subfiles when all subfiles do not have non-null
   * data.
   */
  void CreateArraysFromNonNullPart(hid_t group, vtkDataObject* data);

  Implementation(vtkHDFWriter* writer);
  virtual ~Implementation();

private:
  vtkHDFWriter* Writer;
  vtkHDF::ScopedH5FHandle File;
  vtkHDF::ScopedH5GHandle Root;
  vtkHDF::ScopedH5GHandle StepsGroup;
  std::vector<vtkHDF::ScopedH5FHandle> Subfiles;
  std::vector<std::string> SubfileNames;
  bool SubFilesReady = false;

  const std::array<std::string, 4> PrimitiveNames = { { "Vertices", "Lines", "Polygons",
    "Strips" } };

  /**
   * Look into subfile `subfileId` and return the number of cells in part `part`.
   * Supports UnstructuredGrid and PolyData subfiles.
   */
  hsize_t GetNumberOfCellsSubfile(const std::string& basePath, std::size_t subfileId, hsize_t part,
    bool isPolyData, const std::string& groupName);

  /**
   * Return the digit between 0 and 4 in the order of `PrimitiveNames`,
   * representing the primitive associated to `group`.
   * Return -1 if group is not a polydata primitive group.
   */
  char GetPrimitive(hid_t group);

  /**
   * Retrieve a single value from the 1-dimensional (usually meta-data)
   * group `name` in a given subfile `subfileId`.
   * `part` indicates the line (dimension 0) offset to read in the group.
   * `primitive` is the column offset to use when reading into a 2-D meta-data array for Poly Data.
   * Unless `primitive` is specified, assume that the array is 1-D.
   */
  hsize_t GetSubfileNumberOf(const std::string& base, const std::string& qualifier,
    std::size_t subfileId, hsize_t part, char primitive = 0xff);

  std::string GetBasePath(const std::string& fullPath);

  /**
   * Return true if the given dataset exists in the given existing group.
   */
  bool DatasetAndGroupExist(const std::string& dataset, hid_t group);

  /**
   * Set `totalSize` as the the sum of the subfiles dataset's size given a path to the dataset.
   * Return false on failure (dataset does not exist on every subfile). `totalSize` value should not
   * be used in this case.
   */
  bool GetSubFilesDatasetSize(
    const std::string& datasetPath, const std::string& groupName, hsize_t& totalSize);

  // Possible indexing mode of VTKHDF datasets. See `GetDatasetIndexationMode`
  enum class IndexingMode
  {
    Points,
    Cells,
    Connectivity,
    MetaData,
    Undefined
  };

  /**
   * Return the indexation mode of dataset at the given path: when the dataset adds 1 component for
   * every new time step or part, return `Single`. If we add a number of values equivalent to the
   * number of points of the dataset every step/part, return `Points`. The same goes for `Cells` and
   * `Connectivity`. This is used when creating virtual datasets from different parts, to know how
   * to interleave virtual mappings.
   */
  IndexingMode GetDatasetIndexationMode(const std::string& path);
};

VTK_ABI_NAMESPACE_END
#endif
// VTK-HeaderTest-Exclude: vtkHDFWriterImplementation.h