1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
"""
Phase 6: LAS 3.0 support — multi-dataset, format fields, string columns, delimiters.
Covers reading LAS 3.0 files with multiple data sections (log, drilling, tops),
string-typed columns marked with ``{S}`` format codes, alternate column delimiters
(COMMA and TAB via the DLM field), and the section-name mapping rules that fold
``~Log_Definition`` into ``Curves`` and ``~Log_Parameter`` into ``Parameter``.
Also covers section-name classification beyond the ``Log_`` prefix: any
``*_Definition`` section maps to Curves and any ``*_Parameter`` to Parameter,
so a file whose curve section is titled ``~Curve_Definition`` still parses.
"""
# ---------------------------------------------------------------------------
# Path helper
# ---------------------------------------------------------------------------
=
return
# ---------------------------------------------------------------------------
# Fixture file facts (tests/fixtures/v30/sample_v30.las)
#
# VERS = 3.0
# DLM = COMMA
# ~Log_Parameter → mapped to sections["Parameter"]
# ~Log_Definition → mapped to sections["Curves"]
# Curves: DEPT, GR, RHOB, NPHI, LITH (LITH has {S} format)
# Log data rows : 3 (depths 1450, 1451, 1452)
# Extra sections : Drilling_Definition / Drilling_ASCII_Standard
# Tops_Definition / Tops_ASCII_Standard
# Params : BHT, BS, MWT
# ---------------------------------------------------------------------------
=
=
# A 3.0 file whose sections use the ``~Curve_Definition`` / ``~Curve_Parameter``
# / ``~Curve_Data`` titles instead of the ``Log_`` prefix. Petekio's Petrel
# core-log exports use these, and they currently parse to *empty* curves.
=
# ===========================================================================
# Basic read
# ===========================================================================
"""Reading a valid LAS 3.0 file returns a LASFile instance."""
=
assert
# ===========================================================================
# Version / DLM header items
# ===========================================================================
"""The VERS item in a LAS 3.0 file has value 3.0."""
=
assert ==
"""The DLM item in the version section has value 'COMMA'."""
=
assert ==
# ===========================================================================
# Section-name mapping
# ===========================================================================
"""~Log_Definition is mapped to las.curves (sections['Curves'])."""
=
# The Curves section must exist and contain the expected mnemonics.
=
assert in
assert in
assert in
"""~Log_Parameter is mapped to las.params (sections['Parameter'])."""
=
=
assert in
assert in
"""'Log_Parameter' does not appear as a standalone key in sections —
it is merged into 'Parameter'."""
=
assert not in
# ===========================================================================
# Data shape
# ===========================================================================
"""The main log data section has exactly 3 rows (depths 1450–1452)."""
=
# las.data is a 2-D structure; the first dimension is the row count.
assert == 3
# ===========================================================================
# String columns
# ===========================================================================
"""The LITH column (marked {S}) contains string values, not only floats.
The first row value is 'SANDSTONE', the last is 'SANDY SHALE'.
"""
=
= .
# At least one element must be a non-numeric string.
=
assert > 0
assert in or
# ===========================================================================
# Non-standard (extra) sections
# ===========================================================================
"""Non-standard sections such as Drilling_Definition and Tops_Definition
are retained in the sections dictionary."""
=
=
# At least one drilling or tops section key must be present.
=
=
assert or
# ===========================================================================
# TAB delimiter
# ===========================================================================
"""sample_v30_tab.las (DLM TAB) is read correctly with engine='normal'."""
=
assert
# File has 3 log rows (depths 2100, 2101, 2102) and 5 curves.
assert == 3
assert == 5
"""sample_v30_tab.las (DLM TAB) is read correctly with engine='numpy'."""
=
assert
assert == 3
# ===========================================================================
# Comma-separated data values
# ===========================================================================
"""Numeric columns in the comma-delimited file parse to the correct floats.
Row 0: DEPT=1450.0, GR=55.231, RHOB=2.512, NPHI=0.241
Row 1: DEPT=1451.0, GR=78.645, RHOB=2.634, NPHI=0.198
"""
=
= .
= .
= .
= .
assert ==
assert ==
assert ==
assert ==
assert ==
assert ==
# ===========================================================================
# Section titles beyond the ``Log_`` prefix (~Curve_Definition etc.)
# ===========================================================================
"""A 3.0 file whose curve section is titled ``~Curve_Definition`` (not
``~Log_Definition``) still recovers its curves and index.
Regression for petekio's Petrel core-log exports, which came back with
empty ``curve_mnemonics()``/``index()`` because only ``Log_Definition`` was
special-cased.
"""
=
=
assert ==
assert ==
assert . ==
# ~Curve_Parameter folds into Parameter, just like ~Log_Parameter.
=
assert in
# ===========================================================================
# Index curve resolution by depth alias
# ===========================================================================
"""When the index curve is named DEPTH (not DEPT) and is not column 0,
``las.index`` still resolves it via the depth-alias set rather than
returning the first (non-depth) curve."""
=
=
assert ==
# index must be DEPTH (col 1: 1450..1452), not SN (col 0: 1,2,3).
assert ==
assert ==