Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an R package to parse geophysical "Log Ascii Standard" Files (.las files)?

Is there an R package that can read .las files, i.e. Schlumberger Log Ascii standard files?
It should be capable of reading las 2.0 files.

Please note:

  • I am not talking about LIDAR .las files here.
  • I am talking about geophysical well-hole logging files (not logging files for computer apps, demons and the like)

Searching for R and Las and Logfiles on the internet gives me personally too many red herrings.

Updates from Comments:

I am also considering scripts or APIs that could make use of language bindings for R.

So far, I've found the following scripts:

  • las2witsml - a ruby script
  • Text-LAS-Parser-0.01 - a perl script

However, all these scripts so far seem not very mature to me.

There is also a freeware software package "Log Data Toolbox" by Schlumberger, but it only runs under Windows and might have compatibility issues with non-english Versions of Windows (if I remember correctly).

There is a complex java applet from the Kansas Geological Survey, but it is a bit sluggish for large .las input-files.

There is a ruby project and a python project. Also, see this link for a nice set of example las files.

like image 993
knb Avatar asked Oct 09 '12 16:10

knb


4 Answers

Answering my own question:

Now there is a python library, lasio, which works quite nicely. It could be called from R, maybe via the system2() function; and the output could be fetched into R data structures. Another possibility would be to serialize the lasfile-objects into JSON, save to file and reimport from R. Maybe I'll extend this answer with a code sample, but I don't have the time right now.

  • lasio on github
  • lasio examples - plots at the bottom of the notebook
like image 106
knb Avatar answered Nov 17 '22 15:11

knb


2021 Answer:

LASTOOLS

lastools is an R package on github reads Log Ascii Standard v2.0 files.

It also provides basic plotting, and writing out to las file format.

To install from r command line (can be installed other ways also):

devtools::install_github("Gitmaxwell/lastools")

Example to load lastools, read a las file and display the contents in R :

library(lastools)
las_file <- "your-sample.las"
las <- read_las(las_file)
print(las)

LASR

lasr (in beta testing as of early 2021) Lasr is primarily designed to import LAS files at high speed and in large batches.

To install from r command line:

if (!require('devtools')) install.packages('devtools')
library(devtools)
install_github('https://github.com/donald-keighley/lasr')

Example to load lasr, read and display las file contents in R:

library(lasr)
las = read.las(system.file("extdata", "las_3_cwls.las", package = "lasr"))

#Display the WELL section
head(las$well, 10)
like image 21
DC Slagel Avatar answered Nov 17 '22 15:11

DC Slagel


I have done for my personal (fit for my purpose) use a well log las2 file reader. It has 2 steps 1. create a list of *.las files to read and append 2. read the number of *.las files and append into a single data frame. Both codes are tested on a set of *.las files created from standard commercial packages in 2016 - in Windows 10 under R 3.2.4 (64bit)

Code-1 to read and create simple file list of *.las files to run Code-2

# Read the file having list of well-log LAS files
# Create a R-Object [wellname, path, filename] for LAS reader
# Create filelist from DOS prompt dir *.las > filelist.dat
# G Srikanth 29-May-2016
#
library(stringr)
defaultworkdir <- readline("What is the file path? ")
setwd(defaultworkdir)
welllistfile <- readline("What is the well list file? ")
listfilelines <- readLines(con = welllistfile, skipNul = TRUE)
#
#      search for "Directory of " to get the LAS data folder = lasfolder
#      search for "File(s)" to get the number of files = nlasfiles, linenumber
#      the data file names are before the "Files(s)" line = lasfilenames() char vector of length nlasfiles
#
oneline <- listfilelines[grep("Directory of ",listfilelines)]
lasfilepath <- sub(" Directory of ","",oneline)
oneline <- listfilelines[grep(" File",listfilelines)]
# modified from http://stackoverflow.com/questions/2261079/how-to-trim-leading-and-trailing-whitespace-in-r
numberoflasfiles <- as.numeric(word(sub("^\\s+", "", oneline),1))

# file names occur from - to in the DOS list read-in
fromline <- as.numeric(grep(" File",listfilelines)) -numberoflasfiles

# extract the last word from the fromline - numberoflasfiles times and load into suitable data structure
#     tail(strsplit(oneline,split=" ")[[1]],1)   --- taken from 
#     http://stackoverflow.com/questions/17658216/extract-last-word-in-string-in-r

lasfile <- c(1:numberoflasfiles)
for (n in 1 : numberoflasfiles) 
{
  oneline <- listfilelines[fromline]
  lasfile[n] <- tail(strsplit(oneline,split=" ")[[1]],1)
  fromline=fromline+1
}
# print (lasfile)
rm(fromline)
lasfile<- paste(lasfilepath,"\\",lasfile,sep="")
# print(lasfile)
# temp <- readLines(con=lasfile[1], skipNul = TRUE) 
#
save(lasfile,file="lasfiles.Rdat")

Code-2 Reads many *.las files and constructs a single data frame

# Read the list of lasfiles to read
# open each las file and get data

# G Srikanth 29 May 2016

