or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

data-access.mdfile-operations.mdheader-access.mdindex.mdseismic-unix.mdutilities.md

utilities.mddocs/

0

# Utilities

1

2

Helper functions for format conversion, metadata extraction, array-to-SEG-Y conversion, and common seismic processing operations. These utilities simplify common workflows and provide high-level convenience functions.

3

4

## Capabilities

5

6

### Sample Rate and Timing

7

8

Functions for working with sample rates, timing information, and creating sample indices.

9

10

```python { .api }

11

def dt(f, fallback_dt=4000.0):

12

"""

13

Infer sample rate from SEG-Y file.

14

15

Parameters:

16

- f (SegyFile): Open SEG-Y file handle

17

- fallback_dt (float): Fallback sample rate in microseconds if cannot be determined

18

19

Returns:

20

float: Sample interval in microseconds

21

22

Raises:

23

ValueError: If sample rate cannot be determined and no fallback provided

24

"""

25

26

def sample_indexes(segyfile, t0=0.0, dt_override=None):

27

"""

28

Create sample index list at specified depth/time values.

29

30

Parameters:

31

- segyfile (SegyFile): Open SEG-Y file handle

32

- t0 (float): Start time in milliseconds, default 0.0

33

- dt_override (float): Override sample rate in milliseconds

34

35

Returns:

36

numpy.ndarray: Array of sample indices/times

37

"""

38

```

39

40

**Usage Example:**

41

42

```python

43

import segyio

44

import numpy as np

45

46

with segyio.open('data.sgy') as f:

47

# Get sample rate

48

sample_rate = segyio.dt(f)

49

print(f"Sample rate: {sample_rate} microseconds ({sample_rate/1000} ms)")

50

51

# Create time axis

52

times = segyio.sample_indexes(f, t0=0.0)

53

print(f"Time range: {times[0]} to {times[-1]} ms")

54

55

# Create custom time axis with different start time

56

delayed_times = segyio.sample_indexes(f, t0=100.0) # Start at 100ms

57

58

# Override sample rate

59

custom_times = segyio.sample_indexes(f, dt_override=2.0) # 2ms sampling

60

```

61

62

### Text Header Formatting

63

64

Utilities for creating and formatting SEG-Y textual headers.

65

66

```python { .api }

67

def create_text_header(lines):

68

"""

69

Format textual header from line dictionary.

70

71

Parameters:

72

- lines (dict): Line number to text mapping (1-40)

73

74

Returns:

75

str: Formatted EBCDIC header string (3200 bytes)

76

77

Raises:

78

ValueError: Invalid line numbers or content

79

"""

80

```

81

82

**Usage Example:**

83

84

```python

85

import segyio

86

87

# Create custom textual header

88

header_lines = {

89

1: "C 1 CLIENT: EXAMPLE SEISMIC COMPANY",

90

2: "C 2 DATA TYPE: MIGRATED 3D SEISMIC DATA",

91

3: "C 3 AREA: NORTH SEA BLOCK 123/45",

92

4: "C 4 ",

93

5: "C 5 PROCESSING SEQUENCE:",

94

6: "C 6 1. DEMULTIPLE",

95

7: "C 7 2. DECONVOLUTION",

96

8: "C 8 3. VELOCITY ANALYSIS",

97

9: "C 9 4. DMO CORRECTION",

98

10: "C10 5. POST-STACK TIME MIGRATION",

99

11: "C11 ",

100

12: "C12 DATUM: MEAN SEA LEVEL",

101

13: "C13 COORDINATE SYSTEM: UTM ZONE 31N",

102

14: "C14 SAMPLE RATE: 4 MS",

103

15: "C15 RECORD LENGTH: 2000 MS"

104

}

105

106

text_header = segyio.create_text_header(header_lines)

107

108

# Use in file creation

109

spec = segyio.spec()

110

# ... configure spec ...

111

112

with segyio.create('output.sgy', spec) as f:

113

f.text[0] = text_header

114

```

115

116

### Data Format Conversion

117

118

Functions for converting between different data formats and handling IBM floating point.

119

120

