or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

edf-reading.mdedf-writing.mdhigh-level-functions.mdindex.mdlow-level-interface.md

edf-writing.mddocs/

0

# EDF File Writing

1

2

Interface for creating and writing EDF, EDF+, BDF, and BDF+ files with comprehensive header configuration, signal data writing, and annotation support. The `EdfWriter` class provides Python-friendly methods with automatic resource management and validation.

3

4

## Capabilities

5

6

### File Creation and Management

7

8

Create new EDF files with specified channel count and file type, with automatic resource management through context managers.

9

10

```python { .api }

11

class EdfWriter:

12

def __init__(self, file_name: str, n_channels: int, file_type: int = FILETYPE_EDFPLUS):

13

"""

14

Initialize EDF writer for new file.

15

16

Parameters:

17

- file_name: str, output file path

18

- n_channels: int, number of signal channels

19

- file_type: int, file format (FILETYPE_EDF, FILETYPE_EDFPLUS, FILETYPE_BDF, FILETYPE_BDFPLUS)

20

"""

21

22

def __enter__(self) -> EdfWriter:

23

"""Context manager entry."""

24

25

def __exit__(self, exc_type, exc_val, exc_tb):

26

"""Context manager exit with automatic file closure."""

27

28

def close(self):

29

"""Close file and finalize writing."""

30

31

def update_header(self):

32

"""Update file header with current settings."""

33

```

34

35

Usage example:

36

37

```python

38

# Using context manager (recommended)

39

with pyedflib.EdfWriter('output.edf', 2, pyedflib.FILETYPE_EDFPLUS) as f:

40

# Configure and write data

41

f.setSignalHeaders(signal_headers)

42

f.writeSamples(data)

43

44

# Manual management

45

f = pyedflib.EdfWriter('output.edf', 2)

46

try:

47

f.setSignalHeaders(signal_headers)

48

f.writeSamples(data)

49

finally:

50

f.close()

51

```

52

53

### Header Configuration

54

55

Set file-level and signal-level header information including patient data, recording details, and signal parameters.

56

57

```python { .api }

58

def setHeader(self, fileHeader: Dict):

59

"""

60

Set file header from dictionary.

61

62

Parameters:

63

- fileHeader: dict, complete file header information

64

"""

65

66

def setSignalHeader(self, edfsignal: int, channel_info: Dict):

67

"""

68

Set header for specific signal channel.

69

70

Parameters:

71

- edfsignal: int, channel number (0-based)

72

- channel_info: dict, signal configuration

73

"""

74

75

def setSignalHeaders(self, signalHeaders: List[Dict]):

76

"""

77

Set headers for all signal channels.

78

79

Parameters:

80

- signalHeaders: List[dict], list of signal configurations

81

"""

82

```

83

84

Usage example:

85

86

```python

87

# Create signal headers

88

signal_headers = [

89

{

90

'label': 'EEG Fp1',

91

'dimension': 'uV',

92

'sample_frequency': 256,

93

'physical_min': -500.0,

94

'physical_max': 500.0,

95

'digital_min': -32768,

96

'digital_max': 32767,

97

'transducer': 'AgAgCl electrodes',

98

'prefilter': 'HP:0.1Hz LP:70Hz'

99

},

100

{

101

'label': 'EEG Fp2',

102

'dimension': 'uV',

103

'sample_frequency': 256,

104

'physical_min': -500.0,

105

'physical_max': 500.0,

106

'digital_min': -32768,

107

'digital_max': 32767,

108

'transducer': 'AgAgCl electrodes',

109

'prefilter': 'HP:0.1Hz LP:70Hz'

110

}

111

]

112

113

with pyedflib.EdfWriter('eeg.edf', 2) as f:

114

f.setSignalHeaders(signal_headers)

115

```

116

117

### Patient Information

118

119

Set patient demographics and identification information.

120

121

```python { .api }

122

def setPatientName(self, patient_name: str):

123

"""Set patient name."""

124

125

def setPatientCode(self, patient_code: str):

126

"""Set patient identification code."""

127

128

def setPatientAdditional(self, patient_additional: str):

129

"""Set additional patient information."""

130

131

def setSex(self, sex: int):

132

"""

133

Set patient sex.

134

135

Parameters:

136

- sex: int, patient sex (0=female, 1=male)

137

"""

138

139

def setBirthdate(self, birthdate: Union[str, date]):

140

"""

141

Set patient birthdate.

142

143

Parameters:

144

- birthdate: str or date, birthdate in YYYY-MM-DD format or date object

145

"""

146

```

147

148

### Recording Information

149

150

Set recording session metadata and technical details.

151

152

