1 //============================================================================
2 // Copyright (c) Kitware, Inc.
3 // All rights reserved.
4 // See LICENSE.txt for details.
5 // This software is distributed WITHOUT ANY WARRANTY; without even
6 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
7 // PURPOSE. See the above copyright notice for more information.
8 //
9 //============================================================================
10
11 #include <fides/DataSetReader.h>
12 #include <fides/predefined/DataModelFactory.h>
13 #include <fides/predefined/DataModelHelperFunctions.h>
14 #include <fides/predefined/InternalMetadataSource.h>
15
16 #include <ios>
17 #include <stdexcept>
18 #include <unordered_map>
19 #include <vector>
20
21 #include <fides_rapidjson.h>
22 // clang-format off
23 #include FIDES_RAPIDJSON(rapidjson/document.h)
24 #include FIDES_RAPIDJSON(rapidjson/error/en.h)
25 #include FIDES_RAPIDJSON(rapidjson/filereadstream.h)
26 // clang-format on
27
28 #include <vtkm/cont/CoordinateSystem.h>
29 #include <vtkm/cont/DataSet.h>
30 #include <vtkm/cont/DynamicCellSet.h>
31
32 #include <fides/CellSet.h>
33 #include <fides/CoordinateSystem.h>
34 #include <fides/DataSource.h>
35 #include <fides/Field.h>
36 #include <fides/Keys.h>
37
38 namespace fides
39 {
40 namespace io
41 {
42
43 using DataSourceType = fides::io::DataSource;
44 using DataSourcesType = std::unordered_map<std::string, std::shared_ptr<DataSourceType>>;
45
46 class DataSetReader::DataSetReaderImpl
47 {
48 public:
DataSetReaderImpl(const std::string dataModel,DataModelInput inputType,const Params & params)49 DataSetReaderImpl(const std::string dataModel, DataModelInput inputType, const Params& params)
50 {
51 this->Cleanup();
52 if (inputType == DataModelInput::BPFile)
53 {
54 // in this case the bp file passed in becomes our MetadataSource
55 // which is used to select a predefined data model
56 this->MetadataSource.reset(new fides::predefined::InternalMetadataSource(dataModel));
57 auto dm = predefined::DataModelFactory::GetInstance().CreateDataModel(this->MetadataSource);
58 this->ReadJSON(dm->GetDOM());
59 }
60 else
61 {
62 rapidjson::Document doc = this->GetJSONDocument(dataModel, inputType);
63 this->ParsingChecks(doc, dataModel, inputType);
64 this->ReadJSON(doc);
65 }
66
67 this->SetDataSourceParameters(params);
68 }
69
~DataSetReaderImpl()70 virtual ~DataSetReaderImpl() { this->Cleanup(); }
71
Cleanup()72 void Cleanup()
73 {
74 this->DataSources.clear();
75 this->CoordinateSystem.reset();
76 this->CellSet.reset();
77 }
78
GetJSONDocument(const std::string & dataModel,DataModelInput inputType)79 rapidjson::Document GetJSONDocument(const std::string& dataModel, DataModelInput inputType)
80 {
81 rapidjson::Document d;
82 if (inputType == DataModelInput::JSONFile)
83 {
84 FILE* fp = std::fopen(dataModel.c_str(), "rb");
85 if (!fp)
86 {
87 throw std::ios_base::failure("Unable to open metadata file; does '" + dataModel +
88 "' exist?");
89 }
90 std::vector<char> buffer(65536);
91 rapidjson::FileReadStream is(fp, buffer.data(), buffer.size());
92 d.ParseStream(is);
93 std::fclose(fp);
94 }
95 else if (inputType == DataModelInput::JSONString)
96 {
97 rapidjson::StringStream s(dataModel.c_str());
98 d.ParseStream(s);
99 }
100 else
101 {
102 throw std::runtime_error(
103 "DataModelInput should be either Filename or String containing JSON");
104 }
105 return d;
106 }
107
SetDataSourceParameters(const Params & params)108 void SetDataSourceParameters(const Params& params)
109 {
110 for (const auto& p : params)
111 {
112 this->SetDataSourceParameters(p.first, p.second);
113 }
114 }
115
SetDataSourceParameters(const std::string source,const DataSourceParams & params)116 void SetDataSourceParameters(const std::string source, const DataSourceParams& params)
117 {
118 auto it = this->DataSources.find(source);
119 if (it == this->DataSources.end())
120 {
121 throw std::runtime_error("Source name was not found in DataSources.");
122 }
123 auto& ds = *(it->second);
124 ds.SetDataSourceParameters(params);
125 }
126
SetDataSourceIO(const std::string source,void * io)127 void SetDataSourceIO(const std::string source, void* io)
128 {
129 auto it = this->DataSources.find(source);
130 if (it == this->DataSources.end())
131 {
132 throw std::runtime_error("Source name was not found in DataSources.");
133 }
134 auto& ds = *(it->second);
135 ds.SetDataSourceIO(io);
136 }
137
138 template <typename ValueType>
ProcessDataSources(const ValueType & dataSources)139 void ProcessDataSources(const ValueType& dataSources)
140 {
141 for (auto& dataSource : dataSources)
142 {
143 if (!dataSource.IsObject())
144 {
145 throw std::runtime_error("data_sources must contain data_source objects.");
146 }
147 if (!dataSource.GetObject().HasMember("name"))
148 {
149 throw std::runtime_error("data_source objects must have name.");
150 }
151 std::string name = dataSource.GetObject()["name"].GetString();
152 if (name.empty())
153 {
154 throw std::runtime_error("data_source name must be a non-empty string.");
155 }
156 if (!dataSource.GetObject().HasMember("filename_mode"))
157 {
158 throw std::runtime_error("data_source objects must have filename_mode.");
159 }
160 std::string filename_mode = dataSource.GetObject()["filename_mode"].GetString();
161 if (filename_mode.empty())
162 {
163 throw std::runtime_error("data_source filename_mode must be a non-empty string.");
164 }
165 auto source = std::make_shared<DataSourceType>();
166 if (filename_mode == "input")
167 {
168 source->Mode = fides::io::FileNameMode::Input;
169 }
170 else if (filename_mode == "relative")
171 {
172 source->Mode = fides::io::FileNameMode::Relative;
173 if (!dataSource.GetObject().HasMember("filename"))
174 {
175 throw std::runtime_error("data_source objects must have filename.");
176 }
177 source->FileName = dataSource.GetObject()["filename"].GetString();
178 }
179 else
180 {
181 throw std::runtime_error("data_source filename_mode must be input or relative.");
182 }
183
184 this->DataSources[name] = source;
185 }
186 }
187
ProcessCoordinateSystem(const rapidjson::Value & coordSys)188 void ProcessCoordinateSystem(const rapidjson::Value& coordSys)
189 {
190 this->CoordinateSystem = std::make_shared<fides::datamodel::CoordinateSystem>();
191 this->CoordinateSystem->ObjectName = "coordinate_system";
192
193 this->CoordinateSystem->ProcessJSON(coordSys, this->DataSources);
194 }
195
ProcessCellSet(const rapidjson::Value & cellSet)196 void ProcessCellSet(const rapidjson::Value& cellSet)
197 {
198 this->CellSet = std::make_shared<fides::datamodel::CellSet>();
199 this->CellSet->ObjectName = "cell_set";
200
201 this->CellSet->ProcessJSON(cellSet, this->DataSources);
202 }
203
ProcessField(const rapidjson::Value & fieldJson)204 std::shared_ptr<fides::datamodel::Field> ProcessField(const rapidjson::Value& fieldJson)
205 {
206 if (!fieldJson.IsObject())
207 {
208 throw std::runtime_error("field needs to be an object.");
209 }
210 auto field = std::make_shared<fides::datamodel::Field>();
211 field->ProcessJSON(fieldJson, this->DataSources);
212 field->ObjectName = "field";
213 return field;
214 }
215
ProcessFields(const rapidjson::Value & fields)216 void ProcessFields(const rapidjson::Value& fields)
217 {
218 this->Fields.clear();
219 if (!fields.IsArray())
220 {
221 throw std::runtime_error("fields is not an array.");
222 }
223 auto fieldsArray = fields.GetArray();
224 for (auto& field : fieldsArray)
225 {
226 auto fieldPtr = this->ProcessField(field);
227 this->Fields[std::make_pair(fieldPtr->Name, fieldPtr->Association)] = fieldPtr;
228 }
229 }
230
GetNumberOfSteps()231 size_t GetNumberOfSteps()
232 {
233 if (this->StepSource.empty())
234 {
235 return 0;
236 }
237 auto sourceIter = this->DataSources.find(this->StepSource);
238 if (sourceIter == this->DataSources.end())
239 {
240 return 0;
241 }
242 return sourceIter->second->GetNumberOfSteps();
243 }
244
ProcessStepInformation(const rapidjson::Value & sinf)245 void ProcessStepInformation(const rapidjson::Value& sinf)
246 {
247 if (!sinf.IsObject())
248 {
249 throw std::runtime_error("step_information needs to be an object.");
250 }
251 auto sInf = sinf.GetObject();
252 if (!sInf.HasMember("data_source"))
253 {
254 throw std::runtime_error("step_information needs a data_source.");
255 }
256 this->StepSource = sInf["data_source"].GetString();
257 }
258
259 template <typename ValueType>
FindAndReturnObject(ValueType & root,const std::string name)260 const rapidjson::Value& FindAndReturnObject(ValueType& root, const std::string name)
261 {
262 if (!root.HasMember(name.c_str()))
263 {
264 throw std::runtime_error("Missing " + name + " member.");
265 }
266 auto& val = root[name.c_str()];
267 if (!val.IsObject())
268 {
269 throw std::runtime_error(name + " is expected to be an object.");
270 }
271 return val;
272 }
273
ParsingChecks(rapidjson::Document & document,const std::string & fileName,DataModelInput inputType)274 void ParsingChecks(rapidjson::Document& document,
275 const std::string& fileName,
276 DataModelInput inputType)
277 {
278 std::string nameStr;
279 if (inputType == DataModelInput::JSONFile)
280 {
281 nameStr = fileName;
282 }
283 else if (inputType == DataModelInput::JSONString)
284 {
285 nameStr = "the passed string";
286 }
287
288 if (document.HasParseError())
289 {
290 throw std::logic_error("Unable to parse " + nameStr + " as a json file. Error: " +
291 rapidjson::GetParseError_En(document.GetParseError()));
292 }
293 if (!document.IsObject())
294 {
295 throw std::logic_error("Unable to parse '" + nameStr + "' as a json file; is it valid json?");
296 }
297
298 auto m = document.GetObject().begin();
299 if (m == document.GetObject().end())
300 {
301 throw std::logic_error("There is no data in '" + nameStr +
302 "'; there is nothing that can be achieved with this file/string.");
303 }
304 if (!m->value.IsObject())
305 {
306 throw std::logic_error("Unable to create a sensible object from '" + nameStr +
307 "'; aborting.");
308 }
309 }
310
ReadJSON(rapidjson::Document & document)311 void ReadJSON(rapidjson::Document& document)
312 {
313 auto m = document.GetObject().begin();
314 const auto obj = m->value.GetObject();
315 if (!obj.HasMember("data_sources"))
316 {
317 throw std::runtime_error("Missing data_sources member.");
318 }
319 this->ProcessDataSources(obj["data_sources"].GetArray());
320
321 if (obj.HasMember("number_of_planes"))
322 {
323 auto& nPlanes = obj["number_of_planes"];
324 fides::datamodel::XGCCommon::ProcessNumberOfPlanes(nPlanes, this->DataSources);
325 }
326
327 if (!obj.HasMember("coordinate_system"))
328 {
329 throw std::runtime_error("Missing coordinate_system member.");
330 }
331 auto& cs = this->FindAndReturnObject(obj, "coordinate_system");
332 this->ProcessCoordinateSystem(cs);
333
334 if (!obj.HasMember("cell_set"))
335 {
336 throw std::runtime_error("Missing cell_set member.");
337 }
338 auto& cells = this->FindAndReturnObject(obj, "cell_set");
339 this->ProcessCellSet(cells);
340
341 if (obj.HasMember("fields"))
342 {
343 auto& fields = obj["fields"];
344 this->ProcessFields(fields);
345 }
346
347 if (obj.HasMember("step_information"))
348 {
349 auto& sinf = obj["step_information"];
350 this->ProcessStepInformation(sinf);
351 }
352 }
353
ReadCoordinateSystem(const std::unordered_map<std::string,std::string> & paths,const fides::metadata::MetaData & selections)354 std::vector<vtkm::cont::CoordinateSystem> ReadCoordinateSystem(
355 const std::unordered_map<std::string, std::string>& paths,
356 const fides::metadata::MetaData& selections)
357 {
358 if (!this->CoordinateSystem)
359 {
360 throw std::runtime_error("Cannot read missing coordinate system.");
361 }
362 return this->CoordinateSystem->Read(paths, this->DataSources, selections);
363 }
364
ReadCellSet(const std::unordered_map<std::string,std::string> & paths,const fides::metadata::MetaData & selections)365 std::vector<vtkm::cont::DynamicCellSet> ReadCellSet(
366 const std::unordered_map<std::string, std::string>& paths,
367 const fides::metadata::MetaData& selections)
368 {
369 if (!this->CellSet)
370 {
371 throw std::runtime_error("Cannot read missing cell set.");
372 }
373 return this->CellSet->Read(paths, this->DataSources, selections);
374 }
375
376 // updates this->Fields if we have any wildcard fields. Should be used
377 // in ReadMetaData()
ExpandWildcardFields()378 void ExpandWildcardFields()
379 {
380 auto it = this->Fields.begin();
381 while (it != this->Fields.end())
382 {
383 auto& origField = it->second;
384 // find fields to expand
385 if (origField->IsWildcardField())
386 {
387 auto lists = origField->GetWildcardFieldLists(this->MetadataSource);
388 // need to add each name, association pair to Fields
389 // as well as create the associated Field object
390 auto& names = lists.Names;
391 auto& associations = lists.Associations;
392
393 for (size_t i = 0; i < names.size(); ++i)
394 {
395 std::string isVector = "auto";
396 std::string source = "source";
397 std::string arrayType = "basic";
398 if (!lists.IsVector.empty() && i < lists.IsVector.size())
399 {
400 isVector = lists.IsVector[i];
401 }
402 if (!lists.Sources.empty() && i < lists.Sources.size())
403 {
404 source = lists.Sources[i];
405 }
406 if (!lists.ArrayTypes.empty() && i < lists.ArrayTypes.size())
407 {
408 arrayType = lists.ArrayTypes[i];
409 }
410
411 // the wildcard field uses an ArrayPlaceholder. Now we have enough info
412 // to create the actual JSON for the Array object for this Field. This can
413 // then be passed to Field.ProcessExpandedField which will use it to create
414 // the actual array object.
415 rapidjson::Document arrayObj;
416 arrayObj = predefined::CreateFieldArrayDoc(names[i], source, arrayType, isVector);
417
418 if (!arrayObj.HasMember("array"))
419 {
420 throw std::runtime_error("Field Array Object was not created correctly");
421 }
422 auto fieldPtr = std::make_shared<fides::datamodel::Field>();
423 fieldPtr->ProcessExpandedField(names[i], associations[i], arrayObj, this->DataSources);
424 fieldPtr->ObjectName = "field";
425 this->Fields[std::make_pair(fieldPtr->Name, fieldPtr->Association)] = fieldPtr;
426 }
427
428 // remove the wildcard field now that we're done expanding it
429 it = this->Fields.erase(it);
430 }
431 else
432 {
433 ++it;
434 }
435 }
436 }
437
ReadMetaData(const std::unordered_map<std::string,std::string> & paths)438 fides::metadata::MetaData ReadMetaData(const std::unordered_map<std::string, std::string>& paths)
439 {
440 if (!this->CoordinateSystem)
441 {
442 throw std::runtime_error("Cannot read missing coordinate system.");
443 }
444 size_t nBlocks = this->CoordinateSystem->GetNumberOfBlocks(paths, this->DataSources);
445 fides::metadata::MetaData metaData;
446 fides::metadata::Size nBlocksM(nBlocks);
447 metaData.Set(fides::keys::NUMBER_OF_BLOCKS(), nBlocksM);
448
449 if (!this->Fields.empty())
450 {
451 // updates this->Fields if necessary
452 this->ExpandWildcardFields();
453 fides::metadata::Vector<fides::metadata::FieldInformation> fields;
454 for (auto& item : this->Fields)
455 {
456 auto& field = item.second;
457 fides::metadata::FieldInformation afield(field->Name, field->Association);
458 fields.Data.push_back(afield);
459 }
460 metaData.Set(fides::keys::FIELDS(), fields);
461 }
462
463 size_t nSteps = this->GetNumberOfSteps();
464 if (nSteps > 0)
465 {
466 fides::metadata::Size nStepsM(nSteps);
467 metaData.Set(fides::keys::NUMBER_OF_STEPS(), nStepsM);
468 }
469 return metaData;
470 }
471
PostRead(std::vector<vtkm::cont::DataSet> & pds,const fides::metadata::MetaData & selections)472 void PostRead(std::vector<vtkm::cont::DataSet>& pds, const fides::metadata::MetaData& selections)
473 {
474 this->CoordinateSystem->PostRead(pds, selections);
475 this->CellSet->PostRead(pds, selections);
476 for (auto& f : this->Fields)
477 f.second->PostRead(pds, selections);
478 }
479
DoAllReads()480 void DoAllReads()
481 {
482 for (const auto& source : this->DataSources)
483 {
484 source.second->DoAllReads();
485 }
486 }
487
488 // For BeginStep, we loop on a DataSource if its status is NotReady, because
489 // otherwise with multiple sources, we can get into a weird situation where
490 // step i for DataSource A may take longer to write than step i for DataSource B.
491 // So if we return NotReady in this situation, then on the next call to BeginStep,
492 // DataSource A may finally be ready for step i, but it's possible that DataSource
493 // B is ready for i+1. Or we could run into an ADIOS error, due to not having an
494 // EndStep for DataSource B before the next BeginStep in this type of situation.
495 // Also this function only returns EndOfStream when all DataSources have reached
496 // EndOfStream. In a situation with multiple source, users shouldn't need to worry
497 // about when a single DataSource reaches EndOfStream, because Fides handles this internally
498 // (e.g., having the variables making up a mesh marked as static and only reading initially).
499 // So the user should only care about PrepareNextStep returning EndOfStream when all
500 // DataSources are at the end of their Streams.
BeginStep(const std::unordered_map<std::string,std::string> & paths)501 StepStatus BeginStep(const std::unordered_map<std::string, std::string>& paths)
502 {
503 StepStatus retVal = StepStatus::EndOfStream;
504 for (const auto& source : this->DataSources)
505 {
506 auto& ds = *(source.second);
507 std::string name = source.first;
508 auto itr = paths.find(name);
509 if (itr == paths.end())
510 {
511 throw std::runtime_error("Could not find data_source with name " + name +
512 " among the input paths.");
513 }
514 std::string path = itr->second + ds.FileName;
515 ds.OpenSource(path);
516 auto rc = ds.BeginStep();
517 while (rc == StepStatus::NotReady)
518 {
519 rc = ds.BeginStep();
520 }
521 if (rc == StepStatus::OK)
522 {
523 retVal = StepStatus::OK;
524 }
525 }
526 return retVal;
527 }
528
EndStep()529 void EndStep()
530 {
531 for (const auto& source : this->DataSources)
532 {
533 source.second->EndStep();
534 }
535 }
536
537 DataSourcesType DataSources;
538 std::shared_ptr<fides::predefined::InternalMetadataSource> MetadataSource = nullptr;
539 std::shared_ptr<fides::datamodel::CoordinateSystem> CoordinateSystem = nullptr;
540 std::shared_ptr<fides::datamodel::CellSet> CellSet = nullptr;
541 using FieldsKeyType = std::pair<std::string, vtkm::cont::Field::Association>;
542 std::map<FieldsKeyType, std::shared_ptr<fides::datamodel::Field>> Fields;
543 std::string StepSource;
544 };
545
CheckForDataModelAttribute(const std::string & filename,const std::string & attrName)546 bool DataSetReader::CheckForDataModelAttribute(const std::string& filename,
547 const std::string& attrName /*="Fides_Data_Model"*/)
548 {
549 bool found = false;
550 auto source = std::make_shared<DataSourceType>();
551 source->Mode = fides::io::FileNameMode::Relative;
552 source->FileName = filename;
553 source->OpenSource(filename);
554 if (source->GetAttributeType(attrName) == "string")
555 {
556 std::vector<std::string> result = source->ReadAttribute<std::string>(attrName);
557 if (!result.empty())
558 {
559 found = predefined::DataModelSupported(result[0]);
560 }
561 }
562 if (!found)
563 {
564 // Fides_Data_Model attribute not found, now look for a fides/schema attribute
565 std::string schemaAttr = "fides/schema";
566 if (source->GetAttributeType(schemaAttr) == "string")
567 {
568 found = true;
569 }
570 }
571 return found;
572 }
573
DataSetReader(const std::string dataModel,DataModelInput inputType,const Params & params)574 DataSetReader::DataSetReader(const std::string dataModel,
575 DataModelInput inputType /*=DataModelInput::JSONFile*/,
576 const Params& params)
577 : Impl(nullptr)
578 {
579 if (inputType != DataModelInput::BPFile)
580 {
581 this->Impl.reset(new DataSetReaderImpl(dataModel, inputType, params));
582 return;
583 }
584
585 // we have a BPFile and we need to look for either Fides_Data_Model
586 // or fides/schema attributes
587 std::string fidesAttr = "Fides_Data_Model";
588 auto source = std::make_shared<DataSourceType>();
589 source->Mode = fides::io::FileNameMode::Relative;
590 source->FileName = dataModel; // in this case dataModel should be bp filename
591 source->OpenSource(dataModel);
592 if (source->GetAttributeType(fidesAttr) == "string")
593 {
594 std::vector<std::string> result = source->ReadAttribute<std::string>(fidesAttr);
595 if (!result.empty())
596 {
597 if (predefined::DataModelSupported(result[0]))
598 {
599 this->Impl.reset(new DataSetReaderImpl(dataModel, inputType, params));
600 return;
601 }
602 }
603 }
604
605 // Fides_Data_Model either not found or value was incorrect, now look for fides/schema
606 std::string schemaAttr = "fides/schema";
607 if (source->GetAttributeType(schemaAttr) == "string")
608 {
609 auto schema = source->ReadAttribute<std::string>(schemaAttr);
610 if (!schema.empty())
611 {
612 this->Impl.reset(new DataSetReaderImpl(schema[0], DataModelInput::JSONString, params));
613 return;
614 }
615 }
616
617 throw std::runtime_error("InputType is a BP File, but valid 'Fides_Data_Model' or "
618 "'fides/schema' attributes could not be found in the file.");
619 }
620
621 DataSetReader::~DataSetReader() = default;
622
ReadMetaData(const std::unordered_map<std::string,std::string> & paths)623 fides::metadata::MetaData DataSetReader::ReadMetaData(
624 const std::unordered_map<std::string, std::string>& paths)
625 {
626 return this->Impl->ReadMetaData(paths);
627 }
628
ReadDataSet(const std::unordered_map<std::string,std::string> & paths,const fides::metadata::MetaData & selections)629 vtkm::cont::PartitionedDataSet DataSetReader::ReadDataSet(
630 const std::unordered_map<std::string, std::string>& paths,
631 const fides::metadata::MetaData& selections)
632 {
633 auto ds = this->ReadDataSetInternal(paths, selections);
634 this->Impl->DoAllReads();
635 this->Impl->PostRead(ds, selections);
636
637 // for(size_t i=0; i<ds.GetNumberOfPartitions(); i++)
638 // {
639 // vtkm::io::writer::VTKDataSetWriter writer(
640 // "output" + std::to_string(i) + ".vtk");
641 // writer.WriteDataSet(ds.GetPartition(i));
642 // }
643
644 return vtkm::cont::PartitionedDataSet(ds);
645 }
646
PrepareNextStep(const std::unordered_map<std::string,std::string> & paths)647 StepStatus DataSetReader::PrepareNextStep(const std::unordered_map<std::string, std::string>& paths)
648 {
649 return this->Impl->BeginStep(paths);
650 }
651
ReadStep(const std::unordered_map<std::string,std::string> & paths,const fides::metadata::MetaData & selections)652 vtkm::cont::PartitionedDataSet DataSetReader::ReadStep(
653 const std::unordered_map<std::string, std::string>& paths,
654 const fides::metadata::MetaData& selections)
655 {
656 auto ds = this->ReadDataSetInternal(paths, selections);
657 this->Impl->EndStep();
658 this->Impl->PostRead(ds, selections);
659
660 return vtkm::cont::PartitionedDataSet(ds);
661 }
662
663 // Returning vector of DataSets instead of PartitionedDataSet because
664 // PartitionedDataSet::GetPartition always returns a const DataSet, but
665 // we may need to update the DataSet in the PostRead call
ReadDataSetInternal(const std::unordered_map<std::string,std::string> & paths,const fides::metadata::MetaData & selections)666 std::vector<vtkm::cont::DataSet> DataSetReader::ReadDataSetInternal(
667 const std::unordered_map<std::string, std::string>& paths,
668 const fides::metadata::MetaData& selections)
669 {
670 std::vector<vtkm::cont::CoordinateSystem> coordSystems =
671 this->Impl->ReadCoordinateSystem(paths, selections);
672 std::vector<vtkm::cont::DynamicCellSet> cellSets = this->Impl->ReadCellSet(paths, selections);
673 size_t nPartitions = cellSets.size();
674 std::vector<vtkm::cont::DataSet> dataSets(nPartitions);
675 for (size_t i = 0; i < nPartitions; i++)
676 {
677 if (i < coordSystems.size())
678 {
679 dataSets[i].AddCoordinateSystem(coordSystems[i]);
680 }
681 if (i < cellSets.size())
682 {
683 dataSets[i].SetCellSet(cellSets[i]);
684 }
685 }
686
687 if (selections.Has(fides::keys::FIELDS()))
688 {
689 using FieldInfoType = fides::metadata::Vector<fides::metadata::FieldInformation>;
690 auto& fields = selections.Get<FieldInfoType>(fides::keys::FIELDS());
691 for (auto& field : fields.Data)
692 {
693 auto itr = this->Impl->Fields.find(std::make_pair(field.Name, field.Association));
694 if (itr != this->Impl->Fields.end())
695 {
696 std::vector<vtkm::cont::Field> fieldVec =
697 itr->second->Read(paths, this->Impl->DataSources, selections);
698 for (size_t i = 0; i < nPartitions; i++)
699 {
700 if (i < fieldVec.size())
701 {
702 dataSets[i].AddField(fieldVec[i]);
703 }
704 }
705 }
706 }
707 }
708 else
709 {
710 for (auto& field : this->Impl->Fields)
711 {
712 std::vector<vtkm::cont::Field> fields =
713 field.second->Read(paths, this->Impl->DataSources, selections);
714 for (size_t i = 0; i < nPartitions; i++)
715 {
716 if (i < fields.size())
717 {
718 dataSets[i].AddField(fields[i]);
719 }
720 }
721 }
722 }
723
724 return dataSets;
725 }
726
SetDataSourceParameters(const std::string source,const DataSourceParams & params)727 void DataSetReader::SetDataSourceParameters(const std::string source,
728 const DataSourceParams& params)
729 {
730 this->Impl->SetDataSourceParameters(source, params);
731 }
732
SetDataSourceIO(const std::string source,void * io)733 void DataSetReader::SetDataSourceIO(const std::string source, void* io)
734 {
735 this->Impl->SetDataSourceIO(source, io);
736 }
737
738 FIDES_DEPRECATED_SUPPRESS_BEGIN
GetFieldData()739 std::shared_ptr<fides::datamodel::FieldDataManager> DataSetReader::GetFieldData()
740 {
741 // Function to be removed in next version
742 return nullptr;
743 }
744 FIDES_DEPRECATED_SUPPRESS_END
745
GetDataSourceNames()746 std::vector<std::string> DataSetReader::GetDataSourceNames()
747 {
748 std::vector<std::string> names;
749 for (const auto& source : this->Impl->DataSources)
750 {
751 names.push_back(source.first);
752 }
753 return names;
754 }
755
756 } // end namespace io
757 } // end namespace fides
758