Log I/O
Loading...
Searching...
No Matches
Log I/O

The Petroware AS Log I/O module is a library for accessing (reading or writing) well log files such as DLIS, LAS 2.0, LAS 3.0, LIS, BIT, ASC, SPWLA or CSV.

Log I/O utilize high capacity memory mapped non-blocking I/O in order to get maximum performance for very large (GB) files.

Note that virtually all well logging data from the Norwegian continental shelf are QC'ed through the Log Studio™ application causing the library to get extremely well tested.

Log I/O is available for Java (logio.jar) and .Net (LogIo.dll). The libraries are self-contained, they have no external dependencies.

Release notes

Log I/O Release notes.

Programming examples

The programming examples below demonstrates the .Net API using C#.


DLIS

Digital Log Interchange Standard (DLIS) is a digital well log format introduced as Recommended Practice 66 (RP 66) by the American Petroleum Institute in 1991. RP 66 exists in two versions, V1 and V2. V2 is not commonly used. DLIS is a binary (big-endian) data format.

DLIS is an old format in all possible ways. Available DLIS software is limited and to a large degree orphaned technology. The existence of programming tools for DLIS are absent. There is no easily accessible DLIS format description available, dialects exists, and DLIS is in general very hard to digest.

But still, DLIS is the main storage and communication medium for wellbore logging information. Since logging technology has evolved substantially since the introduction of the format, the amount of information contained may be vast; multi-GB volumes are commonplace.

Using Log I/O, reading and writing DLIS files becomes trivial. Note that a physical DLIS file consist of a file header and one or more logical DLIS files, each containing a number of sets (meta-data), one or more frames containing curve data, and possibly a set of encrypted records. A frame contains an index curve and a set of measurement curves. Each curve may be single- or multi-dimensional.

A complete example program for reading a DLIS file is shown below:

using System;
using System.Collections.Generic;
using System.IO;
namespace Test
{
// <summary>
// Class for testing the LogIo.Net DLIS read API.
// </summary>
public class DlisTest
{
public static void Main(string[] arguments)
{
FileInfo file = new FileInfo("path/to/file.DLIS");
//
// Write some meta information about the disk file
//
Console.WriteLine("File: " + file.FullName);
if (!file.Exists) {
Console.WriteLine("File not found.");
return;
}
Console.WriteLine("Size: " + file.Length);
//
// Read the DLIS file including bulk data. Report the performance.
//
DlisFileReader reader = new DlisFileReader(file);
Console.WriteLine();
Console.WriteLine("Reading...");
int startTime = Environment.TickCount;
IList<DlisFile> dlisFiles = reader.Read(true, true, null);
int time = Environment.TickCount - startTime;
double speed = Math.Round(file.Length / time / 1000.0); // MB/s
Console.WriteLine("Done in " + time + "ms. (" + speed + "MB/s)");
//
// Write the DLIS file header
//
Console.WriteLine();
Console.WriteLine("-- File header:");
Console.WriteLine(dlisFiles[0].GetHeader());
//
// Report number of subfiles. Loop over each of them.
//
Console.WriteLine();
Console.WriteLine("The file contains " + dlisFiles.Count + " subfile(s):");
foreach (DlisFile dlisFile in dlisFiles) {
//
// Report subfile ID
//
Console.WriteLine();
Console.WriteLine("File ID: " + dlisFile.GetFileId());
Console.WriteLine();
//
// Report the meta-data we can conveniently extract through DlisUtil
//
Console.WriteLine("-- Meta-data as reported by DlisUtil:");
Console.WriteLine("Well name.........: " + DlisUtil.GetWellName(dlisFile));
Console.WriteLine("Run number........: " + DlisUtil.GetRunNumber(dlisFile));
Console.WriteLine("Field name........: " + DlisUtil.GetFieldName(dlisFile));
Console.WriteLine("Producer name.....: " + DlisUtil.GetProducerName(dlisFile));
Console.WriteLine("Company...........: " + DlisUtil.GetCompany(dlisFile));
Console.WriteLine("Country...........: " + DlisUtil.GetCountry(dlisFile));
Console.WriteLine("Start date........: " + DlisUtil.GetStartDate(dlisFile));
Console.WriteLine("Bit size..........: " + DlisUtil.GetBitSize(dlisFile));
Console.WriteLine("MD................: " + DlisUtil.GetMd(dlisFile));
Console.WriteLine("Index type........: " + DlisUtil.GetIndexType(dlisFile));
Console.WriteLine("Header identifier.: " + DlisUtil.GetHeaderIdentifier(dlisFile));
double[] interval = DlisUtil.GetInterval(dlisFile);
Console.WriteLine("Interval..........: " + interval[0] + " - " + interval[1]);
//
// Report all the meta-data
//
Console.WriteLine();
Console.WriteLine("-- Meta-data details:");
Console.WriteLine();
Console.WriteLine("The subfile contains " + dlisFile.GetSets().Count + " set(s):");
Console.WriteLine();
foreach (DlisSet set in dlisFile.GetSets()) {
Console.WriteLine("Set type: " + set.GetSetType() + " (Name = " + set.GetName() + ")");
// This will write all the set content as a matrix
Console.WriteLine(set);
}
//
// Encrypted records
//
Console.WriteLine();
Console.WriteLine("-- The subfile contains " + dlisFile.GetEncryptedRecords().Count + " encrypted record(s).");
//
// Report number of frames in this sub file. Loop over each of them.
//
Console.WriteLine();
Console.WriteLine("-- Curve information:");
Console.WriteLine();
Console.WriteLine("The subfile contains " + dlisFile.GetFrames().Count + " frame(s):");
foreach (DlisFrame frame in dlisFile.GetFrames()) {
int nCurves = frame.GetCurves().Count;
int nValues = frame.GetCurves().Count > 0 ? frame.GetCurves()[0].GetNValues() : 0;
//
// Report frame ID and #curves and #values
//
Console.WriteLine();
Console.WriteLine("Frame " + frame.GetName() +
" (" + nCurves + " curves of " + nValues + " values each):");
Console.WriteLine();
//
// For each curve, report name, dimension, unit, type and description, ...
//
foreach (DlisCurve curve in frame.GetCurves()) {
Console.WriteLine(" " + curve.GetName() +
"[" + curve.GetNDimensions() + "], " +
curve.GetUnit() + ", " +
curve.GetValueType() +
"(" + curve.GetRepresentationCode() + "), " +
curve.GetDescription());
//
// ... and the first few values from the first couple of dimensions:
//
for (int dimension = 0; dimension < curve.GetNDimensions(); dimension++) {
Console.Write(" ");
for (int index = 0; index < curve.GetNValues(); index++) {
Console.Write(curve.GetValue(dimension, index) + "; ");
if (index == 2) break; // Write a few values only
}
Console.WriteLine("...");
if (dimension == 2) { // Write a few dimensions only
Console.WriteLine(" :");
break;
}
}
}
}
}
}
}
}
Model a log curve of a DLIS file.
Definition DlisCurve.cs:17
string GetUnit()
Return unit of measure of the values of this curve.
Definition DlisCurve.cs:195
int GetNValues()
Return the number of values (per dimension) in this curve.
Definition DlisCurve.cs:353
int GetNDimensions()
Return the number of dimensions in this curve.
Definition DlisCurve.cs:286
Type GetValueType()
Return value type (i.e the .Net type) of the curve values.
Definition DlisCurve.cs:235
string GetDescription()
Return description of this curve.
Definition DlisCurve.cs:207
object GetValue(int dimension, int index)
Return a specific value from the given dimension of this curve.
Definition DlisCurve.cs:373
string GetName()
Return name of this curve.
Definition DlisCurve.cs:182
int GetRepresentationCode()
Return the DLIS representation code for the values of this curve.
Definition DlisCurve.cs:223
Class representing the content of one DLIS (sub-) file.
Definition DlisFile.cs:31
string GetFileId()
Return the ID of this DLIS file as specified in the ORIGIN set of the file.
Definition DlisFile.cs:122
IList< DlisSet > GetSets()
Return the sets of this DLIS file.
Definition DlisFile.cs:200
IList< DlisEncryptedRecord > GetEncryptedRecords()
Return the encrypted records of this DLIS file.
Definition DlisFile.cs:187
IList< DlisFrame > GetFrames()
Return the frames of this DLIS file.
Definition DlisFile.cs:395
Class for reading DLIS files.
Definition DlisFileReader.cs:44
IList< DlisFile > Read(bool shouldReadBulkData=true, bool shouldCaptureStatistics=false, IDlisDataListener dataListener=null, bool isGrowing=false)
Read all DLIS files from the disk file of this reader.
Definition DlisFileReader.cs:2218
Class representing a DLIS file frame in terms of its ID and the curves defined in that frame.
Definition DlisFrame.cs:17
IList< DlisCurve > GetCurves()
Return the curves of this frame in the order of which the data is organized in the corresponding DLIS...
Definition DlisFrame.cs:349
string GetName()
Return the name of this frame.
Definition DlisFrame.cs:156
Class for modeling a DLIS set.
Definition DlisSet.cs:56
A collection of convenience methods to access common meta-data from DLIS files.
Definition DlisUtil.cs:25
static string GetCompany(DlisFile dlisFile)
Return the company of the specified DLIS file.
Definition DlisUtil.cs:322
static string GetRunNumber(DlisFile dlisFile)
Return run number of the specified DLIS file.
Definition DlisUtil.cs:116
static string GetWellName(DlisFile dlisFile)
Return the well name of the specified DLIS file.
Definition DlisUtil.cs:205
static ? DateTime GetStartDate(DlisFile dlisFile)
Return start date of operation of the specified DLIS file.
Definition DlisUtil.cs:389
static DlisFrame.IndexType GetIndexType(DlisFile dlisFile)
Return the index type of the specified DLIS file.
Definition DlisUtil.cs:483
static string GetHeaderIdentifier(DlisFile dlisFile)
Return the header identifier (parameter "HIDE") from the specified DLIS file.
Definition DlisUtil.cs:140
static string GetProducerName(DlisFile dlisFile)
Return the producer (company) of the specified DLIS file.
Definition DlisUtil.cs:285
static ? double GetBitSize(DlisFile dlisFile)
Return bit size of the specified DLIS file.
Definition DlisUtil.cs:427
static string GetFieldName(DlisFile dlisFile)
Return the field name of the specified DLIS file.
Definition DlisUtil.cs:245
static ? double GetMd(DlisFile dlisFile)
Return MD (measured depth) of the specified DLIS file.
Definition DlisUtil.cs:454
static string GetCountry(DlisFile dlisFile)
Return country of the well of the specified DLIS file.
Definition DlisUtil.cs:359
Definition DlisComponent.cs:7


Creating DLIS files from scratch includes populating DlisFile instances with sets, frames and curves and writing it to a disk file using the DlisFileWriter class.

Note that the write API is by design low-level and there are many possible ways for a client to create an inconsistent DLIS file instance. The design is chosen for simplicity and flexibility. Each client is likely to implement one DLIS writer module anyway, and following the simple procedure below will ensure consistent DLIS instances:

// Create an empty DLIS file instance
DlisFile dlisFile = new DlisFile();
//
// Add the mandatory FILE-HEADER set
//
// Create the set
IList<DlisComponent> fileHeaderAttributes = new List<DlisComponent>();
fileHeaderAttributes.Add(DlisComponent.NewAttributeComponent("SEQUENCE-NUMBER", DlisRepresentationCode.ASCII, null));
fileHeaderAttributes.Add(DlisComponent.NewAttributeComponent("ID", DlisRepresentationCode.ASCII, null));
DlisSet fileHeaderSet = new DlisSet("FILE-HEADER", null, fileHeaderAttributes);
// Create an object and add to the set
DlisComponent fileHeaderObject = DlisComponent.NewObjectComponent(0, "0");
IList<DlisComponent> fileHeaderValues = new List<DlisComponent>();
fileHeaderValues.Add(DlisComponent.NewValueComponent("1", DlisRepresentationCode.ASCII, null)); // SEQUENCE-NUMBER
fileHeaderValues.Add(DlisComponent.NewValueComponent("logSetName", DlisRepresentationCode.ASCII, null)); // ID
fileHeaderSet.AddObject(fileHeaderObject, fileHeaderValues);
// Add set to file
dlisFile.AddSet(fileHeaderSet);
//
// Add the mandatory ORIGIN set
//
// Create set
IList<DlisComponent> originAttributes = new List<DlisComponent>();
originAttributes.Add(DlisComponent.NewAttributeComponent("FILE-ID", DlisRepresentationCode.ASCII, null));
originAttributes.Add(DlisComponent.NewAttributeComponent("WELL-NAME", DlisRepresentationCode.ASCII, null));
originAttributes.Add(DlisComponent.NewAttributeComponent("FIELD-NAME", DlisRepresentationCode.ASCII, null));
originAttributes.Add(DlisComponent.NewAttributeComponent("COMPANY", DlisRepresentationCode.ASCII, null));
DlisSet originSet = new DlisSet("ORIGIN", null, originAttributes);
// Create an object and add to set
DlisComponent originObject = DlisComponent.NewObjectComponent(0, "X");
IList<DlisComponent> originValues = new List<DlisComponent>();
originValues.Add(DlisComponent.NewValueComponent("fileId", DlisRepresentationCode.ASCII, null)); // FILE-ID
originValues.Add(DlisComponent.NewValueComponent("25/1-A-4", DlisRepresentationCode.ASCII, null)); // WELL-NAME
originValues.Add(DlisComponent.NewValueComponent("Frigg", DlisRepresentationCode.ASCII, null)); // FIELD-NAME
originValues.Add(DlisComponent.NewValueComponent("Mobil", DlisRepresentationCode.ASCII, null)); // COMPANY
originSet.AddObject(originObject, originValues);
// Add set to file
dlisFile.AddSet(originSet);
//
// Add the mandatory CHANNEL set describing all curves
//
// Create set
IList<DlisComponent> channelAttributes = new List<DlisComponent>();
channelAttributes.Add(DlisComponent.NewAttributeComponent("LONG-NAME", DlisRepresentationCode.ASCII, null));
channelAttributes.Add(DlisComponent.NewAttributeComponent("PROPERTIES", DlisRepresentationCode.IDENT, null));
channelAttributes.Add(DlisComponent.NewAttributeComponent("REPRESENTATION-CODE", DlisRepresentationCode.USHORT, null));
channelAttributes.Add(DlisComponent.NewAttributeComponent("UNITS", DlisRepresentationCode.UNITS, null));
channelAttributes.Add(DlisComponent.NewAttributeComponent("DIMENSION", DlisRepresentationCode.UVARI, null));
DlisSet channelSet = new DlisSet("CHANNEL", null, channelAttributes);
// Create objects for each curve
DlisComponent channelObject1 = DlisComponent.NewObjectComponent(0, "MD");
IList<DlisComponent> channelValues1 = new List<DlisComponent>();
channelValues1.Add(DlisComponent.NewValueComponent("Measured depth", DlisRepresentationCode.ASCII, null)); // LONG-NAME
channelValues1.Add(DlisComponent.NewValueComponent("BASIC", DlisRepresentationCode.IDENT, null)); // PROPERTIES
channelValues1.Add(DlisComponent.NewValueComponent(DlisRepresentationCode.FDOUBL, DlisRepresentationCode.USHORT, null)); // REPRESENTATION-CODE
channelValues1.Add(DlisComponent.NewValueComponent("m", DlisRepresentationCode.UNITS, null)); // UNITS
channelValues1.Add(DlisComponent.NewValueComponent(1, DlisRepresentationCode.UVARI, null)); // DIMENSION
channelSet.AddObject(channelObject1, channelValues1);
DlisComponent channelObject2 = DlisComponent.NewObjectComponent(0, "GR");
IList<DlisComponent> channelValues2 = new List<DlisComponent>();
channelValues2.Add(DlisComponent.NewValueComponent("Gamma ray", DlisRepresentationCode.ASCII, null)); // LONG-NAME
channelValues2.Add(DlisComponent.NewValueComponent("BASIC", DlisRepresentationCode.IDENT, null)); // PROPERTIES
channelValues2.Add(DlisComponent.NewValueComponent(DlisRepresentationCode.FDOUBL, DlisRepresentationCode.USHORT, null)); // REPRESENTATION-CODE
channelValues2.Add(DlisComponent.NewValueComponent("gAPI", DlisRepresentationCode.UNITS, null)); // UNITS
channelValues2.Add(DlisComponent.NewValueComponent(1, DlisRepresentationCode.UVARI, null)); // DIMENSION
channelSet.AddObject(channelObject2, channelValues2);
// Add set to file
dlisFile.AddSet(channelSet);
//
// Add any other sets containing meta-data
//
:
:
//
// Add the mandatory FRAME set describing all the containing frames
// and what curves they contains
//
// Create set
IList<DlisComponent> frameAttributes = new List<DlisComponent>();
frameAttributes.Add(DlisComponent.NewAttributeComponent("DESCRIPTION", DlisRepresentationCode.ASCII, null));
frameAttributes.Add(DlisComponent.NewAttributeComponent("CHANNELS", DlisRepresentationCode.OBNAME, null));
frameAttributes.Add(DlisComponent.NewAttributeComponent("INDEX-TYPE", DlisRepresentationCode.IDENT, null));
frameAttributes.Add(DlisComponent.NewAttributeComponent("DIRECTION", DlisRepresentationCode.IDENT, null));
frameAttributes.Add(DlisComponent.NewAttributeComponent("SPACING", DlisRepresentationCode.FDOUBL, "m"));
frameAttributes.Add(DlisComponent.NewAttributeComponent("INDEX-MIN", DlisRepresentationCode.FDOUBL, "m"));
frameAttributes.Add(DlisComponent.NewAttributeComponent("INDEX-MAX", DlisRepresentationCode.FDOUBL, "m"));
DlisSet frameSet = new DlisSet("FRAME", null, frameAttributes);
// Create a frame object
DlisComponent frameObject = DlisComponent.NewObjectComponent(0, "s10");
IList<DlisComponent> frameValues = new List<DlisComponent>();
frameValues.Add(DlisComponent.NewValueComponent("", DlisRepresentationCode.ASCII, null)); // DESCRIPTION
frameValues.Add(DlisComponent.NewValueComponent(new List<object>() {"MD", "GR"}, DlisRepresentationCode.OBNAME, null)); // CHANNELS
frameValues.Add(DlisComponent.NewValueComponent("BOREHOLE-DEPTH", DlisRepresentationCode.IDENT, null)); // INDEX-TYPE
frameValues.Add(DlisComponent.NewValueComponent("INCREASING", DlisRepresentationCode.IDENT, null)); // DIRECTION
frameValues.Add(DlisComponent.NewValueComponent(0.5, DlisRepresentationCode.FDOUBL, "m")); // SPACING
frameValues.Add(DlisComponent.NewValueComponent(1450.0, DlisRepresentationCode.FDOUBL, "m")); // INDEX-MIN
frameValues.Add(DlisComponent.NewValueComponent(1451.0, DlisRepresentationCode.FDOUBL, "m")); // INDEX-MAX
frameSet.AddObject(frameObject, frameValues);
// Add set to file
dlisFile.AddSet(frameSet);
//
// Create one frame per frame objects in the FRAME set and populate with curves and data.
// The curves must already have been defined in the CHANNEL set above.
//
DlisFrame frame = new DlisFrame(frameSet, frameObject);
DlisCurve curve1 = new DlisCurve("MD", "m", "Measured depth", DlisRepresentationCode.FDOUBL, 1);
curve1.AddValue(1450.0);
curve1.AddValue(1450.5);
curve1.AddValue(1451.0);
frame.AddCurve(curve1);
DlisCurve curve2 = new DlisCurve("GR", "API", "Gamma ray", DlisRepresentationCode.FDOUBL, 1);
curve2.AddValue(46.89);
curve2.AddValue(30.65);
curve2.AddValue(43.02);
frame.AddCurve(curve2);
// Add frame to file
dlisFile.AddFrame(frame);
//
// Finally write the DLIS file instance to disk
DlisFileWriter fileWriter = new DlisFileWriter(new FileInfo("/path/to/file.DLIS");
fileWriter.Write(dlisFile);


LIS

Log Interchange Standard (LIS) is the predecessor of DLIS and was developed by Schlumberger in the late 1970s.

Like DLIS, LIS is a binary (big-endian) format. It it is based on the VAX binary information standard and has an even more awkward syntax than DLIS.

But still, LIS files are still being produced and immense volumes of historical logging information exists in this format. Log I/O is a convenient platform for being able to manage and maintain this information.

A physical LIS file consists of one or more logical LIS files, each containing a set of records (meta-data) of different types as well as an index curve and a set of measurement curves. Each curve may have one or several samples per depth measure, and in addition the curves may be single- or multi-dimensional.

A complete example program for reading a LIS file is shown below:

using System;
using System.Collections.Generic;
using System.IO;
namespace Test
{
// <summary>
// Class for testing the LogIo.Net LIS read API.
// </summary>
public class LisTest
{
public static void Main(string[] arguments)
{
FileInfo file = new FileInfo("path/to/file.LIS");
//
// Write some meta information about the disk file
//
Console.WriteLine("File: " + file.FullName);
if (!file.Exists) {
Console.WriteLine("File not found.");
return;
}
Console.WriteLine("Size: " + file.Length);
//
// Read the LIS file including bulk data. Report the performance.
//
LisFileReader reader = new LisFileReader(file);
Console.WriteLine();
Console.WriteLine("Reading...");
int startTime = Environment.TickCount;
IList<LisFile> lisFiles = reader.Read(true);
int time = Environment.TickCount - startTime;
double speed = Math.Round(file.Length / time / 1000.0); // MB/s
Console.WriteLine("Done in " + time + "ms. (" + speed + "MB/s)");
// Loop over all logical files
foreach (LisFile lisFile in lisFiles) {
//
// Report subfile name
//
Console.WriteLine();
Console.WriteLine("File name: " + lisFile.GetName());
Console.WriteLine();
//
// Report the meta-data we can conveniently extract through LisUtil
//
Console.WriteLine("-- Meta-data as reported by LisUtil:");
Console.WriteLine("Well name........: " + LisUtil.GetWellName(lisFile));
Console.WriteLine("Field name.......: " + LisUtil.GetFieldName(lisFile));
Console.WriteLine("Run number.......: " + LisUtil.GetRunNumber(lisFile));
Console.WriteLine("Company..........: " + LisUtil.GetCompany(lisFile));
Console.WriteLine("Service company..: " + LisUtil.GetServiceCompany(lisFile));
Console.WriteLine("Country..........: " + LisUtil.GetCountry(lisFile));
Console.WriteLine("Rig name.........: " + LisUtil.GetRigName(lisFile));
Console.WriteLine("Date.............: " + LisUtil.GetDate(lisFile));
Console.WriteLine("Bit size.........: " + LisUtil.GetBitSize(lisFile));
//
// Report all the meta-data
//
Console.WriteLine();
Console.WriteLine("-- Meta-data details:");
Console.WriteLine();
Console.WriteLine("The subfile contains " + lisFile.GetRecords().Count + " record(s):");
Console.WriteLine();
foreach (LisRecord in lisFile.GetRecord())
Console.WriteLine(record);
//
// Report #curves and #values
//
int nCurves = lisFile.GetCurves().Count;
int nValues = nCurves > 0 ? lisFile.GetCurves()[0].GetNValues() : 0;
Console.WriteLine();
Console.WriteLine("The file contains " + nCurves + " curves of " + nValues + " values each.");
Console.WriteLine();
//
// For each curve, report name, dimension, unit, type and description, ...
//
foreach (LisCurve curve in lisFile.GetCurves()) {
Console.WriteLine(" " + curve.GetName() +
"[" + curve.GetNDimensions() + "], " +
curve.GetUnit() + ", " +
curve.GetValueType() +
"(" + curve.GetRepresentationCode() + "), " +
curve.GetDescription());
//
// ... and the first few values from the first couple of dimensions:
//
for (int sample = 0; sample < curve.GetNSamples(), sample++) {
for (int dimension = 0; dimension < curve.GetNDimensions(); dimension++) {
Console.Write(" ");
for (int index = 0; index < curve.GetNValues(); index++) {
Console.Write(curve.GetValue(sample, dimension, index) + "; ");
if (index == 10) break; // Write a few values only
}
Console.WriteLine("...");
if (dimension == 10) { // Write a few dimensions only
Console.WriteLine(" :");
break;
}
}
}
}
}
}
}
}
Model a log curve as it is defined by LIS.
Definition LisCurve.cs:20
int GetNSamples()
Return number of samples per depth for this curve.
Definition LisCurve.cs:194
string GetUnit()
Return unit of measure of the data of this curve.
Definition LisCurve.cs:134
int GetNValues()
Return the number of values in this curve.
Definition LisCurve.cs:249
int GetNDimensions()
Return the number of dimensions of this curve.
Definition LisCurve.cs:182
Type GetValueType()
Return value type (i.e. .Net Type) of curve values.
Definition LisCurve.cs:170
string GetDescription()
Return description of this curve.
Definition LisCurve.cs:146
object GetValue(int sampleNo, int dimension, int index)
Return a specific value from the given dimension of this curve.
Definition LisCurve.cs:273
string GetName()
Return name of this curve.
Definition LisCurve.cs:122
int GetRepresentationCode()
Return the LIS representation code for the data of this curve.
Definition LisCurve.cs:158
Class representing the content of a LIS (sub-) file.
Definition LisFile.cs:13
IList< LisCurve > GetCurves()
Return the curves of this LIS file instance.
Definition LisFile.cs:334
string GetName()
Return name of this LIS file.
Definition LisFile.cs:48
IList< LisRecord > GetRecords()
Return the (non-data) records of this LIS file.
Definition LisFile.cs:132
Class for reading LIS files (sometimes also referred to as TAP files).
Definition LisFileReader.cs:45
Common base class for all LIS record types.
Definition LisRecord.cs:12
Convenience class for extracting information from LIS files.
Definition LisUtil.cs:27
static string GetWellName(LisFile lisFile)
Return well name of the specified LIS file.
Definition LisUtil.cs:215
static ? double GetBitSize(LisFile lisFile)
Return bit size of the specified LIS file.
Definition LisUtil.cs:418
static ? DateTime GetDate(LisFile lisFile)
Return date of the specified LIS file.
Definition LisUtil.cs:447
static string GetFieldName(LisFile lisFile)
Return field name of the specified LIS file.
Definition LisUtil.cs:244
static string GetCountry(LisFile lisFile)
Return country of the specified LIS file.
Definition LisUtil.cs:296
static string GetRunNumber(LisFile lisFile)
Return run number of the specified LIS file.
Definition LisUtil.cs:389
static string GetRigName(LisFile lisFile)
Return rig name of the specified LIS file.
Definition LisUtil.cs:359
static string GetCompany(LisFile lisFile)
Return company of the specified LIS file.
Definition LisUtil.cs:270
static string GetServiceCompany(LisFile lisFile)
Return service company of the specified LIS file.
Definition LisUtil.cs:326
Definition ILisDataListener.cs:2


Creating LIS files from scratch includes populating LisFile instances with records and curves and writing it to a disk file using the LisFileWriter class.

Note that the write API is by design low-level and there are many possible ways for a client to create an inconsistent LIS file instance. The design is chosen for simplicity and flexibility. Each client is likely to implement one LIS writer module anyway, and following the simple procedure below will ensure consistent LIS instances:

//
// Create an empty LisFile instance
//
LisFile lisFile = new LisFile();
//
// Add a reel header record
//
LisRecord reelHeaderRecord = new LisReelHeaderRecord("Serv", new DateTime(), "Orig", "Reel", 1, null, "Created by <name>");
lisFile.AddRecord(reelHeaderRecord);
//
// Add a tape header record
//
LisRecord tapeHeaderRecord = new LisTapeHeaderRecord("Serv", new DateTime(), "Orig", "Reel", 1, null, "Created by <name>");
lisFile.AddRecord(tapeHeaderRecord);
//
// Add a file header record
//
LisRecord fileHeaderRecord = new LisFileHeaderRecord("<name>", "ServID", "<version>", new DateTime(), 99999, "LI", null);
lisFile.AddRecord(fileHeaderRecord);
//
// Add a well site data record
//
LisWellSiteDataRecord wellSiteDataRecord = new LisWellSiteDataRecord("Well site data", new List<string>() {"Name", "Value", "Unit", "Description"});
wellSiteDataRecord.AddRow(new List<string>() {"WELL", "25/1-A-4", null, "Well name"});
wellSiteDataRecord.AddRow(new List<string>() {"FIELD", "Frigg", null, "Field name"});
wellSiteDataRecord.AddRow(new List<string>() {"MD", "2450.5", "m", "Measured depth"});
:
//
// Add the mandatory data format specification
//
TODO
//
// Add curves
//
TODO
Class representing a LIS file header record ("FHLR")
Definition LisFileHeaderRecord.cs:14
void AddRecord(LisRecord record)
Add the specified record to this LIS file.
Definition LisFile.cs:117
void AddRow(IList< object > values)
Add a table row to this component.
Definition LisInformationRecord.cs:146
Class representing a LIS reel header.
Definition LisReelHeaderRecord.cs:18
Class representing a LIS tape header record ("TTLR").
Definition LisTapeHeaderRecord.cs:23
Class representing a LIS well site data record.
Definition LisWellSiteDataRecord.cs:14


LAS

The Log ASCII Standard (LAS) was created by the Canadian Well Logging Society (CWLS) in the late 1980s.

LAS popularity is due to its simple syntax and the fact that it contains human readable ASCII text. Consequently it is easier to work with than the black-box DLIS and LIS files. The ASCII format has a price however; It requires a lot more storage space than equivalent DLIS files, so LAS is not useful for very large log volumes. Also, the easily accessible text format combined with an ambiguous format description has caused many LAS dialects and semantic interpretations over the years.

Three different versions of LAS exists, 1.2, 2.0 and 3.0. Current version is 3.0, published in 2000, but version 2.0 is by far the most common. Log I/O supports all LAS versions, as well as converting between them. Note that LAS does not support multi-frame nor multi-dimensional curves like DLIS. LAS 3.0 supports multiple subfiles per physical disk file.

A complete example program for reading a LAS file is shown below:

using System;
using System.Collections.Generic;
using System.IO;
namespace Test
{
// <summary>
// Class for testing the LogIo.Net LAS read API.
// </summary>
public class LasTest
{
public static void Main(string[] arguments)
{
FileInfo file = new FileInfo("path/to/file.LAS");
//
// Write some meta information about the disk file
//
Console.WriteLine("File: " + file.FullName);
if (!file.Exists) {
Console.WriteLine("File not found.");
return;
}
Console.WriteLine("Size: " + file.Length);
//
// Read the LAS file including bulk data. Report the performance.
//
LasFileReader reader = new LasFileReader(file);
Console.WriteLine();
Console.WriteLine("Reading...");
int startTime = Environment.TickCount;
IList<LasFile> lasFiles = reader.Read();
int time = Environment.TickCount - startTime;
double speed = Math.Round(file.Length / time / 1000.0); // MB/s
Console.WriteLine("Done in " + time + "ms. (" + speed + "MB/s)");
//
// Report number of subfiles. Loop over each of them.
//
Console.WriteLine();
Console.WriteLine("The file contains " + lasFiles.Count + " subfile(s):");
foreach (LasFile lasFile in lasFiles) {
//
// Report subfile name
//
Console.WriteLine();
Console.WriteLine("File name: " + lasFile.GetName());
Console.WriteLine();
//
// Report the meta-data we can conveniently extract through LasUtil
//
Console.WriteLine("-- Meta-data as reported by LasUtil:");
Console.WriteLine("Well name.........: " + LasUtil.GetWellName(lasFile));
Console.WriteLine("Field name........: " + LasUtil.GetFieldName(lasFile));
Console.WriteLine("Rig name..........: " + LasUtil.GetRigName(lasFile));
Console.WriteLine("Company...........: " + LasUtil.GetCompany(lasFile));
Console.WriteLine("Service company...: " + LasUtil.GetServiceCompany(lasFile));
Console.WriteLine("Country...........: " + LasUtil.GetCountry(lasFile));
Console.WriteLine("Run number........: " + LasUtil.GetRunNumber(lasFile));
Console.WriteLine("Bit size..........: " + LasUtil.GetBitSize(lasFile));
Console.WriteLine("Date..............: " + LasUtil.GetDate(lasFile));
Console.WriteLine("MD................: " + LasUtil.GetMd(lasFile));
double?[] interval = LasUtil.GetInterval(lasFile);
if (interval != null)
Console.WriteLine("Interval..........: " + interval[0] + " - " + interval[1]);
// Loop over all curves
foreach (LasCurve curve in lasFile.GetCurves()) {
Console.WriteLine(" " + curve.GetName() +
curve.GetUnit() + ", " +
curve.GetValueType() +
curve.GetDescription());
//
// ... and the first few values
//
for (int index = 0; index < curve.GetNValues(); index++) {
Console.Write(curve.GetValue(index) + "; ");
if (index == 10) { // Write a few values only
Console.WriteLine("...");
break;
}
}
}
}
}
}
}
Model a log curve of a LAS file.
Definition LasCurve.cs:16
string GetUnit()
Return unit of measurement for the values of this curve.
Definition LasCurve.cs:160
int GetNValues()
Return the number of values in this curve.
Definition LasCurve.cs:301
Type GetValueType()
Return data type of the values of this curve.
Definition LasCurve.cs:184
string GetDescription()
Return description of this curve.
Definition LasCurve.cs:172
object GetValue(int dimension, int index)
Return curve value of the specified index.
Definition LasCurve.cs:320
string GetName()
Return name of this curve.
Definition LasCurve.cs:148
Class for representing the content of one logical LAS file.
Definition LasFile.cs:21
IList< LasCurve > GetCurves(LasSection dataSection)
Return the curves of the specified data section.
Definition LasFile.cs:795
string GetName()
Return the name of this LAS file.
Definition LasFile.cs:123
Class for reading LAS files.
Definition LasFileReader.cs:32
Convenience methods for extracting information from LAS files.
Definition LasUtil.cs:16
static string GetFieldName(LasFile lasFile)
Return field name of the specified LAS file.
Definition LasUtil.cs:55
static ? double GetBitSize(LasFile lasFile)
Return bit size of the specified LAS file.
Definition LasUtil.cs:463
static string GetRigName(LasFile lasFile)
Return rig name of the specified LAS file.
Definition LasUtil.cs:107
static double[] GetInterval(LasFile lasFile)
Get logging interval of the specified LAS file.
Definition LasUtil.cs:212
static string GetWellName(LasFile lasFile)
Return well name of the specified LAS file.
Definition LasUtil.cs:30
static string GetCountry(LasFile lasFile)
Return country of the well of the specified LAS file.
Definition LasUtil.cs:182
static string GetRunNumber(LasFile lasFile)
Return run number of the specified LAS file.
Definition LasUtil.cs:80
static ? DateTime GetDate(LasFile lasFile)
Return logging date from the specified LAS file.
Definition LasUtil.cs:488
static string GetCompany(LasFile lasFile)
Return company name of the specified LAS file.
Definition LasUtil.cs:132
static ? double GetMd(LasFile lasFile)
Return MD (measured depth) of the specified LAS file.
Definition LasUtil.cs:511
static string GetServiceCompany(LasFile lasFile)
Return service company name of the specified LAS file.
Definition LasUtil.cs:157
Definition ILasDataListener.cs:2


Creating LAS files from scratch includes populating LasFile instances with sections and curves.

The mandatory ~VERSION section will be auto-populated. The mandatory ~WELL section must be created by the client, but parameters associated with the curve data (STRT, STOP, STEP and NULL) will be auto-populated if  the section is present.

The optional parameter sections must be provided by the client.

The definition section(s) (~CURVE) will be auto-populated based on provided curves.

A complete example program for writing a LAS file is shown below:

using System;
namespace Test
{
// <summary>
// Class for testing the LogIo.Net LAS write API.
// </summary>
public class LasTest
{
public static void Main(string[] arguments)
{
//
// Create LasFile instance
//
LasFile lasFile = new LasFile("WLC_COMPOSITE", LasVersion.VERSION_2_0);
//
// Create the mandatory WELL section
//
LasSection wellSection = new LasSection("Well");
wellSection.AddRecord(new LasParameterRecord("WELL", null, "16/2-16", "Well name"));
wellSection.AddRecord(new LasParameterRecord("CTRY", null, "Norway", "Country"));
wellSection.AddRecord(new LasParameterRecord("COMP", null, "Lundin", "Company"));
wellSection.AddRecord(new LasParameterRecord("FLD", null, "Johan Sverdrup", "Field name"));
wellSection.AddRecord(new LasParameterRecord("SRVC", null, "Schlumberger", "Service company"));
lasFile.AddSection(wellSection);
//
// Create an optional parameter section
//
LasSection parameterSection = new LasSection("Parameters");
parameterSection.AddRecord(new LasParameterRecord("Rshl", "OHMM", "2.0000", "Resistivity shale"));
parameterSection.AddRecord(new LasParameterRecord("TLI", null, "149.5000", "Top Logged Interval"));
parameterSection.AddRecord(new LasParameterRecord("VshCutoff", "V/V", "0.2500", "Shale Volume Cutoff"));
lasFile.AddSection(parameterSection);
//
// Create and populate curves
//
LasCurve depthCurve = new LasCurve("DEPT", "m", "Measured depth", typeof(double));
depthCurve.AddValue(4350.00);
depthCurve.AddValue(4350.50);
depthCurve.AddValue(4351.00);
depthCurve.AddValue(4351.50);
depthCurve.AddValue(4352.00);
lasFile.AddCurve(depthCurve);
LasCurve gammaRayCurve = new LasCurve("GR", "gAPI", "Gamma ray", typeof(double));
gammaRayCurve.AddValue(12.3);
gammaRayCurve.AddValue(8.43);
gammaRayCurve.AddValue(null); // No-value
gammaRayCurve.AddValue(4.1);
gammaRayCurve.AddValue(7.29);
lasFile.AddCurve(gammaRayCurve);
//
// Write instance to disk
//
LasFileWriter.Write(new FileInfo("/path/to/file.LAS"), lasFile);
}
}
}
void AddValue(int dimension, object value)
Add the specified value to the end of this curve.
Definition LasCurve.cs:230
void AddSection(LasSection section)
Add the specified section to this LAS file.
Definition LasFile.cs:212
void AddCurve(string definitionSectionName, LasCurve curve)
Add the specified curve to this LAS file and associate it with the section of the given name.
Definition LasFile.cs:987
Class for writing LAS files to disk.
Definition LasFileWriter.cs:39
void Write(LasFile lasFile)
Write the specified LAS file instance.
Definition LasFileWriter.cs:404
Class representing a LAS parameter record.
Definition LasParameterRecord.cs:24
Class representing a LAS section in terms of its title and its containing records.
Definition LasSection.cs:34
void AddRecord(LasRecord record)
Add the specified record to this LAS section.
Definition LasSection.cs:228
Class representing the possible versions of the LAS standard.
Definition LasVersion.cs:12
static readonly LasVersion VERSION_2_0
LAS version 2.0.
Definition LasVersion.cs:21

The program above will produce the following LAS file:

~Version
VERS. 2.0 : CWLS LAS ASCII Standard - Version 2.0
WRAP. NO : One line per depth step
~Well
WELL. 16/2-16 : Well name
CTRY. Norway : Country
COMP. Lundin : Company
FLD . Johan Sverdrup : Field name
SRVC. Schlumberger : Service company
STRT.m 4350.0 : Start depth
STOP.m 4352.0 : Stop depth
STEP.m 0.5 : Step
NULL. -999.25 : No-value
~Parameters
Rshl .OHMM 2.0000 : Resistivity shale
TLI . 149.5000 : Top Logged Interval
VshCutoff.V/V 0.2500 : Shale Volume Cutoff
~Curves
DEPT.m : Measured depth
GR .gAPI : Gamma ray
~Ascii
4350.0 12.30000
4350.5 8.43000
4351.0 -999.25
4351.5 4.10000
4352.0 7.29000


BIT

The Basic Information Tape (BIT) is a binary well log format created by Dresser Atlas in in the 1970's. Each physical BIT disk file can contain one or more logical BIT files. Each logical file is composed by a simple General Heading record followed by a number of Data records holding data for a maximum of 20 curves (not including the index channel of depth or time). All curve data is 4-byte floating point in the IBM System/360 representation.

The BIT format is no longer in common use, but vast amounts of historic logging data still exists in this format. The format is quite simple, but no public description of it is available.

A complete example program for reading a BIT file is shown below:

using System;
using System.Collections.Generic;
using System.IO;
namespace Test
{
// <summary>
// Class for testing the LogIo.Net BIT read API.
// </summary>
public class BitTest
{
public static void Main(string[] arguments)
{
FileInfo file = new FileInfo("path/to/file.BIT");
//
// Write some meta information about the disk file
//
Console.WriteLine("File: " + file.FullName);
if (!file.Exists) {
Console.WriteLine("File not found.");
return;
}
Console.WriteLine("Size: " + file.Length);
//
// Read the BIT file including bulk data. Report the performance.
//
BitFileReader reader = new BitFileReader(file);
Console.WriteLine();
Console.WriteLine("Reading...");
int startTime = Environment.TickCount;
IList<BitFile> bitFiles = reader.Read(true);
int time = Environment.TickCount - startTime;
double speed = Math.Round(file.Length / time / 1000.0); // MB/s
Console.WriteLine("Done in " + time + "ms. (" + speed + "MB/s)");
//
// Report number of subfiles. Loop over each of them.
//
Console.WriteLine();
Console.WriteLine("The file contains " + bitFiles.Count + " subfile(s):");
foreach (BitFile bitFile in bitFiles) {
//
// Report subfile name
//
Console.WriteLine();
Console.WriteLine("File name: " + bitFile.GetName());
Console.WriteLine();
//
// Get file header containing logging meta-data
//
LisGeneralHeadingRecord header = bitFile.GetHeader();
Console.WriteLine("Well name.....: " + header.GetWellName());
Console.WriteLine("Company.......: " + header.GetCompanyName());
Console.WriteLine("Time..........: " + header.GetTime();
//
// Loop over all curves
//
foreach (BitCurve curve in bitFile.GetCurves()) {
Console.WriteLine(" " + curve.GetName() + " " +
curve.GetQuantity() +
curve.GetUnit() + " " +
curve.GetValueType() + " " +
curve.GetDescription());
//
// ... and list the first few values
//
Console.Write(" ");
for (int index = 0; index < curve.GetNValues(); index++) {
Console.Write(curve.GetValue(index) + "; ");
if (index == 10) {
break;
Console.WriteLine("...");
}
}
}
}
}
}
}
Model a curve of a BIT log file.
Definition BitCurve.cs:15
string GetUnit()
Return unit of measurement for the values of this curve.
Definition BitCurve.cs:122
string GetQuantity()
Return quantity of this curve.
Definition BitCurve.cs:110
int GetNValues()
Return the number of values in this curve.
Definition BitCurve.cs:158
Type GetValueType()
Return type of the values of this curve.
Definition BitCurve.cs:134
string GetDescription()
Return description of this curve.
Definition BitCurve.cs:96
object GetValue(int index)
Return curve value of the specified index.
Definition BitCurve.cs:177
string GetName()
Return name of this curve.
Definition BitCurve.cs:84
Class representing the content of one BIT (sub-) file.
Definition BitFile.cs:15
IList< BitCurve > GetCurves()
Return the curves of this BIT file.
Definition BitFile.cs:125
string GetName()
Return name of this BIT file.
Definition BitFile.cs:81
BitGeneralHeadingRecord GetHeader()
Return header of this BIT file.
Definition BitFile.cs:112
Class for reading BIT log files.
Definition BitFileReader.cs:35
IList< BitFile > Read(bool shouldReadBulkData=true)
Read all BIT files from the stream.
Definition BitFileReader.cs:640
Definition BitCurve.cs:6


Creating BIT files from scratch includes populating BitFile instances with a proper header and associated curve data.

A complete example program for writing a BIT file is shown below:

using System;
namespace Test
{
// <summary>
// Class for testing the LogIo.Net BIT write API.
// </summary>
public class BitTest
{
public static void Main(string[] arguments)
{
//
// Create BIT file with appropriate header
//
"Halliburton",
"34/2-16B T2",
DateTime.Now,
new List<string>() {"GR", "NEU"},
startDepth,
4350.0,
4352.0,
0.5,
"",
"1");
header.setDepthUnit("m");
BitFile bitFile = new BitFile(header);
//
// Curve data
//
BitCurve gammaRayCurve = bitFile.GetCurves()[1];
gammaRayCurve.AddValue(12.3);
gammaRayCurve.AddValue(8.43);
gammaRayCurve.AddValue(null); // No-value
gammaRayCurve.AddValue(4.1);
gammaRayCurve.AddValue(7.29);
BitCurve neutronCurve = bitFile.GetCurves()[2];
neutronCurve.AddValue(0.89);
neutronCurve.AddValue(1.13);
neutronCurve.AddValue(2.32);
neutronCurve.AddValue(0.71);
neutronCurve.AddValue(0.99);
//
// Write instance to disk
//
BitFileWriter writer = new BitFileWriter(new FileInfo("/path/to/file.BIT"));
writer.Write(bitFile);
}
}
}
void AddValue(object value)
Add the specified value to the end of this curve.
Definition BitCurve.cs:146
Class for writing BIT files to disk.
Definition BitFileWriter.cs:24
void Write(BitFile bitFile)
Write the specified BIT file.
Definition BitFileWriter.cs:338
Model the general heading record of a logical BIT file.
Definition BitGeneralHeadingRecord.cs:15