```python { .api }

153

def setTechnician(self, technician: str):

154

"""Set technician name."""

155

156

def setRecordingAdditional(self, recording_additional: str):

157

"""Set additional recording information."""

158

159

def setEquipment(self, equipment: str):

160

"""Set recording equipment information."""

161

162

def setAdmincode(self, admincode: str):

163

"""Set administration code."""

164

165

def setStartdatetime(self, recording_start_time: Union[datetime, str]):

166

"""

167

Set recording start date and time.

168

169

Parameters:

170

- recording_start_time: datetime or str, start time

171

"""

172

173

def setDatarecordDuration(self, record_duration: Union[float, int]):

174

"""

175

Set data record duration in seconds.

176

177

Parameters:

178

- record_duration: float or int, duration per data record

179

"""

180

181

def set_number_of_annotation_signals(self, number_of_annotations: int):

182

"""

183

Set number of annotation signals.

184

185

Parameters:

186

- number_of_annotations: int, annotation signal count

187

"""

188

```

189

190

### Signal Configuration

191

192

Configure individual signal channel properties including sampling rates, calibration, and metadata.

193

194

```python { .api }

195

def setSamplefrequency(self, edfsignal: int, samplefrequency: Union[int, float]):

196

"""

197

Set sampling frequency for signal.

198

199

Parameters:

200

- edfsignal: int, channel number

201

- samplefrequency: int or float, sample rate in Hz

202

"""

203

204

def setPhysicalMaximum(self, edfsignal: int, physical_maximum: Union[int, float]):

205

"""

206

Set physical maximum value for signal.

207

208

Parameters:

209

- edfsignal: int, channel number

210

- physical_maximum: int or float, maximum physical value

211

"""

212

213

def setPhysicalMinimum(self, edfsignal: int, physical_minimum: Union[int, float]):

214

"""

215

Set physical minimum value for signal.

216

217

Parameters:

218

- edfsignal: int, channel number

219

- physical_minimum: int or float, minimum physical value

220

"""

221

222

def setDigitalMaximum(self, edfsignal: int, digital_maximum: int):

223

"""

224

Set digital maximum value for signal.

225

226

Parameters:

227

- edfsignal: int, channel number

228

- digital_maximum: int, maximum digital value

229

"""

230

231

def setDigitalMinimum(self, edfsignal: int, digital_minimum: int):

232

"""

233

Set digital minimum value for signal.

234

235

Parameters:

236

- edfsignal: int, channel number

237

- digital_minimum: int, minimum digital value

238

"""

239

240

def setLabel(self, edfsignal: int, label: str):

241

"""

242

Set signal label.

243

244

Parameters:

245

- edfsignal: int, channel number

246

- label: str, signal label/name

247

"""

248

249

def setPhysicalDimension(self, edfsignal: int, physical_dimension: str):

250

"""

251

Set physical dimension (units) for signal.

252

253

Parameters:

254

- edfsignal: int, channel number

255

- physical_dimension: str, units (e.g., 'uV', 'mV')

256

"""

257

258

def setTransducer(self, edfsignal: int, transducer: str):

259

"""

260

Set transducer information for signal.

261

262

Parameters:

263

- edfsignal: int, channel number

264

- transducer: str, transducer description

265

"""

266

267

def setPrefilter(self, edfsignal: int, prefilter: str):

268

"""

269

Set prefilter information for signal.

270

271

Parameters:

272

- edfsignal: int, channel number

273

- prefilter: str, prefilter description

274

"""

275

```

276

277

### Data Writing

278

279

Write signal data to the file with support for different data types and writing modes.

280

281

```python { .api }

282

def writeSamples(self, data_list: Union[List[np.ndarray], np.ndarray], digital: bool = False):

283

"""

284

Write signal samples to file.

285

286

Parameters:

287

- data_list: List[numpy.ndarray] or numpy.ndarray, signal data for each channel

288

- digital: bool, whether data contains digital values (True) or physical values (False)

289

"""

290

291

def writePhysicalSamples(self, data: np.ndarray) -> int:

292

"""

293

Write physical samples for all channels.

294

295

Parameters:

296

- data: numpy.ndarray, physical sample values

297

298

Returns:

299

int: Number of samples written

300

"""

301

302

def writeDigitalSamples(self, data: np.ndarray) -> int:

303

"""

304

Write digital samples for all channels.

305

306

Parameters:

307

- data: numpy.ndarray, digital sample values

308

309

Returns:

310

int: Number of samples written

311

"""

312

313

def writeDigitalShortSamples(self, data: np.ndarray) -> int:

314

"""

315

Write digital short samples for all channels.

316

317

Parameters:

318

- data: numpy.ndarray, digital short sample values

319

320

Returns:

321

int: Number of samples written

322

"""

323

324

def blockWritePhysicalSamples(self, data: np.ndarray) -> int:

325

"""

326

Block write physical samples.

327

328

Parameters:

329

- data: numpy.ndarray, physical sample data

330

331

Returns:

332

int: Number of samples written

333

"""

334

335

def blockWriteDigitalSamples(self, data: np.ndarray) -> int:

336

"""

337

Block write digital samples.

338

339

Parameters:

340

- data: numpy.ndarray, digital sample data

341

342

Returns:

343

int: Number of samples written

344

"""

345

346

def blockWriteDigitalShortSamples(self, data: np.ndarray) -> int:

347

"""

348

Block write digital short samples.

349

350

Parameters:

351

- data: numpy.ndarray, digital short sample data

352

353

Returns:

354

int: Number of samples written

355

"""

356

```

