LIS API Reference#
Load a LIS-file#
- dlisio.lis.load(path, error_handler=None)#
Loads and indexes a LIS file
Load does more than just opening the file. A LIS file has no random access in itself, so load scans the entire file and creates its own index to enumlate random access. The file is also segmented into Logical Files, see
PhysicalFile
andLogicalFile
.** Incorrectly written files **
It is not uncommon that LIS files are written incorrectly, meaning they are violating the LIS79 specification. Typically it’s only a very small portion of the file that is incorrect, often down to a couple of bytes. Unfortunately, because of how the internal structure of LIS files is defined, the bytes following the incorrect part become unreadable too. In most cases there is little dlisio can do about this as it’s unclear what the original intention was.
However, it may be possible to read the file up until the incorrect part occurs. load has an escape hatch for this, which essentially returns everything that it believes to be successfully indexed prior to the point-of-failure. The caveat being that there is no guarantee that the file is interpreted correctly by dlisio at this point. This escape hatch is controlled by the parameter
error_handler
. Please refer to the examples section for more details of it’s use.Notes
It’s not uncommon that LIS files are stored with different file extensions than .LIS. For example .LTI or .TIF. Load does not care about file extension at all. As long as the content adheres to the Log Interchange Standard, load will read it as such.
- Parameters:
path (str_like) – path to lis-file
error_handler (dlisio.common.ErrorHandler, optional) – Defines how load will behave when encountering any errors while indexing the file.
- Returns:
lis
- Return type:
Examples
Opening a file is straightforward.
dlisio.lis.load()
is designed to work like python’s ownopen()
. That is, it can be used both with- and without python’s`with
-statments:>>> from dlisio import lis >>> with lis.load(filepath) as files: ... pass
If
load
raises a RuntimeError this is likely due to the file being incorrectly written. You can instruct dlisio to return to you what it did manage to index before it failed:>>> from dlisio.common import ErrorHandler, Actions >>> handler = ErrorHandler(critical=Actions.LOG_ERROR) >>> with lis.load(filepath, handler) as files: ... pass
What this effectively does is to turn the
RuntimeError
into alogging.error
and load now returns a partially indexed file. dlisio does not guarantee that what’s being returned is correct at this point, and you should verify for yourself that the data it serves you looks sane.
LIS Physical File#
- class dlisio.lis.PhysicalFile#
Physical File - A regular file on disk
Think of a LIS file as a directory. The top directory is your regular file on disk. The regular file is divided into sub-structures (or subfolders if you will) called ‘Reels’. Each Reel if further divided into ‘Tapes’, which again contains Logical Files:
your_file.lis | |-> Reel 0 | | | |-> Tape 0 | | | | | |-> Logical File 0 | | |-> Logical File 1 | | | |-> Tape 1 | | | | | |-> Logical File 2 | |-> Reel 1 | |-> Tape 0 | |-> Logical File 3
Each Logical File can be thought of as an independent regular file, containing log data.
Each Reel and Tape has its own corresponding Header and Trailer. These contain general information about the Reel or Tape.
When reading the LIS file with
dlisio.lis.load()
, dlisio will flatten the above tree structure and simply return a tuple-like object (PhysicalFile
) of all the Logical Files. The Reel and Tape in which a Logical File belongs to can be queried directly from the Logical File.Notes
More often than not, the tree structure of a LIS file is trivial, containing just a couple of logical files - all belonging to the same Tape and Reel.
Notes
The LIS79 specification opens for the possibility of a Reel spanning across multiples regular files. dlisio does not currently have cross-file support. Each regular file can still be read as a stand-alone LIS-file.
See also
dlisio.lis.load
Open and Index a LIS-file
dlisio.lis.LogicalFile
A wrapper for a single Logical File
LIS Logical File#
- class dlisio.lis.LogicalFile#
Logical File (LF)
This class is the main interface for working with a single LF. A LF is essentially a series of Logical Records (LR). There are many different LR types, each designed to carry a specific piece of information. For example a Logical File Header Record contains static information about the file, while the Data Format Specification Records contain information about curve-data, and how that should be parsed.
This class provides an interface for easy interaction and extraction of the various Logical Records within the Logical File. It is completely independent of other LF’s, and even has its own IO-device. It stores a pre-built index of all LR’s for random access when reading from disk.
Notes
No parsed records are cached by this class. Thus it’s advisable that the result of each record read is cached locally.
- path#
Path to the file as passed to
dlisio.lis.load()
- Type:
str
- io#
The underlying lis-aware IO-device that acts on the file. The iodevice implements primitive io-operations such as seek, read and tell, but also higher level abstractions such as read_record. For normal workflows it should not be necessary to interact directly with the io-device.
- Type:
dlisio.core.lis_stream
- index#
A dlisio-created index of all Logical Records (LR) in the current Logical File (LF). The index is created at load and gives dlisio random access to the LR’s. The index can be iterated and records can be extracted using
dlisio.lis.LogicalFile.io
. For normal workflow it should not be necessary to interact directly with the index.- Type:
dlisio.core.lis_record_index
- reel#
The reel that this Logical File (LF) belongs to.
See
dlisio.lis.PhysicalFile
for more on the relationship between LIS reels and LF’s. Seedlisio.core.reel_header
anddlisio.core.reel_trailer
for more on the Reel Logical Records (RHLR, RTLR).- Type:
- tape#
The tape that this Logical File (LF) belongs to.
See
dlisio.lis.PhysicalFile
for more on the relationship between LIS tapes and LF’s. Seedlisio.core.tape_header
anddlisio.core.tape_trailer
for more on the Tape Logical Records (THLR, TTLR).- Type:
- close()#
Close the file handle
It is not necessary to call this method if you’re using the with statement, which will close the file for you.
- data_format_specs()#
Data Format Specification Records (DFSR)
A DFSR contains all relevant information to extract a specific logset - a logset being a set of channels/curves all sampled along a common index.
See also
dlisio.lis.curves
Read all the curves from a given DFSR
- Returns:
records
- Return type:
list of dlisio.lis.DataFormatSpec
- flic_comment()#
Comment Record
- Returns:
records
- Return type:
list of
dlisio.core.text_record
- header()#
Logical File Header
Reads and parses the Logical File Header from disk - if present.
- Returns:
header
- Return type:
dlisio.core.file_header or None
- job_identification()#
Job Identification Logical Records
- Returns:
records
- Return type:
list of
dlisio.lis.InformationRecord
- operator_command_inputs()#
Operator Command Inputs
- Returns:
records
- Return type:
list of
dlisio.core.text_record
- operator_response_inputs()#
Operator Response Inputs
- Returns:
records
- Return type:
list of
dlisio.core.text_record
- parse_records(rectype)#
Parse Explicit records of given type
- system_outputs_to_operator()#
System Outputs to Operator
- Returns:
records
- Return type:
list of
dlisio.core.text_record
- tool_string_info()#
Tool String Info Logical Records
- Returns:
records
- Return type:
list of
dlisio.lis.InformationRecord
- trailer()#
Logical File Trailer
Reads and parses the Logical File Header from disk - if present.
- Returns:
trailer
- Return type:
dlisio.core.file_trailer or None
- wellsite_data()#
Wellsite Data Logical Records
- Returns:
records
- Return type:
list of
dlisio.lis.InformationRecord
LIS Curves#
- dlisio.lis.curves()#
Read curves
Read the curves described by the Data Format Specification Record (DFSR). The curves are read into a Numpy Structured Array [1]. The mnemonics - as described by the DFSR - of the channels are used as column names.
Fast Channels
Some log sets contain curves that are sampled at unequal sampling rate. More specifically, curves can be sampled at a greater frequency than the recorded index. These are referred to in the LIS79 specification as Fast Channels. The sample rate is not absolute, but rather a factor relative to the index. E.g. a sampling rate of 1 means that the curve are sampled at the same frequency as the index, while a sample rate of 6 means the channel is sampled at 6 times the frequency of the index.
When the sampling rate of a curve is higher than the index, the index is linearly interpolated to create the missing values samples. This is the LIS79 defined behavior [2]. Note that this is only true for the index. Other channels will not be re-sampled.
These LIS79 mechanics of multiple sampling rates within a logset do mean that the result of the entire logset is a sparse array. That is, curves at lower sampling rates will have a lot of undefined samples. Take this example with 2 channels,
CH01
andCH02
, whereCH01
has a sample rate of 1, andCH02
has a sample rate of 3. The full log set would then look like this:DEPTH CH01 CH02 ---------------------------- 0 - 1 0 - 2 300 500 3 310 - 4 320 - 5 330 510 6
The only depth samples that are recorded in the file are
300
and330
. The rest is interpolated between these depth samples. Notice how the first depth samples are 0. That is because there is no prior recorded depth to interpolate against - and constant spacing is not guaranteed.Looking at
CH01
in the above logset we see that only a third of the samples contains actual measurements. Remember, no interpolation rules are defined for curves that are not the index. This is an undesirable situation both from dlisio’s point-of-view - and from the consumer of the log. dlisio would have to fill all these undefined samples with some value on behalf of the user, as there is no such thing as a sparse numpy array. This will have a negative effect on memory consumption. And, depending on the application of course, the consumer of the log would likely want to filter out the “absent-values” and re-sample the logs anyway. To avoid this, only equally sampled curves can be read into the same numpy array bydlisio.lis.curves()
. This means that multiple calls to this function are required to read all the curves in the logset. The parametersample_rate
is used to define which curves to read. Please refer to the example section for more details.[1] Structured Arrays, https://numpy.org/doc/stable/user/basics.rec.html
[2] LIS79 ch 3.3.2.2, https://www.energistics.org/sites/default/files/2022-10/lis-79.pdf
- Parameters:
f (LogicalFile) – The logcal file that the dfsr belongs to
dfsr (dlisio.lis.DataFormatSpec) – Data Format Specification Record
sample_rate (None) – Read channels matching a specific sampling rate (relative to the recorded index). If all curves are sampled equally compared to the index, this can be omitted. If not, a value must be given to tell which subset of the curves in the log set should be read.
strict (boolean, optional) – By default (strict=True) curves() raises a ValueError if there are multiple channels with the same mnemonic. Setting strict=False lifts this restriction and dlisio will append numerical values (i.e. 0, 1, 2 ..) to the labels used for column-names in the returned array.
- Returns:
curves – Numpy structured ndarray with mnemonics as column names
- Return type:
np.ndarray
- Raises:
ValueError – If the DFSR contains the same mnemonic multiple times. Numpy Structured Array requires all column names to be unique. See parameter strict for workaround
NotImplementedError – If the DFSR contains one or more channel where the type of the samples is lis::mask
Examples
The returned array supports both horizontal- and vertical slicing. Slice on a subset of channels:
>>> curves = dlisio.lis.curves(f, dfsr) >>> curves[['CHANN2', 'CHANN3']] array([ (16677259., 852606.), (16678259., 852606.), (16679259., 852606.), (16680259., 852606.) ])
Or slice a subset of the samples:
>>> curves = dlisio.lis.curves(f, dfsr) >>> curves[0:2] array([ (16677259., 852606., 2233., 852606.), (16678259., 852606., 2237., 852606.)])
When the logset described by the DFSR contains channels with different sampling rates, multiple calls to curves are necessary to read all the curves. E.g. we can read all curves that are sampled at the same rate as the index:
>>> dlisio.lis.curves(f, dfsr, sample_rate=1) array([(300, 500), (330, 510)], dtype=[('DEPT', '<i4'), ('CH01', '<i4')])
As we can see the outputted logset contains the index curve (DEPT) and CH01. However, we know from examination of the current dfsr that there is another channel in this logset,
CH02
, which is sampled at 3 times the rate of the index. This curve (and all other curves which are sampled equally to it) can be read by a separate call to curves:>>> dlisio.lis.curves(f, dfsr, sample_rate=3) array([( 0, 1), ( 0, 2), (300, 3), (310, 4), (320, 5), (330, 6)], dtype=[('DEPT', '<i4'), ('CH02', '<i4')])
Note that it’s the same index curve as previously, only re-sampled to fit the higher sampling rate of
CH02
.
- dlisio.lis.curves_metadata()#
Get the metadata corresponding to curves()
This is a sister-function to
dlisio.lis.curves()
, that returns the metadata objects (Spec Blocks) corresponding to the curves returned bydlisio.lis.curves()
.The keys of the returned dict exactly match the (column) names in the numpy array returned by curves.lis.curves. The values are the corresponding Spec Blocks.
Notes
curves_metadata()
andcurves()
should be called with the same values for both parameters sample_rate and strict for the metadata and curves to match.If dfsr.depth_mode is 1, then there is no Spec Block for the index. In this case None is used as value for the index in the returned dict.
See also
DataFormatSpec.index_mnem
The mnemonic of the index
DataFormatSpec.index_units
The units of the index
- Returns:
metadata
- Return type:
dict
Examples
Lets say that you want to read all curves that are sampled 6x the index, and you don’t care if the mnemonics are repeated. And that you are also interested in the metadata of the curves you read:
>>> rate = 6 >>> strict = False >>> curves = lis.curves(f, fs, sample_rate=rate, strict=strict) >>> metadata = lis.curves_metadata( fs, sample_rate=rate, strict=strict)
You now have the curves and their metadata. The metadata lookup mirrors the (column) names in the data. E.g. access data and metadata for the first RCCL curve in this log set:
>>> data = curves['RCCL(0)'] >>> spec = metadata['RCCL(0)']
LIS Logical Records#
Note
dlisio’s LIS reader is not yet feature complete and the following list does not reflect the full set of Logical Records defined in LIS79.
File Header (FHLR)#
- class dlisio.core.file_header#
File Header Logical Record (FHLR)
- file_name#
File Name - A unique, fixed length, name for a Logical File within a Logical Tape. The file name consists of two parts:
Service name - A 6 character Name of the service or program that created the tape
File number - A 3 character counter that counts the files in a logical tape
The service name and file number are seperated by a dot (“.”)
- Type:
str
- service_sublvl_name#
Service Sub Level Name - Subdevision of the Service ID that is used to further classify the source of data.
- Type:
str
- version_number#
Version number for the software that wrote the original data
- Type:
str
- date_of_generation#
Date of generation for the software that wrote the original data. Format: Year/Month/Day
- Type:
str
- max_pr_length#
Maximum physical record length
- Type:
str
- file_type#
Indicator for the kind of information in the file. For example: LL for label, LO for log data or CA for Calibration
- Type:
str
File Trailer (FTLR)#
- class dlisio.core.file_trailer#
File Trailer Logical Record (FTLR)
The FTLR is an optional last record of a Logical File. It’s identical to the
dlisio.core.file_header
with exception of the attributedlisio.core.file_header.prev_file_name
, which in the trailer is replaced withnext_file_name
.- file_name#
- service_sublvl_name#
- version_number#
- date_of_generation#
- max_pr_length#
- file_type#
Tape Header (THLR)#
- class dlisio.core.tape_header#
Tape Header Logical Record (THLR)
- service_name#
The name of the service or program that created the tape. This name is used as the service name in
dlisio.core.file_header.file_name
(anddlisio.core.file_trailer.file_name
) for all Logical Files in the tape- Type:
str
- date#
Date when the original data was acquired. Format: Year/Month/Day
- Type:
str
- origin_of_data#
The system that originally acquired or created the data
- Type:
str
- name#
Tape name - An ID that can aid to identify the Logical Tape, where applicable
- Type:
str
- continuation_number#
Tape continuation number - sequential ordering of tapes on the same reel
- Type:
str
- comment#
Any relevant remarks concerning the Logical Tape or the content of it
- Type:
str
- prev_tape_name#
An ID that can be used to identify the previous Logical Tape, where applicable. Should be blank for the first tape
- Type:
str
Tape Trailer (TTLR)#
- class dlisio.core.tape_trailer#
Tape Trailer Logical Record (TTLR)
The TTLR is optional. It’s identical to the
dlisio.core.tape_header
with exception of the attributedlisio.core.tape_header.prev_tape_name
, which in the trailer is replaced withnext_tape_name
.- service_name#
- date#
- origin_of_data#
- name#
- continuation_number#
- comment#
- next_tape_name#
An ID that can be used to identify the next Logical Tape, where applicable. Should be blank for the last tape
- Type:
str
Reel Header (RHLR)#
- class dlisio.core.reel_header#
Reel Header Logical Record (RHLR)
- service_name#
The name of the service or program that created the tape. This name is used as the service name in
dlisio.core.file_header.file_name
(anddlisio.core.file_trailer.file_name
) for all Logical Files in the tape- Type:
str
- date#
Date when the physical reel was created. Format: Year/Month/Day
- Type:
str
- origin_of_data#
The system that originally acquired or created the data
- Type:
str
- name#
Reel name - A 8 character name used to identify a specific reel of tape. This name matches the visual identification written on the tape container
- Type:
str
- continuation_number#
A number sequentially ordering multiple physical reels. The value is in the range 1 to 99
- Type:
str
- comment#
Any relevant remarks related to the physical reel of tape
- prev_reel_name#
An ID that can be used to identify the previous Physical Reel, where applicable.
- Type:
str
Reel Trailer (RTLR)#
- class dlisio.core.reel_trailer#
Reel Trailer Logical Record (RTLR)
The RTLR is optional. It’s identical to the
dlisio.core.reel_header
with exception of the attributedlisio.core.reel_header.prev_reel_name
, which in the trailer is replaced withnext_reel_name
.- service_name#
- date#
- origin_of_data#
- name#
- continuation_number#
- comment#
- next_reel_name#
An ID that can be used to identify the next Physical Reel, where applicable.
- Type:
str
Data Format Specification#
- class dlisio.lis.DataFormatSpec#
Data Format Specification Record (DFSR)
This is dlisio’s main interface for accessing Data Format Specification Records. A DFSR describes some arbitrary set of channels/curves that are recorded together along some common index.
The DFSR contains two main categories of data: Entry Blocks & Spec Blocks.
Entry Blocks (EB)
EBs are a set of well-defined properties that applies to the DFSR. These are implemented as properties on this class. E.g.
dlisio.lis.DataFormatSpec.depth_units
anddlisio.lis.DataFormatSpec.direction
.Spec Blocks (SB)
SB’s contain information about a single channel/curve in this DFSR such as mnemonics, units and dimensions of the curves. These can be accessed through
dlisio.lis.DataFormatSpec.specs
.Notes
For those familiar with DLIS, DFSRs are analogous to DLIS frames
dlisio.dlis.Frame
.See also
dlisio.lis.curves
Read the curves described by a DataFormatSpec
- property absent_value#
Absent Value
A default value that is used in the frame to indicate that the entry has no valid data and should be ignored.
- property depth_mode#
Depth Recording Mode
The mode in which the depth is recorded in the file. This is mainly an implementation detail and the mode used will not affect the end-user of dlisio in any way.
- property depth_reprc#
Datatype of depth/index channel
The datatype that the depth/index channel is recorded as. This is a number corresponding to LIS79-specific types.
- property depth_units#
Units of depth/index channel
This is typically only defined when
depth_mode
is 1. When depth mode is 0, the depth channel is defined by the first Spec Block inspecs
.If you don’t care about the depth recoding mode and just want the units of the index, use
index_units
instead.
- property direction#
Direction of the acquisition
This UP/DOWN flag indicated whether the measurements where taken going upwards or downwards in the well. A value of 1 means UP, 255 means DOWN while 0 means “neither”. Any other value is unspecified by LIS79.
- property entries#
Entry Blocks (EB)
Gives access to the underlying Entry Blocks. The average user is advised to interact with the Entry Blocks through the properties of this class. E.g. absent_value, depth_units etc..
- property frame_size#
The size of one frame (row)
This refers to the size (in bytes) of one row of data in the file.
Notes
LIS79 uses custom datatypes which do not exist on modern computers. This means that the frame size (dtype.itemsize) of the numpy arrays produced by dlisio may not always correspond to the frame size on disk.
- property index_mnem#
Mnemonic of the index
- Returns:
mnemonic
- Return type:
str
- property index_units#
Units of the index
- Returns:
units
- Return type:
str
- property max_frames#
Maximum frames per Logical Record
The maximum frames (rows) recorded per Logical Record. This refers to the fact that the log data is partitioned onto multiple Logical Record, but that is an implementation detail that most users do not need to care about.
- property optical_log_depth_units#
Optical Log Depth Scale Units
This flag specifies the depth units used on the optical log on the original recording. A value of 1 means ‘feet’, 255 means ‘meters’ while 0 means ‘time’. Any other value is unspecified by LIS79.
- property record_type#
Data Record Type
Indicated the Logical Record type which is used to store the data which is described by this Data Format Specification Record.
Notes
Only Logical Record Type 0 (normal data) was ever defined by LIS79. Hence this attribute has little semantic value.
- property reference_point#
Data Reference Point
LIS79 defined the Data Reference Point as:
Data Reference Point - There is a point on the tool string called the tool reference point. Its distance from the surface corresponds to measured depth. The data reference point is another point which is fixed relative to the tool string. At any instant during the real-time acquisition of data, the data reference point stands opposite the part of the hole to which the current output corresponds. This value is the distance of the data reference point above the tool reference point. It may be positive or negative. It is useful in determining the significance of data, such as tension or frame duration, which are not actually a function of depth. If absent, the value is undefined on the tape.
- property reference_point_units#
Reference point units
Units of the reference point described by
dlisio.lis.DataFormatSpec.reference_point
.
- sample_rates()#
Return all sample rates used by (non-index) Channels in this DFSR
- Returns:
rates
- Return type:
set of ints
- property spacing#
Frame Spacing
Depth difference between consecutive frames
- property spacing_units#
Frame Spacing Units
Units of the frame spacing described by
dlisio.lis.DataFormatSpec.spacing
.
- property spec_block_subtype#
Spec Block Subtype
There are two different subtype of the Spec Blocks (0 or 1). These have slightly different properties.
- property spec_block_type#
Spec Block Type
Defines which Block type is being used. Default is 0.
- property specs#
Spec Blocks (SB)
Gives access to the underlying Spec Blocks. A Spec Block is the LIS79 structure that defines channels/curves. Each Spec Block defines one channel and its properties.
LIS79 defines 2 different Spec Block types, namely subtype 0 and 1. These mostly share the same attributes, but there are a couple of attributes that differ between the 2 subtypes.
spec_block_type
defines which of the 2 subtypes is being used in the DFSR.See also
dlisio.core.spec_block_0
Speck Block - subtype 0
dlisio.core.spec_block_1
Speck Block - subtype 1
Job Identification#
Job Identification Logical Records implement the interface of
dlisio.lis.InformationRecord
Tool String Info#
Tool String Info Logical Records implement the interface of
dlisio.lis.InformationRecord
Wellsite Data#
Wellsite Data Logical Records implement the interface of
dlisio.lis.InformationRecord
Operator Command Inputs#
Operator Command Inputs Records implement the interface of
dlisio.core.text_record
Operator Response Inputs#
Operator Response Inputs Records are used to store input issued to the operator in
response to a system request for information. They implement the interface of
dlisio.core.text_record
System Outputs to Operator#
System Outputs to Operator Records are used to store system output messages
issued by the operator. They implement the interface of
dlisio.core.text_record
FLIC Comment#
Comment Records implement the interface of dlisio.core.text_record
LIS Structures#
Other structures defined by LIS79
- class dlisio.core.spec_block_0#
Spec Block - Subtype 0
A Spec Block contains information needed to correctly parse one channel from a frame. It also contains useful information such as the units of the curve measurement.
Note
For those familiar with DLIS, Spec Blocks are analogous to DLIS Channels
dlisio.dlis.Channel
.- mnemonic#
Name of the channel
- Type:
str
- service_id#
The service ID identifies the tool, the tool string used to measure the datum, or the name of the computed product.
- Type:
str
- service_order_nr#
A unique number which identifies the logging trip to the well-site.
- Type:
str
- units#
Units of the channel
- Type:
str
- file_nb#
Indicates the file number at the time the data was first acquired and written (for well-site data acquisitions only). This number, together with service_id and service_order_nr will uniquely identify any data string for the purpose of merging or other processing.
- Type:
int
- reserved_size#
The number of bytes reserved for this channel in the frame. If size is negative, the output is suppressed. The space is still reserved, and is the absolute value of this entry.
- Type:
int
- samples#
The number of samples recorded per frame. When samples == 1, the channel is sampled at the same interval as the index of the frame.
- Type:
int
- reprc#
The type of the recorded channel data. This number refers to one of the LIS79-defined data types.
- Type:
int
- api_log_type#
This, together with the attributes
api_curve_type
,api_curve_class
andapi_modifier
form a largly outdated log/curve code system utilizing a 2 digit curve code. Ref API Bulletin D-9 Feb ‘79.- Type:
int
- api_curve_type#
See
api_log_type
.- Type:
int
- api_curve_class#
See
api_log_type
.- Type:
int
- api_modifier#
See
api_log_type
.- Type:
int
- process_level#
Process level is a measure of the amount of processing done to obtain the curve. The size of the number increases in proportion to the amount of processing. However, the system has never been objectively defined.
- Type:
int
- class dlisio.core.spec_block_1#
Spec Block - Subtype 1
Spec Blocks subtype 1 share most of its attributes with
dlisio.core.spec_block_0
. However, there are 3 notable differences:The
api_*
-attributes are replaced withapi_codes
Subtype 1 has no
process_level
Subtype 1 defines
process_indicators
, which do not exist in subtype 0.
- mnemonic#
- service_id#
- service_order_nr#
- units#
- file_nb#
- reserved_size#
- samples#
- reprc#
- api_codes#
API codes form a log/curve system featuring a 3-digit curve code (Ref: API Bulletin D-9 Jul ‘79). The API codes are represented as a 32 bit integer. The 8-digit number can be masked out to dd/ddd/dd/d. E.g
45310011
should be interpreted as:- Log Type = 45 - Curve Type = 310 - Curve Class = 01 - Modifier = 1
- Type:
int
- process_indicators#
Process Indicators are used to define different processes or corrections that have been performed on the channel. The process indicators are defined as a bit-mask of 40 bits:
Bit nr
Definition
0-1
original logging direction [1]
2
true vertical depth correction
3
data channel not on depth
4
data channel is filtered
5
data channel is calibrated
6
computed (processed thru a function former)
7
derived (computed from more than one tool)
8
tool defined correction nb 2
9
tool defined correction nb 1
10
mudcake correction
11
lithology correction
12
inclinometry correction
13
pressure correction
14
hole size correction
15
temperature correction
22
auxiliary data flag
23
schlumberger proprietary
A value of 1 for a specific bit means that the correction or process is applied. Note that bits not listed in the table are undefined / unassigned by LIS79.
[1] Bits 0 and 1 form a single entry that defines the original logging direction for this channel. A value of ‘01’ (1) indicates down-hole. ‘10’ (2) indicated up-hole, while ‘00’ (0) indicates an ambiguous direction. I.e. stationary. ‘11’ (3) is undefined.
For convenience the bitmask is expanded to an object with all the above definitions as attributes.
- class dlisio.core.process_indicators#
- original_logging_direction: int#
- true_vertical_depth_correction: bool#
- data_channel_not_on_depth: bool#
- data_channel_is_filtered: bool#
- data_channel_is_calibrated: bool#
- computed: bool#
- derived: bool#
- tool_defined_correction_nb_2: bool#
- tool_defined_correction_nb_1: bool#
- mudcake_correction: bool#
- lithology_correction: bool#
- inclinometry_correction: bool#
- pressure_correction: bool#
- hole_size_correction: bool#
- temperature_correction: bool#
- auxiliary_data_flag: bool#
- schlumberger_proprietary: bool#
- class dlisio.core.component_block#
Component Block (CB)
Component Blocks are the basic structure of an Information Record. Each CB contains an individual piece of information.
- type_nb#
Helps define how a
dlisio.lis.InformationRecord
is formatted. E.g. as a series of individual pieces of information or a table of information.- Type:
int
- category#
Category is undefined by LIS79
- Type:
int
- mnemonic#
The name of the Component Block
- Type:
str
- component#
The actual data of this Component Block
- class dlisio.lis.InformationRecord(attic)#
Information Record
The 3 LIS Logical Record types Job Identification, Wellsite Data and Tool String Info are structured identically. This class implements the interface for them all.
An Information Record can contain:
Identification of company name, well name and similar
Parameters used in computation
Data environments, such as how a curve is presented on a graphical display
The content of a Information Record can be formatted in one of 2 ways:
As a table (structured)
As a list of single parameter values (unstructured)
Whether the record is structured as a table or not, each individual entry is represented by a LIS Component Block (CB)
dlisio.core.component_block
.Notes
The LIS79 Specification is ambiguous on which record types that count as Information Records. The table in
figure 3.9: Logical Record Types
includes Encrypted Table Dump and Table dump in the group called Information Records. The rest of the specification refers to Information Records as Job Identification, Wellsite Data and Tool String Info Records. This is how dlisio defines an Information Record too, as the structure of these are identical while Table Dump and Encrypted Table Dump Record share a different record structure.- components()#
Component Blocks
Return all the Component Blocks in the record in an unstructured list - Regardless of the intended structure of the record.
- Returns:
Component Blocks
- Return type:
list of
dlisio.core.component_block
- isstructured()#
Is the record structured as a table
Return True if the content of the record is structured as a table, otherwise returns False. Empty records - that is records with zero Component Blocks are considered unstructured.
- Returns:
isstructured
- Return type:
bool
- table(fill=None, simple=False)#
Format the Information Record components as a table
LIS explicitly allows Tables in Information Records to be sparse. That is, missing entries are allowed. If some table entries are not recorded in the file dlisio will fill that table cell with a default value, given by argument
fill
. E.g. if the following table information is recorded in the Information Record:MNEM GCOD GDEC DEST DSCA ------------------------ 1 E2E 2 S5 2 BBB - PF2
Then row 1 of ‘DEST’ and row 2 of ‘DSCA’ will be filled by dlisio.
- Parameters:
fill – A default value to fill into cells with no data
simple (bool) – If simple=False, the table will be populated with the
component_block
directly. If simple=True, then the resulting table will be populated with the values from thedlisio.core.component_block
.
- Raises:
ValueError – If the content of the record is not structured as a table.
ValueError – If the content of the record is ill-formed.
- Returns:
table – The Information Record structured in a Numpy Structured Array
- Return type:
np.ndarray
- table_name()#
Table name
When the record contains a table, the name of the table is defined by the first Component Block in the record
- Raises:
ValueError – If the record contains unstructured data. I.e. the content is not formatted as a table.
- Returns:
A CB containing the name of the table stored in this record
- Return type:
Utilities#
- class dlisio.lis.HeaderTrailer(header=None, trailer=None)#
Container for Header-Trailer pairs
Both Reels and Tapes have a Header Logical Record (RHLR and THLR) - and optionally a Trailer Logical Record (RTLR / TTLR).
The Trailer Records have an identical structure to their corresponding header, except for the prev_reel_name/prev_tape_name, which in the trailer is named next_reel_name/next_tape_name.
- header()#
Header Record
Returns the Reel or Tape Header Logical Record (RHLR or THLR), depending on the context in which the current instance lives.
- Returns:
header – Returns None if the Header Record is missing.
- Return type:
core.reel_header, core.tape_header or None
- trailer()#
Trailer Record
Returns the Reel or Tape Trailer Logical Record (RTLR or TTLR), depending on the context in which the current instance lives.
- Returns:
trailer – Returns None if the Trailer Record is missing.
- Return type:
core.reel_trailer, core.tape_trailer or None
- class dlisio.core.text_record#
Describes Miscellaneous records which contain one text field.
- message#
Complete content of the record. Text might be fully human-readable, partly human-readable or be just a bytes sequence. To get more control over the returned value refer to Strings and encodings.
- Type:
str or bytes