Skip to content

Commit c59003f

Browse files
committed
Add xml layout parameter to open
1 parent 2c4e429 commit c59003f

3 files changed

Lines changed: 76 additions & 10 deletions

File tree

python/segyio/open.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ def open(filename, mode="r", iline = None,
4343
strict = True,
4444
ignore_geometry = False,
4545
endian = None,
46-
encoding = None):
46+
encoding = None,
47+
layout_xml = None
48+
):
4749
"""Open a segy file.
4850
4951
Opens a segy file and tries to figure out its sorting, inline numbers,
@@ -110,6 +112,10 @@ def open(filename, mode="r", iline = None,
110112
into latin-1 encoding as per SEG-Y specification. For ascii encoding
111113
data would be returned as is.
112114
115+
layout_xml: bytearray
116+
SEG-Y revision 2.1 D8 xml layout. Takes precedence over layout
117+
definition xml inside the file.
118+
113119
Returns
114120
-------
115121
@@ -130,6 +136,9 @@ def open(filename, mode="r", iline = None,
130136
.. versionchanged:: 1.8
131137
endian argument
132138
139+
.. versionchanged:: 2.0
140+
Support for SEG-Y revision 2.1
141+
133142
When a file is opened non-strict, only raw traces access is allowed, and
134143
using modes such as ``iline`` raise an error.
135144
@@ -168,7 +177,7 @@ def open(filename, mode="r", iline = None,
168177

169178
return _open(
170179
FileDatasourceDescriptor(filename, mode),
171-
iline, xline, strict, ignore_geometry, endian, encoding
180+
iline, xline, strict, ignore_geometry, endian, encoding, layout_xml
172181
)
173182

174183

@@ -179,7 +188,8 @@ def open_with(stream,
179188
ignore_geometry=False,
180189
endian=None,
181190
encoding=None,
182-
minimize_requests_number=True
191+
minimize_requests_number=True,
192+
layout_xml = None
183193
):
184194
"""
185195
Opens a segy file from a stream.
@@ -209,7 +219,7 @@ def open_with(stream,
209219
stream,
210220
minimize_requests_number
211221
),
212-
iline, xline, strict, ignore_geometry, endian, encoding
222+
iline, xline, strict, ignore_geometry, endian, encoding, layout_xml
213223
)
214224

215225

@@ -220,6 +230,7 @@ def open_from_memory(memory_buffer,
220230
ignore_geometry=False,
221231
endian=None,
222232
encoding=None,
233+
layout_xml = None
223234
):
224235
"""
225236
Opens a segy file from memory.
@@ -241,7 +252,7 @@ def open_from_memory(memory_buffer,
241252
MemoryBufferDatasourceDescriptor(
242253
memory_buffer
243254
),
244-
iline, xline, strict, ignore_geometry, endian, encoding
255+
iline, xline, strict, ignore_geometry, endian, encoding, layout_xml
245256
)
246257

247258

@@ -252,6 +263,7 @@ def _open(datasource_descriptor,
252263
ignore_geometry=False,
253264
endian=None,
254265
encoding=None,
266+
layout_xml = None
255267
):
256268

257269
fd = datasource_descriptor.make_segyfile_descriptor()
@@ -265,7 +277,8 @@ def _open(datasource_descriptor,
265277
endianness=to_c_endianness(endian),
266278
encoding=to_c_encoding(encoding),
267279
iline=iline,
268-
xline=xline
280+
xline=xline,
281+
layout_xml=layout_xml
269282
)
270283
metrics = fd.metrics()
271284

python/segyio/segyio.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -650,21 +650,25 @@ PyObject* segyopen( segyfd* self, PyObject* args, PyObject* kwargs ) {
650650
int encoding = -1;
651651
PyObject *py_iline = Py_None;
652652
PyObject *py_xline = Py_None;
653+
PyObject* py_layout_xml = Py_None;
654+
653655
static const char* keywords[] = {
654656
"endianness",
655657
"encoding",
656658
"iline",
657659
"xline",
660+
"layout_xml",
658661
NULL
659662
};
660663

661664
if( !PyArg_ParseTupleAndKeywords(
662-
args, kwargs, "|iiOO",
665+
args, kwargs, "|iiOOO",
663666
const_cast<char**>( keywords ),
664667
&endianness,
665668
&encoding,
666669
&py_iline,
667-
&py_xline
670+
&py_xline,
671+
&py_layout_xml
668672
) ) {
669673
return NULL;
670674
}
@@ -680,8 +684,18 @@ PyObject* segyopen( segyfd* self, PyObject* args, PyObject* kwargs ) {
680684
if( err ) return Error( err );
681685

682686
std::vector<char> layout_stanza_data;
683-
err = extract_layout_stanza( self, layout_stanza_data );
684-
if( err ) return Error( err );
687+
if( py_layout_xml != Py_None ) {
688+
buffer_guard layout_xml( py_layout_xml, PyBUF_CONTIG );
689+
layout_stanza_data.resize( layout_xml.len() );
690+
std::memcpy(
691+
layout_stanza_data.data(),
692+
layout_xml.buf<char>(),
693+
layout_xml.len()
694+
);
695+
} else {
696+
err = extract_layout_stanza( self, layout_stanza_data );
697+
if( err ) return Error( err );
698+
}
685699

686700
err = set_traceheader_mappings( self, layout_stanza_data, py_iline, py_xline );
687701
if( err ) return NULL;

python/test/segy.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2639,4 +2639,43 @@ def test_revision_2_1_file_creation(tmpdir):
26392639
dst.trace = src.trace
26402640
dst.traceheader = src.traceheader
26412641

2642+
with segyio.open(fresh, "r+", ignore_geometry=True) as dst:
2643+
pass
2644+
26422645
assert filecmp.cmp(orig, fresh)
2646+
2647+
2648+
def test_custom_layout_xml(tmpdir):
2649+
small = str(testdata / 'small.sgy')
2650+
orig = str(testdata / 'trace-header-extensions.sgy')
2651+
fresh = tmpdir / '2.1-headers-not-copied.sgy'
2652+
with segyio.open(orig) as src:
2653+
spec = segyio.spec()
2654+
spec.format = int(src.format)
2655+
spec.sorting = int(src.sorting)
2656+
spec.samples = src.samples
2657+
spec.ilines = src.ilines
2658+
spec.xlines = src.xlines
2659+
spec.ext_headers = 0
2660+
spec.traceheader_count = src.traceheader_count
2661+
spec.tracecount = src.tracecount
2662+
2663+
layout = src.stanza[0]
2664+
2665+
with segyio.open(small, "r") as f:
2666+
assert len(f.tracefield[0].names()) == 92
2667+
with segyio.open(small, "r", layout_xml=layout) as f:
2668+
assert len(f.tracefield[0].names()) == 8
2669+
2670+
with segyio.create(fresh, spec, layout_xml=layout) as dst:
2671+
dst.bin = src.bin
2672+
dst.bin[BinField.ExtendedHeaders] = 0
2673+
dst.trace = src.trace
2674+
dst.traceheader = src.traceheader
2675+
2676+
with pytest.raises(KeyError, match="traceheader mapping for 'PRIVATE1' not found"):
2677+
segyio.open(fresh, "r", ignore_geometry=True)
2678+
2679+
with segyio.open(fresh, "r", ignore_geometry=True, layout_xml=layout) as f:
2680+
assert f.tracefield.names() == ['SEG00000', 'SEG00001', 'PRIVATE1']
2681+
assert f.tracefield.SEG00001.names() == ['linetrc', 'header_name']

0 commit comments

Comments
 (0)