0
# Groups and Hierarchical Organization
1
2
NetCDF4 groups provide hierarchical organization of data, similar to directories in a file system. Groups can contain dimensions, variables, attributes, and other groups, enabling complex data structures and namespace organization.
3
4
## Capabilities
5
6
### Group Creation and Access
7
8
Create and navigate hierarchical group structures.
9
10
```python { .api }
11
class Group(Mapping):
12
def __init__(self, parent: Group, name: str):
13
"""
14
Create or access a group within a netCDF4 file.
15
16
Args:
17
parent (Group): Parent group (File for root level)
18
name (str): Name of the group
19
"""
20
...
21
22
def create_group(self, name: str) -> Group:
23
"""
24
Create a new child group.
25
26
Args:
27
name (str): Name for the new group
28
29
Returns:
30
Group: The newly created group
31
"""
32
...
33
```
34
35
### Group Properties
36
37
Access group metadata and hierarchical relationships.
38
39
```python { .api }
40
@property
41
def name(self) -> str:
42
"""Full path name of the group."""
43
...
44
45
@property
46
def parent(self) -> Group:
47
"""Parent group reference (None for root File)."""
48
...
49
50
@property
51
def groups(self) -> Frozen:
52
"""Dictionary-like access to child groups."""
53
...
54
55
@property
56
def variables(self) -> Frozen:
57
"""Dictionary-like access to variables in this group."""
58
...
59
60
@property
61
def dimensions(self) -> Dimensions:
62
"""Dictionary-like access to dimensions in this group."""
63
...
64
65
@property
66
def dims(self) -> Dimensions:
67
"""Alias for dimensions property."""
68
...
69
70
@property
71
def attrs(self) -> Attributes:
72
"""Dictionary-like access to group attributes."""
73
...
74
```
75
76
### Type Management
77
78
Manage user-defined types within groups.
79
80
```python { .api }
81
@property
82
def enumtypes(self) -> Frozen:
83
"""Dictionary-like access to enumeration types."""
84
...
85
86
@property
87
def vltypes(self) -> Frozen:
88
"""Dictionary-like access to variable-length types."""
89
...
90
91
@property
92
def cmptypes(self) -> Frozen:
93
"""Dictionary-like access to compound types."""
94
...
95
```
96
97
### Variable and Dimension Management
98
99
Create and manage variables and dimensions within the group.
100
101
```python { .api }
102
def create_variable(self, name: str, dimensions: tuple = (), dtype=None,
103
data=None, fillvalue=None, chunks=None, **kwargs) -> Variable:
104
"""
105
Create a new variable in this group.
106
107
Args:
108
name (str): Variable name
109
dimensions (tuple): Dimension names
110
dtype: Data type specification
111
data: Initial data (optional)
112
fillvalue: Fill value for missing data
113
chunks: Chunk sizes for each dimension
114
**kwargs: Additional HDF5 dataset creation parameters
115
116
Returns:
117
Variable: The newly created variable
118
"""
119
...
120
121
def resize_dimension(self, dim: str, size: int) -> None:
122
"""
123
Resize an unlimited dimension.
124
125
Args:
126
dim (str): Dimension name
127
size (int): New size for the dimension
128
"""
129
...
130
```
131
132
### User-Defined Type Creation
133
134
Create custom data types within the group.
135
136
```python { .api }
137
def create_enumtype(self, datatype, datatype_name: str, enum_dict: dict) -> EnumType:
138
"""
139
Create an enumeration type.
140
141
Args:
142
datatype: Base data type
143
datatype_name (str): Name for the enum type
144
enum_dict (dict): Mapping of names to values
145
146
Returns:
147
EnumType: The created enumeration type
148
"""
149
...
150
151
def create_vltype(self, datatype, datatype_name: str) -> VLType:
152
"""
153
Create a variable-length type.
154
155
Args:
156
datatype: Base data type
157
datatype_name (str): Name for the VL type
158
159
Returns:
160
VLType: The created variable-length type
161
"""
162
...
163
164
def create_cmptype(self, datatype, datatype_name: str) -> CompoundType:
165
"""
166
Create a compound type.
167
168
Args:
169
datatype: NumPy structured dtype
170
datatype_name (str): Name for the compound type
171
172
Returns:
173
CompoundType: The created compound type
174
"""
175
...
176
```
177
178
### Group Operations
179
180
Perform operations on the group structure.
181
182
```python { .api }
183
def flush(self) -> None:
184
"""Flush pending changes to disk."""
185
...
186
187
def sync(self) -> None:
188
"""Alias for flush() - synchronize with disk."""
189
...
190
```
191
192
### Dictionary-like Interface
193
194
Groups implement the Mapping protocol for intuitive access.
195
196
```python { .api }
197
def __getitem__(self, key: str):
198
"""Access child groups by name."""
199
...
200
201
def __contains__(self, key: str) -> bool:
202
"""Check if child group exists."""
203
...
204
205
def __iter__(self):
206
"""Iterate over child group names."""
207
...
208
209
def __len__(self) -> int:
210
"""Number of child groups."""
211
...
212
213
def keys(self):
214
"""Child group names."""
215
...
216
217
def values(self):
218
"""Child group objects."""
219
...
220
221
def items(self):
222
"""(name, group) pairs."""
223
...
224
225
def __repr__(self) -> str:
226
"""String representation of the group."""
227
...
228
```
229
230
## Usage Examples
231
232
### Creating Hierarchical Structure
233
234
```python
235
import h5netcdf
236
237
with h5netcdf.File('hierarchical.nc', 'w') as f:
238
# Create top-level groups
239
obs_group = f.create_group('observations')
240
model_group = f.create_group('model')
241
242
# Create nested groups
243
temp_obs = obs_group.create_group('temperature')
244
precip_obs = obs_group.create_group('precipitation')
245
246
# Each group can have its own dimensions and variables
247
temp_obs.dimensions['time'] = 100
248
temp_obs.dimensions['station'] = 50
249
250
temp_var = temp_obs.create_variable('values', ('time', 'station'), dtype='f4')
251
temp_var.attrs['units'] = 'K'
252
temp_var.attrs['long_name'] = 'Temperature observations'
253
```
254
255
### Navigating Group Hierarchy
256
257
```python
258
with h5netcdf.File('hierarchical.nc', 'r') as f:
259
# Access groups by name
260
obs_group = f['observations']
261
temp_group = obs_group['temperature']
262
263
# Or use the groups property
264
for name, group in f.groups.items():
265
print(f"Group: {name}")
266
print(f" Variables: {list(group.variables.keys())}")
267
print(f" Dimensions: {list(group.dimensions.keys())}")
268
print(f" Child groups: {list(group.groups.keys())}")
269
270
# Navigate using parent references
271
parent = temp_group.parent # Returns observations group
272
root = parent.parent # Returns root File
273
```
274
275
### Group Attributes
276
277
```python
278
with h5netcdf.File('attributed.nc', 'w') as f:
279
experiment = f.create_group('experiment_1')
280
281
# Set group attributes
282
experiment.attrs['description'] = 'Temperature sensitivity experiment'
283
experiment.attrs['start_date'] = '2023-01-01'
284
experiment.attrs['investigator'] = 'Dr. Smith'
285
286
# Access attributes
287
print(f"Description: {experiment.attrs['description']}")
288
289
# List all attributes
290
for attr_name in experiment.attrs:
291
print(f"{attr_name}: {experiment.attrs[attr_name]}")
292
```
293
294
### Working with Multiple Levels
295
296
```python
297
with h5netcdf.File('multi_level.nc', 'w') as f:
298
# Create a complex hierarchy
299
data = f.create_group('data')
300
301
# Geographic regions
302
na = data.create_group('north_america')
303
eu = data.create_group('europe')
304
as_ = data.create_group('asia')
305
306
# Observation types within each region
307
for region in [na, eu, as_]:
308
surface = region.create_group('surface')
309
atmosphere = region.create_group('atmosphere')
310
311
# Each can have its own coordinate system
312
surface.dimensions['lat'] = 180
313
surface.dimensions['lon'] = 360
314
surface.dimensions['time'] = None # Unlimited
315
316
atmosphere.dimensions['lat'] = 90
317
atmosphere.dimensions['lon'] = 180
318
atmosphere.dimensions['level'] = 50
319
atmosphere.dimensions['time'] = None # Unlimited
320
```
321
322
### Checking Group Contents
323
324
```python
325
with h5netcdf.File('check_contents.nc', 'r') as f:
326
def explore_group(group, indent=0):
327
prefix = " " * indent
328
print(f"{prefix}Group: {group.name}")
329
330
if group.dimensions:
331
print(f"{prefix} Dimensions: {list(group.dimensions.keys())}")
332
333
if group.variables:
334
print(f"{prefix} Variables: {list(group.variables.keys())}")
335
336
if group.attrs:
337
print(f"{prefix} Attributes: {list(group.attrs.keys())}")
338
339
# Recursively explore child groups
340
for child_name, child_group in group.groups.items():
341
explore_group(child_group, indent + 1)
342
343
explore_group(f)
344
```
345
346
## Group Naming and Path Conventions
347
348
- Group names follow HDF5 naming conventions
349
- Full group paths use forward slashes: `/observations/temperature`
350
- Names are case-sensitive
351
- Avoid special characters and spaces
352
- Root group (File) has name "/"
353
354
## Group vs Variables Access
355
356
```python
357
with h5netcdf.File('mixed.nc', 'r') as f:
358
# Groups are accessed via .groups or direct indexing
359
group = f['observations'] # Same as f.groups['observations']
360
361
# Variables are accessed via .variables
362
variable = f.variables['temperature'] # NOT f['temperature']
363
364
# But within a group, both work:
365
obs = f['observations']
366
temp1 = obs['temperature'] # Direct access to child group
367
temp2 = obs.variables['temperature'] # Access to variable (if exists)
368
```