```python { .api }

121

def native(data, format=SegySampleFormat.IBM_FLOAT_4_BYTE, copy=True):

122

"""

123

Convert numpy array to native float format.

124

125

Parameters:

126

- data (numpy.ndarray): Input data array

127

- format (int or SegySampleFormat): Source data format

128

- copy (bool): Whether to copy data or modify in-place

129

130

Returns:

131

numpy.ndarray: Data converted to native float format

132

133

Raises:

134

ValueError: Unsupported format or invalid data

135

"""

136

```

137

138

**Usage Example:**

139

140

```python

141

import segyio

142

import numpy as np

143

144

with segyio.open('ibm_data.sgy') as f:

145

# Read trace with IBM float format

146

ibm_trace = f.trace[0]

147

148

# Convert to native IEEE float

149

ieee_trace = segyio.native(ibm_trace, segyio.SegySampleFormat.IBM_FLOAT_4_BYTE)

150

151

# Check format in binary header

152

format_code = f.bin[segyio.BinField.Format]

153

if format_code == segyio.SegySampleFormat.IBM_FLOAT_4_BYTE:

154

print("Converting from IBM to IEEE float")

155

converted = segyio.native(ibm_trace, format_code)

156

else:

157

converted = ibm_trace # Already in native format

158

```

159

160

### Data Collection and Aggregation

161

162

Functions for collecting and combining trace data into larger arrays.

163

164

```python { .api }

165

def collect(itr):

166

"""

167

Collect iterable of traces/lines into single ndarray.

168

169

Parameters:

170

- itr (iterable): Iterable of numpy.ndarray objects (traces, lines, etc.)

171

172

Returns:

173

numpy.ndarray: Combined array with additional dimension

174

175

Raises:

176

ValueError: Inconsistent array shapes

177

"""

178

179

def cube(f):

180

"""

181

Read full 3D cube from file into memory.

182

183

Parameters:

184

- f (str or SegyFile): File path or open file handle

185

186

Returns:

187

numpy.ndarray: 3D array (inlines, crosslines, samples)

188

189

Raises:

190

ValueError: File is not 3D structured

191

MemoryError: Insufficient memory for cube

192

"""

193

```

194

195

**Usage Example:**

196

197

```python

198

import segyio

199

import numpy as np

200

201

# Read and collect multiple inlines

202

with segyio.open('3d_data.sgy') as f:

203

# Collect first 10 inlines into 3D array

204

inline_list = [f.iline[il] for il in f.ilines[:10]]

205

collected_inlines = segyio.collect(inline_list)

206

print(f"Collected shape: {collected_inlines.shape}")

207

208

# Read full cube (memory intensive!)

209

full_cube = segyio.cube(f)

210

print(f"Full cube shape: {full_cube.shape}")

211

212

# Collect traces with processing

213

with segyio.open('data.sgy') as f:

214

def process_trace(trace):

215

# Apply some processing

216

return trace * 2.0 # Simple gain

217

218

processed_traces = segyio.collect(

219

process_trace(f.trace[i]) for i in range(min(100, f.tracecount))

220

)

221

```

222

223

### Survey Metadata Extraction

224

225

Functions for extracting survey metadata and geometry information.

226

227

```python { .api }

228

def rotation(f, line='fast'):

229

"""

230

Find rotation angle of survey.

231

232

Parameters:

233

- f (SegyFile): Open SEG-Y file handle

234

- line (str): 'fast' or 'slow' dimension

235

236

Returns:

237

tuple: (rotation_angle, cdpx_center, cdpy_center)

238

"""

239

240

def metadata(f):

241

"""

242

Extract survey metadata as spec object.

243

244

Parameters:

245

- f (str or SegyFile): File path or open file handle

246

247

Returns:

248

segyio.spec: Specification object containing file metadata

249

"""

250

```

251

252

**Usage Example:**

253

254

```python

255

import segyio

256

257

# Analyze survey rotation

258

with segyio.open('3d_survey.sgy') as f:

259

rotation_angle, center_x, center_y = segyio.rotation(f)

260

print(f"Survey rotation: {rotation_angle:.2f} degrees")

261

print(f"Survey center: ({center_x:.2f}, {center_y:.2f})")

262

263

# Extract complete metadata

264

survey_spec = segyio.metadata('survey.sgy')

265

print(f"Inline range: {survey_spec.ilines}")

266

print(f"Crossline range: {survey_spec.xlines}")

267

print(f"Sample count: {len(survey_spec.samples)}")

268

print(f"Data format: {survey_spec.format}")

269

```

