### Import Petrolib and Get Version Source: https://petrolib.readthedocs.io/en/latest/index.html Import the petrolib package and print its version. This confirms a successful installation. ```python import petrolib print(petrolib.__version__) ``` -------------------------------- ### Example Usage of Flags Method Source: https://petrolib.readthedocs.io/en/latest/_modules/petrolib/workflow.html Demonstrates how to use the flags method to either display a plot or return data. The first example shows how to display a plot with specified parameters, while the second shows how to retrieve and print the resulting data. ```python # 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) ``` -------------------------------- ### Install petrolib Package Source: https://petrolib.readthedocs.io/en/latest/overview.html Install the petrolib package using pip. This command should be run in your terminal or command prompt. ```bash pip install petrolib ``` -------------------------------- ### Call Quanti Object to Get Results Source: https://petrolib.readthedocs.io/en/latest/_modules/petrolib/workflow.html Invoke the instantiated Quanti object to compute and retrieve results such as GR_matrix, GR_Shale, GR_Sand, and Zone_Names. ```python pp = Quanti(df, zn, ztop, zbot, fm, 'DEPTH', 'GR', 'RT', 'NPHI', 'RHOB', use_mean=True) x = pp() ``` -------------------------------- ### Initialize Quanti Class and Plot Reservoir Properties Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Initializes the Quanti class with well log data and then displays plots for Vshale, porosity, water saturation, and permeability. Ensure all necessary data columns are provided. ```python >>> 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)) ``` -------------------------------- ### Initialize Quanti Class and Display Reservoir Property Data Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Initializes the Quanti class and retrieves data for Vshale, porosity, water saturation, and permeability. The results are concatenated and printed. ```python >>> pp = Quanti(df, zn, ztop, zbot, fm, 'DEPTH', 'GR', 'RT', 'NPHI', 'RHOB') >>> # 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) ``` -------------------------------- ### Initialize Quanti Class for Petrophysics Workflow Source: https://petrolib.readthedocs.io/en/latest/_modules/petrolib/workflow.html Instantiate the Quanti class with well log data and zonation information. Specify column names for depth, GR, RT, NPHI, RHOB, and optionally sonic. Control GR cutoff behavior with use_mean or use_median. ```python 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) ``` -------------------------------- ### Setting up NPHI and RHOB Fill Source: https://petrolib.readthedocs.io/en/latest/_modules/petrolib/workflow.html Initializes variables for setting up the fill between Neutron Porosity (NPHI) and Bulk Density (RHOB) logs. This prepares data for subsequent filling operations. ```python #setting up the nphi and rhob fill #inspired from x2=data[self._rhob] x1=data[self._nphi] x = np.array(rhob_.get_xlim()) z = np.array(nphi_.get_xlim()) ``` -------------------------------- ### Import Libraries and Load Data Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Loads necessary libraries and packages, then reads a well log file and its corresponding zonation data. ```python from petrolib.workflow import Quanti from petrolib.plot import Zonation from petrolib.file_reader import load_las from pathlib import Path ``` ```python well_path = Path(r"./15_9-F-1A.LAS") contact_path = Path(r"./well tops.csv") ``` ```python las, df= load_las(well_path, curves=['GR', 'RT', 'NPHI', 'RHOB'], return_las=True) ``` ```python zones = Zonation(df, path=contact_path) ztop, zbot, zn, fm = zones() ``` -------------------------------- ### Initialize Zonation with Path or Zones Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Instantiate the Zonation class by providing either a path to a CSV file containing well tops or a list of dictionaries with zone information. ```python from petrolib.plots import Zonation >>> zones = Zonation(df, path='./well tops.csv') >>> zones = Zonation(df, zones = [{'RES_A':[3000, 3100]}, {'RES_B':[3300, 3400]}]) ``` -------------------------------- ### Initialize Zonation Class from DataFrame and Path Source: https://petrolib.readthedocs.io/en/latest/_modules/petrolib/plots.html Initializes the Zonation class using a pandas DataFrame and a path to a CSV file containing zone information. ```python from petrolib.plots import Zonation zones = Zonation(df, path='./well tops.csv') ``` -------------------------------- ### Plotting Zonation with Combo Logs Source: https://petrolib.readthedocs.io/en/latest/_modules/petrolib/plots.html Plots three combo logs (GR, Resistivity, Neutron Porosity, Bulk Density) alongside a zonation/reservoir track. Allows filling of the gamma ray track based on specified limits and highlighting porous/non-porous zones using neutron-density crossover. Use for detailed reservoir characterization. ```python >>> 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') ``` -------------------------------- ### Initialize Quanti Class for Porosity Calculation Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Creates an instance of the Quanti class, which is a prerequisite for performing porosity calculations. Ensure the DataFrame `df` and other parameters are correctly defined. ```python >>> # create Quanti class >>> pp = Quanti(df, zn, ztop, zbot, fm, 'DEPTH', 'GR', 'RT', 'NPHI', 'RHOB') ``` -------------------------------- ### Initialize Quanti Class Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Initializes the Quanti class with the DataFrame, zonation information, and well log curve names. Use_mean parameter controls GR cutoff calculation. ```python pp = Quanti(df, zn, ztop, zbot, fm, 'DEPTH', 'GR', 'RT', 'NPHI', 'RHOB', use_mean=True) ``` -------------------------------- ### Initialize Zonation Class from DataFrame and Zone List Source: https://petrolib.readthedocs.io/en/latest/_modules/petrolib/plots.html Initializes the Zonation class using a pandas DataFrame and a list of dictionaries specifying zone information. ```python from petrolib.plots import Zonation zones = Zonation(df, zones = [{'RES_A':[3000, 3100]}, {'RES_B':[3300, 3400]}]) ``` -------------------------------- ### Import Necessaries Source: https://petrolib.readthedocs.io/en/latest/quickstart.html Import necessary modules from the petrolib library and pathlib for path manipulation. ```python from pathlib import Path from petrolib import procs from petrolib import file_reader as fr from petrolib.workflow import Quanti from petrolib.plots import tripleCombo, Zonation, plotLog ``` -------------------------------- ### paySummary Method Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Computes and displays a summary report for each of the three flags {ROCK, RES, PAY}, including net/gross thicknesses, average shale volume, average porosity, bulk volume of water, and water saturation. ```APIDOC ## paySummary Method ### Description Computes the net, gross and not net thicknesses, net-to-gross ratio, average volume of shale, average porosity value, bulk volume of water, and water saturation for each of the three flags {ROCK, RES, PAY}. ### Parameters - **name** (str) - Name of the well. ### Return Type Displays the Pay Summary Report table. ``` -------------------------------- ### Quanti Class Initialization Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Initializes the Quanti class with essential petrophysical data and parameters. This class is used for evaluating reservoirs and computing properties like IGR/VSH, porosities, and saturations. ```APIDOC ## Quanti Class ### Description Class to perform petrophysics workflow to evaluate any number of reservoirs of interest. Computes IGR/VSH, Total and Effective Porosities, Water and Hydrocarbon Saturation, Permeability. ### Parameters - **df** (pd.DataFrame) - Dataframe of data. - **zonename** (list) - List of zonenames. - **ztop** (list) - Tops of the reservoirs. - **zbot** (list) - Bottoms of the reservoirs. - **f_mids** (list) - Formation mids to help place the zonename in the plots. - **depth** (str) - Depth column name. - **gr** (str) - Gamma ray column name. - **rt** (str) - Resistivity column name. - **nphi** (str) - Neutron porosity column name. - **rhob** (str) - Bulk density column name. - **sonic** (str, optional) - Sonic column name. Defaults to None. - **use_mean** (bool, optional) - For cutoff. Whether to use mean of GR in IGR/VSH computation or not. If None, uses either median or average value. Defaults to None. - **use_median** (bool, optional) - For cutoff. Whether to use median of GR in IGR/VSH computation or not. If None, uses either mean or average value. Defaults to None. ``` -------------------------------- ### paySummary() Source: https://petrolib.readthedocs.io/en/latest/genindex.html Generates a summary of pay zones. This method belongs to the Quanti class in petrolib.workflow. ```APIDOC ## paySummary() ### Description Generates a summary of pay zones. ### Method (Method signature implies a callable function or method) ### Parameters (No specific parameters documented in the source) ### Response (No specific response documented in the source) ``` -------------------------------- ### Perform Formation Evaluation Source: https://petrolib.readthedocs.io/en/latest/quickstart.html Conduct formation evaluation using the `Quanti` class. This involves calculating various petrophysical properties like shale volume, porosity, water saturation, and permeability using different methods. Plots can be generated for each calculation. ```python pp = Quanti(df, zn, ztop, zbot, fm, 'DEPTH', 'GR', 'RT', 'NPHI', 'RHOB', use_mean=True) vsh = pp.vshale(method='clavier', show_plot=True, palette_op='cubehelix', figsize=(9,12)) por = pp.porosity(method='density', show_plot=True, figsize=(10, 12)) sw = pp.water_saturation(method='archie', show_plot=True, figsize=(10, 12)) perm = pp.permeability(show_plot=True, figsize=(9, 10)) flags = pp.flags(por_cutoff=.12, vsh_cutoff=.5, sw_cutoff=0.8, show_plot=True, palette_op='cubehelix', figsize=(20, 15)) ``` -------------------------------- ### Calculate and Plot Volume of Shale using Clavier Method Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Computes and displays the volume of shale using the Clavier method. This requires the Quanti class to be initialized. `palette_op` can be used to customize plot colors. ```python >>> # display plot only >>> pp.vshale(method='clavier', show_plot=True, palette_op='cubehelix', figsize=(9,12)) ``` -------------------------------- ### Calculate Volume of Shale using Clavier Method and Display Data Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Calculates the volume of shale using the Clavier method and returns the data. The results are concatenated and printed. This method requires prior initialization of the Quanti class. ```python >>> # display data only >>> x = pp.vshale(method='clavier') >>> x = pd.concat(x) >>> print(x) ``` -------------------------------- ### Calculate Porosity using Density Method and Display Data Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Calculates porosity using the density method and returns the data. The results are then concatenated and printed. This method requires prior initialization of the Quanti class. ```python >>> # display data only >>> y = pp.porosity(method='density') >>> result = pd.concat(y) >>> print(result) ``` -------------------------------- ### Displaying Facies Flags with Colorbar Source: https://petrolib.readthedocs.io/en/latest/_modules/petrolib/workflow.html Visualizes facies flags (ROCK, RES, PAY) using imshow and adds a corresponding colorbar. This is useful for displaying classified rock types or properties across different depth intervals. ```python #for flags im=ax[8].imshow(cluster1, interpolation='none', aspect='auto', cmap=cmap_facies, vmin=0,vmax=1) im=ax[9].imshow(cluster2, interpolation='none', aspect='auto', cmap=cmap_facies, vmin=0,vmax=1) im=ax[10].imshow(cluster3, interpolation='none', aspect='auto', cmap=cmap_facies, vmin=0,vmax=1) divider = make_axes_locatable(ax[10]) cax = divider.append_axes("right", size="20%", pad=0.05) cbar = plt.colorbar(im, cax=cax) cbar.set_label((17*' ').join([ 'Gross Flag', 'Net Flag' ])) cbar.set_ticks(range(0,1)); cbar.set_ticklabels('') x = [8, 9, 10] flag_name = ['ROCK', 'RES', 'PAY'] ``` -------------------------------- ### Generate Zone and Log Plots Source: https://petrolib.readthedocs.io/en/latest/quickstart.html Create zone plots and standard log plots for visualization. The `Zonation` object is used to define zones based on well tops, and `plotZone` and `plotLog` functions visualize these zones and logs within a specified depth range. ```python zones = Zonation(df, path=tops_path) zones.plotZone('DEPTH', ['GR', 'RT', 'RHOB', 'NPHI', 'CALI'], 3300, 3600, '15_9-19') plotLog('DEPTH', ['GR', 'RT', 'RHOB', 'NPHI', 'CALI'], 3300, 3600, '15_9-19') ``` -------------------------------- ### Generate Pay Summary Report Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Computes and displays a summary report for each reservoir flag (ROCK, RES, PAY), including net/gross thickness, average shale volume, average porosity, bulk water volume, and water saturation. ```python pp.paySummary(name='15-9_F1A') ``` -------------------------------- ### report Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Displays the methods used in each parameter estimations and cutoff used for flagging. ```APIDOC ## report ### Description Displays the methods used in each parameter estimations and cutoff used for flagging. ``` -------------------------------- ### Compute Pay Summary Report Source: https://petrolib.readthedocs.io/en/latest/_modules/petrolib/workflow.html Computes and displays a detailed Pay Summary Report for a given well, including net/gross thicknesses, average shale volume, porosity, and water saturation for ROCK, RES, and PAY flags. Requires `pandas` and `numpy` to be imported. ```python def paySummary(self, name:str): ''' Computes the * 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} Parameters ---------- name: str Name of the well Returns ------- Displays the Pay Summary Report table Example ------- >>> pp.paySummary(name='15-9_F1A') ''' self._name = name new_data = self.flags(self._por_cutoff, self._vsh_cutoff, self._sw_cutoff, show_plot=False, palette_op=self._pale) # attributes flag_name= list() net = list() gross = list() top = list() bot = list() unit = list() zone_name = list() net_to_gross = list() wellname = list() avg_bvw = list() # por_th = list() # hcpor_th = list() avg_shale = list() avg_por = list() avg_sw = list() not_net = list() # np.random.seed(2) for d, i in zip(new_data, self._zonename): # np.random.seed(2) # top and bottom and unit top_ = d[self._depth].min() bot_ = d[self._depth].max() top.append([top_, top_, top_]) bot.append([bot_, bot_, bot_]) unit.append([self._ref, self._ref, self._ref]) #ntg ntg_rock = d['ROCK_NET_FLAG'].sum()/d.shape[0] ntg_res = d['RES_NET_FLAG'].sum()/d.shape[0] ntg_pay = d['PAY_NET_FLAG'].sum()/d.shape[0] net_to_gross.append([ntg_rock, ntg_res, ntg_pay]) #gross gross_ = d[self._depth].max() - d[self._depth].min() gross.append([gross_, gross_, gross_]) #net net_rock = ntg_rock * gross_ net_res = ntg_res * gross_ net_pay = ntg_pay * gross_ net.append([net_rock, net_res, net_pay]) #not net not_net.append([gross_-net_rock, gross_-net_res, gross_-net_pay]) #zonename and flag name flag_name.append(['ROCK', 'RES', 'PAY']) zone_name.append([i, i, i]) #average volume of shale, water saturationa and porosity rock_filter = d[d['ROCK_NET_FLAG'] == 1] res_filter = d[d['RES_NET_FLAG'] == 1] pay_filter = d[d['PAY_NET_FLAG'] == 1] #avg shale avg_shale_rock = rock_filter['VShale'].mean() avg_shale_res = res_filter['VShale'].mean() avg_shale_pay = pay_filter['VShale'].mean() avg_shale.append([avg_shale_rock, avg_shale_res, avg_shale_pay]) #avg porosity avg_por_rock = rock_filter['PHIE'].mean() avg_por_res = res_filter['PHIE'].mean() avg_por_pay = pay_filter['PHIE'].mean() avg_por.append([avg_por_rock, avg_por_res, avg_por_pay]) #avg water saturation avg_water_rock = rock_filter['SW'].mean() avg_water_res = res_filter['SW'].mean() avg_water_pay = pay_filter['SW'].mean() avg_sw.append([avg_water_rock, avg_water_res, avg_water_pay]) #avg bulk volume of water avg_bulk_rock = (rock_filter['SW'] * rock_filter['PHIE']).mean() avg_bulk_res = (res_filter['SW'] * res_filter['PHIE']).mean() avg_bulk_pay = (pay_filter['SW'] * pay_filter['PHIE']).mean() avg_bvw.append([avg_bulk_rock, avg_bulk_res, avg_bulk_pay]) #wellname wellname.append([name, name, name]) #store info in dataframe df = { 'Well': wellname, 'Zones' : zone_name, 'Flag Name': flag_name, 'Top': top, 'Bottom': bot, 'Unit': unit, 'Gross': gross, 'Net': net, 'Not Net': not_net, 'NTG': net_to_gross, 'BVW': avg_bvw, 'Average VShale': avg_shale, 'Average Porosity': avg_por, 'Average Water Saturation': avg_sw } summary = pd.DataFrame(df).apply(pd.Series.explode).reset_index(drop=True) n = len(summary.columns) def highlight(x): ''' highlighting cell colors by flag type ''' if x['Flag Name']== 'ROCK': return ["background-color: yellow"]*n elif x['Flag Name'] == 'RES': return ["background-color: green"]*n else: ``` -------------------------------- ### Delineating and Labeling Formation Zones Source: https://petrolib.readthedocs.io/en/latest/_modules/petrolib/workflow.html Visualizes formation zones by drawing horizontal spans and adding text labels for zone names. Use this to clearly mark and identify different geological layers in the well log. ```python #formation subplot ax[7].set_ylim(data[self._depth].min(), data[self._depth].max()); ax[7].invert_yaxis() ax[7].set_title('Zones', pad=45) ax[7].set_xticks([]) ax[7].set_yticklabels([]) ax[7].set_xticklabels([]) ax[7].hlines([t for t in self._ztop], xmin=0, xmax=1, colors='black', linestyles='solid', linewidth=1.) ax[7].hlines([b for b in self._zbot], xmin=0, xmax=1, colors='black', linestyles='solid', linewidth=1.) formations = ax[7] # #delineating zones cycol = cycle('bgyrcmk') color = [choice(next(cycol)) for i in range(len(self._zonename))] np.random.shuffle(color) for i in ax: for t,b, c in zip(self._ztop, self._zbot, color): i.axhspan(t, b, color=c, alpha=0.2) # pass #adding zone names for label, fm_mids in zip(self._zonename, self._f_mids): formations.text(0.5, fm_mids, label, rotation=0, verticalalignment='center', fontweight='bold', fontsize='large') ``` -------------------------------- ### Plot Log Curves with Zonation Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Use the plotZone method to visualize log curves within a specified depth range, with zonation tracks. ```python Zonation.plotZone('DEPTH', ['GR', 'RT', 'RHOB', 'NPHI', 'CALI'], 3300, 3600, 'Volve') ``` -------------------------------- ### Bulk Density Plotting and Customization Source: https://petrolib.readthedocs.io/en/latest/_modules/petrolib/workflow.html Sets up and plots the Bulk Density (RHOB) log using a twin y-axis. Customizes grid, limits, and axis appearance with red color coding. ```python #for rhob ax[5].minorticks_on() ax[5].yaxis.grid(which='major', linestyle='-', linewidth=1, color='darkgrey') ax[5].yaxis.grid(which='minor', linestyle='-', linewidth=0.5, color='lightgrey') ax[5].set_yticklabels([]) ax[5].set_xticklabels([]);ax[5].set_xticks([]) nphi_ = ax[5].twiny() nphi_.grid(which='major', linestyle='-', color='darkgrey') nphi_.plot(data[self._rhob], data[self._depth], color='red', linestyle='-', linewidth=0.5) nphi_.set_xlim(data[self._rhob].min(), data[self._rhob].max()) nphi_.set_ylim(data[self._depth].min(), data[self._depth].max()) nphi_.invert_yaxis() nphi_.xaxis.label.set_color('red') nphi_.tick_params(axis='x', colors='red') nphi_.spines['top'].set_edgecolor('red') nphi_.set_xlabel(self._rhob, color='red') nphi_.spines["top"].set_position(("axes", 1.02)) nphi_.xaxis.set_ticks_position("top") nphi_.xaxis.set_label_position("top") nphi_.set_xticks(list(np.linspace(data[self._rhob].min(), data[self._rhob].max(), num=3))) ``` -------------------------------- ### Calculate and Plot Porosity using Density Method Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Computes and displays the porosity using the density method. This requires the Quanti class to be initialized. Adjust `figsize` for plot dimensions. ```python >>> # display plot only >>> pp.porosity(method='density', show_plot=True, figsize=(10, 12)) ``` -------------------------------- ### Model Lithofacies with Gamma Ray Log Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Models lithofacies from a Gamma ray log, specific to a given environment. Use 'SS' for Siliclastic or 'CO' for Carbonate environments. ```python >>> from petrolib.interp import model_facies >>> model_facies(df, gr='GR', env='SS') ``` -------------------------------- ### Calculate Water Saturation using Archie Method and Display Data Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Calculates water saturation using the Archie method and returns the data. The results are concatenated and printed. This method requires prior initialization of the Quanti class and calls to `vshale` and `porosity`. ```python >>> # display data only >>> z = pp.water_saturation(method='archie') >>> result = pd.concat(z) >>> print(result) ``` -------------------------------- ### Generate Report Summary Source: https://petrolib.readthedocs.io/en/latest/_modules/petrolib/workflow.html Generates a styled report summarizing the methods used for parameter estimations and the cutoffs applied for flagging. This report is presented as a Pandas DataFrame with a caption and custom table styles. ```python def report(self): ''' Displays the methods used in each parameter estimations and cutoff used for flagging ''' df = { 'VShale': self._v_method.title(), 'Porosity': self._p_method.title(), 'Water Saturation': self._sw_method.title(), 'VSH Cutoff':self._vsh_cutoff, 'SH Cutoff': self._sw_cutoff, 'PHI Cutoff': self._por_cutoff } df = pd.DataFrame.from_records(df, index=np.arange(0, 1)).T.rename({0:''}, axis=1).style.set_caption('Methods and Cutoffs').set_table_styles(self._styles) return df ``` -------------------------------- ### Plotting Well Log Data with Porosity and Lithology Source: https://petrolib.readthedocs.io/en/latest/_modules/petrolib/workflow.html This code snippet visualizes well log data, including porosity (PHIT and PHIE) and depth. It configures grid lines, horizontal lines for ztop and zbot, and twin axes for different porosity types. Use this for detailed log plotting. ```python ax[2].set_xticklabels([]);ax[2].set_xticks([]) ax[2].yaxis.grid(which='major', linestyle='-', linewidth=1, color='darkgrey') ax[2].yaxis.grid(which='minor', linestyle='-', linewidth=0.5, color='lightgrey') ax[2].hlines([t for t in self._ztop], xmin=data["PHIT"].min(), xmax=data["PHIT"].max(), colors='black', linestyles='solid', linewidth=1.) ax[2].hlines([b for b in self._zbot], xmin=data["PHIT"].min(), xmax=data["PHIT"].max(), colors='black', linestyles='solid', linewidth=1.) nphi_ = ax[2].twiny() nphi_.grid(which='major', linestyle='-', linewidth=0.5, color='darkgrey') nphi_.plot(data['PHIT'], data[self._depth], color='blue', linewidth=0.5) nphi_.fill_betweenx(data[self._depth], data['PHIE'].max(), data['PHIT'], color='slategray', linewidth=1.) nphi_.set_xlim(data['PHIT'].min(), data['PHIT'].max()) nphi_.set_ylim(data[self._depth].min(), data[self._depth].max()) nphi_.invert_yaxis() nphi_.invert_xaxis() nphi_.tick_params(axis='x', colors='blue') nphi_.spines['top'].set_edgecolor('blue') nphi_.set_xlabel('PHIT_'+method[0].upper(), color='blue') nphi_.spines["top"].set_position(("axes", 1.02)) nphi_.xaxis.set_ticks_position("top") nphi_.xaxis.set_label_position("top") nphi_.set_xticks(list(np.linspace(data['PHIT'].min(), data['PHIT'].max(), num=5))) #for PHIE phi = ax[2].twiny() phi.plot(data['PHIE'], data[self._depth], color='red', linewidth=0.5) phi.fill_betweenx(data[self._depth], data["PHIE"], data['PHIE'].max(), color='lightblue') phi.set_xlim(data['PHIE'].min(), data['PHIE'].max()) phi.set_ylim(data[self._depth].min(), data[self._depth].max()) phi.invert_yaxis() phi.invert_xaxis() phi.xaxis.label.set_color('red') phi.tick_params(axis='x', colors='red') phi.spines['top'].set_edgecolor('red') phi.set_xlabel('PHIE_'+method[0].upper(), color='red') phi.spines["top"].set_position(("axes", 1.05)) phi.xaxis.set_ticks_position("top") phi.xaxis.set_label_position("top") phi.set_xticks(list(np.linspace(data['PHIE'].min(), data['PHIE'].max(), num=5))) #formation subplot ax[-1].set_ylim(data[self._depth].min(), data[self._depth].max()); ax[-1].invert_yaxis() ax[-1].set_title('Zones', pad=45) ax[-1].set_xticks([]) # ax[-1].set_yticklabels([]) ax[-1].set_xticklabels([]) ax[-1].hlines([t for t in self._ztop], xmin=0, xmax=1, colors='black', linestyles='solid', linewidth=1.) ax[-1].hlines([b for b in self._zbot], xmin=0, xmax=1, colors='black', linestyles='solid', linewidth=1.) formations = ax[-1] #delineating zones cycol = cycle('bgrcmk') color = [choice(next(cycol)) for i in range(len(self._zonename))] np.random.shuffle(color) for i in ax: for t,b, c in zip(self._ztop, self._zbot, color): i.axhspan(t, b, color=c, alpha=0.3) #adding zone names for label, fm_mids in zip(self._zonename, self._f_mids): formations.text(0.5, fm_mids, label, rotation=0, verticalalignment='center', fontweight='bold', fontsize='large') # plt.tight_layout(h_pad=1) fig.subplots_adjust(wspace = 0.01) # plt.show() return new_data elif show_plot==False: ``` -------------------------------- ### flags Method Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Creates the {ROCK, RES, PAY} flags based on calculated petrophysical properties and specified cutoffs. This method can optionally display a plot visualizing various petrophysical parameters and flags. ```APIDOC ## flags Method ### Description Create the {ROCK, RES, PAY} flags. To use, must have called vshale, porosity, water_saturation and permeability methods. ### Parameters - **vsh_cutoff** (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, optional) - Reference unit for measured depth. Defaults to 'm'. - **show_plot** (bool, optional) - Display plot if True. Plots GR, RT, VSH, SW, Perm, NPHI/RHOB, PHIE/PHIT, [‘ROCK’, ‘RES’, ‘PAY] flags and Zonation track. Defaults to False. - **palette_op** (str, optional) - Palette option for VSH coloring. Defaults to None. - **figsize** (tuple, optional) - Size of plot. Defaults to None. ### Return Type Either/Both Dataframe containing the flags and the plot if show_plot=True. ``` -------------------------------- ### Calculate Permeability with Plot Source: https://petrolib.readthedocs.io/en/latest/_modules/petrolib/workflow.html Computes permeability using a specified method and displays a plot of PHIE, Permeability, and Zone track. Requires prior calculation of vshale, porosity, and water saturation. Ensure 'figsize' is provided when 'show_plot' is True. ```python >>> # 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)) ``` -------------------------------- ### Plotting Resistivity Log Data Source: https://petrolib.readthedocs.io/en/latest/_modules/petrolib/plots.html Configures and plots the Resistivity (ILD) log using a logarithmic scale. It includes color-filling for values above a threshold and horizontal lines for top/bottom markers. Requires depth, resistivity log data, and plot configuration. ```python #for resitivity ax[1].minorticks_on() ax[1].grid(which='major', linestyle='-', linewidth=1.0, color='darkgrey') ax[1].grid(which='minor', linestyle='-', linewidth=0.5, color='lightgrey') ax[1].yaxis.grid(which='minor', linestyle='-', linewidth=0.5, color='lightgrey') ax[1].semilogx(res_log, depth_log, color='red', linewidth=1.0, linestyle='--') ax[1].set_xlim(res_log.min(), res_log.max()) ax[1].set_ylim(ztop, zbot) ax[1].invert_yaxis() ax[1].xaxis.label.set_color('red') ax[1].tick_params(axis='x', colors='red') ax[1].spines['top'].set_edgecolor('red') ax[1].set_xlabel('Resistivity\nILD (ohm.m)', labelpad=15) ax[1].spines["top"].set_position(("axes", 1.01)) ax[1].xaxis.set_ticks_position("top") ax[1].xaxis.set_label_position("top") ax[1].fill_betweenx(depth_log, res_thres, res_log, where=res_log >= res_thres, interpolate=True, color='red', linewidth=0) ax[1].hlines([t for t in ztops], xmin=res_log.min(), xmax=res_log.max(), colors='black', linestyles='solid',linewidth=1.) ax[1].hlines([b for b in zbots], xmin=res_log.min(), xmax=res_log.max(), colors='black', linestyles='solid', linewidth=1.) ``` -------------------------------- ### Plot Triple Combo Log Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Generates a three-combo log plot including Gamma Ray, Resistivity, Neutron Porosity, and Bulk Density. Supports filling for porous/non-porous zones and specific gamma ray track filling. ```python petrolib.plots.tripleCombo(_data : DataFrame_, _depth : str_, _gr : str_, _res : str_, _nphi : str_, _rhob : str_, _ztop : float_, _zbot : float_, _res_thres : float = 10.0_, _fill : str | None = None_, _palette_op : str | None = None_, _limit : str | None = None_, _figsize : tuple = (9, 10)_, _title : str = 'Three Combo Log Plot'_) → None[source] Plots a three combo log of well data Parameters: * **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') ``` ``` -------------------------------- ### Retrieve Reservoir Information from Zonation Object Source: https://petrolib.readthedocs.io/en/latest/_modules/petrolib/plots.html Retrieves reservoir top, bottom, zone name, and formation midpoint information by calling a Zonation object. ```python #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() ``` -------------------------------- ### Load LAS File Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Use this function to load a LAS file and return only the lasio object. This is useful when you need to access all LAS file properties directly. ```python >>> #return only LAS object >>> las = load_las(well_path) ``` -------------------------------- ### Generate Reservoir Flags Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Generates reservoir flags (ROCK, RES, PAY) based on cutoff values for VSH, porosity, and water saturation. Can optionally display a plot of the results. ```python # Create Quanti class pp = Quanti(df, zn, ztop, zbot, fm, 'DEPTH', 'GR', 'RT', 'NPHI', 'RHOB') ``` ```python # Display plot only pp.flags(por_cutoff=.12, vsh_cutoff=.5, sw_cutoff=0.8, show_plot=True, palette_op='cubehelix', figsize=(20, 15)) ``` ```python # Display data only y = pp.flags(por_cutoff=.12, vsh_cutoff=.5, sw_cutoff=0.8) result = pd.concat(y) print(result) ``` -------------------------------- ### Create Geological Flags Source: https://petrolib.readthedocs.io/en/latest/_modules/petrolib/workflow.html Generates ROCK, RES, and PAY flags based on provided cutoffs for VShale, Porosity, and Water Saturation. Requires prior calculation of vshale, porosity, water saturation, and permeability methods. ```python d['ROCK_NET_FLAG'] = [1 if (j < vsh_cutoff) else 0 for j in d['VShale']] d['RES_NET_FLAG'] = [1 if (i > por_cutoff) or (j < vsh_cutoff) else 0 for i, j in zip(d['PHIE'], d['VShale'])] d['PAY_NET_FLAG'] = [1 if (i > por_cutoff) or (j < vsh_cutoff) or (k < sw_cutoff) else 0 for i, j, k in zip(d['PHIE'], d['VShale'], d['SW'])] ``` -------------------------------- ### Compute Volume of Shale (VSH) with Different Methods Source: https://petrolib.readthedocs.io/en/latest/_modules/petrolib/workflow.html Computes the Volume of Shale (VShale) using various methods including linear, Clavier, Larionov (tertiary and older), and Stieber (1, 2, and Miocene/Pliocene). Optionally displays a plot of GR and VShale. ```python d['VShale'] = [(i - (results['GR_Sand'])[idx])/(results['GR_Shale'][idx]-results['GR_Sand'][idx]) for i in d[self._gr]] if method == 'clavier': d['VShale'] = 1.7 - np.sqrt((3.38 - (d['VShale'] + .7)**2)) new_data.append(d) elif method == 'larionov_ter': d['VShale'] = .083*((2 ** (3.7*d['VShale'])) - 1) new_data.append(d) elif method == 'larionov_older': d['VShale'] = .33 *((2 ** (2*d['VShale'])) - 1) new_data.append(d) elif method == 'stieber_1': d['VShale'] = d['VShale'] / (2 - d['VShale']) new_data.append(d) elif method == 'stieber_2': d['VShale'] = d['VShale'] / (4 - (3 * d['VShale'])) new_data.append(d) elif method == 'stieber_m_pliocene': d['VShale'] = d['VShale'] / (3 - (2 * d['VShale'])) new_data.append(d) elif method=='linear': new_data.append(d) ``` -------------------------------- ### Calculate Zone Parameters and Results Source: https://petrolib.readthedocs.io/en/latest/_modules/petrolib/workflow.html This function processes zone data to calculate GR matrix, shale, and sand parameters, storing the results in a DataFrame. It handles different methods for GR matrix calculation (mean, median, or a default value). ```python #store parameter info in dataframe df = {'GR_Matrix': self._grMatrix, 'GR_Shale': self._grShale, 'GR_Sand' : self._grSand, 'Zone' : self._zone} self._results = pd.DataFrame.from_records(df) #return result return self._results, data ``` -------------------------------- ### Generate Pay Summary Source: https://petrolib.readthedocs.io/en/latest/quickstart.html Generate a pay summary report, which aggregates formation evaluation results. This summary can be named for identification. ```python ps = pp.paySummary(name='15-9_F1A') ``` -------------------------------- ### Zonation.plotZone Method Source: https://petrolib.readthedocs.io/en/latest/petrolib.html Plots log curves with an added zonation track, allowing visualization of geological zones alongside log data within a specified depth range. ```APIDOC ## Method Zonation.plotZone ### Description Plots log curves with zonation track. ### Parameters - **depth** (str): Depth column name in the DataFrame. - **logs** (list of str): A list of log curve names to include in the plot. - **top** (float): The minimum depth (top) for the plot range. - **bottom** (float): The maximum depth (bottom) for the plot range. - **title** (str, optional): The title of the plot. Defaults to 'Log Plot'. - **figsize** (tuple, optional): The size of the plot figure (width, height). Defaults to (8, 12). ### Example ```python >>> Zonation.plotZone('DEPTH', ['GR', 'RT', 'RHOB', 'NPHI', 'CALI'], 3300, 3600, 'Volve') ``` ```