Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support header-only LAS files--don't lose the last header section before a missng ~A section #326

Merged
merged 3 commits into from
May 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 33 additions & 14 deletions lasio/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,13 +314,18 @@ def read_file_contents(file_obj, regexp_subs, value_null_subs, ignore_data=False
# HARD CODED FOR VERSION 1.2 and 2.0; needs review for 3.0
# We have finished looking at the metadata and need
# to start reading numerical data.

if not sect_title_line is None:
sections[sect_title_line] = {
"section_type": "header",
"title": sect_title_line,
"lines": sect_lines,
"line_nos": sect_line_nos,
}
sections[sect_title_line] = {
"section_type": "header",
"title": sect_title_line,
"lines": sect_lines,
"line_nos": sect_line_nos,
}
sect_lines = []
sect_line_nos = []


if not ignore_data:
try:
data = read_data_section_iterative(
Expand All @@ -340,19 +345,22 @@ def read_file_contents(file_obj, regexp_subs, value_null_subs, ignore_data=False
"array": data,
}
logger.debug('Data section ["array"].shape = {}'.format(data.shape))

section_exists = False
break

elif line.startswith("~"):
if section_exists:
# We have ended a section and need to start the next
sections[sect_title_line] = {
"section_type": "header",
"title": sect_title_line,
"lines": sect_lines,
"line_nos": sect_line_nos,
}
sect_lines = []
sect_line_nos = []
if not sect_title_line is None:
sections[sect_title_line] = {
"section_type": "header",
"title": sect_title_line,
"lines": sect_lines,
"line_nos": sect_line_nos,
}
sect_lines = []
sect_line_nos = []
else:
# We are entering into a section for the first time
section_exists = True
Expand All @@ -365,6 +373,17 @@ def read_file_contents(file_obj, regexp_subs, value_null_subs, ignore_data=False
sect_lines.append(line)
sect_line_nos.append(i + 1)

# If the file had header data only, and is truncated before the ~A section
# we need to save the last header section.
if section_exists and not sect_title_line is None:
sections[sect_title_line] = {
"section_type": "header",
"title": sect_title_line,
"lines": sect_lines,
"line_nos": sect_line_nos,
}


# Find the number of columns in the data section(s). This is only
# useful if WRAP = NO, but we do it for all since we don't yet know
# what the wrap setting is.
Expand Down
55 changes: 55 additions & 0 deletions tests/examples/header_only.las
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
~VERSION INFORMATION
VERS . 2.0 :CWLS Log ASCII Standard - VERSION 2.0
WRAP . NO :One Line per Depth step
PROD . Schlumberger Technology Corp. :LAS Producer
PROG . Horizon LASWriter 9.0.106845.3100 :LAS Program name and version
SOURCE. 1B-Main[5]/Up :Run&Pass Information
CREA . 07/01/2019 :LAS Creation date {MM/DD/YYYY}
#--------------------------------------------------
~WELL INFORMATION
#MNEM .UNIT DATA :DESCRIPTION
#---- ------ -------------- -----------------------------
STRT .ft 9000.00000 :START DEPTH
STOP .ft 10000.00000 :STOP DEPTH
STEP .ft 0.5 :STEP
NULL . -999.25 :NULL VALUE
COMP . I2KCONNECT ENERGY :COMPANY
WELL . GUSHER :WELL NAME
FLD . MINUTEMAID :FIELD NAME
RIGN . BTC2 :Rig Name
RIGTYP . Land :Rig Type
SON . 123456 :Service Order Number
SRVC . Schlumberger :SERVICE COMPANY
DATE . 07/01/2019 :LOG DATE(Composite Date for Composite LAP) (MM/DD/YYYY)
APD .ft 32.00000 :Elevation of Depth Reference (LMF) Above Permanent Datum
EPD .ft 64.00000 :Elevation of Permanent Datum (PDAT) above Mean Sea Level
EKB .ft 32.00000 :Elevation of Kelly Bushing Above Permanent Datum
EDF .ft 31.00000 :Elevation of Drill Floor Above Permanent Datum
EGL .ft 0.00000 :Elevation of Ground Level Above Permanent Datum
ECF .ft -999.25 :Elevation of Casing Flange above Permanent Datum
#--------------------------------------------------
~CURVE INFORMATION
#MNEM .UNIT API CODE :DESCRIPTION
#---- ------ -------------- -----------------------------
DEPT .ft : Depth Index
F3_S11_PHA .deg : (ADT-C) (0.2in) Frequency 3 Mudcake Probe S11 Reflection Phase
F1_S11_REF_AMP .dB.mW : (ADT-C) (6in) Frequency 1 Mudcake Probe S11 Reflection Reference Amplitude
PEA . : (HDRS-H) (2in) Short Spacing Formation Photoelectric Factor
T2L7 .ms : (CMRT-F) (7.5in) T2 Logarithmic Mean of Bin 7
PWXO .ft3/ft3 : (ADT-C) (2in) Invaded Zone Water-filled Porosity
CYAL . : (NEXT-C) (6in) Capture Aluminum Relative Yield
CYMN_SIG_INCP . : (NEXT-C) (6in) Capture Manganese Relative Yield Uncertainty (Filtered and Corrected for Input to INCP Processing)
LWTO .1/s : (HDRS-H) (1in) Window Total from Long Spacing
NUM_MSG . : (CMRT-F) (7.5in) Number of Messages
DWGD_INCP .ppm : (NEXT-C) (6in) Dry Weight Gadolinium from Inelastic-Capture Processing
CYBA_SIG . : (NEXT-C) (6in) Capture Barium Relative Yield Uncertainty
WPHI_FIT[1] .ft3/ft3 : (CMRT-F) (7.5in) Window Porosity Fit
WPHI_FIT[2] .ft3/ft3 : (CMRT-F) (7.5in) Window Porosity Fit
WPHI_FIT[3] .ft3/ft3 : (CMRT-F) (7.5in) Window Porosity Fit
WPHI_FIT[4] .ft3/ft3 : (CMRT-F) (7.5in) Window Porosity Fit
WPHI_FIT[5] .ft3/ft3 : (CMRT-F) (7.5in) Window Porosity Fit
WPHI_FIT[6] .ft3/ft3 : (CMRT-F) (7.5in) Window Porosity Fit
WPHI_FIT[7] .ft3/ft3 : (CMRT-F) (7.5in) Window Porosity Fit
WPHI_FIT[8] .ft3/ft3 : (CMRT-F) (7.5in) Window Porosity Fit
WPHI_FIT[9] .ft3/ft3 : (CMRT-F) (7.5in) Window Porosity Fit
#-------------------------------------------------------------
9 changes: 9 additions & 0 deletions tests/test_read.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,3 +415,12 @@ def test_issue_201_non_delimiter_colon_end():
assert las.params["TIML"].unit == "hh:mm"
assert las.params["TIML"].value == "23:15 23-JAN-2001"
assert las.params["TIML"].descr == "Time Logger At Bottom:"

def test_header_only_file():
las = lasio.read(egfn("header_only.las"))
assert las.well.STRT.value == 9000.0
assert las.well.STOP.value == 10000.0
assert las.curves[0].mnemonic == "DEPT"
assert las.curves[0].unit == "ft"
assert las.curves[12].mnemonic == "WPHI_FIT[1]"
assert len(las.curves) == 21