A Python module for loading data into code environment.
Handle files with extension such LAS, TSV, CSV or TXT
Function to read LAS file
file (pathlib.Path or str) – Filename or filepath specifying the LAS file
return_csv (bool default False) – If True, both dataframe and LAS object are returned. If False, returns only LAS object
curves (list or tuple, optional) – If specified, returns only dataframe containing the log curves specified. If not, all available logs are imported
Returns either LAS and/or dataframe object of the well data
Example
>>> #return both dataframe containing only ['GR','RT', 'RHOB'] curves and the lasio object
>>> df, las = load_las(well_path, return_csv=True, curves=['GR', 'RT', 'RHOB'])
>>> #return only LAS object
>>> las = load_las(well_path)
Function to load a table data, either csv, tsv, or excel file
file (pathlib.Path or str) – Filename or filepath specifying the file
curves (list or tuple, optional) – If specified, returns only dataframe containing the log curves specified If not, all available logs are imported
delimiter (str, default ',') – Delimiter to use
header (int, list of int, default 'infer') – Row number(s) to use as the column names, and the start of the data. Default behavior is to infer the column names. See official pandas doc for more..
skiprows (list, int , optional) – Line numbers to skip (0-indexed) or number of lines to skip (int) at the start of the file
sheet_name (str, int, list, default None) –
Strings are used for sheet names. Integers are used in zero-indexed sheet positions.
Available cases:
0 : 1st sheet as a DataFrame
1: 2nd sheet as a DataFrame
”Sheet1” : Load sheet with name “Sheet1”
[0, 1, “Sheet5”]: Load first, second and sheet named “Sheet5” as a dict of DataFrame
defaults to None: All sheets.
See help(pd.read_excel) for more
Example
>>> well_path = Path(r"C:\Users\USER\Documents\petrolib\test\petrolib\petrolib\15_9-19.csv")
>>> #loads all logs
>>> df = load_table(well_path)
>>> #loads specific
>>> df = load_table(well_path, ['GR', 'RT'], skiprows=[1])
>>> df
Python module for reservoir interpretation from plots
Plots the cross plot relationship of density against porosity on compatible scales to facilitate in identification of reservoir type and its fluid type.
This code was initially written by Yohanes Nuwara but was modified to give the resulting plot a more classic and pretty view.
df (pd.DataFrame) – Dataframe of well
column_x (str) – Porosity column
column_y (str) – Density column
hue (str) – Column to color code the scatter plot by
color_code (str default None) – Color code typing. If ‘num’, arg hue must be a continuous column. If ‘cat’, argument hue must be a categorical column
figsize (tuple) – Size of plot
rhob_fluid (float, default 1.0) – Fluid density
res_name (str) – Reservoir name
cmap (str) – color map
A plot showing the neutron-density cross plot
Example
>>> from petrolib.interp import crossPlot
>>> crossPlot(df=df, column_x='NPHI', column_y='RHOB', res_name='RES_A', color_code='num', hue='GR')
Plot Pickett plot based on a pattern recognition approach to solving Archie’s equation. The resistivity and porosity logs are plotted on a logarithmic scales to evaluate formation characteristics of conventional, granular reservoirs. Read more here: https://wiki.seg.org/wiki/Pickett_plot
df (pd.DataFrame) – Dataframe
rt (str) – Resistivity column
rwa (float default 0.03) – Formation water resisitivity
a (float default, 1.) – Turtuosity factor
m (float default 2.) – Cementation factor
n (float default 2.) – Saturation exponent
res_name (str) – Reservoir/Zone name
figsize (tuple) – Size of plot
hue (str) – Column to color code the scatter plot by.
color_code (str default None) – Color code typing. If ‘num’, arg hue must be a continuous column If ‘cat’, argument hue must be a categorical column if None, there is no color coding
cmap (str) – Color map option
Example
>>> import petrolib.interp.picketPlot
>>> picketPlot(df, color_code='num', hue='GR', cmap='rainbow')
>>> from petrolib.interp import picketPlot
>>> picketPlot(df, rt='RT', por='NPHI')
A Python module for displaying log, lithofacies and zonation plots
Bases: object
This is a zonation class that extract zone/reservoir information from the file. This information may include top, bottom and zone/reservoir name. This information can be accessed when an instance of Zonation object is called.
Dataframe of well data
pd.DataFrame
A optional attribute containing list of dictionaries that holds zone information If None, path must be supplied
list of dictionaries, default None
A csv file containing reservoir info. To be able to use this, the information in the file should be entered in the following format
top, bottom, zonename 100, 200, RES_A 210, 220, RES_B
If None, zone must be passed
Path or str, default None
Example
>>> from petrolib.plots import Zonation
>>> zones = Zonation(df, path='./well tops.csv')
>>> zones = Zonation(df, zones = [{'RES_A':[3000, 3100]}, {'RES_B':[3300, 3400]}])
>>> #get reservoir information by calling the Zonation object
>>> #ztop = top ; zbot = base; zn = zonename ; fm = formation mids to place zone name in plot
>>> ztop, zbot, zn, fm = zones()
Plots log curves with zonation track.
depth (str) – Depth column
logs (list of str) – A list of logs curves to include in plot
top (float) – Minimum depth to zoom on
bottom (float) – Maximum depth to zoom on
title (str) – Plot title
figsize (tuple) – Size of plot
Example
>>> Zonation.plotZone('DEPTH', ['GR', 'RT', 'RHOB', 'NPHI', 'CALI'], 3300, 3600, 'Volve')
Plots location of wells The longitude and latitude must be available in the LAS files
data (list) – List of lasio.las.LASFile objects
shape_file (str, default None) – A .shp, .shx or .dbf file containing the shape file of the area where the well is located If not supplied, area must be passed
area (str default, None) – Well location. Must inlcude area from gpd.datasets.get_path(‘naturalearth_lowres’)
figsize (tuple) – Size of plot
label (list of str) – Well name(s). Must be a list of equal length with data
withmap (bool default False) – Plots location of wells on a map if True Plots the location on a scatter plot if False
return_table (bool default False) – Return well information such as the long, lat and name
Example
>>> plotLoc(data=[las], area='Norway', label=['15_9-F-1A'], withmap=True, figsize=(30, 10))
Plots log curves singly. To plot overlay plots use plots.plotLogs or plots.plotLogFacies
df (pd.DataFrame) – Dataframe
depth (str) – Depth column
logs (list of str) – A list of logs curves to include in plot
top (float) – Minimum depth to zoom on
bottom (float) – Maximum depth to zoom on
title (str) – Plot title
figsize (tuple) – Size of plot
Example
>>> from petrolib.plots import plotLog
>>> plotLog('DEPTH', ['GR', 'RT', 'RHOB', 'NPHI', 'CALI'], 3300, 3600, 'Volve')
>>> plotLog(df,'DEPTH', ['NPHI'], 2751, 2834.58, 'Fre-1')
Plots overlayed/super-imposed log curves along with the facies.
df (pd.DataFrame) – Dataframe
depth (str) – Depth column
logs (list of lists/str) – A list of logs curves to include in plot
top (float) – Minimum depth to zoom on
bottom (float) – Maximum depth to zoom on
facies (str) –
[‘Sandstone’, ‘Sandstone/Shale’, ‘Shale’, ‘Marl’, ‘Dolomite’, ‘Limestone’, ‘Chalk’, ‘Halite’, ‘Anhydrite’, ‘Tuff’, ‘Coal’, ‘Basement’]
title (str) – Plot title
figsize (tuple) – Size of plot
Example
>>> from petrolib.plots import *
>>> plotLogFacies(well11, 'DEPTH', ['GR', 'RT', ['RHOB', 'NPHI']], facies='litho', top=well11.DEPTH.min(),
bottom=well11.DEPTH.max(), figsize=(9, 12), title='15-9-F1A')
Plots overlayed/super-imposed log curves.
df (pd.DataFrame) – Dataframe
depth (str) – Depth column
logs (list of lists/str) – A list of logs curves to include in plot
top (float) – Minimum depth to zoom on
bottom (float) – Maximum depth to zoom on
title (str) – Plot title
figsize (tuple) – Size of plot
Example
>>> plotLogs(well11, 'DEPTH', ['GR', 'RT', ['RHOB', 'NPHI']], top=well11.DEPTH.min(),
>>> bottom=well11.DEPTH.max(), figsize=(9, 12), title='15-9-F1A')
Function for plotting three combo logs alongside the zonation/reservoir track
df (pd.DataFrame) – Dataframe of data
depth (str) – Depth column
gr (str) – Gamma ray column
res (str) – Resistivity column
nphi (str) – Neutron porosity column
rhob (str) – Bulk density column
ztop (float) – Top or minimum depth value
zbot (float) – Bottom or maximum depth value
ztops (list of float) – Tops (depth) of each reservoir/zones
zbots (list of float) – Bottom (depth) of each reservoir/zones
zonename (list of str) – Name of each zones
limit (str default None) – Tells which side to fill the gamma ray track, [‘left’, ‘right’]. lf None, it’s filled in both sides delineating shale-sand region
res_thres (float) – Resistivity threshold to use in the identification on hydrocarbon bearing zone
palette_op (str optional) – Palette option to fill gamma ray log. If None, `fill must be provided
fill (str default None) –
To show either of the porous and/or non porous zones in the neutron-density crossover. Can either be [‘left’, ‘right’, ‘both’]
default None - show neither of the porous nor non-porous zones
’left’ - shows only porous zones
’right’ - shows only non-porous zones
’both’ - shows both porous and non-porous zones
figsize (tuple) – Size of plot
Example
>>> from petrolib.plots import plotZoneCombo
>>> plotZoneCombo(well11, 'DEPTH', 'GR', 'RT', 'NPHI', 'RHOB', min(ztop), max(zbot),
>>> ztop, zbot, zn, fill='both', limit=None, figsize=(13, 30), title='ATAGA-11')
Plots a three combo log of well data
data (pd.DataFrame) – Dataframe of data
depth (str) – Depth column
gr (str) – Gamma ray column
res (str) – Resistivity column
nphi (str) – Neutron porosity column
rhob (str) – Bulk density column
ztop (list) – Top or minimum depth to zoom on.
zbot (list) – Bottom or maximum depth to zoom on.
res_thres (float) – Resistivity threshold to use in the identification on hydrocarbon bearing zone
fill (str default None) –
To show either of the porous and/or non porous zones in the neutron-density crossover. Can either be [‘left’, ‘right’, ‘both’]
default None - show neither of the porous nor non-porous zones
’left’ - shows only porous zones
’right’ - shows only non-porous zones
’both’ - shows both porous and non-porous zones
palette_op (str optional) – Palette option to fill gamma ray log
limit (str default None) – Tells which side to fill the gamma ray track, [‘left’, ‘right’] lf None, it’s filled in both sides delineating shale-sand region
figsize (tuple) – Size of plot
title (str) – Title of plot
Example
>>> import matplotlib inline
>>> from petrolib.plots import tripleCombo
>>> # %matplotlib inline
>>> tripleCombo(df, 'DEPTH', 'GR', 'RT', 'NPHI', 'RHOB', ztop=3300,
>>> zbot=3450, res_thres=10, fill='right', palette_op='rainbow', limit='left')
Python module for data processing and lithofacies modelling
Models lithofacies from Gamma ray log specific to a particular environment
df (pd.DataFrame) – dataframe
gr (str) – Gamma ray log column
env (str) – Environment type. Either siliciclastic or carbonate * ‘SS’ for Siliclastic (Shale and Sandstone) environment * ‘CO’ for carbonate (Anhydrite, Limestone, Dolomite, Sandstone, Shale) environment
Example
>>> from petrolib.interp import model_facies
>>> model_facies(df, gr='GR', env='SS')
Function to preprocess data before beginning petrophysics workflow. This processing workflow uses conventional values for the log curves. To use user-defined preprocessing method , refer to the petrolib.data.procs.trim()
df (pd.DataFrame) – dataframe object
gr (str) – Gamma ray column
rt (str) – Resistivity column
nphi (str) – Neutron porosity column
rhob (str) – Bulk density column
sonic (str, default None) – Sonic column (optional)
trim (str default 'both') – Conditions for trim arbitrary values * ‘max’ : to trim values higher than conventional maximum values * ‘min’ : to trim values lower than conventional lower values * default ‘both’ : to trim both lower and higher values to conventional high and lower values
A new copy of dataframe containing processed data
Example
>>> df = process_data(df, 'GR', 'RT', 'NPHI', 'RHOB')
>>> df.describe()
|DEPTH | GR | RT | NPHI | RHOB|
+-------+-------+-------+--------+------+
count | 35361 | 34671 | 34211 | 10524 |10551 |
-------+-------+-------+-------+--------+------+
mean | 1913.9| 56.97 | 1.95 | 0.17 | 2.48 |
-------+-------+-------+-------+--------+------+
min | 145.9| 0.15 | 0.2 | 0.03 | 1.98 |
------+-------+-------+-------+--------+------+
max | 3681.9| 200 | 2000 | 0.45 | 2.93|
----------------------------------------------
Function to rename the log curves in order to maintain petrophysics conventions
df (pd.DataFrame) – dataframe object
DEPTH (str) – Depth column
GR (str) – Gamma ray column
RT (str) – Resistivity column
NPHI (str) – Neutron porosity column
RHOB (str) – Bulk density column
DT (str, default None) – Sonic column (optional)
Returns data of renamed log curves
Example
>>> df = set_alias(df, 'DEPT', 'GR','RES', 'NPHI', 'RHOB')
>>> print(df.columns)
>>> ['DEPTH', 'GR', 'RT', 'NPHI', 'RHOB']
Function to preprocess data by trimming arbitrary values
df (pd.DataFrame) – Dataframe
col (str) – Log curve to trim its values
lower (int or float) – Lower limit or minimum value
upper (int or float) – Upper limit or maximum value
Dataframe with user defined log limits
Example
>>> trim(df, 'GR', lower=0, upper=200)
Python module for handling data statistics
Bases: object
A correlation class for pearson and chatterjee method of statistical significance.
df (pd.DataFrame) – Takes in only the dataframe
Function to calculate the linear (Pearson’s) and non-linear (Chatterjee’s) relationships between log curves. Relationship between well logs are usually non-linear.
method (str, default 'chatterjee') –
Method of correlation. {‘chatterjee’, ‘pearsonr’, ‘linear’, ‘nonlinear’}
’linear’ is the same as ‘pearsonr’
’nonlinear’ is the same as ‘chatterjee’
Correlation matrix of all possible log curves combination
Example
>>> corr = Correlation(df)
>>> v = corr.corr(method='chatterjee)
Plots the heat map of Correlation Matrix
title (str) – Title of plot
figsize (slice) – Size of plot
annot (bool, default True) – To annotate the coefficient in the plot
cmap (matplotlib colormap name or object, or list of colors, optional) – The mapping from data values to color space
Example
>>> corr = Correlation(df)
>>> v = corr.corr(method='chatterjee)
>>> corr.plot_heatmap(cmap='Reds')
Function to plot the frequency distribution of well log curves
df (pd.DataFrame) – Dataframe of data
cols (tuple[str]) – log curves to show its distribution
bins (int) – Number of bins to group the data
figsize (slice) – Size of plot
Shows a plot of the frequency distribution of well log curves
Example
>>> from petrolib.stats import displayFreq
>>> displayFreq(df, 'GR','CALI', 'COAL', 'DT', 'DT_LOG', bins=15, figsize=(20,10))
Bases: Exception
Exception raised if the log curve/menemonic passed is not found
Python module for petrophysics
Bases: object
Class to petrophysics workflow to evaluate any number of reservoirs of interest. Computes IGR/VSH, Total and Effective Porosities, Water and Hydrocarbon Saturation, Permeability
Dataframe of data
pd.DataFrame
List of zonenames. Will be accessed from the zonation file passed into Zonation class
list
Tops of the reservoirs. Will be accessed from the zonation file passed into Zonation class
list
Bottoms of the reservoirs. Will be accessed from the zonation file passed into Zonation class
list
Formation mids to help place the zonename in the plots. Will be accessed from the zonation file passed into Zonation class
list
Depth column
str
Gamma ray column
str
Resistivity column
str
Neutron porosity column
str
Bulk density column
str
Sonic column (optional)
str default None
For cutoff. Whether to use mean of GR in IGR/VSH computation or not. If None, uses either median or average value
bool default None
For cutoff. Whether to use median of GR in IGR/VSH computation or not. If None, uses either mean or average value
Example
>>> #loading libraries/packages
>>> from petrolib.workflow import Quanti
>>> from petrolib.plot import Zonation
>>> from petrolib.file_reader import load_las
>>> from pathlib import Path
>>> #loading well file and zonation/tops file
>>> well_path = Path(r"./15_9-F-1A.LAS")
>>> contact_path = Path(r"./well tops.csv")
>>> las, df= load_las(well_path, curves=['GR', 'RT', 'NPHI', 'RHOB'], return_las=True)
>>> #creating zonation class to extra info
>>> zones = Zonation(df, path=contact_path)
>>> ztop, zbot, zn, fm = zones()
>>> #creating quanti class
>>> pp = Quanti(df, zn, ztop, zbot, fm, 'DEPTH', 'GR', 'RT', 'NPHI', 'RHOB', use_mean=True)
Create the {ROCK, RES, PAY} flags
To use, must have called vshale, porosity, water_saturation and permeability methods
vsh_method (float) – Volume of Shale cutoff. Applied only to [‘ROCK’] flag
por_cutoff (float) – Porosity cutoff. Applied only to the [‘ROCK’, ‘RES’] flags
sw_cutoff (float) – Water Saturation cutoff. Applied only to the [‘ROCK’, ‘RES’, ‘PAY] flags
ref_unit (str default 'm') – Reference unit for measured depth. Defaults to metres
show_plot (bool default False) – Display plot if True.. Plots GR, RT, VSH, SW, Perm, NPHI/RHOB, PHIE/PHIT, [‘ROCK’, ‘RES’, ‘PAY] flags and Zonation track
palette_op (str default None) – palette option for VSH coloring. Check https://matplotlib.org/stable/tutorials/colors/colormaps.html for availabel palette options
figsize (tuple default None) – Size of plot
Either/Both Dataframe containing the flags and the plot if show_plot=True
Example
>>> # Create Quanti class
>>> pp = Quanti(df, zn, ztop, zbot, fm, 'DEPTH', 'GR', 'RT', 'NPHI', 'RHOB')
>>> # Display plot only
>>> pp.flags(por_cutoff=.12, vsh_cutoff=.5, sw_cutoff=0.8, show_plot=True, palette_op='cubehelix', figsize=(20, 15))
>>> # Display data only
>>> y = pp.flags(por_cutoff=.12, vsh_cutoff=.5, sw_cutoff=0.8)
>>> result = pd.concat(y)
>>> print(result)
net, grossand not net thicknesses
net-to-gross
average volume of shale
average porosity value
bulk volume of water
water saturation
for each of the three flags {ROCK, RES, PAY}
name (str) – Name of the well
Displays the Pay Summary Report table
Example
>>> pp.paySummary(name='15-9_F1A')
Computes the permeability. To use, must have called vshale and porosity and water_saturation methods
show_plot (bool default False) – Display plot if True.. Plots PHIE, Permeability and Zone track
figsize (tuple default None) – Size of plot
Either/Both Dataframe containing the Perm and the plot if show_plot=True
Example
>>> # create Quanti class
>>> pp = Quanti(df, zn, ztop, zbot, fm, 'DEPTH', 'GR', 'RT', 'NPHI', 'RHOB')
>>> # display plot only
>>> pp.vshale(method='clavier')
>>> pp.porosity(method='density')
>>> pp.water_saturation(method='archie')
>>> pp.permeability(show_plot=True, figsize=(9, 10))
>>> # display data only
>>> x = pp.vshale(method='clavier')
>>> y = pp.porosity(method='density')
>>> z = pp.water_saturation(method='archie')
>>> a = pp.permeability()
>>> result = pd.concat(a)
>>> print(result)
Computes the effective and total porosities using the ‘density’ and Wyllie’s ‘sonic’ method. To use, must have called the vshale method
method (str default 'density') – Porosity method. {‘density’, ‘sonic’}
rhob_shale (float default 2.4) – Shale matrix
rhob_fluid (float default 1.0) – Fluid density
rhob_matrix (float default 2.65) – Matrix density
fzs (float default None) – Flushed zone saturation for PHIE. If None, it is calculated from rhob_fluid, rhob_shale and rhob_matrix
show_plot (bool default False) – Display plot if True.. Plots RHOB, VSH, PHIE/PHIT and Zone track
figsize (tuple default None) – Size of plot
Either/Both Dataframe containing the PHIE/PHIT and the plot if show_plot=True
Example
>>> # create Quanti class
>>> pp = Quanti(df, zn, ztop, zbot, fm, 'DEPTH', 'GR', 'RT', 'NPHI', 'RHOB')
>>> # display plot only
>>> pp.porosity(method='density', show_plot=True, figsize=(10, 12))
>>> # display data only
>>> y = pp.porosity(method='density')
>>> result = pd.concat(y)
>>> print(result)
Displays the methods used in each parameter estimations and cutoff used for flagging
A method to save the pay summary results into a excel file
file_name (str) – name of to save the pay summary report as
Computes the Volume of Shale
method (str default 'linear') – Volume of Shale method. {‘linear’, ‘clavier’, ‘larionov_ter’, ‘larionov_older’, ‘stieber_1’, ‘stieber_2, ‘stieber_m_pliocene’} * Linear = Gamma Ray Index (IGR) * Larionov Tertiary * Larionov Older Rocks * Stieber (Miocene/Pliocene)
show_plot (bool default False) – Display plot if True.. Plots GR, VSH and Zone track
palette_op (str default None) – Palette option for to color code vshale plot. Check https://matplotlib.org/stable/tutorials/colors/colormaps.html
figsize (tuple default None) – Size of plot
Either/Both Dataframe containing the VSH and the plot if show_plot=True
Example
>>> # create Quanti class
>>> pp = Quanti(df, zn, ztop, zbot, fm, 'DEPTH', 'GR', 'RT', 'NPHI', 'RHOB')
>>> # display plot only
>>> pp.vshale(method='clavier', show_plot=True, palette_op='cubehelix', figsize=(9,12))
>>> # display data only
>>> x = pp.vshale(method='clavier')
>>> x = pd.concat(x)
>>> print(x)
Computes water and hydrocarbon saturation To use, must have called both vshale and porosity methods
method (str default 'archie') – Water Saturation method. {‘archie’, ‘simmandoux’}
rw (float default 0.03) – Formation water resisitivity
a (float default, 1.) – Turtuosity factor
m (float default 2.) – Cementation factor
n (float default 2.) – Saturation exponent
show_plot (bool default False) – Display plot if True.. Plots RT, SW, PHIE/PHIT and Zone track
figsize (tuple default None) – Size of plot
Either/Both Dataframe containing the SW, SH and the plot if show_plot=True
Example
>>> # create Quanti class
>>> pp = Quanti(df, zn, ztop, zbot, fm, 'DEPTH', 'GR', 'RT', 'NPHI', 'RHOB')
>>> # display plot only
>>> pp.water_saturation(method='archie', show_plot=True, figsize=(10, 12))
>>> # display data only
>>> z = pp.water_saturation(method='archie')
>>> result = pd.concat(z)
>>> print(result)