segyio 2.0.0a1__cp312-cp312-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
segyio/field.py ADDED
@@ -0,0 +1,657 @@
1
+ try:
2
+ from collections.abc import Mapping # noqa
3
+ from collections.abc import MutableMapping # noqa
4
+ except ImportError:
5
+ from collections import Mapping # noqa
6
+ from collections import MutableMapping # noqa
7
+
8
+ import segyio
9
+ from .binfield import BinField
10
+ from .tracefield import TraceField
11
+
12
+ class Field(MutableMapping):
13
+ """
14
+ The Field implements the dict interface, with a fixed set of keys. It's
15
+ used for both binary- and trace headers. Any modifications to this
16
+ dict_like object will be reflected on disk.
17
+
18
+ The keys can be integers, int_likes, or enumerations such as BinField,
19
+ TraceField, and su. If raw, numerical offsets are used they must align with
20
+ the defined byte offsets by the SEGY specification.
21
+
22
+ Notes
23
+ -----
24
+ .. versionadded:: 1.1
25
+
26
+ .. versionchanged:: 1.3
27
+ common dict operations (update, keys, values)
28
+
29
+ .. versionchanged:: 1.6
30
+ more common dict operations (MutableMapping)
31
+
32
+ .. versionchanged:: 2.0
33
+ Support for SEG-Y revision 2.1
34
+ """
35
+ _bin_keys = [x for x in BinField.enums()
36
+ if x != BinField.Unassigned1
37
+ and x != BinField.Unassigned2]
38
+
39
+ _tr_keys = [x for x in TraceField.enums()
40
+ if x != TraceField.UnassignedInt1
41
+ and x != TraceField.UnassignedInt2]
42
+
43
+ _kwargs = {
44
+ 'tracl' : TraceField.TRACE_SEQUENCE_LINE,
45
+ 'tracr' : TraceField.TRACE_SEQUENCE_FILE,
46
+ 'fldr' : TraceField.FieldRecord,
47
+ 'tracf' : TraceField.TraceNumber,
48
+ 'ep' : TraceField.EnergySourcePoint,
49
+ 'cdp' : TraceField.CDP,
50
+ 'cdpt' : TraceField.CDP_TRACE,
51
+ 'trid' : TraceField.TraceIdentificationCode,
52
+ 'nvs' : TraceField.NSummedTraces,
53
+ 'nhs' : TraceField.NStackedTraces,
54
+ 'duse' : TraceField.DataUse,
55
+ 'offset': TraceField.offset,
56
+ 'gelev' : TraceField.ReceiverGroupElevation,
57
+ 'selev' : TraceField.SourceSurfaceElevation,
58
+ 'sdepth': TraceField.SourceDepth,
59
+ 'gdel' : TraceField.ReceiverDatumElevation,
60
+ 'sdel' : TraceField.SourceDatumElevation,
61
+ 'swdep' : TraceField.SourceWaterDepth,
62
+ 'gwdep' : TraceField.GroupWaterDepth,
63
+ 'scalel': TraceField.ElevationScalar,
64
+ 'scalco': TraceField.SourceGroupScalar,
65
+ 'sx' : TraceField.SourceX,
66
+ 'sy' : TraceField.SourceY,
67
+ 'gx' : TraceField.GroupX,
68
+ 'gy' : TraceField.GroupY,
69
+ 'counit': TraceField.CoordinateUnits,
70
+ 'wevel' : TraceField.WeatheringVelocity,
71
+ 'swevel': TraceField.SubWeatheringVelocity,
72
+ 'sut' : TraceField.SourceUpholeTime,
73
+ 'gut' : TraceField.GroupUpholeTime,
74
+ 'sstat' : TraceField.SourceStaticCorrection,
75
+ 'gstat' : TraceField.GroupStaticCorrection,
76
+ 'tstat' : TraceField.TotalStaticApplied,
77
+ 'laga' : TraceField.LagTimeA,
78
+ 'lagb' : TraceField.LagTimeB,
79
+ 'delrt' : TraceField.DelayRecordingTime,
80
+ 'muts' : TraceField.MuteTimeStart,
81
+ 'mute' : TraceField.MuteTimeEND,
82
+ 'ns' : TraceField.TRACE_SAMPLE_COUNT,
83
+ 'dt' : TraceField.TRACE_SAMPLE_INTERVAL,
84
+ 'gain' : TraceField.GainType,
85
+ 'igc' : TraceField.InstrumentGainConstant,
86
+ 'igi' : TraceField.InstrumentInitialGain,
87
+ 'corr' : TraceField.Correlated,
88
+ 'sfs' : TraceField.SweepFrequencyStart,
89
+ 'sfe' : TraceField.SweepFrequencyEnd,
90
+ 'slen' : TraceField.SweepLength,
91
+ 'styp' : TraceField.SweepType,
92
+ 'stat' : TraceField.SweepTraceTaperLengthStart,
93
+ 'stae' : TraceField.SweepTraceTaperLengthEnd,
94
+ 'tatyp' : TraceField.TaperType,
95
+ 'afilf' : TraceField.AliasFilterFrequency,
96
+ 'afils' : TraceField.AliasFilterSlope,
97
+ 'nofilf': TraceField.NotchFilterFrequency,
98
+ 'nofils': TraceField.NotchFilterSlope,
99
+ 'lcf' : TraceField.LowCutFrequency,
100
+ 'hcf' : TraceField.HighCutFrequency,
101
+ 'lcs' : TraceField.LowCutSlope,
102
+ 'hcs' : TraceField.HighCutSlope,
103
+ 'year' : TraceField.YearDataRecorded,
104
+ 'day' : TraceField.DayOfYear,
105
+ 'hour' : TraceField.HourOfDay,
106
+ 'minute': TraceField.MinuteOfHour,
107
+ 'sec' : TraceField.SecondOfMinute,
108
+ 'timbas': TraceField.TimeBaseCode,
109
+ 'trwf' : TraceField.TraceWeightingFactor,
110
+ 'grnors': TraceField.GeophoneGroupNumberRoll1,
111
+ 'grnofr': TraceField.GeophoneGroupNumberFirstTraceOrigField,
112
+ 'grnlof': TraceField.GeophoneGroupNumberLastTraceOrigField,
113
+ 'gaps' : TraceField.GapSize,
114
+ 'otrav' : TraceField.OverTravel,
115
+ 'cdpx' : TraceField.CDP_X,
116
+ 'cdpy' : TraceField.CDP_Y,
117
+ 'iline' : TraceField.INLINE_3D,
118
+ 'xline' : TraceField.CROSSLINE_3D,
119
+ 'sp' : TraceField.ShotPoint,
120
+ 'scalsp': TraceField.ShotPointScalar,
121
+ 'trunit': TraceField.TraceValueMeasurementUnit,
122
+ 'tdcm' : TraceField.TransductionConstantMantissa,
123
+ 'tdcp' : TraceField.TransductionConstantPower,
124
+ 'tdunit': TraceField.TransductionUnit,
125
+ 'triden': TraceField.TraceIdentifier,
126
+ 'sctrh' : TraceField.ScalarTraceHeader,
127
+ 'stype' : TraceField.SourceType,
128
+ 'sedv' : TraceField.SourceEnergyDirectionVert,
129
+ 'sedxl' : TraceField.SourceEnergyDirectionXline,
130
+ 'sedil' : TraceField.SourceEnergyDirectionIline,
131
+ 'smm' : TraceField.SourceMeasurementMantissa,
132
+ 'sme' : TraceField.SourceMeasurementExponent,
133
+ 'smunit': TraceField.SourceMeasurementUnit,
134
+ 'uint1' : TraceField.UnassignedInt1,
135
+ 'uint2' : TraceField.UnassignedInt2,
136
+
137
+ 'jobid' : BinField.JobID,
138
+ 'lino' : BinField.LineNumber,
139
+ 'reno' : BinField.ReelNumber,
140
+ 'ntrpr' : BinField.EnsembleTraces,
141
+ 'nart' : BinField.AuxEnsembleTraces,
142
+ 'hdt' : BinField.Interval,
143
+ 'dto' : BinField.IntervalOriginal,
144
+ 'hns' : BinField.Samples,
145
+ 'nso' : BinField.SamplesOriginal,
146
+ 'format' : BinField.Format,
147
+ 'fold' : BinField.EnsembleFold,
148
+ 'tsort' : BinField.SortingCode,
149
+ 'vscode' : BinField.VerticalSum,
150
+ 'hsfs' : BinField.SweepFrequencyStart,
151
+ 'hsfe' : BinField.SweepFrequencyEnd,
152
+ 'hslen' : BinField.SweepLength,
153
+ 'hstyp' : BinField.Sweep,
154
+ 'schn' : BinField.SweepChannel,
155
+ 'hstas' : BinField.SweepTaperStart,
156
+ 'hstae' : BinField.SweepTaperEnd,
157
+ 'htatyp' : BinField.Taper,
158
+ 'hcorr' : BinField.CorrelatedTraces,
159
+ 'bgrcv' : BinField.BinaryGainRecovery,
160
+ 'rcvm' : BinField.AmplitudeRecovery,
161
+ 'mfeet' : BinField.MeasurementSystem,
162
+ 'polyt' : BinField.ImpulseSignalPolarity,
163
+ 'vpol' : BinField.VibratoryPolarity,
164
+ 'extntrpr' : BinField.ExtEnsembleTraces,
165
+ 'extnart' : BinField.ExtAuxEnsembleTraces,
166
+ 'exthns' : BinField.ExtSamples,
167
+ 'exthdt' : BinField.ExtInterval,
168
+ 'extdto' : BinField.ExtIntervalOriginal,
169
+ 'extnso' : BinField.ExtSamplesOriginal,
170
+ 'extfold' : BinField.ExtEnsembleFold,
171
+ 'intconst' : BinField.IntConstant,
172
+ 'unas1' : BinField.Unassigned1,
173
+ 'rev' : BinField.SEGYRevision,
174
+ 'revmin' : BinField.SEGYRevisionMinor,
175
+ 'trflag' : BinField.TraceFlag,
176
+ 'exth' : BinField.ExtendedHeaders,
177
+ 'maxtrh' : BinField.MaxAdditionalTraceHeaders,
178
+ 'survty' : BinField.SurveyType,
179
+ 'timebc' : BinField.TimeBasisCode,
180
+ 'ntrst' : BinField.NrTracesInStream,
181
+ 'ftroff' : BinField.FirstTraceOffset,
182
+ 'ntr' : BinField.NrTrailerRecords,
183
+ 'unas2' : BinField.Unassigned2,
184
+ }
185
+
186
+ def __init__(self, segyfile, buf, kind, keys, traceno=None, traceheader_index=None):
187
+ self.kind = kind
188
+ self._keys = keys
189
+ self.traceheader_index = traceheader_index
190
+ self.buf = buf
191
+ self.traceno = traceno
192
+ self.segyfd = segyfile.segyfd
193
+ self.getfield = self.segyfd.getfield
194
+ self.putfield = self.segyfd.putfield
195
+
196
+ self.readonly = segyfile.readonly
197
+
198
+ def fetch(self, buf = None, traceno = None, traceheader_index = None):
199
+ """Fetch the header from disk
200
+
201
+ This object will read header when it is constructed, which means it
202
+ might be out-of-date if the file is updated through some other handle.
203
+ This method is largely meant for internal use - if you need to reload
204
+ disk contents, use ``reload``.
205
+
206
+ Fetch does not update any internal state (unless `buf` is ``None`` on a
207
+ trace header, and the read succeeds), but returns the fetched header
208
+ contents.
209
+
210
+ This method can be used to reposition the trace header, which is useful
211
+ for constructing generators.
212
+
213
+ If this is called on a writable, new file, and this header has not yet
214
+ been written to, it will successfully return an empty buffer that, when
215
+ written to, will be reflected on disk.
216
+
217
+ Parameters
218
+ ----------
219
+ buf : bytearray
220
+ buffer to read into instead of ``self.buf``
221
+ traceno : int
222
+ traceheader_index: int
223
+
224
+ Returns
225
+ -------
226
+ buf : bytearray
227
+
228
+ Notes
229
+ -----
230
+ .. versionadded:: 1.6
231
+
232
+ This method is not intended as user-oriented functionality, but might
233
+ be useful in high-performance code.
234
+ """
235
+
236
+ if buf is None:
237
+ buf = self.buf
238
+
239
+ if traceno is None:
240
+ traceno = self.traceno
241
+ if traceheader_index is None:
242
+ traceheader_index = self.traceheader_index
243
+
244
+ try:
245
+ if self.kind == TraceField:
246
+ if traceno is None: return buf
247
+ if traceheader_index is None: return buf
248
+ return self.segyfd.getth(traceno, traceheader_index, buf)
249
+ else:
250
+ return self.segyfd.getbin()
251
+ except IOError:
252
+ if not self.readonly:
253
+ # the file was probably newly created and the trace header
254
+ # hasn't been written yet, and we set the buffer to zero. if
255
+ # this is the case we want to try and write it later, and if
256
+ # the file was broken, permissions were wrong etc writing will
257
+ # fail too
258
+ #
259
+ # if the file is opened read-only and this happens, there's no
260
+ # way to actually write and the error is an actual error
261
+ return bytearray(len(self.buf))
262
+ else: raise
263
+
264
+ def reload(self):
265
+ """
266
+ This object will read header when it is constructed, which means it
267
+ might be out-of-date if the file is updated through some other handle.
268
+
269
+ It's rarely required to call this method, and it's a symptom of fragile
270
+ code. However, if you have multiple handles to the same header, it
271
+ might be necessary. Consider the following example::
272
+
273
+ >>> x = f.header[10]
274
+ >>> y = f.header[10]
275
+ >>> x[1, 5]
276
+ { 1: 5, 5: 10 }
277
+ >>> y[1, 5]
278
+ { 1: 5, 5: 10 }
279
+ >>> x[1] = 6
280
+ >>> x[1], y[1] # write to x[1] is invisible to y
281
+ 6, 5
282
+ >>> y.reload()
283
+ >>> x[1], y[1]
284
+ 6, 6
285
+ >>> x[1] = 5
286
+ >>> x[1], y[1]
287
+ 5, 6
288
+ >>> y[5] = 1
289
+ >>> x.reload()
290
+ >>> x[1], y[1, 5] # the write to x[1] is lost
291
+ 6, { 1: 6; 5: 1 }
292
+
293
+ In segyio, headers writes are atomic, and the write to disk writes the
294
+ full cache. If this cache is out of date, some writes might get lost,
295
+ even though the updates are compatible.
296
+
297
+ The fix to this issue is either to use ``reload`` and maintain buffer
298
+ consistency, or simply don't let header handles alias and overlap in
299
+ lifetime.
300
+
301
+ Notes
302
+ -----
303
+ .. versionadded:: 1.6
304
+ """
305
+
306
+ self.buf = self.fetch(buf = self.buf)
307
+ return self
308
+
309
+ def flush(self):
310
+ """Commit backing storage to disk
311
+
312
+ This method is largely internal, and it is not necessary to call this
313
+ from user code. It should not be explicitly invoked and may be removed
314
+ in future versions.
315
+ """
316
+
317
+ if self.kind == TraceField:
318
+ self.segyfd.putth(self.traceno, self.traceheader_index, self.buf)
319
+
320
+ elif self.kind == BinField:
321
+ self.segyfd.putbin(self.buf)
322
+
323
+ else:
324
+ msg = 'Object corrupted: kind {} not valid'
325
+ raise RuntimeError(msg.format(self.kind))
326
+
327
+ def __getitem__(self, key):
328
+ """d[key]
329
+
330
+ Read the associated value of `key`.
331
+
332
+ `key` can be any iterable, to retrieve multiple keys at once. In this
333
+ case, a mapping of key -> value is returned.
334
+
335
+ Parameters
336
+ ----------
337
+ key : int, or iterable of int
338
+
339
+ Returns
340
+ -------
341
+ value : int, float, bytearray or dict_like
342
+
343
+ Notes
344
+ -----
345
+ .. versionadded:: 1.1
346
+
347
+ .. note::
348
+ Since version 1.6, KeyError is appropriately raised on key misses,
349
+ whereas ``IndexError`` was raised before. This is an old bug, since
350
+ header types were documented to be dict-like. If you rely on
351
+ catching key-miss errors in your code, you might want to handle
352
+ both ``IndexError`` and ``KeyError`` for multi-version robustness.
353
+
354
+ .. warning::
355
+ segyio considers reads/writes full headers, not individual fields,
356
+ and does the read from disk when this class is constructed. If the
357
+ file is updated through some other handle, including a secondary
358
+ access via `f.header`, this cache might be out-of-date.
359
+
360
+ Examples
361
+ --------
362
+ Read a single value:
363
+
364
+ >>> d[3213]
365
+ 15000
366
+
367
+ Read multiple values at once:
368
+
369
+ >>> d[37, 189]
370
+ { 37: 5, 189: 2484 }
371
+ >>> d[37, TraceField.INLINE_3D]
372
+ { 37: 5, 189: 2484 }
373
+ """
374
+
375
+ try: return self.getfield(self.buf, self.traceheader_index, int(key))
376
+ except TypeError: pass
377
+
378
+ return {self.kind(k): self.getfield(self.buf, self.traceheader_index, int(k)) for k in key}
379
+
380
+
381
+ def __setitem__(self, key, val):
382
+ """d[key] = val
383
+
384
+ Set d[key] to val. Setting keys commits changes to disk, although the
385
+ changes may not be visible until the kernel schedules the write.
386
+
387
+ Unlike d[key], this method does not support assigning multiple values
388
+ at once. To set multiple values at once, use the `update` method.
389
+
390
+ Attempting to set value of the type not supported by the trace header
391
+ layout at the `key` offset will result in error.
392
+
393
+ Parameters
394
+ ----------
395
+ key : int_like
396
+ val : int_like or float_like
397
+
398
+ Returns
399
+ -------
400
+ val : int or float
401
+ The value set
402
+
403
+ Notes
404
+ -----
405
+ .. versionadded:: 1.1
406
+
407
+ .. note::
408
+ Since version 1.6, KeyError is appropriately raised on key misses,
409
+ whereas ``IndexError`` was raised before. This is an old bug, since
410
+ header types were documented to be dict-like. If you rely on
411
+ catching key-miss errors in your code, you might want to handle
412
+ both ``IndexError`` and ``KeyError`` for multi-version robustness.
413
+
414
+ .. warning::
415
+ segyio considers reads/writes full headers, not individual fields,
416
+ and does the read from disk when this class is constructed. If the
417
+ file is updated through some other handle, including a secondary
418
+ access via `f.header`, this cache might be out-of-date. That means
419
+ writing an individual field will write the full header to disk,
420
+ possibly overwriting previously set values.
421
+
422
+ Examples
423
+ --------
424
+ Set a value and keep in a variable:
425
+
426
+ >>> x = header[189] = 5
427
+ >>> x
428
+ 5
429
+ """
430
+
431
+ self.putfield(self.buf, self.traceheader_index, key, val)
432
+ self.flush()
433
+
434
+ return val
435
+
436
+ def __delitem__(self, key):
437
+ """del d[key]
438
+
439
+ 'Delete' the key by setting value to zero. Equivalent to ``d[key] =
440
+ 0``.
441
+
442
+ Notes
443
+ -----
444
+ .. versionadded:: 1.6
445
+ """
446
+
447
+ self[key] = 0
448
+
449
+ def keys(self):
450
+ """D.keys() -> a set-like object providing a view on D's keys"""
451
+ return list(self._keys)
452
+
453
+ def __len__(self):
454
+ """x.__len__() <==> len(x)"""
455
+ return len(self._keys)
456
+
457
+ def __iter__(self):
458
+ """x.__iter__() <==> iter(x)"""
459
+ return iter(self._keys)
460
+
461
+ def __eq__(self, other):
462
+ """x.__eq__(y) <==> x == y"""
463
+
464
+ if not isinstance(other, Mapping):
465
+ return NotImplemented
466
+
467
+ if len(self) != len(other):
468
+ return False
469
+
470
+ def intkeys(d):
471
+ return { int(k): v for k, v in d.items() }
472
+
473
+ return intkeys(self) == intkeys(other)
474
+
475
+
476
+ def update(self, *args, **kwargs):
477
+ """d.update([E, ]**F) -> None. Update D from mapping/iterable E and F.
478
+
479
+ Overwrite the values in `d` with the keys from `E` and `F`. If any key
480
+ in `value` is invalid in `d`, ``KeyError`` is raised.
481
+
482
+ This method is atomic - either all values in `value` are set in `d`, or
483
+ none are. ``update`` does not commit a partially-updated version to
484
+ disk.
485
+
486
+ For kwargs, Seismic Unix-style names are supported. `BinField` and
487
+ `TraceField` are not, because there are name collisions between them,
488
+ although this restriction may be lifted in the future.
489
+
490
+ Notes
491
+ -----
492
+ .. versionchanged:: 1.3
493
+ Support for common dict operations (update, keys, values)
494
+
495
+ .. versionchanged:: 1.6
496
+ Atomicity guarantee
497
+
498
+ .. versionchanged:: 1.6
499
+ `**kwargs` support
500
+
501
+ Examples
502
+ --------
503
+ >>> e = { 1: 10, 9: 5 }
504
+ >>> d.update(e)
505
+ >>> l = [ (105, 11), (169, 4) ]
506
+ >>> d.update(l)
507
+ >>> d.update(e, iline=189, xline=193, hour=5)
508
+ >>> d.update(sx=7)
509
+
510
+ """
511
+
512
+ if len(args) > 1:
513
+ msg = 'update expected at most 1 non-keyword argument, got {}'
514
+ raise TypeError(msg.format(len(args)))
515
+
516
+ buf = bytearray(self.buf)
517
+
518
+ # Implementation largely borrowed from Mapping
519
+ # If E present and has a .keys() method: for k in E: D[k] = E[k]
520
+ # If E present and lacks .keys() method: for (k, v) in E: D[k] = v
521
+ # In either case, this is followed by: for k, v in F.items(): D[k] = v
522
+ if len(args) == 1:
523
+ other = args[0]
524
+ if isinstance(other, Mapping):
525
+ for key in other:
526
+ self.putfield(buf, self.traceheader_index, int(key), other[key])
527
+ elif hasattr(other, "keys"):
528
+ for key in other.keys():
529
+ self.putfield(buf, self.traceheader_index, int(key), other[key])
530
+ else:
531
+ for key, value in other:
532
+ self.putfield(buf, self.traceheader_index, int(key), value)
533
+
534
+ for key, value in kwargs.items():
535
+ self.putfield(buf, self.traceheader_index, int(self._kwargs[key]), value)
536
+
537
+ self.buf = buf
538
+ self.flush()
539
+
540
+ @classmethod
541
+ def binary(cls, segyfile):
542
+ buf = bytearray(segyio._segyio.binsize())
543
+ return Field(segyfile, buf, kind=BinField, keys=Field._bin_keys).reload()
544
+
545
+ @classmethod
546
+ def trace(cls, traceno, traceheader_index, segyfile):
547
+ buf = bytearray(segyio._segyio.thsize())
548
+ return Field(
549
+ segyfile, buf, kind=TraceField, keys=Field._tr_keys,
550
+ traceno=traceno, traceheader_index=traceheader_index,
551
+ ).reload()
552
+
553
+ def __repr__(self):
554
+ return repr(self[self.keys()])
555
+
556
+
557
+ class HeaderFieldAccessor(Field):
558
+ """
559
+ Same as :class:`Field`, only to be used with
560
+ :meth:`segyio.SegyFile.traceheader` interface.
561
+
562
+ Notes
563
+ -----
564
+ .. versionadded:: 2.0
565
+ """
566
+
567
+ def __init__(self, segyfile, buf, keys, traceno=None, traceheader_index=None):
568
+ self.segyfile = segyfile
569
+ self.traceheader_index = traceheader_index
570
+ super().__init__(segyfile, buf, TraceField, keys, traceno, traceheader_index)
571
+
572
+ def __getattr__(self, name):
573
+ """d.name
574
+
575
+ Read the associated value of `name`. `name` must be a name defined by
576
+ the layout on trace header.
577
+
578
+ Wrapper around :meth:`.__getitem__`, so refer to it for more
579
+ information.
580
+
581
+ Parameters
582
+ ----------
583
+ name : str
584
+
585
+ Returns
586
+ -------
587
+ value : int, float of bytearray
588
+
589
+ Notes
590
+ -----
591
+ .. versionadded:: 2.0
592
+
593
+ Examples
594
+ --------
595
+ Read a single value:
596
+
597
+ >>> d.linetrc
598
+ 1005
599
+ """
600
+ layout = self.segyfile._traceheader_entries[self.traceheader_index]
601
+ entry = layout.entry_by_name(name)
602
+ return self[entry.byte]
603
+
604
+ def __setattr__(self, name, value):
605
+ """d.name = value
606
+
607
+ Set d.name to value. `name` must be a name defined by
608
+ the layout on trace header.
609
+
610
+ Wrapper around :meth:`.__setitem__`, so refer to it for more
611
+ information.
612
+
613
+ Parameters
614
+ ----------
615
+ name : str
616
+ value : int_like or float_like
617
+
618
+ Returns
619
+ -------
620
+ val : int or float
621
+ The value set
622
+
623
+ Notes
624
+ -----
625
+ .. versionadded:: 2.0
626
+
627
+ Examples
628
+ --------
629
+ Set a value:
630
+
631
+ >>> header.linetrc = 1006
632
+ """
633
+ # note: adding this function directly to Field slowed down original
634
+ # interface. so a new subclass was created to set new performance
635
+ # baselines
636
+ if name == "segyfile" or name == "traceheader_index":
637
+ super().__setattr__(name, value)
638
+ return
639
+ if self.traceheader_index != None:
640
+ layout = self.segyfile._traceheader_entries[self.traceheader_index]
641
+ entry = layout.entry_by_name(name)
642
+ if entry != None:
643
+ self[entry.byte] = value
644
+ return
645
+
646
+ super().__setattr__(name, value)
647
+
648
+ @classmethod
649
+ def trace(cls, traceno, traceheader_index, segyfile):
650
+ buf = bytearray(segyio._segyio.thsize())
651
+ keys = []
652
+ if traceheader_index != None:
653
+ layout = segyfile._traceheader_entries[traceheader_index]
654
+ keys = layout._by_byte.keys()
655
+ return HeaderFieldAccessor(
656
+ segyfile, buf, keys, traceno=traceno, traceheader_index=traceheader_index,
657
+ ).reload()