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/__init__.py +101 -0
- segyio/_segyio.cp310-win_amd64.pyd +0 -0
- segyio/_segyio.cp311-win_amd64.pyd +0 -0
- segyio/_segyio.cp312-win_amd64.pyd +0 -0
- segyio/binfield.py +153 -0
- segyio/create.py +314 -0
- segyio/depth.py +180 -0
- segyio/field.py +657 -0
- segyio/gather.py +444 -0
- segyio/line.py +498 -0
- segyio/open.py +306 -0
- segyio/segy.py +1182 -0
- segyio/segyio.cpp +3281 -0
- segyio/segysampleformat.py +19 -0
- segyio/su/__init__.py +2 -0
- segyio/su/file.py +120 -0
- segyio/su/words.py +286 -0
- segyio/tools.py +731 -0
- segyio/trace.py +1624 -0
- segyio/tracefield.py +204 -0
- segyio/tracesortingformat.py +6 -0
- segyio/utils.py +199 -0
- segyio-2.0.0a1.dist-info/METADATA +67 -0
- segyio-2.0.0a1.dist-info/RECORD +25 -0
- segyio-2.0.0a1.dist-info/WHEEL +5 -0
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()
|