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:
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:
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.
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.
2021 Answer:
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 (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)
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)
# 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")
# 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!!
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With