/*-------------------------------------------------------------*/ static void validateFloat3Attribute(pNXVcontext self, hid_t dpField, char *name) { hid_t attID, attType, attSpace; H5T_class_t h5class; hsize_t dims[2], maxDims[2]; char fname[512]; memset(fname,0,sizeof(fname)); H5Iget_name(dpField,fname,sizeof(fname)); if(!H5LTfind_attribute(dpField,name)){ NXVsetLog(self,"sev","error"); NXVprintLog(self,"message", "Missing attribute %s on %s", name, fname); NXVlog(self); self->errCount++; } else { attID = H5Aopen(dpField,name,H5P_DEFAULT); assert(attID >= 0); attType = H5Aget_type(attID); assert(attType >= 0); h5class = H5Tget_class(attType); if(h5class != H5T_FLOAT){ NXVsetLog(self,"sev","error"); NXVprintLog(self,"message", "%s attribute on %s is of wrong type, expected float", name, fname); NXVlog(self); self->errCount++; } else { attSpace = H5Aget_space(attID); if(H5Sget_simple_extent_ndims(attSpace) != 1){ NXVsetLog(self,"sev","error"); NXVprintLog(self,"message", "%s attribute on %s is of wrong rank, expected 1", name, fname); NXVlog(self); self->errCount++; } else { H5Sget_simple_extent_dims(attSpace,dims,maxDims); if(dims[0] != 3){ NXVsetLog(self,"sev","error"); NXVprintLog(self,"message", "%s attribute on %s is of wrong size, expected 3", name, fname); NXVlog(self); self->errCount++; } } H5Sclose(attSpace); } H5Tclose(attType); H5Aclose(attID); } }
/*-------------------------------------------------------------- This validates the lesser depends_on chain fields like vector, offset and transformation_type ----------------------------------------------------------------*/ static void validateDependsOnAttributes(pNXVcontext self,hid_t dpField) { char fname[512], transData[512]; hid_t attID, attType, attSpace; H5T_class_t h5class; memset(fname,0,sizeof(fname)); memset(transData,0,sizeof(transData)); H5Iget_name(dpField,fname,sizeof(fname)); /* deal with transformation_type */ if(!H5LTfind_attribute(dpField,"transformation_type")){ NXVsetLog(self,"sev","error"); NXVprintLog(self,"message", "Missing attribute transformation_type on %s", fname); NXVlog(self); self->errCount++; } else { attID = H5Aopen(dpField,"transformation_type",H5P_DEFAULT); assert(attID >= 0); attType = H5Aget_type(attID); assert(attType >= 0); h5class = H5Tget_class(attType); if(h5class != H5T_STRING){ NXVsetLog(self,"sev","error"); NXVprintLog(self,"message", "transformation_type on %s is of wrong type, expected string", fname); NXVlog(self); self->errCount++; } else { H5NXget_attribute_string(self->fileID, fname, "transformation_type",transData); if(strcmp(transData,"translation") != 0 && strcmp(transData,"rotation") != 0){ NXVsetLog(self,"sev","error"); NXVprintLog(self,"message", "transformation_type on %s contains bad data: %s", fname, "expected rotation or translation"); NXVlog(self); self->errCount++; } } H5Tclose(attType); H5Aclose(attID); } validateFloat3Attribute(self,dpField,"offset"); validateFloat3Attribute(self,dpField,"vector"); }
/// Return the attribute name of obj, and "" if the attribute does not exist. void h5_read_attribute(hid_t id, std::string const &name, std::string & s) { s = ""; // if the attribute is not present, return 0 if (H5LTfind_attribute(id, name.c_str()) == 0) return; // not present attribute attr = H5Aopen(id, name.c_str(), H5P_DEFAULT); if (!attr.is_valid()) TRIQS_RUNTIME_ERROR << "Cannot open the attribute " << name; dataspace space = H5Aget_space(attr); int rank = H5Sget_simple_extent_ndims(space); if (rank != 0) TRIQS_RUNTIME_ERROR << "Reading a string attribute and got rank !=0"; datatype strdatatype = H5Aget_type(attr); std::vector<char> buf(H5Aget_storage_size(attr) + 1, 0x00); auto err = H5Aread(attr, strdatatype, (void *)(&buf[0])); if (err < 0) TRIQS_RUNTIME_ERROR << "Cannot read the attribute " << name; s.append(&(buf.front())); }
/// Return the attribute name of obj, and "" if the attribute does not exist. inline std::string read_string_attribute (H5::H5Object const * obj, std::string name ) { std::string value =""; H5::Attribute attr; if (H5LTfind_attribute(obj -> getId(), name.c_str() )==0) return value;// not present // can not find how to get the size with hl. Using full interface //herr_t err2 = H5LTget_attribute_string(gr.getId(), x.c_str(), name.c_str() , &(buf.front()) ) ; //value.append( &(buf.front()) ); try { attr= obj->openAttribute(name.c_str());} catch (H5::AttributeIException) { return value;} try { H5::DataSpace dataspace = attr.getSpace(); int rank = dataspace.getSimpleExtentNdims(); if (rank != 0) TRIQS_RUNTIME_ERROR << "Reading a string attribute and got rank !=0"; size_t size = attr.getStorageSize(); H5::StrType strdatatype(H5::PredType::C_S1, size+1); std::vector<char> buf(size+1, 0x00); attr.read(strdatatype, (void *)(&buf[0])); value.append( &(buf.front()) ); } TRIQS_ARRAYS_H5_CATCH_EXCEPTION; return value; }
/*--------------------------------------------------------------*/ static herr_t SecondPassIterator(hid_t g_id, const char *name, const H5L_info_t *info, void *op_data) { SecondPassData *spd = (SecondPassData *)op_data; H5O_info_t obj_info; hid_t attID, groupID, dataID; char nxClass[512], fname[512]; /* have we seen that yet? */ if(hash_lookup((char *)name,spd->namesSeen) != NULL){ return 0; } /* Nope, we will have to warn... */ H5Oget_info_by_name(g_id, name, &obj_info,H5P_DEFAULT); if(obj_info.type == H5O_TYPE_GROUP){ groupID = H5Gopen(g_id,name,H5P_DEFAULT); H5Iget_name(groupID, fname,sizeof(fname)); NXVsetLog(spd->self,"dataPath",fname); if(H5LTfind_attribute(groupID,"NX_class") == 1){ memset(nxClass,0,sizeof(nxClass)); H5NXget_attribute_string(g_id,name, "NX_class", nxClass); if(hash_lookup(nxClass,spd->baseNames) == NULL){ NXVsetLog(spd->self,"sev","warnundef"); NXVprintLog(spd->self,"message","Unknown group %s of class %s found", name, nxClass); NXVlog(spd->self); spd->self->warnCount++; } else { NXVsetLog(spd->self,"sev","warnbase"); NXVprintLog(spd->self,"message", "Additional base class group %s of type %s found", name, nxClass); NXVlog(spd->self); spd->self->warnCount++; } } else { NXVsetLog(spd->self,"sev","warnundef"); NXVprintLog(spd->self,"message", "Additional non NeXus group %s found", name); NXVlog(spd->self); spd->self->warnCount++; } H5Gclose(groupID); } else if (obj_info.type == H5O_TYPE_DATASET) { dataID = H5Dopen(g_id,name,H5P_DEFAULT); H5Iget_name(dataID, fname,sizeof(fname)); H5Dclose(dataID); NXVsetLog(spd->self,"dataPath",fname); if(hash_lookup((char *)name,spd->baseNames) == NULL){ NXVsetLog(spd->self,"sev","warnundef"); NXVprintLog(spd->self,"message","Unknown dataset %s found", name); NXVlog(spd->self); spd->self->warnCount++; } else { NXVsetLog(spd->self,"sev","warnbase"); NXVprintLog(spd->self,"message","Additional base class dataset %s found", name); NXVlog(spd->self); spd->self->warnCount++; } } return 0; }
/*--------------------------------------------------------------*/ static void validateDependsOnField(pNXVcontext self, hid_t groupID,hid_t dpFieldID) { char fname[512], transData[512]; hid_t attID, attType, attSpace, dpField; H5T_class_t h5class; memset(fname,0,sizeof(fname)); memset(transData,0,sizeof(transData)); H5Iget_name(dpFieldID,fname,sizeof(fname)); NXVsetLog(self,"dataPath", fname); NXVsetLog(self,"sev","debug"); NXVprintLog(self,"message","Validating depends_on element %s", fname); NXVlog(self); /* validate the simple ones */ validateDependsOnAttributes(self,dpFieldID); /* follow the depends_on chain */ if(!H5LTfind_attribute(dpFieldID,"depends_on")){ NXVsetLog(self,"sev","error"); NXVprintLog(self,"message", "Missing attribute depends_on on %s", fname); NXVlog(self); self->errCount++; } else { attID = H5Aopen(dpFieldID,"depends_on",H5P_DEFAULT); assert(attID >= 0); attType = H5Aget_type(attID); assert(attType >= 0); h5class = H5Tget_class(attType); if(h5class != H5T_STRING){ NXVsetLog(self,"sev","error"); NXVprintLog(self,"message", "depends_onattribute on %s is of wrong type, expected string", fname); NXVlog(self); self->errCount++; } else { H5NXget_attribute_string(self->fileID, fname, "depends_on",transData); if(strcmp(transData,".") == 0){ H5Dclose(dpFieldID); return; } else { dpField = findDependentField(self,dpFieldID,transData); if(dpField < 0){ NXVsetLog(self,"sev","error"); NXVprintLog(self,"message","Dependency chain broken at %s, %s %s", fname, transData, "pointing nowhere (nirvana?)"); NXVlog(self); self->errCount++; } else { validateDependsOnField(self,groupID,dpField); H5Dclose(dpField); } } } } }
static void validateGroupAttributes(pNXVcontext self, hid_t groupID, xmlNodePtr groupNode) { xmlNodePtr cur; xmlChar *type, *name; herr_t attID; char data[512], gname[512]; memset(data,0,sizeof(data)); memset(gname,0,sizeof(gname)); H5Iget_name(groupID,gname,sizeof(gname)); type = xmlGetProp(groupNode,(xmlChar *)"type"); attID = H5NXget_attribute_string(groupID,gname,"NX_class",data); if(attID < 0){ NXVsetLog(self,"sev","error"); NXVsetLog(self,"message","Required group attribute NX_class missing"); NXVlog(self); self->errCount++; } else { if(strcmp(data,(char *)type) != 0){ /* accept NXsubentry if NXentry is asked for */ if(!(strcmp((char *)type,"NXentry") == 0 && strcmp(data,"NXsubentry") == 0)){ NXVsetLog(self,"sev","error"); NXVprintLog(self,"message","Wrong group type, expected %s, got %s", (char *)type, data); NXVlog(self); self->errCount++; } } } xmlFree(type); /* search attribute child nodes */ cur = groupNode->xmlChildrenNode; while(cur != NULL){ if(xmlStrcmp(cur->name, (xmlChar *)"attribute") == 0){ name = xmlGetProp(cur,(xmlChar *)"name"); if(!H5LTfind_attribute(groupID,(char *)name)){ NXVsetLog(self,"sev","error"); NXVprintLog(self,"message","Required group attribute %s missing", name); NXVlog(self); self->errCount++; } else { /* TODO validate attribute data. As we do not use group attributes heavily, deferred for now */ } xmlFree(name); } cur = cur->next; } }
void rdiff(const char *name, hid_t f1, hid_t f2) { hid_t g1 = H5Gopen(f1, name, H5P_DEFAULT); hid_t g2 = H5Gopen(f2, name, H5P_DEFAULT); if (g1 >= 0 && g2 >= 0) { int n1 = H5Aget_num_attrs(g1); for (int i = 0; i < n1; i++) { char aname[MAXNAME]; hid_t a1 = H5Aopen_idx(g1, i); assert(H5Aget_name(a1, MAXNAME, aname) < MAXNAME); H5Aclose(a1); if (!H5LTfind_attribute(g2, aname)) { printf("Only in %s[%s%s]\n", file1, name, aname); continue; } int d1, d2; H5LTget_attribute_ndims(f1, name, aname, &d1); H5LTget_attribute_ndims(f2, name, aname, &d2); assert(d1 <= 1 && d2 <= 1); hsize_t dims1, dims2; H5T_class_t t1, t2; size_t ts1, ts2; H5LTget_attribute_info(f1, name, aname, &dims1, &t1, &ts1); H5LTget_attribute_info(f2, name, aname, &dims2, &t2, &ts2); assert(t1 == t2); assert(t1 == H5T_INTEGER || t1 == H5T_FLOAT || t1 == H5T_STRING); if (t1 == H5T_INTEGER) { assert(d1==0 || (dims1 == 1 && dims2 == 1)); assert(ts1 == 4 && ts2 == 4); int v1, v2; H5LTget_attribute_int(f1, name, aname, &v1); H5LTget_attribute_int(f2, name, aname, &v2); if (v1 != v2) { printf("%s[%s%s]=%d %s[%s%s]=%d\n", file1, name, aname, v1, file2, name, aname, v2); } } if (t1 == H5T_FLOAT) { assert(d1==0 || (dims1 == 1 && dims2 == 1)); assert(ts1 == 4 && ts2 == 4); float v1, v2; H5LTget_attribute_float(f1, name, aname, &v1); H5LTget_attribute_float(f2, name, aname, &v2); if (v1 != v2) { printf("%s[%s%s]=%g %s[%s%s]=%g\n", file1, name, aname, v1, file2, name, aname, v2); } } if (t1 == H5T_STRING) { assert(ts1 < 256 && ts2 < 256); char buf1[256]; char buf2[256]; H5LTget_attribute_string(f1, name, aname, buf1); H5LTget_attribute_string(f2, name, aname, buf2); if (strcmp(buf1, buf2)) { printf("%s[%s%s]=%s %s[%s%s]=%s\n", file1, name, aname, buf1, file2, name, aname, buf2); } } } int n2 = H5Aget_num_attrs(g2); for (int i = 0; i < n2; i++) { char aname[MAXNAME]; hid_t a2 = H5Aopen_idx(g2, i); assert(H5Aget_name(a2, MAXNAME, aname) < MAXNAME); H5Aclose(a2); if (!H5LTfind_attribute(g1, aname)) { printf("Only in %s[%s%s]\n", file2, name, aname); continue; } } hsize_t nobj; H5Gget_num_objs(g1, &nobj); for (int i = 0; i < nobj; i++) { char oname[MAXNAME]; assert(H5Gget_objname_by_idx(g1, i, oname, MAXNAME) < MAXNAME); int otype = H5Gget_objtype_by_idx(g1, i); assert(otype == H5G_DATASET); if (!H5LTfind_dataset(g2, oname)) { printf("Only in %s[%s%s]\n", file1, name, oname); continue; } hsize_t dims1[2], dims2[2]; H5T_class_t t1, t2; size_t ts1, ts2; H5LTget_dataset_info(g1, oname, dims1, &t1, &ts1); H5LTget_dataset_info(g2, oname, dims2, &t2, &ts2); if (dims1[0] != dims2[0] || dims1[1] != dims2[1]) { printf("%s[%s%s](%d,%d) != %s[%s%s](%d,%d)\n", file1, name, oname, dims1[1], dims1[0], file2, name, oname, dims2[1], dims2[0]); continue; } float *data1 = malloc(dims1[0]*dims1[1]*sizeof(float)); float *data2 = malloc(dims1[0]*dims1[1]*sizeof(float)); H5LTread_dataset_float(g1, oname, data1); H5LTread_dataset_float(g2, oname, data2); float maxdiff = 0; for (int i = dims1[0]*dims1[1]-1; i >= 0; i--) { float d = data1[i] - data2[i]; if (d < 0) d = -d; if (d > maxdiff) maxdiff = d; } printf("max |%s[%s%s] - %s[%s%s]| = %g\n", file1, name, oname, file2, name, oname, maxdiff); free(data1); free(data2); } H5Gget_num_objs(g2, &nobj); for (int i = 0; i < nobj; i++) { char oname[MAXNAME]; assert(H5Gget_objname_by_idx(g2, i, oname, MAXNAME) < MAXNAME); int otype = H5Gget_objtype_by_idx(g2, i); assert(otype == H5G_DATASET); if (!H5LTfind_dataset(g1, oname)) { printf("Only in %s[%s%s]\n", file2, name, oname); continue; } } H5Gclose(g1); H5Gclose(g2); } else if (g1 >= 0) { printf("Only in %s:%s\n", file1, name); H5Gclose(g1); } else if (g2 >= 0) { printf("Only in %s:%s\n", file2, name); H5Gclose(g2); } else { printf("Group %s does not exist in either file.\n", name); } }