or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

attributes.mddimensions.mdfile-operations.mdgroups.mdindex.mdlegacy-api.mduser-types.mdvariables.md

legacy-api.mddocs/

0

# Legacy API Compatibility

1

2

The h5netcdf legacy API provides drop-in compatibility with netCDF4-python, enabling existing code to work with minimal modifications. This API mirrors the method names, behavior, and conventions of the netCDF4-python library.

3

4

## Capabilities

5

6

### Dataset Class

7

8

Main file interface compatible with netCDF4.Dataset.

9

10

```python { .api }

11

class Dataset(File, Group, HasAttributesMixin):

12

def __init__(self, filename, mode: str = 'r', format: str = 'NETCDF4',

13

group: str = None, invalid_netcdf: bool = False,

14

phony_dims: str = None, **kwargs):

15

"""

16

Open or create a netCDF dataset (compatible with netCDF4.Dataset).

17

18

Args:

19

filename: Path to the netCDF file or file-like object

20

mode (str): File access mode ('r', 'w', 'a', 'r+')

21

format (str): File format (only 'NETCDF4' supported)

22

group (str): Group to open (None for root)

23

invalid_netcdf (bool): Allow non-netCDF4 features

24

phony_dims (str): Handle unlabeled dimensions ('sort', 'access')

25

**kwargs: Additional file creation parameters

26

"""

27

...

28

29

def close(self) -> None:

30

"""Close the dataset."""

31

...

32

33

def sync(self) -> None:

34

"""Synchronize data to disk."""

35

...

36

37

def flush(self) -> None:

38

"""Flush data to disk."""

39

...

40

```

41

42

### Group Operations

43

44

Group management with netCDF4-python compatible method names.

45

46

```python { .api }

47

class Group(Group, HasAttributesMixin):

48

def createGroup(self, name: str) -> Group:

49

"""Create child group (compatible with netCDF4)."""

50

...

51

52

@property

53

def groups(self) -> dict:

54

"""Dictionary of child groups."""

55

...

56

57

@property

58

def variables(self) -> dict:

59

"""Dictionary of variables in this group."""

60

...

61

62

@property

63

def dimensions(self) -> dict:

64

"""Dictionary of dimensions in this group."""

65

...

66

67

def createDimension(self, name: str, size: int = None) -> Dimension:

68

"""

69

Create dimension (compatible with netCDF4).

70

71

Args:

72

name (str): Dimension name

73

size (int): Dimension size (None for unlimited)

74

75

Returns:

76

Dimension: The created dimension

77

"""

78

...

79

80

def createVariable(self, varname: str, datatype, dimensions: tuple = (),

81

zlib: bool = False, complevel: int = 4, shuffle: bool = True,

82

fletcher32: bool = False, contiguous: bool = False,

83

chunksizes: tuple = None, endian: str = 'native',

84

least_significant_digit: int = None, fill_value = None,

85

chunk_cache = None, **kwargs) -> Variable:

86

"""

87

Create variable (compatible with netCDF4).

88

89

Args:

90

varname (str): Variable name

91

datatype: Data type (numpy dtype, string, or UserType)

92

dimensions (tuple): Dimension names

93

zlib (bool): Enable gzip compression

94

complevel (int): Compression level (1-9)

95

shuffle (bool): Apply shuffle filter

96

fletcher32 (bool): Apply Fletcher32 checksum

97

contiguous (bool): Store data contiguously

98

chunksizes (tuple): Chunk sizes

99

endian (str): Byte order ('native', 'little', 'big')

100

least_significant_digit (int): Precision for compression

101

fill_value: Fill value for missing data

102

chunk_cache: HDF5 chunk cache settings

103

**kwargs: Additional creation parameters

104

105

Returns:

106

Variable: The created variable

107

"""

108

...

109

```

110

111

### Type Creation

112

113

User-defined type creation with netCDF4-python method names.

114

115

