49 #include <H5Epublic.h> 51 #include <boost/tokenizer.hpp> 52 #include <boost/utility.hpp> 82 const std::string k_mappingStr(
"mapping");
83 const std::string k_partitionName(
"partition");
84 const std::string k_versionAttrName(
"version_number");
85 const std::string k_classNameAttrName(
"class_name");
86 const std::string k_mappingTypeAttrName(
"mapping_type");
91 int k_currentFileVersion[3] =
93 int k_minFileVersion[2] = { 0, 0 };
97 std::vector<std::string> makeUnique(std::vector<std::string> vec)
99 std::vector<string> ret;
100 std::sort(vec.begin(), vec.end());
101 std::vector<std::string>::iterator newEnd =
102 std::unique(vec.begin(), vec.end());
103 ret.resize(std::distance(vec.begin(), newEnd));
104 std::copy(vec.begin(), newEnd, ret.begin());
112 class print : std::unary_function<T, void>
118 void operator()(
const T& x)
const 120 for (
int i = 0; i < indent; i++)
122 std::cout << x << std::endl;
134 bool fileExists(
const std::string &filename)
137 return (stat(filename.c_str(), &statbuf) != -1);
145 void checkFile(
const std::string &filename)
147 if (!fileExists(filename))
149 throw NoSuchFileException(filename);
155 bool isSupportedFileVersion(
const int fileVersion[3],
156 const int minVersion[2])
158 stringstream currentVersionStr;
159 currentVersionStr << k_currentFileVersion[0] <<
"." 160 << k_currentFileVersion[1] <<
"." 161 << k_currentFileVersion[2];
162 stringstream fileVersionStr;
163 fileVersionStr << fileVersion[0] <<
"." 164 << fileVersion[1] <<
"." 166 stringstream minVersionStr;
167 minVersionStr << minVersion[0] <<
"." 170 if (fileVersion[0] > k_currentFileVersion[0] ||
171 (fileVersion[0] == k_currentFileVersion[0] &&
172 fileVersion[1] > k_currentFileVersion[1])) {
174 " is higher than the current version " +
175 currentVersionStr.str());
179 if (fileVersion[0] < minVersion[0] ||
180 (fileVersion[0] == minVersion[0] &&
181 fileVersion[1] < minVersion[1])) {
183 " is lower than the minimum supported version " +
184 minVersionStr.str());
192 static herr_t localPrintError( hid_t estack_id,
void *stream )
194 printf(
"H5E message -----------------------\n");
195 return H5Eprint2(estack_id, static_cast<FILE*>(stream));
206 std::string Partition::className()
const 208 return k_partitionName;
214 Partition::addScalarLayer(
const Layer &layer)
216 m_scalarLayers.push_back(layer);
222 Partition::addVectorLayer(
const Layer &layer)
224 m_vectorLayers.push_back(layer);
230 Partition::scalarLayer(
const std::string &name)
const 232 for (ScalarLayerList::const_iterator i = m_scalarLayers.begin();
233 i != m_scalarLayers.end(); ++i) {
243 Partition::vectorLayer(
const std::string &name)
const 245 for (VectorLayerList::const_iterator i = m_vectorLayers.begin();
246 i != m_vectorLayers.end(); ++i) {
256 Partition::getScalarLayerNames(std::vector<std::string> &names)
const 260 for (ScalarLayerList::const_iterator i = m_scalarLayers.begin();
261 i != m_scalarLayers.end(); ++i) {
262 names.push_back(i->name);
269 Partition::getVectorLayerNames(std::vector<std::string> &names)
const 273 for (VectorLayerList::const_iterator i = m_vectorLayers.begin();
274 i != m_vectorLayers.end(); ++i) {
275 names.push_back(i->name);
284 : m_file(-1), m_metadata(this)
289 if (getenv(
"DEBUG_HDF")) {
290 cerr <<
"Field3DFile -- HDF5 messages are on" << endl;
291 H5Eset_auto(H5E_DEFAULT, localPrintError, NULL);
293 H5Eset_auto(H5E_DEFAULT, NULL, NULL);
308 const std::string &layerName,
312 for (PartitionList::const_iterator i =
m_partitions.begin();
315 if ((**i).mapping->isIdentical(field->mapping())) {
340 if ((**i).name == partitionName)
352 for (PartitionList::const_iterator i =
m_partitions.begin();
354 if ((**i).name == partitionName)
366 size_t pos = partitionName.rfind(
".");
367 if (pos == partitionName.npos) {
368 return partitionName;
370 return partitionName.substr(0, pos);
381 vector<string> tempNames;
383 for (PartitionList::const_iterator i =
m_partitions.begin();
388 names = makeUnique(tempNames);
395 const string &partitionName)
const 403 part->getScalarLayerNames(names);
406 names = makeUnique(names);
413 const string &partitionName)
const 421 part->getVectorLayerNames(names);
424 names = makeUnique(names);
434 for (PartitionList::const_iterator i =
m_partitions.begin();
436 names.push_back((**i).name);
451 Msg::print(
"getIntScalarLayerNames no partition: " + intPartitionName);
455 part->getScalarLayerNames(names);
469 Msg::print(
"getIntVectorLayerNames no partition: " + intPartitionName);
473 part->getVectorLayerNames(names);
499 if (H5Fclose(
m_file) < 0) {
514 for (PartitionList::const_iterator i =
m_partitions.begin();
516 string name = (**i).name;
517 size_t pos = name.rfind(
".");
518 if (pos != name.npos) {
519 if (name.substr(0, pos) == partitionName) {
534 return partitionName +
"." + boost::lexical_cast<std::string>(i);
542 GroupMembershipMap::const_iterator i= groupMembers.begin();
543 GroupMembershipMap::const_iterator end= groupMembers.end();
545 for (; i != end; ++i) {
546 GroupMembershipMap::iterator foundGroupIter =
581 m_filename = filename;
592 m_file = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
595 throw NoSuchFileException(filename);
602 if (!isSupportedFileVersion(fileVersion, k_minFileVersion)) {
603 stringstream versionStr;
604 versionStr << fileVersion[0] <<
"." 605 << fileVersion[1] <<
"." 607 throw UnsupportedVersionException(versionStr.str());
611 catch (MissingAttributeException &e) {
616 if (H5Lexists(
m_file,
"field3d_global_metadata", H5P_DEFAULT)) {
619 if (metadataGroup.
id() > 0) {
620 readMetadata(metadataGroup.
id());
626 "Unknown error when reading file metadata ");
631 if (!readPartitionAndLayerInfo()) {
635 catch (MissingGroupException &e) {
637 throw BadFileHierarchyException(filename);
639 catch (ReadMappingException &e) {
642 throw BadFileHierarchyException(filename);
647 throw BadFileHierarchyException(filename);
651 "Unknown error when reading file hierarchy. ");
652 throw BadFileHierarchyException(filename);
656 catch (NoSuchFileException &e) {
658 +
string(e.what()) );
661 catch (MissingAttributeException &e) {
663 "In file: " + filename +
" - " 664 +
string(e.what()) );
667 catch (UnsupportedVersionException &e) {
669 "In file: " + filename +
" - File version can not be read: " 673 catch (BadFileHierarchyException &e) {
675 "In file: " + filename +
" - Bad file hierarchy. ");
680 "In file: " + filename +
" Unknown exception ");
699 status = H5Literate(
m_file, H5_INDEX_NAME, H5_ITER_NATIVE, NULL,
719 string mappingPath =
"/" + (**i).name +
"/" + k_mappingStr;
723 if (mappingGroup.
id() < 0)
724 throw MissingGroupException((**i).name +
"/" + k_mappingStr);
732 throw ReadMappingException((**i).name);
736 (**i).mapping = mapping;
742 for (PartitionList::const_iterator i =
m_partitions.begin();
755 status = H5Literate(partitionGroup.
id(), H5_INDEX_NAME, H5_ITER_NATIVE,
760 for (std::vector<LayerInfo>::iterator i =
m_layerInfo.begin();
763 std::string parent = i->parentName;
768 layer.
name = i->name;
769 layer.
parent = i->parentName;
770 if (i->components == 1) {
771 part->addScalarLayer(layer);
772 }
else if (i->components == 3) {
773 part->addVectorLayer(layer);
785 const std::string itemName)
799 const std::string &partitionName,
800 const std::string &layerName)
803 if (!
readAttribute(layerGroup,
string(
"components"), 1, components)) {
805 + partitionName +
"/" + layerName);
809 LayerInfo linfo(partitionName,layerName,components);
824 hsize_t num_attrs = H5Aget_num_attrs(metadata_id);
827 for (hsize_t idx=0; idx < num_attrs ; ++idx) {
829 size_t len = H5Aget_name(attrIdx.
id(), 0, NULL);
831 char *name =
new char[len+1];
832 if (H5Aget_name(attrIdx.
id(), len+1, name) > 0) {
836 H5T_class_t typeClass = H5Tget_class(attrType);
838 if (typeClass == H5T_STRING) {
842 "Failed to read metadata " +
string(name));
848 field->metadata().setStrMetadata(name, value);
853 if (H5Sget_simple_extent_ndims(attrSpace) != 1) {
863 H5Sget_simple_extent_dims(attrSpace, dims, NULL);
865 if (typeClass == H5T_INTEGER) {
871 field->metadata().setIntMetadata(name, value);
873 else if (dims[0] == 3){
878 field->metadata().setVecIntMetadata(name, value);
882 "Attribute of size " +
883 boost::lexical_cast<std::string>(dims[0])
884 +
" is not valid for metadata");
887 else if (typeClass == H5T_FLOAT) {
894 field->metadata().setFloatMetadata(name, value);
896 else if (dims[0] == 3){
901 field->metadata().setVecFloatMetadata(name, value);
905 boost::lexical_cast<std::string>(dims[0]) +
906 " is not valid for metadata");
911 +
"' has unsupported data type for metadata");
933 hsize_t num_attrs = H5Aget_num_attrs(metadata_id);
936 for (hsize_t idx=0; idx < num_attrs ; ++idx) {
938 size_t len = H5Aget_name(attrIdx.
id(), 0, NULL);
940 char *name =
new char[len+1];
941 if (H5Aget_name(attrIdx.
id(), len+1, name) > 0) {
945 H5T_class_t typeClass = H5Tget_class(attrType);
947 if (typeClass == H5T_STRING) {
951 "Failed to read metadata " +
string(name));
962 if (H5Sget_simple_extent_ndims(attrSpace) != 1) {
972 H5Sget_simple_extent_dims(attrSpace, dims, NULL);
974 if (typeClass == H5T_INTEGER) {
982 else if (dims[0] == 3){
991 "Attribute of size " +
992 boost::lexical_cast<std::string>(dims[0])
993 +
" is not valid for metadata");
996 else if (typeClass == H5T_FLOAT) {
1005 else if (dims[0] == 3){
1014 boost::lexical_cast<std::string>(dims[0]) +
1015 " is not valid for metadata");
1020 +
"' has unsupported data type for metadata");
1041 if (!H5Lexists(
m_file,
"field3d_group_membership", H5P_DEFAULT)) {
1046 if (memberGroup < 0) {
1050 typedef boost::tokenizer<boost::char_separator<char> > Tok;
1052 hsize_t num_attrs = H5Aget_num_attrs(memberGroup);
1053 if (num_attrs > 0) {
1055 for (hsize_t idx=0; idx < num_attrs ; ++idx) {
1057 size_t len = H5Aget_name(attrIdx.
id(), 0, NULL);
1059 char *name =
new char[len+1];
1060 if (H5Aget_name(attrIdx.
id(), len+1, name) > 0) {
1062 if (
string(name) ==
"is_field3d_group_membership")
1068 H5T_class_t typeClass = H5Tget_class(attrType);
1070 if (typeClass == H5T_STRING) {
1074 "Failed to read group membership data " 1080 boost::char_separator<char> sep(
" :");
1081 Tok tok(value, sep);
1083 for(Tok::iterator beg=tok.begin(); beg!=tok.end();){
1085 string fieldgroup = *beg; ++beg;
1087 new_value += fieldgroup +
" ";
1091 gpMembershipMap[name] = new_value;
1111 const H5L_info_t *linfo,
void *opdata)
1116 status = H5Oget_info_by_name(loc_id, itemName, &infobuf, H5P_DEFAULT);
1122 if (infobuf.type == H5O_TYPE_GROUP) {
1130 if (
string(itemName) !=
"field3d_group_membership" &&
1131 string(itemName) !=
"field3d_global_metadata")
1149 const H5L_info_t *linfo,
void *opdata)
1154 status = H5Oget_info_by_name (loc_id, itemName, &infobuf, H5P_DEFAULT);
1156 if (infobuf.type == H5O_TYPE_GROUP) {
1176 if (classType ==
string(
"field3d_layer"))
1181 catch (MissingAttributeException &e) {
1219 bool success =
true;
1223 hid_t faid = H5Pcreate(H5P_FILE_ACCESS);
1224 H5Pset_libver_bounds(faid, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST);
1229 m_file = H5Fcreate(filename.c_str(),
1230 H5F_ACC_TRUNC, H5P_DEFAULT, faid);
1232 case FailOnExisting:
1233 m_file = H5Fcreate(filename.c_str(),
1234 H5F_ACC_EXCL, H5P_DEFAULT, faid);
1240 throw ErrorCreatingFileException(filename);
1244 k_currentFileVersion[0])) {
1251 catch (ErrorCreatingFileException &e) {
1255 catch (WriteAttributeException &e) {
1257 " - Couldn't add attribute " +
string(e.what()) );
1262 "Unknown error when creating file: " + filename );
1277 if (mappingGroup.
id() < 0)
1278 throw CreateGroupException(k_mappingStr);
1281 throw WriteMappingException(k_mappingStr);
1283 catch (CreateGroupException &e) {
1285 throw WriteMappingException(k_mappingStr);
1301 for (; i != end; ++i) {
1315 for (; i != end; ++i) {
1329 for (; i != end; ++i) {
1343 for (; i != end; ++i) {
1357 for (; i != end; ++i) {
1382 for (; i != end; ++i) {
1396 for (; i != end; ++i) {
1410 for (; i != end; ++i) {
1424 for (; i != end; ++i) {
1438 for (; i != end; ++i) {
1460 if (metadataGroup.
id() < 0) {
1464 if (!writeMetadata(metadataGroup.
id())) {
1477 using namespace std;
1486 "Error creating field3d_group_membership group.");
1490 if (!
writeAttribute(group,
"is_field3d_group_membership",
"1")) {
1492 "Failed to write field3d_group_membership attribute.");
1496 std::map<std::string, std::string>::const_iterator iter =
1498 std::map<std::string, std::string>::const_iterator iEnd =
1501 for (; iter != iEnd; ++iter) {
1504 "Failed to write groupMembership string: "+ iter->first);
1536 for (PartitionList::const_iterator i =
m_partitions.begin();
1538 cout <<
"Name: " << (**i).name << endl;
1540 cout <<
" Mapping: " << (**i).mapping->className() << endl;
1542 cout <<
" Mapping: NULL" << endl;
1543 cout <<
" Scalar layers: " << endl;
1544 vector<string> sNames;
1545 (**i).getScalarLayerNames(sNames);
1546 for_each(sNames.begin(), sNames.end(), print<string>(4));
1547 cout <<
" Vector layers: " << endl;
1548 vector<string> vNames;
1549 (**i).getVectorLayerNames(vNames);
1550 for_each(vNames.begin(), vNames.end(), print<string>(4));
1566 field->className());
1572 field->className())) {
1577 return io->write(layerGroup, field);
1586 std::string className;
1588 if (!
readAttribute(mappingGroup, k_mappingTypeAttrName, className)) {
1618 std::string className = mapping->className();
1620 if (!
writeAttribute(mappingGroup, k_mappingTypeAttrName, className)) {
1633 return io->write(mappingGroup, mapping);
Namespace for file I/O specifics.
Scoped object - opens an attribute data type on creation and closes it on destruction.
FieldMappingIO::Ptr createFieldMappingIO(const std::string &className) const
Instances an IO object by name.
bool writeGroupMembership()
This routine is called just before closing to write out any group membership to disk.
boost::intrusive_ptr< FieldMappingIO > Ptr
bool writeGlobalMetadata()
This routine is call if you want to write out global metadata to disk.
int numIntPartitions(const std::string &partitionName) const
Returns the number of internal partitions for a given partition name.
Contains utility functions and classes for Hdf5 files.
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 getScalarLayerNames(std::vector< std::string > &names, const std::string &partitionName) const
Gets the names of all the scalar layers in a given partition.
Contains the Field3DFile classesOSS sanitized.
boost::intrusive_ptr< Partition > Ptr
#define FIELD3D_NAMESPACE_SOURCE_CLOSE
Namespace for Exception objects.
bool writeMetadata(hid_t metadataGroup, FieldBase::Ptr layer)
Writes metadata for this layer.
std::map< std::string, std::string > GroupMembershipMap
void clear()
Clear the data structures and close the file.
boost::intrusive_ptr< FieldBase > Ptr
static ClassFactory & singleton()
}
bool writeField(hid_t layerGroup, FieldBase::Ptr field)
This function creates a FieldIO instance based on field->className() which then writes the field data...
virtual const char * what() const
void print(Severity severity, const std::string &message)
Sends the string to the assigned output, prefixing the message with the severity. ...
boost::intrusive_ptr< FieldRes > Ptr
bool create(const std::string &filename, CreateMode cm=OverwriteMode)
Creates a .f3d file on disk.
File::Partition::Ptr partition(const std::string &partitionName)
Returns a pointer to the given partition.
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 ...
Scoped object - creates a group on creation and closes it on destruction.
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 ...
PartitionCountMap m_partitionCount
Contains a counter for each partition name. This is used to keep multiple fields with the same name u...
Scoped object - Opens attribute by name and closes it on destruction.
std::vector< std::string > m_partitionNames
This stores partition names.
boost::intrusive_ptr< FieldMapping > Ptr
void printHierarchy() const
Scoped object - Opens attribute by index and closes it on destruction.
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 getPartitionNames(std::vector< std::string > &names) const
Gets the names of all the partitions in the file.
FieldMapping::Ptr readFieldMapping(hid_t mappingGroup)
This function creates a FieldMappingIO instance based on className read from mappingGroup location wh...
std::string name
The name of the layer (always available)
void addGroupMembership(const GroupMembershipMap &groupMembers)
Add to the group membership.
FieldIO::Ptr createFieldIO(const std::string &className) const
Instances an IO object by name.
bool readAttribute(hid_t location, const std::string &attrName, std::string &value)
Reads a string attribute.
#define FIELD3D_MINOR_VER
PartitionList m_partitions
Vector of partitions.
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...
void closeInternal()
Closes the file if open.
bool writeAttribute(hid_t location, const std::string &attrName, const std::string &value)
Writes a string attribute.
virtual ~Field3DFileBase()=0
Pure virtual destructor to ensure we never instantiate this class.
virtual ~Field3DOutputFile()
Scoped object - opens an attribute data space on creation and closes it on destruction.
bool close()
Closes the file. No need to call this unless you specifically want to close the file early...
void getIntPartitionNames(std::vector< std::string > &names) const
Gets the names of all the -internal- partitions in the file.
std::string removeUniqueId(const std::string &partitionName) const
Strips any unique identifiers from the partition name and returns the original name.
std::vector< LayerInfo > m_layerInfo
This stores layer info.
bool writeFieldMapping(hid_t mappingGroup, FieldMapping::Ptr mapping)
This function creates a FieldMappingIO instance based on mapping->className() which then writes Field...
FieldMetadata< Field3DFileBase > & metadata()
accessor to the m_metadata class
Contains Field, WritableField and ResizableField classes.
Contains the ClassFactory class for registering Field3D classes.
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 ...
boost::intrusive_ptr< FieldIO > Ptr
hid_t id() const
Query the hid_t value.
#define FIELD3D_MICRO_VER
hid_t m_file
The hdf5 id of the current file. Will be -1 if no file is open.
GroupMembershipMap m_groupMembership
Keeps track of group membership for each layer of partition name. The key is the "group" and the valu...
#define FIELD3D_MAJOR_VER
Scoped object - opens a group on creation and closes it on destruction.
std::string incrementPartitionName(std::string &pname)
increment the partition or make it zero if there's not an integer suffix
std::string parent
The name of the parent partition. We need this in order to open its group.