Source code for logio.logplot.plot_logs

import matplotlib.pyplot as plt
import lasio
from pandas import DataFrame
from numpy import arange

class InvalidFormatException(Exception):
    """Format does not conform with the required format"""
    pass

[docs]class LogPlot:
[docs] def __init__(self, data): """ Visualize well logs Parameters ---------- data: lasio.las.LASFile or pd.DataFrame object """ if type(data) == lasio.las.LASFile: self.df = data.df() elif type(data) == DataFrame: self.df = data else: raise InvalidFormatException('data input is neither a LASFile nor DataFrame object')
[docs] def plot_log(self, plots: list, y: str="DEPTH", y_range:tuple = (0,0,0), xscale:list = ['linear'], **kwargs): """ Base function/method for visualization Parameters ---------- plots: list; a list of required plots to make. The list can contain strings and tuples. Use tuple to plot more than one log on an axes i.e ("GR", "BS") will plot the GR log and the BS log on the same axes y: str; name of column in dataframe to be plotted on the vertical axis y_range: tuple, value range for the y-axis, passed to the plot as ylim() xscale : {"linear", "log", "symlog", "logit", ...} The scale type to apply to the x-axis, default = 'linear'. **kwargs: These are passed to the subplots function, e.g: figsize = (4, 9), dpi = 60 """ # Checking the inputs dataframe = self.df.reset_index() if len(y_range) == 2: self.dr = y_range else: self.dr = (dataframe[y].min() - (dataframe[y].max()* 0.02), dataframe[y].max() * 1.02) self.plots = plots self.fig, self.axes = plt.subplots(ncols=len(self.plots), facecolor = '#E9E9E9', **kwargs) colors = ['black', 'darkred', 'green', 'darkblue', 'orange', ''] if len(xscale) == 1: self.xscale = [xscale[0] for i in self.plots] elif len(xscale) != len(plots): raise InvalidFormatException('Length of xscale != length of plots') else: self.xscale = xscale # Plotting a single variable on an axis def plotter(axis, plot_var, scale): axis.plot(dataframe[plot_var], dataframe[y], lw=.8) axis.set_xscale(scale) axis.set_xlabel(plot_var) axis.legend(labels = [plot_var]) axis.set_ylim(self.dr) axis.invert_yaxis() axis.minorticks_on() axis.grid(which="major", linestyle='-', linewidth=0.7, color="black") axis.grid(which="minor", linestyle='-.', linewidth=0.7, color="#CDC0B0") # Plotting 2 variables on an axis def tuple_plotter(axis, plot_var, scale): axis.plot(dataframe[plot_var[0]], dataframe[y], lw= .6) axis.set_xscale(scale) axis.set_xlabel(plot_var[0]) axis.legend(labels = [plot_var[0]], loc = 'upper right', borderaxespad = .1, bbox_to_anchor=(0.95, 0.96)) ax2 = axis.twiny() ax2.plot(dataframe[plot_var[1]], dataframe[y], color= 'red', lw= .6) ax2.set_xscale(scale) ax2.set_xlabel(plot_var[1]) ax2.legend(labels = [plot_var[1]], loc = 'upper right', borderaxespad = .1, bbox_to_anchor=(0.95, 0.94)) axis.set_ylim(self.dr) axis.invert_yaxis() axis.minorticks_on() axis.grid(which="major", linestyle='-', linewidth=0.7, color="black") axis.grid(which="minor", linestyle='-.', linewidth=0.7, color="#CDC0B0") try: self.axes[0].set_ylabel(y) for plott, x_scale, axe in zip(self.plots, self.xscale, self.axes): if type(plott) == tuple: tuple_plotter(axe, plott, x_scale) else: plotter(axe, plott, x_scale) if axe != self.axes[0]: axe.set_yticklabels([]) plt.subplots_adjust(wspace = .02, hspace=.05) except TypeError: self.axes.set_ylabel(y) for plott in self.plots: if type(plott) == tuple: tuple_plotter(self.axes, plott, self.xscale[0]) else: plotter(self.axes, plott, self.xscale[0]) plt.subplots_adjust(wspace = .05, hspace=.05)
[docs] def show(self): plt.tight_layout() plt.show()
[docs] def cutoff_plot(self, x, y, x_cutoff, y_range: tuple = (0,0), xscale:str = 'linear', colors: list = ['red', 'lightblue'],labels: list = ['Cat_A', 'Cat_B'], fig_size : tuple = (4.5, 10)): """ Plots a visualization for a single log with a cutoff value for the x variable Parameters ---------- dataframe: pandas.DataFrame object containing the data to be analysed x: name of column to be plotted on the x-axis y: name of column to be plotted on the y-axis x_cutoff: x value for delineating the categories in the x variable If specified as a fraction between 0 and 1, it is calculated as: (max_x_value - min_x_value) * x_cutoff + min_x_value Otherwise, the x plot is separated into sections based on the x value passed y_range: tuple, value range for the y-axis, passed to th plot as ylim(), default = (y.min, y.max) xscale : {"linear", "log", "symlog", "logit", ...} The scale type to apply to the x-axis, default = 'linear'. colors: list containing the colors for filliung the cutoff sections labels: list containing the labels for the cutoff sections figsize: tuple (width, height) for controlling the size of the plot """ #Check if len(colors) == 2: pass else: raise InvalidFormatException('Length of colors does not match number of partitions') if len(labels) == 2: pass else: raise InvalidFormatException('Length of labels does not match number of partitions') # Removing null values from the data to be plotted dataframe = self.df[~self.df[x].isnull()] y1 = dataframe.reset_index()[y] x1 = dataframe[x] # Determining the cutoff if (x_cutoff > 0) & (x_cutoff< 1): x2 = (x1.max() - x1.min()) * x_cutoff + x1.min() else: x2 = x_cutoff plt.figure(figsize = fig_size, dpi = 100, facecolor = '#E9E9E9') plt.axes().set_axisbelow(True) # Plotting the cutoff plt.fill_betweenx(y1, x1, x2, where = x2>=x1, facecolor = colors[0], label = labels[0]) plt.fill_betweenx(y1, x1, x2, where = x2<x1, facecolor = colors[1], label = labels[1]) plt.vlines(x2, y1.min(), y1.max(), linestyles='dashed', color = '#000000', lw = 1, label = 'cutoff') plt.xscale(xscale) if y_range[1] != 0: plt.ylim(y_range) plt.xlabel(x, fontsize = 12) plt.ylabel(y, fontsize = 12) plt.minorticks_on() plt.grid(which="major", linestyle='-', linewidth=0.5, color="black") plt.grid(which="minor", linewidth=0.5, color="#CDC0B0") plt.gca().invert_yaxis() plt.legend();