```python { .api }

116

def createEnumType(self, datatype, datatype_name: str, enum_dict: dict) -> EnumType:

117

"""Create enumeration type (compatible with netCDF4)."""

118

...

119

120

def createVLType(self, datatype, datatype_name: str) -> VLType:

121

"""Create variable-length type (compatible with netCDF4)."""

122

...

123

124

def createCompoundType(self, datatype, datatype_name: str) -> CompoundType:

125

"""Create compound type (compatible with netCDF4)."""

126

...

127

128

@property

129

def enumtypes(self) -> dict:

130

"""Dictionary of enumeration types in this group."""

131

...

132

133

@property

134

def vltypes(self) -> dict:

135

"""Dictionary of variable-length types in this group."""

136

...

137

138

@property

139

def cmptypes(self) -> dict:

140

"""Dictionary of compound types in this group."""

141

...

142

```

143

144

### Variable Interface

145

146

Variable class with netCDF4-python compatible methods.

147

148

```python { .api }

149

class Variable(BaseVariable, HasAttributesMixin):

150

def chunking(self):

151

"""

152

Return chunking information (compatible with netCDF4).

153

154

Returns:

155

tuple or str: Chunk sizes or 'contiguous' if not chunked

156

"""

157

...

158

159

def filters(self) -> dict:

160

"""

161

Return HDF5 filter parameters (compatible with netCDF4).

162

163

Returns:

164

dict: Filter settings including complevel, zlib, shuffle, fletcher32

165

"""

166

...

167

168

@property

169

def dtype(self):

170

"""Return numpy dtype (compatible with netCDF4.Variable)."""

171

...

172

```

173

174

### Attribute Compatibility

175

176

NetCDF4-python style attribute access methods.

177

178

```python { .api }

179

class HasAttributesMixin:

180

def getncattr(self, name: str):

181

"""

182

Get attribute by name (compatible with netCDF4).

183

184

Args:

185

name (str): Attribute name

186

187

Returns:

188

Attribute value

189

"""

190

...

191

192

def setncattr(self, name: str, value) -> None:

193

"""

194

Set attribute by name (compatible with netCDF4).

195

196

Args:

197

name (str): Attribute name

198

value: Attribute value

199

"""

200

...

201

202

def ncattrs(self) -> list:

203

"""

204

List attribute names (compatible with netCDF4).

205

206

Returns:

207

list: Attribute names

208

"""

209

...

210

211

def __getattr__(self, name: str):

212

"""Direct attribute access (compatible with netCDF4)."""

213

...

214

215

def __setattr__(self, name: str, value) -> None:

216

"""Direct attribute assignment (compatible with netCDF4)."""

217

...

218

```

219

220

### Constants and Utilities

221

222

Default fill values and utility functions.

223

224

```python { .api }

225

default_fillvals = {

226

'S1': '\x00',

227

'i1': -127,

228

'u1': 255,

229

'i2': -32767,

230

'u2': 65535,

231

'i4': -2147483647,

232

'u4': 4294967295,

233

'i8': -9223372036854775806,

234

'u8': 18446744073709551614,

235

'f4': 9.969209968386869e36,

236

'f8': 9.969209968386869e36,

237

}

238

239

def _get_default_fillvalue(dtype) -> any:

240

"""Get default fill value for data type."""

241

...

242

243

def _check_return_dtype_endianess(endian: str = "native") -> str:

244

"""Check and normalize endianness specification."""

245

...

246

```

247

248

## Usage Examples

249

250

### Basic Migration from netCDF4-python

251

252

```python

253

# Original netCDF4-python code:

254

# import netCDF4

255

256

# h5netcdf equivalent (drop-in replacement):

257

import h5netcdf.legacyapi as netCDF4

258

259

# Rest of the code remains identical

260

with netCDF4.Dataset('data.nc', 'r') as dataset:

261

# Access variables through .variables

262

temperature = dataset.variables['temperature'][:]

263

264

# Access dimensions through .dimensions

265

time_size = len(dataset.dimensions['time'])

266

267

# Access attributes using netCDF4 methods

268

units = dataset.variables['temperature'].getncattr('units')

269

global_attrs = dataset.ncattrs()

270

```