270

271

### Array-to-SEG-Y Conversion

272

273

Functions for creating SEG-Y files from numpy arrays with various geometries.

274

275

```python { .api }

276

def from_array(filename, data, iline=189, xline=193, format=SegySampleFormat.IBM_FLOAT_4_BYTE, dt=4000, delrt=0):

277

"""

278

Create SEG-Y file from n-dimensional numpy array.

279

280

Parameters:

281

- filename (str): Output file path

282

- data (numpy.ndarray): Input data array

283

- iline (int): Inline header field number

284

- xline (int): Crossline header field number

285

- format (SegySampleFormat): Output data format

286

- dt (int): Sample interval in microseconds

287

- delrt (int): Delay recording time in milliseconds

288

289

Returns:

290

None: Creates file on disk

291

"""

292

293

def from_array2D(filename, data, format=SegySampleFormat.IBM_FLOAT_4_BYTE, dt=4000, delrt=0):

294

"""

295

Create SEG-Y file from 2D array (shot records).

296

297

Parameters:

298

- filename (str): Output file path

299

- data (numpy.ndarray): 2D array (traces, samples)

300

- format (SegySampleFormat): Output data format

301

- dt (int): Sample interval in microseconds

302

- delrt (int): Delay recording time in milliseconds

303

304

Returns:

305

None: Creates file from 2D geometry

306

"""

307

308

def from_array3D(filename, data, iline=189, xline=193, format=SegySampleFormat.IBM_FLOAT_4_BYTE, dt=4000, delrt=0):

309

"""

310

Create SEG-Y file from 3D array (post-stack volume).

311

312

Parameters:

313

- filename (str): Output file path

314

- data (numpy.ndarray): 3D array (inlines, crosslines, samples)

315

- iline (int): Inline header field number

316

- xline (int): Crossline header field number

317

- format (SegySampleFormat): Output data format

318

- dt (int): Sample interval in microseconds

319

- delrt (int): Delay recording time in milliseconds

320

321

Returns:

322

None: Creates file from 3D geometry

323

"""

324

325

def from_array4D(filename, data, iline=189, xline=193, format=SegySampleFormat.IBM_FLOAT_4_BYTE, dt=4000, delrt=0):

326

"""

327

Create SEG-Y file from 4D array (pre-stack volume).

328

329

Parameters:

330

- filename (str): Output file path

331

- data (numpy.ndarray): 4D array (inlines, crosslines, offsets, samples)

332

- iline (int): Inline header field number

333

- xline (int): Crossline header field number

334

- format (SegySampleFormat): Output data format

335

- dt (int): Sample interval in microseconds

336

- delrt (int): Delay recording time in milliseconds

337

338

Returns:

339

None: Creates file from 4D geometry

340

"""

341

```

342

343

**Usage Example:**

344

345

```python

346

import segyio

347

import numpy as np

348

349

# Create synthetic seismic data

350

ni, nx, nt = 50, 40, 500 # 50 inlines, 40 crosslines, 500 samples

351

synthetic_data = np.random.randn(ni, nx, nt).astype(np.float32)

352

353

# Add some realistic seismic features

354

for i in range(ni):

355

for j in range(nx):

356

# Add a reflector at 200ms

357

synthetic_data[i, j, 50:60] += 0.5 * np.sin(np.linspace(0, 4*np.pi, 10))

358

359

# Convert to SEG-Y

360

segyio.from_array3D(

361

'synthetic_3d.sgy',

362

synthetic_data,

363

format=segyio.SegySampleFormat.IEEE_FLOAT_4_BYTE,

364

dt=4000, # 4ms sampling

365

delrt=0 # Start at 0ms

366

)

367

368

# 2D seismic line (shot records)

369

shot_data = np.random.randn(120, 1000).astype(np.float32) # 120 traces, 1000 samples

370

segyio.from_array2D('shot_record.sgy', shot_data, dt=2000) # 2ms sampling

371

372

# 4D pre-stack data

373

prestack_data = np.random.randn(30, 25, 5, 750).astype(np.float32) # 5 offsets

374

segyio.from_array4D('prestack_4d.sgy', prestack_data, dt=4000)

375

```

