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/line.py
ADDED
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
try:
|
|
2
|
+
from collections.abc import Mapping # noqa
|
|
3
|
+
except ImportError:
|
|
4
|
+
from collections import Mapping # noqa
|
|
5
|
+
|
|
6
|
+
import itertools
|
|
7
|
+
try: from future_builtins import zip
|
|
8
|
+
except ImportError: pass
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
from .utils import castarray
|
|
12
|
+
|
|
13
|
+
# in order to support [:end] syntax, we must make sure
|
|
14
|
+
# start has a non-None value. lineno.indices() would set it
|
|
15
|
+
# to 0, but we don't know if that's a reasonable value or
|
|
16
|
+
# not. If start is None we set it to the first line
|
|
17
|
+
def sanitize_slice(s, source):
|
|
18
|
+
if all((s.start, s.stop, s.step)):
|
|
19
|
+
return s
|
|
20
|
+
|
|
21
|
+
start, stop, step = s.start, s.stop, s.step
|
|
22
|
+
increasing = step is None or step > 0
|
|
23
|
+
|
|
24
|
+
if start is None:
|
|
25
|
+
start = min(source) if increasing else max(source)
|
|
26
|
+
|
|
27
|
+
if stop is None:
|
|
28
|
+
stop = max(source) + 1 if increasing else min(source) - 1
|
|
29
|
+
|
|
30
|
+
return slice(start, stop, step)
|
|
31
|
+
|
|
32
|
+
class Line(Mapping):
|
|
33
|
+
"""
|
|
34
|
+
The Line implements the dict interface, with a fixed set of int_like keys,
|
|
35
|
+
the line numbers/labels. Data is read lazily from disk, so iteration does
|
|
36
|
+
not consume much memory, and are returned as numpy.ndarrays.
|
|
37
|
+
|
|
38
|
+
It provides a convenient interface for reading data in a cartesian grid
|
|
39
|
+
system, provided one exists and is detectable by segyio.
|
|
40
|
+
|
|
41
|
+
Lines can be accessed individually or with slices, and writing is done via
|
|
42
|
+
assignment. Note that accessing lines uses the line numbers, not their
|
|
43
|
+
position, so if a files has lines [2400..2500], accessing line [0..100]
|
|
44
|
+
will be an error. Note that since each line is returned as a numpy.ndarray,
|
|
45
|
+
meaning accessing the intersections of the inline and crossline is
|
|
46
|
+
0-indexed - orthogonal labels are not preserved.
|
|
47
|
+
|
|
48
|
+
Additionally, the line has a concept of offsets, which is useful when
|
|
49
|
+
dealing with prestack files. Offsets are accessed via sub indexing, meaning
|
|
50
|
+
iline[10, 4] will give you line 10 at offset 4. Please note that offset,
|
|
51
|
+
like lines, are accessed via their labels, not their indices. If your file
|
|
52
|
+
has the offsets [150, 250, 350, 450] and the lines [2400..2500], you can
|
|
53
|
+
access the third offset with [2403, 350]. Please refer to the examples for
|
|
54
|
+
more details. If no offset is specified, segyio will give you the first.
|
|
55
|
+
|
|
56
|
+
Notes
|
|
57
|
+
-----
|
|
58
|
+
.. versionadded:: 1.1
|
|
59
|
+
|
|
60
|
+
.. versionchanged:: 1.6
|
|
61
|
+
common dict operations (Mapping)
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
def __init__(self, segyfile, labels, length, stride, offsets, name):
|
|
65
|
+
self.segyfd = segyfile.segyfd
|
|
66
|
+
self.lines = labels
|
|
67
|
+
self.length = length
|
|
68
|
+
self.stride = stride
|
|
69
|
+
self.shape = (length, len(segyfile.samples))
|
|
70
|
+
self.dtype = segyfile.dtype
|
|
71
|
+
|
|
72
|
+
# pre-compute all line beginnings
|
|
73
|
+
from ._segyio import fread_trace0
|
|
74
|
+
self.heads = {
|
|
75
|
+
label: fread_trace0(label,
|
|
76
|
+
length,
|
|
77
|
+
stride,
|
|
78
|
+
len(offsets),
|
|
79
|
+
labels,
|
|
80
|
+
name)
|
|
81
|
+
for label in labels
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
self.offsets = { x: i for i, x in enumerate(offsets) }
|
|
85
|
+
self.default_offset = offsets[0]
|
|
86
|
+
|
|
87
|
+
def ranges(self, index, offset):
|
|
88
|
+
if not isinstance(index, slice):
|
|
89
|
+
index = slice(index, index + 1)
|
|
90
|
+
|
|
91
|
+
if not isinstance(offset, slice):
|
|
92
|
+
offset = slice(offset, offset + 1)
|
|
93
|
+
|
|
94
|
+
index = sanitize_slice(index, self.heads.keys())
|
|
95
|
+
offset = sanitize_slice(offset, self.offsets.keys())
|
|
96
|
+
irange = range(*index.indices(max(self.heads.keys()) + 1))
|
|
97
|
+
orange = range(*offset.indices(max(self.offsets.keys()) + 1))
|
|
98
|
+
irange = filter(self.heads.__contains__, irange)
|
|
99
|
+
orange = filter(self.offsets.__contains__, orange)
|
|
100
|
+
# offset-range is used in inner loops, so make it a list for
|
|
101
|
+
# reusability. offsets are usually few, so no real punishment by using
|
|
102
|
+
# non-generators here
|
|
103
|
+
return irange, list(orange)
|
|
104
|
+
|
|
105
|
+
def __getitem__(self, index):
|
|
106
|
+
"""line[i] or line[i, o]
|
|
107
|
+
|
|
108
|
+
The line `i`, or the line `i` at a specific offset `o`. ``line[i]``
|
|
109
|
+
returns a numpy array, and changes to this array will *not* be
|
|
110
|
+
reflected on disk.
|
|
111
|
+
|
|
112
|
+
The `i` and `o` are *keys*, and should correspond to the line- and
|
|
113
|
+
offset labels in your file, and in the `ilines`, `xlines`, and
|
|
114
|
+
`offsets` attributes.
|
|
115
|
+
|
|
116
|
+
Slices can contain lines and offsets not in the file, and like with
|
|
117
|
+
list slicing, these are handled gracefully and ignored.
|
|
118
|
+
|
|
119
|
+
When `i` or `o` is a slice, a generator of numpy arrays is returned. If
|
|
120
|
+
the slice is defaulted (:), segyio knows enough about the structure to
|
|
121
|
+
give you all of the respective labels.
|
|
122
|
+
|
|
123
|
+
When both `i` and `o` are slices, only one generator is returned, and
|
|
124
|
+
the lines are yielded offsets-first, roughly equivalent to the double
|
|
125
|
+
for loop::
|
|
126
|
+
|
|
127
|
+
>>> for line in lines:
|
|
128
|
+
... for off in offsets:
|
|
129
|
+
... yield line[line, off]
|
|
130
|
+
...
|
|
131
|
+
|
|
132
|
+
Parameters
|
|
133
|
+
----------
|
|
134
|
+
i : int or slice
|
|
135
|
+
o : int or slice
|
|
136
|
+
|
|
137
|
+
Returns
|
|
138
|
+
-------
|
|
139
|
+
line : numpy.ndarray of dtype or generator of numpy.ndarray of dtype
|
|
140
|
+
|
|
141
|
+
Raises
|
|
142
|
+
------
|
|
143
|
+
KeyError
|
|
144
|
+
If `i` or `o` don't exist
|
|
145
|
+
|
|
146
|
+
Notes
|
|
147
|
+
-----
|
|
148
|
+
.. versionadded:: 1.1
|
|
149
|
+
|
|
150
|
+
Examples
|
|
151
|
+
--------
|
|
152
|
+
|
|
153
|
+
Read an inline:
|
|
154
|
+
|
|
155
|
+
>>> x = line[2400]
|
|
156
|
+
|
|
157
|
+
Copy every inline into a list:
|
|
158
|
+
|
|
159
|
+
>>> l = [numpy.copy(x) for x in iline[:]]
|
|
160
|
+
|
|
161
|
+
Numpy operations on every other inline:
|
|
162
|
+
|
|
163
|
+
>>> for line in line[::2]:
|
|
164
|
+
... line = line * 2
|
|
165
|
+
... avg = np.average(line)
|
|
166
|
+
|
|
167
|
+
Read lines up to 2430:
|
|
168
|
+
|
|
169
|
+
>>> for line in line[:2430]:
|
|
170
|
+
... line.mean()
|
|
171
|
+
|
|
172
|
+
Copy all lines at all offsets:
|
|
173
|
+
|
|
174
|
+
>>> l = [numpy.copy(x) for x in line[:,:]]
|
|
175
|
+
|
|
176
|
+
Copy all offsets of a line:
|
|
177
|
+
|
|
178
|
+
>>> x = numpy.copy(iline[10,:])
|
|
179
|
+
|
|
180
|
+
Copy all lines at a fixed offset:
|
|
181
|
+
|
|
182
|
+
>>> x = numpy.copy(iline[:, 120])
|
|
183
|
+
|
|
184
|
+
Copy every other line and offset:
|
|
185
|
+
|
|
186
|
+
>>> map(numpy.copy, line[::2, ::2])
|
|
187
|
+
|
|
188
|
+
Copy all offsets [200, 250, 300, 350, ...] in the range [200, 800) for
|
|
189
|
+
all lines [2420,2460):
|
|
190
|
+
|
|
191
|
+
>>> l = [numpy.copy(x) for x in line[2420:2460, 200:800:50]]
|
|
192
|
+
"""
|
|
193
|
+
|
|
194
|
+
offset = self.default_offset
|
|
195
|
+
try: index, offset = index
|
|
196
|
+
except TypeError: pass
|
|
197
|
+
|
|
198
|
+
# prioritise the code path that's potentially in loops externally
|
|
199
|
+
if not isinstance(index, slice) and not isinstance(offset, slice):
|
|
200
|
+
head = self.heads[index] + self.offsets[offset]
|
|
201
|
+
return self.segyfd.getline(head,
|
|
202
|
+
self.length,
|
|
203
|
+
self.stride,
|
|
204
|
+
len(self.offsets),
|
|
205
|
+
np.empty(self.shape, dtype=self.dtype),
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
# at this point, either offset or index is a slice (or proper
|
|
209
|
+
# type-error), so we're definitely making a generator. make them both
|
|
210
|
+
# slices to unify all code paths
|
|
211
|
+
irange, orange = self.ranges(index, offset)
|
|
212
|
+
|
|
213
|
+
def gen():
|
|
214
|
+
x = np.empty(self.shape, dtype=self.dtype)
|
|
215
|
+
y = np.copy(x)
|
|
216
|
+
|
|
217
|
+
# only fetch lines that exist. the slice can generate both offsets
|
|
218
|
+
# and line numbers that don't exist, so filter out misses before
|
|
219
|
+
# they happen
|
|
220
|
+
for line in irange:
|
|
221
|
+
for off in orange:
|
|
222
|
+
head = self.heads[line] + self.offsets[off]
|
|
223
|
+
self.segyfd.getline(head,
|
|
224
|
+
self.length,
|
|
225
|
+
self.stride,
|
|
226
|
+
len(self.offsets),
|
|
227
|
+
y,
|
|
228
|
+
)
|
|
229
|
+
y, x = x, y
|
|
230
|
+
yield x
|
|
231
|
+
|
|
232
|
+
return gen()
|
|
233
|
+
|
|
234
|
+
def __setitem__(self, index, val):
|
|
235
|
+
"""line[i] = val or line[i, o] = val
|
|
236
|
+
|
|
237
|
+
Follows the same rules for indexing and slicing as ``line[i]``.
|
|
238
|
+
|
|
239
|
+
In either case, if the `val` iterable is exhausted before the line(s),
|
|
240
|
+
assignment stops with whatever is written so far. If `val` is longer
|
|
241
|
+
than an individual line, it's essentially truncated.
|
|
242
|
+
|
|
243
|
+
Parameters
|
|
244
|
+
----------
|
|
245
|
+
i : int or slice
|
|
246
|
+
offset : int or slice
|
|
247
|
+
val : array_like
|
|
248
|
+
|
|
249
|
+
Raises
|
|
250
|
+
------
|
|
251
|
+
KeyError
|
|
252
|
+
If `i` or `o` don't exist
|
|
253
|
+
|
|
254
|
+
Notes
|
|
255
|
+
-----
|
|
256
|
+
.. versionadded:: 1.1
|
|
257
|
+
|
|
258
|
+
Examples
|
|
259
|
+
--------
|
|
260
|
+
Copy a full line:
|
|
261
|
+
|
|
262
|
+
>>> line[2400] = other[2834]
|
|
263
|
+
|
|
264
|
+
Copy first half of the inlines from g to f:
|
|
265
|
+
|
|
266
|
+
>>> line[:] = other[:labels[len(labels) / 2]]
|
|
267
|
+
|
|
268
|
+
Copy every other line consecutively:
|
|
269
|
+
|
|
270
|
+
>>> line[:] = other[::2]
|
|
271
|
+
|
|
272
|
+
Copy every third offset:
|
|
273
|
+
|
|
274
|
+
>>> line[:,:] = other[:,::3]
|
|
275
|
+
|
|
276
|
+
Copy a line into a set line and offset:
|
|
277
|
+
|
|
278
|
+
>>> line[12, 200] = other[21]
|
|
279
|
+
"""
|
|
280
|
+
|
|
281
|
+
offset = self.default_offset
|
|
282
|
+
try: index, offset = index
|
|
283
|
+
except TypeError: pass
|
|
284
|
+
|
|
285
|
+
if not isinstance(index, slice) and not isinstance(offset, slice):
|
|
286
|
+
head = self.heads[index] + self.offsets[offset]
|
|
287
|
+
return self.segyfd.putline(head,
|
|
288
|
+
self.length,
|
|
289
|
+
self.stride,
|
|
290
|
+
len(self.offsets),
|
|
291
|
+
index,
|
|
292
|
+
offset,
|
|
293
|
+
castarray(val, dtype = self.dtype),
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
irange, orange = self.ranges(index, offset)
|
|
297
|
+
|
|
298
|
+
val = iter(val)
|
|
299
|
+
for line in irange:
|
|
300
|
+
for off in orange:
|
|
301
|
+
head = self.heads[line] + self.offsets[off]
|
|
302
|
+
try: self.segyfd.putline(head,
|
|
303
|
+
self.length,
|
|
304
|
+
self.stride,
|
|
305
|
+
len(self.offsets),
|
|
306
|
+
line,
|
|
307
|
+
off,
|
|
308
|
+
next(val),
|
|
309
|
+
)
|
|
310
|
+
except StopIteration: return
|
|
311
|
+
|
|
312
|
+
# can't rely on most Mapping default implementations of
|
|
313
|
+
# dict-like, because iter() does not yield keys for this class, it gives
|
|
314
|
+
# the lines themselves. that violates some assumptions (but segyio's always
|
|
315
|
+
# worked that way), and it's the more natural behaviour for segyio, so it's
|
|
316
|
+
# acceptible. additionally, the default implementations would be very slow
|
|
317
|
+
# and ineffective because they assume __getitem__ is sufficiently cheap,
|
|
318
|
+
# but it isn't here since it involves a disk operation
|
|
319
|
+
def __len__(self):
|
|
320
|
+
"""x.__len__() <==> len(x)"""
|
|
321
|
+
return len(self.heads)
|
|
322
|
+
|
|
323
|
+
def __iter__(self):
|
|
324
|
+
"""x.__iter__() <==> iter(x)"""
|
|
325
|
+
return self[:]
|
|
326
|
+
|
|
327
|
+
def __contains__(self, key):
|
|
328
|
+
"""x.__contains__(y) <==> y in x"""
|
|
329
|
+
return key in self.heads
|
|
330
|
+
|
|
331
|
+
def keys(self):
|
|
332
|
+
"""D.keys() -> a set-like object providing a view on D's keys"""
|
|
333
|
+
return sorted(self.heads.keys())
|
|
334
|
+
|
|
335
|
+
def values(self):
|
|
336
|
+
"""D.values() -> generator of D's values"""
|
|
337
|
+
return self[:]
|
|
338
|
+
|
|
339
|
+
def items(self):
|
|
340
|
+
"""D.values() -> generator of D's (key,values), as 2-tuples"""
|
|
341
|
+
return zip(self.keys(), self[:])
|
|
342
|
+
|
|
343
|
+
class HeaderLine(Line):
|
|
344
|
+
"""
|
|
345
|
+
The Line implements the dict interface, with a fixed set of int_like keys,
|
|
346
|
+
the line numbers/labels. The values are iterables of Field objects.
|
|
347
|
+
|
|
348
|
+
Notes
|
|
349
|
+
-----
|
|
350
|
+
.. versionadded:: 1.1
|
|
351
|
+
|
|
352
|
+
.. versionchanged:: 1.6
|
|
353
|
+
common dict operations (Mapping)
|
|
354
|
+
"""
|
|
355
|
+
# a lot of implementation details are shared between reading data traces
|
|
356
|
+
# line-by-line and trace headers line-by-line, so (ab)use inheritance for
|
|
357
|
+
# __len__, keys() etc., however, the __getitem__ is way different and is re-implemented
|
|
358
|
+
|
|
359
|
+
def __init__(self, header, base, direction):
|
|
360
|
+
super(HeaderLine, self).__init__(header.segyfile,
|
|
361
|
+
base.lines,
|
|
362
|
+
base.length,
|
|
363
|
+
base.stride,
|
|
364
|
+
sorted(base.offsets.keys()),
|
|
365
|
+
'header.' + direction,
|
|
366
|
+
)
|
|
367
|
+
self.header = header
|
|
368
|
+
|
|
369
|
+
def __getitem__(self, index):
|
|
370
|
+
"""line[i] or line[i, o]
|
|
371
|
+
|
|
372
|
+
The line `i`, or the line `i` at a specific offset `o`. ``line[i]``
|
|
373
|
+
returns an iterable of `Field` objects, and changes to these *will* be
|
|
374
|
+
reflected on disk.
|
|
375
|
+
|
|
376
|
+
The `i` and `o` are *keys*, and should correspond to the line- and
|
|
377
|
+
offset labels in your file, and in the `ilines`, `xlines`, and
|
|
378
|
+
`offsets` attributes.
|
|
379
|
+
|
|
380
|
+
Slices can contain lines and offsets not in the file, and like with
|
|
381
|
+
list slicing, these are handled gracefully and ignored.
|
|
382
|
+
|
|
383
|
+
When `i` or `o` is a slice, a generator of iterables of headers are
|
|
384
|
+
returned.
|
|
385
|
+
|
|
386
|
+
When both `i` and `o` are slices, one generator is returned for the
|
|
387
|
+
product `i` and `o`, and the lines are yielded offsets-first, roughly
|
|
388
|
+
equivalent to the double for loop::
|
|
389
|
+
|
|
390
|
+
>>> for line in lines:
|
|
391
|
+
... for off in offsets:
|
|
392
|
+
... yield line[line, off]
|
|
393
|
+
...
|
|
394
|
+
|
|
395
|
+
Parameters
|
|
396
|
+
----------
|
|
397
|
+
|
|
398
|
+
i : int or slice
|
|
399
|
+
o : int or slice
|
|
400
|
+
|
|
401
|
+
Returns
|
|
402
|
+
-------
|
|
403
|
+
line : iterable of Field or generator of iterator of Field
|
|
404
|
+
|
|
405
|
+
Raises
|
|
406
|
+
------
|
|
407
|
+
KeyError
|
|
408
|
+
If `i` or `o` don't exist
|
|
409
|
+
|
|
410
|
+
Notes
|
|
411
|
+
-----
|
|
412
|
+
.. versionadded:: 1.1
|
|
413
|
+
|
|
414
|
+
"""
|
|
415
|
+
offset = self.default_offset
|
|
416
|
+
try: index, offset = index
|
|
417
|
+
except TypeError: pass
|
|
418
|
+
|
|
419
|
+
if not isinstance(index, slice) and not isinstance(offset, slice):
|
|
420
|
+
start = self.heads[index] + self.offsets[offset]
|
|
421
|
+
step = self.stride * len(self.offsets)
|
|
422
|
+
stop = start + step * self.length
|
|
423
|
+
return self.header[start:stop:step]
|
|
424
|
+
|
|
425
|
+
def gen():
|
|
426
|
+
irange, orange = self.ranges(index, offset)
|
|
427
|
+
for line in irange:
|
|
428
|
+
for off in orange:
|
|
429
|
+
yield self[line, off]
|
|
430
|
+
|
|
431
|
+
return gen()
|
|
432
|
+
|
|
433
|
+
def __setitem__(self, index, val):
|
|
434
|
+
"""line[i] = val or line[i, o] = val
|
|
435
|
+
|
|
436
|
+
Follows the same rules for indexing and slicing as ``line[i]``. If `i`
|
|
437
|
+
is an int, and `val` is a dict or Field, that value is replicated and
|
|
438
|
+
assigned to every trace header in the line, otherwise it's treated as
|
|
439
|
+
an iterable, and each trace in the line is assigned the ``next()``
|
|
440
|
+
yielded value.
|
|
441
|
+
|
|
442
|
+
If `i` or `o` is a slice, `val` must be an iterable.
|
|
443
|
+
|
|
444
|
+
In either case, if the `val` iterable is exhausted before the line(s),
|
|
445
|
+
assignment stops with whatever is written so far.
|
|
446
|
+
|
|
447
|
+
Parameters
|
|
448
|
+
----------
|
|
449
|
+
i : int or slice
|
|
450
|
+
offset : int or slice
|
|
451
|
+
val : dict_like or iterable of dict_like
|
|
452
|
+
|
|
453
|
+
Raises
|
|
454
|
+
------
|
|
455
|
+
KeyError
|
|
456
|
+
If `i` or `o` don't exist
|
|
457
|
+
|
|
458
|
+
Notes
|
|
459
|
+
-----
|
|
460
|
+
.. versionadded:: 1.1
|
|
461
|
+
|
|
462
|
+
Examples
|
|
463
|
+
--------
|
|
464
|
+
Rename the iline 3 to 4:
|
|
465
|
+
|
|
466
|
+
>>> line[3] = { TraceField.INLINE_3D: 4 }
|
|
467
|
+
>>> # please note that rewriting the header won't update the
|
|
468
|
+
>>> # file's interpretation of the file until you reload it, so
|
|
469
|
+
>>> # the new iline 4 will be considered iline 3 until the file
|
|
470
|
+
>>> # is reloaded
|
|
471
|
+
|
|
472
|
+
Set offset line 3 offset 3 to 5:
|
|
473
|
+
|
|
474
|
+
>>> line[3, 3] = { TraceField.offset: 5 }
|
|
475
|
+
"""
|
|
476
|
+
offset = self.default_offset
|
|
477
|
+
try: index, offset = index
|
|
478
|
+
except TypeError: pass
|
|
479
|
+
|
|
480
|
+
if not isinstance(index, slice) and not isinstance(offset, slice):
|
|
481
|
+
start = self.heads[index] + self.offsets[offset]
|
|
482
|
+
step = self.stride * len(self.offsets)
|
|
483
|
+
stop = start + step * self.length
|
|
484
|
+
self.header[start:stop:step] = val
|
|
485
|
+
return
|
|
486
|
+
|
|
487
|
+
# if this is a dict-like, just repeat it
|
|
488
|
+
if hasattr(val, 'keys'):
|
|
489
|
+
val = itertools.repeat(val)
|
|
490
|
+
|
|
491
|
+
irange, orange = self.ranges(index, offset)
|
|
492
|
+
val = iter(val)
|
|
493
|
+
for line in irange:
|
|
494
|
+
for off in orange:
|
|
495
|
+
try:
|
|
496
|
+
self[line, off] = next(val)
|
|
497
|
+
except StopIteration:
|
|
498
|
+
return
|