271

272

### Creating Files with Legacy API

273

274

```python

275

import h5netcdf.legacyapi as netCDF4

276

import numpy as np

277

278

# Create file using netCDF4-python syntax

279

with netCDF4.Dataset('output.nc', 'w', format='NETCDF4') as dataset:

280

# Create dimensions

281

time_dim = dataset.createDimension('time', None) # Unlimited

282

lat_dim = dataset.createDimension('lat', 180)

283

lon_dim = dataset.createDimension('lon', 360)

284

285

# Create coordinate variables

286

times = dataset.createVariable('time', 'f8', ('time',))

287

latitudes = dataset.createVariable('lat', 'f4', ('lat',))

288

longitudes = dataset.createVariable('lon', 'f4', ('lon',))

289

290

# Create data variable with compression

291

temperature = dataset.createVariable(

292

'temperature', 'f4', ('time', 'lat', 'lon'),

293

zlib=True, # Enable compression

294

complevel=6, # Compression level

295

shuffle=True, # Shuffle filter

296

fletcher32=True # Checksum

297

)

298

299

# Set attributes using netCDF4 methods

300

dataset.setncattr('title', 'Global Temperature Data')

301

dataset.setncattr('institution', 'Climate Research Center')

302

303

temperature.setncattr('units', 'K')

304

temperature.setncattr('long_name', 'Air Temperature')

305

306

# Write coordinate data

307

latitudes[:] = np.linspace(-89.5, 89.5, 180)

308

longitudes[:] = np.linspace(-179.5, 179.5, 360)

309

310

# Write time series data

311

for t in range(10):

312

times[t] = t

313

temperature[t, :, :] = np.random.random((180, 360)) * 50 + 273.15

314

```

315

316

### Group Operations

317

318

```python

319

import h5netcdf.legacyapi as netCDF4

320

321

with netCDF4.Dataset('groups.nc', 'w') as dataset:

322

# Create groups using netCDF4 syntax

323

obs_group = dataset.createGroup('observations')

324

model_group = dataset.createGroup('model')

325

326

# Create dimensions in groups

327

obs_group.createDimension('time', 100)

328

obs_group.createDimension('station', 50)

329

330

# Create variables in groups

331

temp_obs = obs_group.createVariable('temperature', 'f4', ('time', 'station'))

332

333

# Set group attributes

334

obs_group.setncattr('description', 'Observational data')

335

model_group.setncattr('description', 'Model output')

336

```

337

338

### User-Defined Types

339

340

```python

341

import h5netcdf.legacyapi as netCDF4

342

import numpy as np

343

344

with netCDF4.Dataset('types.nc', 'w') as dataset:

345

# Create enumeration type

346

quality_enum = dataset.createEnumType('i1', 'quality_flag', {

347

'good': 0,

348

'questionable': 1,

349

'bad': 2,

350

'missing': 3

351

})

352

353

# Create compound type

354

obs_dtype = np.dtype([

355

('value', 'f4'),

356

('uncertainty', 'f4'),

357

('quality', 'i1')

358

])

359

obs_compound = dataset.createCompoundType(obs_dtype, 'observation')

360

361

# Create variable-length type

362

vlen_str = dataset.createVLType(str, 'vlen_string')

363

364

# Use these types in variables

365

dataset.createDimension('n', 100)

366

367

quality_var = dataset.createVariable('quality', quality_enum, ('n',))

368

obs_var = dataset.createVariable('observations', obs_compound, ('n',))

369

comment_var = dataset.createVariable('comments', vlen_str, ('n',))

370

```

371

372

### Attribute Access Patterns

373

374