357

358

Usage example:

359

360

```python

361

import numpy as np

362

363

# Generate sample data (1000 samples at 256 Hz for 2 channels)

364

data_ch1 = np.random.normal(0, 100, 1000) # EEG-like signal in uV

365

data_ch2 = np.random.normal(0, 100, 1000)

366

367

with pyedflib.EdfWriter('sample.edf', 2) as f:

368

f.setSignalHeaders(signal_headers)

369

370

# Write as list of arrays (recommended)

371

f.writeSamples([data_ch1, data_ch2])

372

373

# Or write as 2D array (channels x samples)

374

data_2d = np.array([data_ch1, data_ch2])

375

f.writeSamples(data_2d)

376

```

377

378

### Annotation Writing

379

380

Add annotations (events, markers) to EDF+ and BDF+ files with timing and description information.

381

382

```python { .api }

383

def writeAnnotation(self, onset_in_seconds: Union[int, float],

384

duration_in_seconds: Union[int, float],

385

description: str, str_format: str = 'utf8'):

386

"""

387

Write annotation to file.

388

389

Parameters:

390

- onset_in_seconds: int or float, annotation start time in seconds

391

- duration_in_seconds: int or float, annotation duration in seconds

392

- description: str, annotation text description

393

- str_format: str, text encoding ('utf8' or 'latin1')

394

"""

395

```

396

397

Usage example:

398

399

```python

400

with pyedflib.EdfWriter('annotated.edf', 2, pyedflib.FILETYPE_EDFPLUS) as f:

401

f.setSignalHeaders(signal_headers)

402

f.writeSamples([data_ch1, data_ch2])

403

404

# Add annotations

405

f.writeAnnotation(10.0, 0.0, "Stimulus onset")

406

f.writeAnnotation(15.5, 2.0, "Patient movement")

407

f.writeAnnotation(30.0, 0.0, "End of trial")

408

```

409

410

### Utility Methods

411

412

Helper methods for configuration and validation.

413

414

```python { .api }

415

def get_smp_per_record(self, ch_idx: int) -> int:

416

"""

417

Get samples per record for channel.

418

419

Parameters:

420

- ch_idx: int, channel index

421

422

Returns:

423

int: Samples per data record

424

"""

425

```

426

427

## Complete Writing Example

428

429

```python

430

import pyedflib

431

import numpy as np

432

from datetime import datetime

433

434

# Create sample EEG data

435

n_channels = 4

436

n_samples = 2560 # 10 seconds at 256 Hz

437

sample_rate = 256

438

439

# Generate realistic EEG-like signals

440

channels = ['EEG Fp1', 'EEG Fp2', 'EEG C3', 'EEG C4']

441

data = []

442

for i in range(n_channels):

443

# Mix of sine waves with noise to simulate EEG

444

t = np.linspace(0, 10, n_samples)

445

signal = (np.sin(2*np.pi*10*t) * 50 + # 10 Hz alpha-like

446

np.sin(2*np.pi*4*t) * 30 + # 4 Hz theta-like

447

np.random.normal(0, 20, n_samples)) # noise

448

data.append(signal)

449

450

# Create signal headers

451

signal_headers = []

452

for i, label in enumerate(channels):

453

signal_headers.append({

454

'label': label,

455

'dimension': 'uV',

456

'sample_frequency': sample_rate,

457

'physical_min': -500.0,

458

'physical_max': 500.0,

459

'digital_min': -32768,

460

'digital_max': 32767,

461

'transducer': 'AgAgCl electrodes',

462

'prefilter': 'HP:0.1Hz LP:70Hz'

463

})

464

465

# Create file header

466

file_header = {

467

'technician': 'Dr. Smith',

468

'recording_additional': 'EEG sleep study',

469

'patientname': 'Patient001',

470

'patient_additional': 'Age 25',

471

'patientcode': 'P001',

472

'equipment': 'EEG System v2.1',

473

'admincode': 'ADMIN001',

474

'sex': 'M',

475

'startdate': datetime.now(),

476

'birthdate': '1998-01-15'

477

}

478

479

# Write EDF file

480

with pyedflib.EdfWriter('complete_example.edf', n_channels, pyedflib.FILETYPE_EDFPLUS) as f:

481

# Set headers

482

f.setHeader(file_header)

483

f.setSignalHeaders(signal_headers)

484

485

# Write data

486

f.writeSamples(data)

487

488

# Add annotations

489

f.writeAnnotation(2.0, 0.0, "Eyes closed")

490

f.writeAnnotation(5.0, 1.0, "Sleep spindle")

491

f.writeAnnotation(8.0, 0.0, "Eyes open")

492

493

print("EDF file created successfully!")

494

```

495

496

## Constants

497

498

```python { .api }

499

# File type constants

500

FILETYPE_EDF: int # Standard EDF format

501

FILETYPE_EDFPLUS: int # EDF+ format with annotations

502

FILETYPE_BDF: int # BDF format (24-bit)

503

FILETYPE_BDFPLUS: int # BDF+ format with annotations

504

```