53#include <boost/tokenizer.hpp>
54#include <boost/utility.hpp>
84 const std::string k_mappingStr(
"mapping");
85 const std::string k_partitionName(
"partition");
86 const std::string k_versionAttrName(
"version_number");
87 const std::string k_classNameAttrName(
"class_name");
88 const std::string k_mappingTypeAttrName(
"mapping_type");
93 int k_currentFileVersion[3] =
95 int k_minFileVersion[2] = { 0, 0 };
99 std::vector<std::string> makeUnique(std::vector<std::string> vec)
101 std::vector<string> ret;
102 std::sort(vec.begin(), vec.end());
103 std::vector<std::string>::iterator newEnd =
104 std::unique(vec.begin(), vec.end());
105 ret.resize(std::distance(vec.begin(), newEnd));
106 std::copy(vec.begin(), newEnd, ret.begin());
114 class print : std::unary_function<T, void>
120 void operator()(
const T& x)
const
122 for (
int i = 0; i < indent; i++)
124 std::cout << x << std::endl;
139 struct __stat64 statbuf;
140 return (_stat64(filename.c_str(), &statbuf) != -1);
143 return (stat(filename.c_str(), &statbuf) != -1);
152 void checkFile(
const std::string &filename)
156 throw NoSuchFileException(filename);
162 bool isSupportedFileVersion(
const int fileVersion[3],
163 const int minVersion[2])
165 stringstream currentVersionStr;
166 currentVersionStr << k_currentFileVersion[0] <<
"."
167 << k_currentFileVersion[1] <<
"."
168 << k_currentFileVersion[2];
169 stringstream fileVersionStr;
170 fileVersionStr << fileVersion[0] <<
"."
171 << fileVersion[1] <<
"."
173 stringstream minVersionStr;
174 minVersionStr << minVersion[0] <<
"."
177 if (fileVersion[0] > k_currentFileVersion[0] ||
178 (fileVersion[0] == k_currentFileVersion[0] &&
179 fileVersion[1] > k_currentFileVersion[1])) {
181 " is higher than the current version " +
182 currentVersionStr.str());
186 if (fileVersion[0] < minVersion[0] ||
187 (fileVersion[0] == minVersion[0] &&
188 fileVersion[1] < minVersion[1])) {
190 " is lower than the minimum supported version " +
191 minVersionStr.str());
199 static herr_t localPrintError( hid_t estack_id,
void *stream )
201 printf(
"H5E message -----------------------\n");
202 return H5Eprint2(estack_id,
static_cast<FILE*
>(stream));
215 return k_partitionName;
269 names.push_back(i->name);
282 names.push_back(i->name);
291 : m_file(-1), m_metadata(this)
298 if (getenv(
"DEBUG_HDF")) {
299 cerr <<
"Field3DFileHDF5 -- HDF5 messages are on" << endl;
300 H5Eset_auto(H5E_DEFAULT, localPrintError, NULL);
302 H5Eset_auto(H5E_DEFAULT, NULL, NULL);
317 const std::string & ,
321 for (PartitionList::const_iterator i =
m_partitions.begin();
324 if ((**i).mapping->isIdentical(field->mapping())) {
349 if ((**i).name == partitionName)
361 for (PartitionList::const_iterator i =
m_partitions.begin();
363 if ((**i).name == partitionName)
375 size_t pos = partitionName.rfind(
".");
376 if (pos == partitionName.npos) {
377 return partitionName;
379 return partitionName.substr(0, pos);
390 vector<string> tempNames;
392 for (PartitionList::const_iterator i =
m_partitions.begin();
397 names = makeUnique(tempNames);
404 const string &partitionName)
const
412 part->getScalarLayerNames(names);
415 names = makeUnique(names);
422 const string &partitionName)
const
430 part->getVectorLayerNames(names);
433 names = makeUnique(names);
443 for (PartitionList::const_iterator i =
m_partitions.begin();
445 names.push_back((**i).name);
453 const string &intPartitionName)
const
464 part->getScalarLayerNames(names);
471 const string &intPartitionName)
const
482 part->getVectorLayerNames(names);
510 if (H5Fclose(
m_file) < 0) {
525 for (PartitionList::const_iterator i =
m_partitions.begin();
527 string name = (**i).name;
528 size_t pos = name.rfind(
".");
529 if (pos != name.npos) {
530 if (name.substr(0, pos) == partitionName) {
545 return partitionName +
"." + boost::lexical_cast<std::string>(i);
553 GroupMembershipMap::const_iterator i= groupMembers.begin();
554 GroupMembershipMap::const_iterator end= groupMembers.end();
556 for (; i != end; ++i) {
557 GroupMembershipMap::iterator foundGroupIter =
606 m_file = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
609 throw NoSuchFileException(filename);
616 if (!isSupportedFileVersion(fileVersion, k_minFileVersion)) {
617 stringstream versionStr;
618 versionStr << fileVersion[0] <<
"."
619 << fileVersion[1] <<
"."
621 throw UnsupportedVersionException(versionStr.str());
625 catch (MissingAttributeException &) {
630 if (H5Lexists(
m_file,
"field3d_global_metadata", H5P_DEFAULT)) {
633 if (metadataGroup.
id() > 0) {
640 "Unknown error when reading file metadata ");
649 catch (MissingGroupException &e) {
651 throw BadFileHierarchyException(filename);
653 catch (ReadMappingException &e) {
656 throw BadFileHierarchyException(filename);
661 throw BadFileHierarchyException(filename);
665 "Unknown error when reading file hierarchy. ");
666 throw BadFileHierarchyException(filename);
670 catch (NoSuchFileException &e) {
672 +
string(e.what()) );
675 catch (MissingAttributeException &e) {
677 "In file: " + filename +
" - "
678 +
string(e.what()) );
681 catch (UnsupportedVersionException &e) {
683 "In file: " + filename +
" - File version can not be read: "
687 catch (BadFileHierarchyException &) {
689 "In file: " + filename +
" - Bad file hierarchy. ");
694 "In file: " + filename +
" Unknown exception ");
715 status = H5Literate(
m_file, H5_INDEX_NAME, H5_ITER_NATIVE, NULL,
716 &parsePartitions,
this);
735 string mappingPath =
"/" + (**i).name +
"/" + k_mappingStr;
739 if (mappingGroup.
id() < 0)
740 throw MissingGroupException((**i).name +
"/" + k_mappingStr);
748 throw ReadMappingException((**i).name);
752 (**i).mapping = mapping;
758 for (PartitionList::const_iterator i =
m_partitions.begin();
771 status = H5Literate(partitionGroup.
id(), H5_INDEX_NAME, H5_ITER_NATIVE,
772 NULL, &parseLayers, &info);
776 for (std::vector<LayerInfo>::iterator i =
m_layerInfo.begin();
779 std::string parent = i->parentName;
784 layer.
name = i->name;
785 layer.
parent = i->parentName;
786 if (i->components == 1) {
787 part->addScalarLayer(layer);
788 }
else if (i->components == 3) {
789 part->addVectorLayer(layer);
801 const std::string itemName)
815 const std::string &partitionName,
816 const std::string &layerName)
819 if (!
readAttribute(layerGroup,
string(
"components"), 1, components)) {
821 + partitionName +
"/" + layerName);
825 LayerInfo linfo(partitionName,layerName,components);
841 hsize_t num_attrs = H5Aget_num_attrs(metadata_id);
844 for (hsize_t idx=0; idx < num_attrs ; ++idx) {
846 size_t len = H5Aget_name(attrIdx.
id(), 0, NULL);
848 char *name =
new char[len+1];
849 if (H5Aget_name(attrIdx.
id(), len+1, name) > 0) {
853 H5T_class_t typeClass = H5Tget_class(attrType);
855 if (typeClass == H5T_STRING) {
859 "Failed to read metadata " +
string(name));
865 field->metadata().setStrMetadata(name, value);
870 if (H5Sget_simple_extent_ndims(attrSpace) != 1) {
880 H5Sget_simple_extent_dims(attrSpace, dims, NULL);
882 if (typeClass == H5T_INTEGER) {
888 field->metadata().setIntMetadata(name, value);
890 else if (dims[0] == 3){
895 field->metadata().setVecIntMetadata(name, value);
899 "Attribute of size " +
900 boost::lexical_cast<std::string>(dims[0])
901 +
" is not valid for metadata");
904 else if (typeClass == H5T_FLOAT) {
911 field->metadata().setFloatMetadata(name, value);
913 else if (dims[0] == 3){
918 field->metadata().setVecFloatMetadata(name, value);
922 boost::lexical_cast<std::string>(dims[0]) +
923 " is not valid for metadata");
928 +
"' has unsupported data type for metadata");
951 hsize_t num_attrs = H5Aget_num_attrs(metadata_id);
954 for (hsize_t idx=0; idx < num_attrs ; ++idx) {
956 size_t len = H5Aget_name(attrIdx.
id(), 0, NULL);
958 char *name =
new char[len+1];
959 if (H5Aget_name(attrIdx.
id(), len+1, name) > 0) {
963 H5T_class_t typeClass = H5Tget_class(attrType);
965 if (typeClass == H5T_STRING) {
969 "Failed to read metadata " +
string(name));
980 if (H5Sget_simple_extent_ndims(attrSpace) != 1) {
990 H5Sget_simple_extent_dims(attrSpace, dims, NULL);
992 if (typeClass == H5T_INTEGER) {
1000 else if (dims[0] == 3){
1009 "Attribute of size " +
1010 boost::lexical_cast<std::string>(dims[0])
1011 +
" is not valid for metadata");
1014 else if (typeClass == H5T_FLOAT) {
1023 else if (dims[0] == 3){
1032 boost::lexical_cast<std::string>(dims[0]) +
1033 " is not valid for metadata");
1038 +
"' has unsupported data type for metadata");
1061 if (!H5Lexists(
m_file,
"field3d_group_membership", H5P_DEFAULT)) {
1066 if (memberGroup < 0) {
1070 typedef boost::tokenizer<boost::char_separator<char> > Tok;
1072 hsize_t num_attrs = H5Aget_num_attrs(memberGroup);
1073 if (num_attrs > 0) {
1075 for (hsize_t idx=0; idx < num_attrs ; ++idx) {
1077 size_t len = H5Aget_name(attrIdx.
id(), 0, NULL);
1079 char *name =
new char[len+1];
1080 if (H5Aget_name(attrIdx.
id(), len+1, name) > 0) {
1082 if (
string(name) ==
"is_field3d_group_membership")
1088 H5T_class_t typeClass = H5Tget_class(attrType);
1090 if (typeClass == H5T_STRING) {
1094 "Failed to read group membership data "
1100 boost::char_separator<char> sep(
" :");
1101 Tok tok(value, sep);
1103 for(Tok::iterator beg=tok.begin(); beg!=tok.end();){
1105 string fieldgroup = *beg; ++beg;
1107 new_value += fieldgroup +
" ";
1111 gpMembershipMap[name] = new_value;
1131 const H5L_info_t * ,
void *opdata)
1138 status = H5Oget_info_by_name(loc_id, itemName, &infobuf, H5P_DEFAULT);
1144 if (infobuf.type == H5O_TYPE_GROUP) {
1152 if (
string(itemName) !=
"field3d_group_membership" &&
1153 string(itemName) !=
"field3d_global_metadata")
1171 const H5L_info_t * ,
void *opdata)
1178 status = H5Oget_info_by_name (loc_id, itemName, &infobuf, H5P_DEFAULT);
1180 if (infobuf.type == H5O_TYPE_GROUP) {
1200 if (classType ==
string(
"field3d_layer"))
1205 catch (MissingAttributeException &) {
1245 bool success =
true;
1249 hid_t faid = H5Pcreate(H5P_FILE_ACCESS);
1250 H5Pset_libver_bounds(faid, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST);
1255 m_file = H5Fcreate(filename.c_str(),
1256 H5F_ACC_TRUNC, H5P_DEFAULT, faid);
1259 m_file = H5Fcreate(filename.c_str(),
1260 H5F_ACC_EXCL, H5P_DEFAULT, faid);
1266 throw ErrorCreatingFileException(filename);
1270 k_currentFileVersion[0])) {
1277 catch (ErrorCreatingFileException &e) {
1281 catch (WriteAttributeException &e) {
1283 " - Couldn't add attribute " +
string(e.what()) );
1288 "Unknown error when creating file: " + filename );
1305 if (mappingGroup.
id() < 0)
1306 throw CreateGroupException(k_mappingStr);
1309 throw WriteMappingException(k_mappingStr);
1311 catch (CreateGroupException &e) {
1313 throw WriteMappingException(k_mappingStr);
1325 FieldMetadata::StrMetadata::const_iterator i =
1326 field->metadata().strMetadata().begin();
1327 FieldMetadata::StrMetadata::const_iterator end =
1328 field->metadata().strMetadata().end();
1329 for (; i != end; ++i) {
1339 FieldMetadata::IntMetadata::const_iterator i =
1340 field->metadata().intMetadata().begin();
1341 FieldMetadata::IntMetadata::const_iterator end =
1342 field->metadata().intMetadata().end();
1343 for (; i != end; ++i) {
1353 FieldMetadata::FloatMetadata::const_iterator i =
1354 field->metadata().floatMetadata().begin();
1355 FieldMetadata::FloatMetadata::const_iterator end =
1356 field->metadata().floatMetadata().end();
1357 for (; i != end; ++i) {
1367 FieldMetadata::VecIntMetadata::const_iterator i =
1368 field->metadata().vecIntMetadata().begin();
1369 FieldMetadata::VecIntMetadata::const_iterator end =
1370 field->metadata().vecIntMetadata().end();
1371 for (; i != end; ++i) {
1381 FieldMetadata::VecFloatMetadata::const_iterator i =
1382 field->metadata().vecFloatMetadata().begin();
1383 FieldMetadata::VecFloatMetadata::const_iterator end =
1384 field->metadata().vecFloatMetadata().end();
1385 for (; i != end; ++i) {
1406 FieldMetadata::StrMetadata::const_iterator i =
1408 FieldMetadata::StrMetadata::const_iterator end =
1410 for (; i != end; ++i) {
1420 FieldMetadata::IntMetadata::const_iterator i =
1422 FieldMetadata::IntMetadata::const_iterator end =
1424 for (; i != end; ++i) {
1434 FieldMetadata::FloatMetadata::const_iterator i =
1436 FieldMetadata::FloatMetadata::const_iterator end =
1438 for (; i != end; ++i) {
1448 FieldMetadata::VecIntMetadata::const_iterator i =
1450 FieldMetadata::VecIntMetadata::const_iterator end =
1452 for (; i != end; ++i) {
1462 FieldMetadata::VecFloatMetadata::const_iterator i =
1464 FieldMetadata::VecFloatMetadata::const_iterator end =
1466 for (; i != end; ++i) {
1489 if (metadataGroup.
id() < 0) {
1506 using namespace std;
1517 "Error creating field3d_group_membership group.");
1521 if (!
writeAttribute(group,
"is_field3d_group_membership",
"1")) {
1523 "Failed to write field3d_group_membership attribute.");
1527 std::map<std::string, std::string>::const_iterator iter =
1529 std::map<std::string, std::string>::const_iterator iEnd =
1532 for (; iter != iEnd; ++iter) {
1535 "Failed to write groupMembership string: "+ iter->first);
1567 for (PartitionList::const_iterator i =
m_partitions.begin();
1569 cout <<
"Name: " << (**i).name << endl;
1571 cout <<
" Mapping: " << (**i).mapping->className() << endl;
1573 cout <<
" Mapping: NULL" << endl;
1574 cout <<
" Scalar layers: " << endl;
1575 vector<string> sNames;
1576 (**i).getScalarLayerNames(sNames);
1577 for_each(sNames.begin(), sNames.end(), print<string>(4));
1578 cout <<
" Vector layers: " << endl;
1579 vector<string> vNames;
1580 (**i).getVectorLayerNames(vNames);
1581 for_each(vNames.begin(), vNames.end(), print<string>(4));
1597 field->className());
1603 field->className())) {
1608 return io->write(layerGroup, field);
1617 std::string className;
1619 if (!
readAttribute(mappingGroup, k_mappingTypeAttrName, className)) {
1649 std::string className = mapping->className();
1651 if (!
writeAttribute(mappingGroup, k_mappingTypeAttrName, className)) {
1664 return io->write(mappingGroup, mapping);
Contains the ClassFactory class for registering Field3D classes.
FieldMapping::Ptr readFieldMapping(hid_t mappingGroup)
This function creates a FieldMappingIO instance based on className read from mappingGroup location wh...
bool writeFieldMapping(hid_t mappingGroup, FieldMapping::Ptr mapping)
This function creates a FieldMappingIO instance based on mapping->className() which then writes Field...
bool writeField(hid_t layerGroup, FieldBase::Ptr field)
This function creates a FieldIO instance based on field->className() which then writes the field data...
Contains the Field3DFileHDF5 classes.
FIELD3D_API bool writeFieldMapping(hid_t mappingGroup, FieldMapping::Ptr mapping)
This function creates a FieldMappingIO instance based on mapping->className() which then writes Field...
FIELD3D_API FieldMapping::Ptr readFieldMapping(hid_t mappingGroup)
This function creates a FieldMappingIO instance based on className read from mappingGroup location wh...
bool fileExists(const std::string &filename)
checks to see if a file/directory exists or not
Contains Field, WritableField and ResizableField classes.
FIELD3D_NAMESPACE_OPEN FIELD3D_API boost::recursive_mutex g_hdf5Mutex
boost::recursive_mutex::scoped_lock GlobalLock
FieldIO::Ptr createFieldIO(const std::string &className) const
Instances an IO object by name.
static ClassFactory & singleton()
}
FieldMappingIO::Ptr createFieldMappingIO(const std::string &className) const
Instances an IO object by name.
std::vector< std::string > m_partitionNames
This stores partition names.
PartitionList m_partitions
Vector of partitions.
std::string makeIntPartitionName(const std::string &partitionsName, int i) const
Makes an internal partition name given the external partition name. Effectively just tacks on ....
void getVectorLayerNames(std::vector< std::string > &names, const std::string &partitionName) const
Gets the names of all the vector layers in a given partition.
void printHierarchy() const
void getPartitionNames(std::vector< std::string > &names) const
Gets the names of all the partitions in the file.
bool close()
Closes the file. No need to call this unless you specifically want to close the file early....
void getIntVectorLayerNames(std::vector< std::string > &names, const std::string &intPartitionName) const
Gets the names of all the vector layers in a given partition, but assumes that partition name is the ...
GroupMembershipMap m_groupMembership
Keeps track of group membership for each layer of partition name. The key is the "group" and the valu...
hid_t m_file
The hdf5 id of the current file. Will be -1 if no file is open.
void getIntScalarLayerNames(std::vector< std::string > &names, const std::string &intPartitionName) const
Gets the names of all the scalar layers in a given partition, but assumes that partition name is the ...
void closeInternal()
Closes the file if open.
std::string intPartitionName(const std::string &partitionName, const std::string &layerName, FieldRes::Ptr field)
Returns a unique partition name given the requested name. This ensures that partitions with matching ...
std::map< std::string, std::string > GroupMembershipMap
virtual ~Field3DFileHDF5Base()=0
Pure virtual destructor to ensure we never instantiate this class.
FieldMetadata & metadata()
accessor to the m_metadata class
void addGroupMembership(const GroupMembershipMap &groupMembers)
Add to the group membership.
void getScalarLayerNames(std::vector< std::string > &names, const std::string &partitionName) const
Gets the names of all the scalar layers in a given partition.
std::vector< LayerInfo > m_layerInfo
This stores layer info.
int numIntPartitions(const std::string &partitionName) const
Returns the number of internal partitions for a given partition name.
std::string removeUniqueId(const std::string &partitionName) const
Strips any unique identifiers from the partition name and returns the original name.
FileHDF5::Partition::Ptr partition(const std::string &partitionName)
Returns a pointer to the given partition.
PartitionCountMap m_partitionCount
Contains a counter for each partition name. This is used to keep multiple fields with the same name u...
void getIntPartitionNames(std::vector< std::string > &names) const
Gets the names of all the -internal- partitions in the file.
void clear()
Clear the data structures and close the file.
bool writeGlobalMetadata()
This routine is call if you want to write out global metadata to disk.
bool create(const std::string &filename, CreateMode cm=OverwriteMode)
Creates a .f3d file on disk.
bool writeMapping(hid_t partitionLocation, FieldMapping::Ptr mapping)
Writes the mapping to the given hdf5 node. Mappings are assumed to be light-weight enough to be store...
bool writeMetadata(hid_t metadataGroup, FieldBase::Ptr layer)
Writes metadata for this layer.
bool writeGroupMembership()
This routine is called just before closing to write out any group membership to disk.
virtual ~Field3DOutputFileHDF5()
std::string incrementPartitionName(std::string &pname)
increment the partition or make it zero if there's not an integer suffix
boost::intrusive_ptr< FieldBase > Ptr
boost::intrusive_ptr< FieldIO > Ptr
boost::intrusive_ptr< FieldMappingIO > Ptr
boost::intrusive_ptr< FieldMapping > Ptr
boost::intrusive_ptr< FieldRes > Ptr
std::string parent
The name of the parent partition. We need this in order to open its group.
std::string name
The name of the layer (always available)
void getVectorLayerNames(std::vector< std::string > &names) const
Gets all the vector layer names.
void getScalarLayerNames(std::vector< std::string > &names) const
Gets all the scalar layer names.
virtual std::string className() const
boost::intrusive_ptr< Partition > Ptr
const FileHDF5::Layer * vectorLayer(const std::string &name) const
Finds a vector layer.
void addScalarLayer(const FileHDF5::Layer &layer)
Adds a scalar layer.
void addVectorLayer(const FileHDF5::Layer &layer)
Adds a vector layer.
std::string name
Name of the partition.
VectorLayerList m_vectorLayers
The vector-valued layers belonging to this partition.
const FileHDF5::Layer * scalarLayer(const std::string &name) const
Finds a scalar layer.
ScalarLayerList m_scalarLayers
The scalar-valued layers belonging to this partition.
hid_t id() const
Query the hid_t value.
Scoped object - opens an attribute data space on creation and closes it on destruction.
Scoped object - opens an attribute data type on creation and closes it on destruction.
Scoped object - Opens attribute by index and closes it on destruction.
Scoped object - Opens attribute by name and closes it on destruction.
Scoped object - creates a group on creation and closes it on destruction.
Scoped object - opens a group on creation and closes it on destruction.
FIELD3D_API bool readAttribute(hid_t location, const std::string &attrName, std::string &value)
Reads a string attribute.
FIELD3D_API bool writeAttribute(hid_t location, const std::string &attrName, const std::string &value)
Writes a string attribute.
Namespace for Exception objects.
Namespace for file I/O specifics.
Contains utility functions and classes for Hdf5 files.
FIELD3D_API void print(Severity severity, const std::string &message)
Sends the string to the assigned output, prefixing the message with the severity.
#define FIELD3D_MAJOR_VER
#define FIELD3D_NAMESPACE_SOURCE_CLOSE
#define FIELD3D_MINOR_VER
#define FIELD3D_MICRO_VER