```python

375

import h5netcdf.legacyapi as netCDF4

376

377

with netCDF4.Dataset('attributes.nc', 'r') as dataset:

378

# NetCDF4 style attribute access

379

title = dataset.getncattr('title')

380

all_global_attrs = dataset.ncattrs()

381

382

# Direct attribute access (also supported)

383

title = dataset.title # Same as getncattr('title')

384

385

# Variable attributes

386

temp = dataset.variables['temperature']

387

units = temp.getncattr('units')

388

var_attrs = temp.ncattrs()

389

390

# Direct variable attribute access

391

units = temp.units # Same as getncattr('units')

392

393

# Check attribute existence

394

if 'long_name' in temp.ncattrs():

395

long_name = temp.getncattr('long_name')

396

```

397

398

### Variable Information

399

400

```python

401

import h5netcdf.legacyapi as netCDF4

402

403

with netCDF4.Dataset('info.nc', 'r') as dataset:

404

temp = dataset.variables['temperature']

405

406

# Get chunking information (netCDF4 method)

407

chunks = temp.chunking()

408

if chunks:

409

print(f"Variable is chunked: {chunks}")

410

else:

411

print("Variable is not chunked")

412

413

# Get filter information (netCDF4 method)

414

filters = temp.filters()

415

print(f"Compression: {filters.get('zlib', False)}")

416

print(f"Shuffle: {filters.get('shuffle', False)}")

417

print(f"Fletcher32: {filters.get('fletcher32', False)}")

418

419

# Other netCDF4-compatible properties

420

print(f"Shape: {temp.shape}")

421

print(f"Dimensions: {temp.dimensions}")

422

print(f"Data type: {temp.dtype}")

423

```

424

425

### Error Handling and Compatibility

426

427

```python

428

import h5netcdf.legacyapi as netCDF4

429

430

try:

431

with netCDF4.Dataset('test.nc', 'r') as dataset:

432

# Code that works with both netCDF4-python and h5netcdf

433

pass

434

435

except FileNotFoundError:

436

print("File not found")

437

except OSError as e:

438

print(f"I/O error: {e}")

439

```

440

441

### Mixed API Usage

442

443

```python

444

# You can mix modern and legacy APIs

445

import h5netcdf

446

import h5netcdf.legacyapi as netCDF4

447

448

# Open with legacy API

449

with netCDF4.Dataset('mixed.nc', 'w') as legacy_dataset:

450

# Use legacy methods

451

legacy_dataset.createDimension('time', 10)

452

temp = legacy_dataset.createVariable('temperature', 'f4', ('time',))

453

454

# Access underlying modern API objects

455

modern_file = legacy_dataset # Dataset inherits from File

456

457

# Use modern API methods on the same object

458

modern_file.flush() # Modern API method

459

460

# Variables also support both APIs

461

temp.attrs['units'] = 'K' # Modern API attribute access

462

temp.setncattr('long_name', 'Temperature') # Legacy API method

463

```

464

465

## Migration Guidelines

466

467

### From netCDF4-python to h5netcdf

468

469

1. **Import change**: Replace `import netCDF4` with `import h5netcdf.legacyapi as netCDF4`

470

471

2. **Method compatibility**: All major netCDF4-python methods are supported

472

473

3. **Performance differences**: h5netcdf may have different performance characteristics

474

475

4. **Feature differences**: Some advanced netCDF4-python features may not be available

476

477

### Key Differences from netCDF4-python

478

479

- **Backend**: Uses h5py instead of the C netCDF library

480

- **Dependencies**: Fewer binary dependencies

481

- **Performance**: May be faster for some operations, slower for others

482

- **Memory usage**: Different memory access patterns

483

- **HDF5 features**: Direct access to HDF5-specific features when needed

484

485

### Best Practices for Legacy API

486

487

- Use the legacy API for existing codebases requiring compatibility

488

- Consider migrating to the modern API for new projects

489

- Test performance characteristics for your specific use case

490

- Be aware of subtle behavioral differences in edge cases