376

377

### File Resampling

378

379

Destructive resampling operations for changing sample rates and timing.

380

381

```python { .api }

382

def resample(f, rate=None, delay=None, micro=False, trace=True, binary=True):

383

"""

384

Resample file traces (destructive operation).

385

386

Parameters:

387

- f (SegyFile): File handle (must be writable)

388

- rate (float): New sample rate

389

- delay (float): New delay time

390

- micro (bool): Whether rate/delay are in microseconds

391

- trace (bool): Update trace headers

392

- binary (bool): Update binary header

393

394

Returns:

395

SegyFile: Modified file handle

396

397

Raises:

398

ValueError: Invalid resampling parameters

399

RuntimeError: File not writable

400

"""

401

```

402

403

**Usage Example:**

404

405

```python

406

import segyio

407

408

# Resample file from 4ms to 2ms

409

with segyio.open('input_4ms.sgy', 'r+') as f:

410

print(f"Original sample rate: {segyio.dt(f)/1000} ms")

411

412

# Resample to 2ms (note: this is destructive!)

413

segyio.resample(f, rate=2.0, micro=False) # 2ms

414

415

print(f"New sample rate: {segyio.dt(f)/1000} ms")

416

417

# Update delay time to 100ms

418

segyio.resample(f, delay=100.0, micro=False)

419

```

420

421

## Processing Workflows

422

423

### Quality Control Pipeline

424

425

```python

426

def qc_workflow(input_file, output_report):

427

"""Complete QC workflow for SEG-Y files."""

428

report = {}

429

430

with segyio.open(input_file) as f:

431

# Basic file information

432

report['filename'] = input_file

433

report['traces'] = f.tracecount

434

report['samples'] = len(f.samples)

435

report['sample_rate'] = segyio.dt(f) / 1000 # ms

436

437

# Geometry analysis

438

if not f.unstructured:

439

report['inlines'] = len(f.ilines)

440

report['crosslines'] = len(f.xlines)

441

report['offsets'] = len(f.offsets)

442

443

# Survey rotation

444

rotation_angle, _, _ = segyio.rotation(f)

445

report['rotation'] = rotation_angle

446

447

# Amplitude analysis

448

sample_traces = [f.trace[i] for i in range(0, f.tracecount, max(1, f.tracecount//100))]

449

all_samples = np.concatenate(sample_traces)

450

451

report['amplitude_stats'] = {

452

'min': float(all_samples.min()),

453

'max': float(all_samples.max()),

454

'mean': float(all_samples.mean()),

455

'std': float(all_samples.std())

456

}

457

458

# Save report

459

import json

460

with open(output_report, 'w') as f:

461

json.dump(report, f, indent=2)

462

463

return report

464

```

465

466

### Data Conversion Pipeline

467

468

```python

469

def convert_to_ieee(input_file, output_file):

470

"""Convert IBM float SEG-Y to IEEE float format."""

471

with segyio.open(input_file) as src:

472

# Check current format

473

current_format = src.bin[segyio.BinField.Format]

474

475

if current_format != segyio.SegySampleFormat.IBM_FLOAT_4_BYTE:

476

print("File is not IBM float format")

477

return

478

479

# Create new file spec

480

spec = segyio.metadata(src)

481

spec.format = segyio.SegySampleFormat.IEEE_FLOAT_4_BYTE

482

483

with segyio.create(output_file, spec) as dst:

484

# Copy and convert data

485

for i in range(src.tracecount):

486

ibm_trace = src.trace[i]

487

ieee_trace = segyio.native(ibm_trace, current_format)

488

dst.trace[i] = ieee_trace

489

490

# Copy headers

491

dst.header[i] = src.header[i]

492

493

# Copy text headers

494

for i in range(src.ext_headers + 1):

495

dst.text[i] = src.text[i]

496

497

# Update binary header

498

for field in [segyio.BinField.Samples, segyio.BinField.Interval,

499

segyio.BinField.Traces, segyio.BinField.Format]:

500

dst.bin[field] = src.bin[field]

501

502

# Set new format

503

dst.bin[segyio.BinField.Format] = segyio.SegySampleFormat.IEEE_FLOAT_4_BYTE

504

```