#                                                   install.packages("data.table")
# 1. set working directory and read the file list
library(stringr)
library(data.table)
defaultworkdir <- readline("What is the file path? ")
setwd(defaultworkdir)
lasfilelist <- readline("What is the well list file? ")
load(lasfilelist)
welllogdata <- data.frame()

#     load("lasfiles.Rdat")    name of saved file
#     determine number of well files
nwells <- length(lasfile)
uwi<-c(1:nwells)
# 2. Main read loop for each well las file in directory
for (wellno in 1:nwells)
{
  # 2a. Get uwi
  # 2b. Get curve names
  # 2c. Read the curve data

  # LAS files have all the headers within first 100 lines
  # read 100 lines into a vector
  headerlines <- readLines(con = lasfile[wellno], n=100L, ok=TRUE, skipNul = TRUE)
  # extract uwi  NOTE - many las files write only proper well name and not UWI. in such case replace UWI with WELL in next line
    oneline <- headerlines[grep(" UWI",headerlines)]
    # remove multiple spaces with gsub() extract 3rd word with word()
    #     ref: http://rfunction.com/archives/2354
    uwi[wellno]<-word(gsub("\\s+"," ",str_trim(oneline)),3)
  # extract curve information and data location
    #locate ~A  in the headerlines. This has the log names.
    oneline <- headerlines[grep("~A",headerlines)]# line having curves names
    oneline <- gsub("\\s+"," ",str_trim(oneline)) # trim leading trailing and extra blanks
    ncurves <- str_count(oneline, " ")
    # ncurves <- str_count(gsub("\\s+"," ",str_trim(headerlines[grep("~A",headerlines)]))," ")
    # The next record in data file is numeric las data.
    dataline <- as.numeric(grep("~A",headerlines)+1)
    curvenameline <- as.numeric(grep("~A",headerlines)- ncurves) 
    # curve names start at curvenameline and contine for ncurves. The first word in each line is curve name
    logname <- c(1:ncurves)
    for (nc in 1:ncurves)
    {
      logname[nc] <- word(gsub("\\s+"," ",str_trim(headerlines[curvenameline+(nc-1)])),1)
    }
  # read the data matrix from the line - dataline in the well las file
    # null value used in the las file
    lasnull <- word(gsub("\\s+"," ",str_trim(headerlines[grep(" NULL",headerlines)])),3)
    temp<- read.table(lasfile[wellno], header=F, na.strings=lasnull, skip=dataline-1, col.names = logname)
    temp <- merge(temp,uwi[wellno])
    names(temp) <- c(logname,"uwi")
  # concatenate this data into a single data-frame. use the lognames to merge.
    if (wellno == 1) welldata <- temp else welldata <- rbind.fill(welldata, temp)    #rbind doesnt merge with different names, Thanks to stackoverflow!
        # to clean the logname vector between files
    rm(logname)
}
save(welldata,"welldata.Rdat")

Hope it is useful!!

like image 29
Srikanth G Avatar answered Nov 17 '22 14:11

Srikanth G


Sample of a *.las file:

…
…
…
#MNEM           .UNIT                  API CODE            :DESCRIPTION
#----            ------          --------------            -----------------------------
DEPT            .ft                                        :                                                        Station Depth
INCL            .deg                                       :                                                        Hole inclination
AZIM            .deg                                       :                                                        Measured Azimuth
#-------------------------------------------------------------
#        DEPT         INCL         AZIM
~ASCII
0.00         0.00         0.00
36.00         0.33       123.98
126.00         0.17       183.28
218.00         0.19       202.04
308.00         0.24       191.24
398.00         0.21       198.60
495.00         0.02       179.55
…
…
…

The objective when reading the file is to ignore the file header and copy only the data which came after (~ASCII) line in addition each column header So we copy all the file, and search in it line-by-line until we reach the (~ASCII) line, then we copy the line before it (the header) and all what came after it (the data), and we remove the (~ASCII) line.

Note that we remove the (#) symbol from the header line.

The last step is convert the data to table and then write it as csv file.

The complete code:

#remove all variables (cleanup)
rm(list=ls(all=TRUE))
gc()
MWD_filePath="MWD_file.las";
conn=file(MWD_filePath,open="r")
Ascii_txt=readLines(conn);
mwd_txt = 0;

for (i in 1:length(Ascii_txt)){
    if(Ascii_txt[i] == "~ASCII"){
    mwd_txt <- Ascii_txt[(i-1):length(Ascii_txt)]

    # remove (#) from the header line
    substr(mwd_txt[1], 1, 2) <- " ";

    # remove "~ASCII" line
    mwd_txt <- mwd_txt[-2]

    break;
    }

}
close(conn)
#mwd_txt;
mwd <- read.table(header = TRUE, text=mwd_txt);
#head(mwd)

#write the mwd data to file ... in CSV format
mwd_csv_file <- paste(MWD_filePath, ".csv", sep="");
write.csv(mwd, file = mwd_csv_file);
like image 1
Salem Gharbi Avatar answered Nov 17 '22 15:11

Salem Gharbi