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 and LogicalFile.

** 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:

dlisio.lis.PhysicalFile

Examples

Opening a file is straightforward. dlisio.lis.load() is designed to work like python’s own open(). 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 a logging.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. See dlisio.core.reel_header and dlisio.core.reel_trailer for more on the Reel Logical Records (RHLR, RTLR).

Type:

dlisio.lis.HeaderTrailer

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. See dlisio.core.tape_header and dlisio.core.tape_trailer for more on the Tape Logical Records (THLR, TTLR).

Type:

dlisio.lis.HeaderTrailer

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 and CH02, where CH01 has a sample rate of 1, and CH02 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 and 330. 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 by dlisio.lis.curves(). This means that multiple calls to this function are required to read all the curves in the logset. The parameter sample_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, http://w3.energistics.org/LIS/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 by dlisio.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() and curves() 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

prev_file_name#

Optional previous file number. When used, it has the same format as file_name.

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 attribute dlisio.core.file_header.prev_file_name, which in the trailer is replaced with next_file_name.

file_name#
service_sublvl_name#
version_number#
date_of_generation#
max_pr_length#
file_type#
next_file_name#

Optional next file number. When used, it has the same format as file_name.

Type:

str

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 (and dlisio.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 attribute dlisio.core.tape_header.prev_tape_name, which in the trailer is replaced with next_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 (and dlisio.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 attribute dlisio.core.reel_header.prev_reel_name, which in the trailer is replaced with next_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 and dlisio.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 in specs.

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 and api_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 with api_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.

Type:

dlisio.core.process_indicators

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

reprc#

The type of component

Type:

int

size#

The size of component

Type:

int

category#

Category is undefined by LIS79

Type:

int

mnemonic#

The name of the Component Block

Type:

str

units#

The units of measurement for component

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 the dlisio.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:

dlisio.core.component_block

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