/// <summary> /// Create a sub-Group with a given `key` relative to this Group. /// An attempt to create multiple groups or to write a readonly-file /// will throw an `InvalidOperationException`. /// </summary> /// <remarks> /// Groups can only be created one at a time. To create a hierarchy /// like "/one/two/three" under the Root-Group in an empty file, call /// <code> /// H5Group grp = h5file.Root; /// grp = grp.CreateGroup("one"); /// grp = grp.CreateGroup("two"); /// grp = grp.CreateGroup("three"); /// </code> /// Afterwards, the H5Group *three* is accessible through /// <code> /// H5Group three = h5file.Root.SubGroup("one/two/three"); /// </code> /// </remarks> public H5Group CreateGroup(string key) { if (H5Link.Exists(ID, key) || key.Contains("/")) { throw new InvalidOperationException($"Cannot create group at <{key}>"); } return(Create(ID, key)); }
/// <summary> /// Retrieve the `H5DataSet` located by the `key` relative to this Group. /// The type of dataset returned depends on the actual datatype under /// the `key`. A non-existing `key` throws a `KeyNotFoundException`. /// </summary> /// <remarks> /// In order to use the object, an explicit cast to one of the generic /// datasets is necessary. Beware of casting as it might throw an /// `InvalidCastException`. /// </remarks> /// <example> /// <code> /// H5Group root = h5file.Root; /// double2d dset = (double2d)root["level1/doubleset"]; /// string1d names = root["level1/names"] as string1d; /// if (names == null) /// throw new ApplicationException("no such dataset: level1/names!"); /// </code> /// </example> public H5DataSet this[string key] { get { if (key.StartsWith("/") || key.EndsWith("/") || !H5Link.Exists(ID, key)) { throw new KeyNotFoundException(key); } if (!H5Link.Exists(ID, key)) { throw new KeyNotFoundException(key); } return(H5DataSet.FromID(H5DataSet.Open(ID, key))); } }
/// <summary> /// Access the sub-Group given by `key` relative to this Group. /// If the sub-Group does not exist and `create = false` (default), /// a `KeyNotFoundException` is thrown. /// An attempt to create multiple groups or to write a readonly-file /// will throw an `InvalidOperationException`. /// </summary> public H5Group SubGroup(string key, bool create = false) { if (H5Link.Exists(ID, key)) { return(H5Group.Open(ID, key, IsWritable)); } if (create) { return(CreateGroup(key)); } else { throw new KeyNotFoundException(key); } }
/// <summary> /// Remove the link to the sub-group specified by `key` from this group. /// Throws a `KeyNotFoundException` if the given `key` does not exist. /// </summary> public void DeleteGroup(string key) { H5Link.Delete(ID, key); }
/// <summary> /// Automagically fill data fields with their Hdf5 implementations. /// </summary> private void Initialize(H5Group grp) { var collectedH5Attrs = new Dictionary <string, H5Attribute>(); foreach (object attr in this.GetType().GetCustomAttributes(inherit: true)) { if (attr.GetType() == typeof(AttributeAttribute)) { string name = ((AttributeAttribute)attr).name; try { collectedH5Attrs.Add(name, grp.GetAttribute(name)); } catch (KeyNotFoundException) { Type primitive = ((AttributeAttribute)attr).primitive; object default_ = ((AttributeAttribute)attr).default_; if (primitive == null && default_ == null) { continue; } collectedH5Attrs.Add(name, grp.SetAttribute(name, primitive, default_)); } } } var pendingAttrs = new List <Tuple <string, Type, object> >(); var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy; foreach (FieldInfo dsetInfo in this.GetType().GetFields(flags)) { // skip fields that don't interest us here.. if (!dsetInfo.FieldType.IsSubclassOf(typeof(H5DataSet))) { continue; } // ..as well as those that have been already defined: if (!(dsetInfo.GetValue(this) == null)) { continue; } // set default dataset creation parameters.. string key = dsetInfo.Name; bool readonli = false; Match match = Regex.Match(dsetInfo.FieldType.Name, @".*([1-3])d"); int rank = Int32.Parse(match.Groups[1].Value); long[] dims = new long[rank]; long[] maxdims = new long[rank]; dims.Fill <long>(1L); maxdims.Fill <long>(-1L); // use H5S.UNLIMITED on all dimensions // ..which may be overridden by Attributes: pendingAttrs.Clear(); foreach (object attr in dsetInfo.GetCustomAttributes(inherit: false)) { if (attr.GetType() == typeof(LocationAttribute)) { key = ((LocationAttribute)attr).key; } else if (attr.GetType() == typeof(ReadonlyAttribute)) { readonli = true; } else if (attr.GetType() == typeof(ShapeAttribute)) { dims = ((ShapeAttribute)attr).dims; } else if (attr.GetType() == typeof(MaximumShapeAttribute)) { maxdims = ((MaximumShapeAttribute)attr).dims; } else if (attr.GetType() == typeof(AttributeAttribute)) { pendingAttrs.Add(new Tuple <string, Type, object>( ((AttributeAttribute)attr).name, ((AttributeAttribute)attr).primitive, ((AttributeAttribute)attr).default_ )); } } // initialize the dataset.. H5DataSet dset; if (H5Link.Exists(grp.ID, key)) { dset = grp[key]; } else if (readonli) { continue; } else { Type dtype, field_type = dsetInfo.FieldType; if (field_type.IsGenericType) { dtype = field_type.GenericTypeArguments[0]; } else if (field_type == typeof(string1d)) { dtype = typeof(string); } else if (field_type == typeof(string2d)) { dtype = typeof(string); } else { throw new NotImplementedException(field_type.ToString()); } dset = grp.CreateDataset(key, rank, dims, dtype, maxdims); } // add pending hdf5 attributes.. foreach (var tup in pendingAttrs) { string name = tup.Item1; Type primitive = tup.Item2; object default_ = tup.Item3; try { collectedH5Attrs.Add(name, dset.GetAttribute(name)); } catch (KeyNotFoundException) { if (primitive == null && default_ == null) { continue; } collectedH5Attrs.Add(name, dset.SetAttribute(name, primitive, default_)); } } // finally, set this instance's field to the new object. // Note that, even if `dset` is declared as `object`, it will be // of type `field.FieldType`: dsetInfo.SetValue(this, dset); } Attr = new ReadOnlyDictionary <string, H5Attribute>(collectedH5Attrs); }