\n",
"\n",
"## Interactive Simple Kriging Demonstration\n",
"\n",
"\n",
"### Michael Pyrcz, Associate Professor, University of Texas at Austin \n",
"\n",
"##### [Twitter](https://twitter.com/geostatsguy) | [GitHub](https://github.com/GeostatsGuy) | [Website](http://michaelpyrcz.com) | [GoogleScholar](https://scholar.google.com/citations?user=QVZ20eQAAAAJ&hl=en&oi=ao) | [Book](https://www.amazon.com/Geostatistical-Reservoir-Modeling-Michael-Pyrcz/dp/0199731446) | [YouTube](https://www.youtube.com/channel/UCLqEr-xV-ceHdXXXrTId5ig) | [LinkedIn](https://www.linkedin.com/in/michael-pyrcz-61a648a1)\n",
"\n",
"\n",
"### The Interactive Workflow\n",
"\n",
"Here's a simple workflow for calculating the simple kriging estimate and the estimation variance for a local uncertainty model\n",
"\n",
"* we use a 'toy problem' with only 3 data for speed and interpretability of the results\n",
"\n",
"#### Spatial Estimation\n",
"\n",
"Consider the case of making an estimate at some unsampled location, $𝑧(\\bf{u}_0)$, where $z$ is the property of interest (e.g. porosity etc.) and $𝐮_0$ is a location vector describing the unsampled location.\n",
"\n",
"How would you do this given data, $𝑧(\\bf{𝐮}_1)$, $𝑧(\\bf{𝐮}_2)$, and $𝑧(\\bf{𝐮}_3)$?\n",
"\n",
"It would be natural to use a set of linear weights to formulate the estimator given the available data.\n",
"\n",
"\\begin{equation}\n",
"z^{*}(\\bf{u}) = \\sum^{n}_{\\alpha = 1} \\lambda_{\\alpha} z(\\bf{u}_{\\alpha})\n",
"\\end{equation}\n",
"\n",
"We could add an unbiasedness constraint to impose the sum of the weights equal to one. What we will do is assign the remainder of the weight (one minus the sum of weights) to the global average; therefore, if we have no informative data we will estimate with the global average of the property of interest.\n",
"\n",
"\\begin{equation}\n",
"z^{*}(\\bf{u}) = \\sum^{n}_{\\alpha = 1} \\lambda_{\\alpha} z(\\bf{u}_{\\alpha}) + \\left(1-\\sum^{n}_{\\alpha = 1} \\lambda_{\\alpha} \\right) \\overline{z}\n",
"\\end{equation}\n",
"\n",
"We will make a stationarity assumption, so let's assume that we are working with residuals, $y$. \n",
"\n",
"\\begin{equation}\n",
"y^{*}(\\bf{u}) = z^{*}(\\bf{u}) - \\overline{z}(\\bf{u})\n",
"\\end{equation}\n",
"\n",
"If we substitute this form into our estimator the estimator simplifies, since the mean of the residual is zero.\n",
"\n",
"\\begin{equation}\n",
"y^{*}(\\bf{u}) = \\sum^{n}_{\\alpha = 1} \\lambda_{\\alpha} y(\\bf{u}_{\\alpha})\n",
"\\end{equation}\n",
"\n",
"while satisfying the unbaisedness constraint. \n",
"\n",
"#### Kriging\n",
"\n",
"Now the next question is what weights should we use? \n",
"\n",
"We could use equal weighting, $\\lambda = \\frac{1}{n}$, and the estimator would be the average of the local data applied for the spatial estimate. This would not be very informative.\n",
"\n",
"We could assign weights considering the spatial context of the data and the estimate:\n",
"\n",
"* **spatial continuity** as quantified by the variogram (and covariance function)\n",
"* **redundancy** the degree of spatial continuity between all of the available data with themselves \n",
"* **closeness** the degree of spatial continuity between the avaiable data and the estimation location\n",
"\n",
"The kriging approach accomplishes this, calculating the best linear unbiased weights for the local data to estimate at the unknown location. The derivation of the kriging system and the resulting linear set of equations is available in the lecture notes. Furthermore kriging provides a measure of the accuracy of the estimate! This is the kriging estimation variance (sometimes just called the kriging variance).\n",
"\n",
"\\begin{equation}\n",
"\\sigma^{2}_{E}(\\bf{u}) = C(0) - \\sum^{n}_{\\alpha = 1} \\lambda_{\\alpha} C(\\bf{u}_0 - \\bf{u}_{\\alpha})\n",
"\\end{equation}\n",
"\n",
"What is 'best' about this estimate? Kriging estimates are best in that they minimize the above estimation variance. \n",
"\n",
"#### Properties of Kriging\n",
"\n",
"Here are some important properties of kriging:\n",
"\n",
"* **Exact interpolator** - kriging estimates with the data values at the data locations\n",
"* **Kriging variance** can be calculated before getting the sample information, as the kriging estimation variance is not dependent on the values of the data nor the kriging estimate, i.e. the kriging estimator is homoscedastic. \n",
"* **Spatial context** - kriging takes into account, furthermore to the statements on spatial continuity, closeness and redundancy we can state that kriging accounts for the configuration of the data and structural continuity of the variable being estimated.\n",
"* **Scale** - kriging may be generalized to account for the support volume of the data and estimate. We will cover this later.\n",
"* **Multivariate** - kriging may be generalized to account for multiple secondary data in the spatial estimate with the cokriging system. We will cover this later.\n",
"* **Smoothing effect** of kriging can be forecast. We will use this to build stochastic simulations later.\n",
"\n",
"#### Spatial Continuity \n",
"\n",
"**Spatial Continuity** is the correlation between values over distance.\n",
"\n",
"* No spatial continuity – no correlation between values over distance, random values at each location in space regardless of separation distance.\n",
"\n",
"* Homogenous phenomenon have perfect spatial continuity, since all values as the same (or very similar) they are correlated. \n",
"\n",
"We need a statistic to quantify spatial continuity! A convenient method is the Semivariogram.\n",
"\n",
"#### The Semivariogram\n",
"\n",
"Function of difference over distance.\n",
"\n",
"* The expected (average) squared difference between values separated by a lag distance vector (distance and direction), $h$:\n",
"\n",
"\\begin{equation}\n",
"\\gamma(\\bf{h}) = \\frac{1}{2 N(\\bf{h})} \\sum^{N(\\bf{h})}_{\\alpha=1} (z(\\bf{u}_\\alpha) - z(\\bf{u}_\\alpha + \\bf{h}))^2 \n",
"\\end{equation}\n",
"\n",
"where $z(\\bf{u}_\\alpha)$ and $z(\\bf{u}_\\alpha + \\bf{h})$ are the spatial sample values at tail and head locations of the lag vector respectively.\n",
"\n",
"* Calculated over a suite of lag distances to obtain a continuous function.\n",
"\n",
"* the $\\frac{1}{2}$ term converts a variogram into a semivariogram, but in practice the term variogram is used instead of semivariogram.\n",
"* We prefer the semivariogram because it relates directly to the covariance function, $C_x(\\bf{h})$ and univariate variance, $\\sigma^2_x$:\n",
"\n",
"\\begin{equation}\n",
"C_x(\\bf{h}) = \\sigma^2_x - \\gamma(\\bf{h})\n",
"\\end{equation}\n",
"\n",
"Note the correlogram is related to the covariance function as:\n",
"\n",
"\\begin{equation}\n",
"\\rho_x(\\bf{h}) = \\frac{C_x(\\bf{h})}{\\sigma^2_x}\n",
"\\end{equation}\n",
"\n",
"The correlogram provides of function of the $\\bf{h}-\\bf{h}$ scatter plot correlation vs. lag offset $\\bf{h}$. \n",
"\n",
"\\begin{equation}\n",
"-1.0 \\le \\rho_x(\\bf{h}) \\le 1.0\n",
"\\end{equation}\n",
"\n",
"#### Objective \n",
"\n",
"In the PGE 383: Stochastic Subsurface Modeling class I want to provide hands-on experience with building subsurface modeling workflows. Python provides an excellent vehicle to accomplish this. I have coded a package called GeostatsPy with GSLIB: Geostatistical Library (Deutsch and Journel, 1998) functionality that provides basic building blocks for building subsurface modeling workflows. \n",
"\n",
"The objective is to remove the hurdles of subsurface modeling workflow construction by providing building blocks and sufficient examples. This is not a coding class per se, but we need the ability to 'script' workflows working with numerical methods. \n",
"\n",
"#### Getting Started\n",
"\n",
"Here's the steps to get setup in Python with the GeostatsPy package:\n",
"\n",
"1. Install Anaconda 3 on your machine (https://www.anaconda.com/download/). \n",
"2. From Anaconda Navigator (within Anaconda3 group), go to the environment tab, click on base (root) green arrow and open a terminal. \n",
"3. In the terminal type: pip install geostatspy. \n",
"4. Open Jupyter and in the top block get started by copy and pasting the code block below from this Jupyter Notebook to start using the geostatspy functionality. \n",
"\n",
"You will need to copy the data file to your working directory. They are available here:\n",
"\n",
"* Tabular data - sample_data.csv at https://git.io/fh4gm.\n",
"\n",
"There are exampled below with these functions. You can go here to see a list of the available functions, https://git.io/fh4eX, other example workflows and source code. \n",
"\n",
"#### Load the required libraries\n",
"\n",
"The following code loads the required libraries."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"import geostatspy.GSLIB as GSLIB # GSLIB utilies, visualization and wrapper\n",
"import geostatspy.geostats as geostats # GSLIB methods convert to Python "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We will also need some standard packages. These should have been installed with Anaconda 3."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"%matplotlib inline\n",
"import os # to set current working directory \n",
"import sys # supress output to screen for interactive variogram modeling\n",
"import io\n",
"import numpy as np # arrays and matrix math\n",
"import pandas as pd # DataFrames\n",
"import matplotlib.pyplot as plt # plotting\n",
"from matplotlib.pyplot import cm # color maps\n",
"from matplotlib.patches import Ellipse # plot an ellipse\n",
"import math # sqrt operator\n",
"from scipy.stats import norm\n",
"from ipywidgets import interactive # widgets and interactivity\n",
"from ipywidgets import widgets \n",
"from ipywidgets import Layout\n",
"from ipywidgets import Label\n",
"from ipywidgets import VBox, HBox\n",
"plt.rc('axes', axisbelow=True) # grid behind plotting elements"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you get a package import error, you may have to first install some of these packages. This can usually be accomplished by opening up a command window on Windows and then typing 'python -m pip install [package-name]'. More assistance is available with the respective package docs. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Simple, Simple Kriging Function\n",
"\n",
"Let's write a fast Python function to take data points and unknown location and provide the:\n",
"\n",
"* **simple kriging estimate**\n",
"\n",
"* **simple kriging variance / estimation variance**\n",
"\n",
"* **simple kriging weights**\n",
"\n",
"This provides a fast method for small datasets, with less parameters (no search parameters) and the ability to see the simple kriging weights "
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"def simple_simple_krige(df,xcol,ycol,vcol,dfl,xlcol,ylcol,vario,skmean):\n",
"# load the variogram\n",
" nst = vario['nst']; pmx = 9999.9\n",
" cc = np.zeros(nst); aa = np.zeros(nst); it = np.zeros(nst)\n",
" ang = np.zeros(nst); anis = np.zeros(nst)\n",
" nug = vario['nug']; sill = nug \n",
" cc[0] = vario['cc1']; sill = sill + cc[0]\n",
" it[0] = vario['it1']; ang[0] = vario['azi1']; \n",
" aa[0] = vario['hmaj1']; anis[0] = vario['hmin1']/vario['hmaj1'];\n",
" if nst == 2:\n",
" cc[1] = vario['cc2']; sill = sill + cc[1]\n",
" it[1] = vario['it2']; ang[1] = vario['azi2']; \n",
" aa[1] = vario['hmaj2']; anis[1] = vario['hmin2']/vario['hmaj2']; \n",
"\n",
"# set up the required matrices\n",
" rotmat, maxcov = geostats.setup_rotmat(nug,nst,it,cc,ang,pmx) \n",
" ndata = len(df); a = np.zeros([ndata,ndata]); r = np.zeros(ndata); s = np.zeros(ndata); rr = np.zeros(ndata)\n",
" nest = len(dfl)\n",
"\n",
" est = np.zeros(nest); var = np.full(nest,sill); weights = np.zeros([nest,ndata])\n",
"\n",
"# Make and solve the kriging matrix, calculate the kriging estimate and variance \n",
" for iest in range(0,nest):\n",
" for idata in range(0,ndata):\n",
" for jdata in range(0,ndata):\n",
" a[idata,jdata] = geostats.cova2(df[xcol].values[idata],df[ycol].values[idata],df[xcol].values[jdata],df[ycol].values[jdata],\n",
" nst,nug,pmx,cc,aa,it,ang,anis,rotmat,maxcov)\n",
" r[idata] = geostats.cova2(df[xcol].values[idata],df[ycol].values[idata],dfl[xlcol].values[iest],dfl[ylcol].values[iest],\n",
" nst,nug,pmx,cc,aa,it,ang,anis,rotmat,maxcov)\n",
" rr[idata] = r[idata]\n",
" \n",
" s = geostats.ksol_numpy(ndata,a,r) \n",
" sumw = 0.0\n",
" for idata in range(0,ndata): \n",
" sumw = sumw + s[idata]\n",
" weights[iest,idata] = s[idata]\n",
" est[iest] = est[iest] + s[idata]*df[vcol].values[idata]\n",
" var[iest] = var[iest] - s[idata]*rr[idata]\n",
" est[iest] = est[iest] + (1.0-sumw)*skmean\n",
" return est,var,weights "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Setup the Spatial Problem\n",
"\n",
"Here you can specify the values of the 3 data samples (v1, v2, v3) and the global mean (vmean)."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"v1 = 25.0 # value of sample data #1\n",
"v2 = 43.0 # value of sample data #1 \n",
"v3 = 56.0 # value of sample data #1 \n",
"value = [v1,v2,v3] # make a data value list\n",
"vmean = 38.0 # value of the global mean for simple kriging\n",
"sill = 25.0 # sill, variance of the dataset \n",
"vmin = np.min(value) - 3 * np.sqrt(sill) # minimum value for plotting\n",
"vmax = np.max(value) + 3 * np.sqrt(sill) # maximum value for plotting"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Interactive Simple Kriging Method\n",
"\n",
"The following code includes:\n",
"\n",
"* dashboard with variogram model data locations \n",
"\n",
"* plots of variogram model, data locations with point scaled by weights and uncertainty distribution at the unknown location"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"import warnings; warnings.simplefilter('ignore')\n",
"\n",
"# interactive calculation of the sample set (control of source parametric distribution and number of samples)\n",
"style = {'description_width': 'initial'}\n",
"l = widgets.Text(value=' Simple Kriging, Michael Pyrcz, Associate Professor, The University of Texas at Austin',layout=Layout(width='950px', height='30px'))\n",
"nug = widgets.FloatSlider(min = 0, max = 1.0, value = 0.0, step = 0.1, description = '$c_{nug}$',orientation='vertical',\n",
" layout=Layout(width='25px', height='218px'))\n",
"nug.style.handle_color = 'gray'\n",
"it1 = widgets.Dropdown(options=['Sph', 'Exp', 'Gaus'],value='Sph',\n",
" description='$it_1$',disabled=False,layout=Layout(width='120px', height='30px'), style=style,continuous_update=False)\n",
"\n",
"azi = widgets.FloatSlider(min=0, max = 360, value = 0, step = 22.5, description = '$Azi$',\n",
" orientation='vertical',layout=Layout(width='40px', height='178px'),continuous_update=False)\n",
"azi.style.handle_color = 'gray'\n",
"hmaj1 = widgets.FloatSlider(min=0.01, max = 10000.0, value = 100.0, step = 25.0, description = '$a_{maj}$',\n",
" orientation='vertical',layout=Layout(width='40px', height='178px'),continuous_update=False)\n",
"hmaj1.style.handle_color = 'gray'\n",
"hmin1 = widgets.FloatSlider(min = 0.01, max = 10000.0, value = 100.0, step = 25.0, description = '$a_{min}$',\n",
" orientation='vertical',layout=Layout(width='40px', height='178px'),continuous_update=False)\n",
"hmin1.style.handle_color = 'gray'\n",
"uikvar = widgets.HBox([azi,hmaj1,hmin1],) # basic widget formatting\n",
"uikvar2 = widgets.VBox([it1,uikvar],) # basic widget formatting\n",
"uikvar3 = widgets.HBox([nug,uikvar2],) # basic widget formatting\n",
"\n",
"x1 = widgets.FloatSlider(min=0.0, max = 1000.0, value = 100.0, step = 1.0, description = '$x_1$',orientation='horizontal',\n",
" layout=Layout(width='160px', height='30px'),readout_format = '.0f',style=style,continuous_update=False)\n",
"x1.style.handle_color = 'blue'\n",
"y1 = widgets.FloatSlider(min=0.0, max = 1000.0, value = 200.0, step = 1.0, description = '$y_1$',orientation='vertical',\n",
" layout=Layout(width='160px', height='180px',margin='0 0 0 10px'),readout_format = '.0f',style=style,continuous_update=False)\n",
"y1.style.handle_color = 'blue'\n",
"uik1 = widgets.VBox([x1,y1],)\n",
"\n",
"x2 = widgets.FloatSlider(min=0.0, max = 1000.0, value = 500.0, step = 1.0, description = '$x_2$',orientation='horizontal',\n",
" layout=Layout(width='160px', height='30px'),readout_format = '.0f',style=style,continuous_update=False)\n",
"x2.style.handle_color = 'red'\n",
"y2 = widgets.FloatSlider(min=0.0, max = 1000.0, value = 800.0, step = 1.0, description = '$y_2$',orientation='vertical',\n",
" layout=Layout(width='160px', height='180px'),readout_format = '.0f',style=style,continuous_update=False)\n",
"y2.style.handle_color = 'red'\n",
"uik2 = widgets.VBox([x2,y2],)\n",
"\n",
"x3 = widgets.FloatSlider(min=0.0, max = 1000.0, value = 700.0, step = 1.0, description = '$x_3$',orientation='horizontal',\n",
" layout=Layout(width='160px', height='30px'),readout_format = '.0f',style=style,continuous_update=False)\n",
"x3.style.handle_color = 'green'\n",
"y3 = widgets.FloatSlider(min=0.0, max = 1000.0, value = 200.0, step = 1.0, description = '$y_3$',orientation='vertical',\n",
" layout=Layout(width='160px', height='180px'),readout_format = '.0f',style=style,continuous_update=False)\n",
"y3.style.handle_color = 'green'\n",
"uik3 = widgets.VBox([x3,y3],)\n",
"\n",
"xu = widgets.FloatSlider(min=0.0, max = 1000.0, value = 500.0, step = 1.0, description = '$x_0$',orientation='horizontal',\n",
" layout=Layout(width='160px', height='30px'),readout_format = '.0f',style=style,continuous_update=False)\n",
"xu.style.handle_color = 'gray'\n",
"yu = widgets.FloatSlider(min=0.0, max = 1000.0, value = 500.0, step = 1.0, description = '$y_0$',orientation='vertical',\n",
" layout=Layout(width='160px', height='180px'),readout_format = '.0f',style=style,continuous_update=False)\n",
"yu.style.handle_color = 'gray'\n",
"uiku = widgets.VBox([xu,yu],)\n",
"\n",
"uipars = widgets.HBox([uikvar3,uik1,uik2,uik3,uiku],) \n",
"uik = widgets.VBox([l,uipars],)\n",
"\n",
"def convert_type(it):\n",
" if it == 'Spherical': \n",
" return 1\n",
" elif it == 'Exponential':\n",
" return 2\n",
" else: \n",
" return 3\n",
"\n",
"def f_make_krige(nug,it1,azi,hmaj1,hmin1,x1,y1,x2,y2,x3,y3,xu,yu,): # function to take parameters, make sample and plot\n",
" text_trap = io.StringIO()\n",
" sys.stdout = text_trap\n",
" it1 = convert_type(it1)\n",
" nst = 1; xlag = 10; nlag = int(hmaj1/xlag); c1 = 1.0-nug\n",
" vario = GSLIB.make_variogram(nug,nst,it1,c1,azi,hmaj1,hmin1) # make model object\n",
" index_maj,h_maj,gam_maj,cov_maj,ro_maj = geostats.vmodel(nlag,xlag,azi,vario) # project the model in the major azimuth # project the model in the 135 azimuth\n",
" index_min,h_min,gam_min,cov_min,ro_min = geostats.vmodel(nlag,xlag,azi+90.0,vario) # project the model in the minor azimuth\n",
" \n",
" clist = ['blue','red','green']\n",
" x = [x1,x2,x3]; y = [y1,y2,y3]; \n",
" df = pd.DataFrame({'X':x,'Y':y,'Value':value})\n",
"\n",
" xl = [xu,0,1]; yl = [yu,0,1]; value1 = [0,0,0]\n",
" dfl = pd.DataFrame({'X':xl,'Y':yl, 'Value':value1})\n",
" \n",
" sk_est, sk_var, sk_weights = simple_simple_krige(df,'X','Y','Value',dfl,'X','Y',vario,skmean=vmean)\n",
" if sk_var[0] == 0: # sk_std is used for plotting only, leave with sill = 1.0\n",
" sk_std = 0.0\n",
" else:\n",
" sk_std = math.sqrt(sk_var[0])\n",
" sk_var[0] = sk_var[0]*sill \n",
" xlag = 10.0; nlag = int(hmaj1/xlag)\n",
" \n",
" plt.subplot(1,3,1)\n",
" plt.plot([0,hmaj1*1.5],[1.0,1.0],color = 'black')\n",
" plt.plot(h_maj,gam_maj,color = 'black',label = 'Major ' + str(azi)) \n",
" plt.plot(h_min,gam_min,color = 'black',label = 'Minor ' + str(azi+90.0))\n",
" deltas = [22.5, 45, 67.5]; \n",
" ndelta = len(deltas); hd = np.zeros(ndelta); gamd = np.zeros(ndelta);\n",
" color=iter(cm.plasma(np.linspace(0,1,ndelta)))\n",
" for delta in deltas:\n",
" index,hd,gamd,cov,ro = geostats.vmodel(nlag,xlag,azi+delta,vario);\n",
" c=next(color)\n",
" plt.plot(hd,gamd,color = c,label = 'Azi ' + str(azi+delta))\n",
" plt.xlabel(r'Lag Distance $\\bf(h)$, (m)')\n",
" plt.ylabel(r'$\\gamma \\bf(h)$')\n",
" plt.title('Interpolated NSCORE Porosity Variogram Models')\n",
" plt.xlim([0,hmaj1*1.5])\n",
" plt.ylim([0,1.4])\n",
" plt.legend(loc='upper left')\n",
" \n",
" plt.subplot(1,3,2)\n",
" \n",
" ax = plt.gca()\n",
" plt.xlabel('X (m)'); plt.ylabel('Y (m)')\n",
" plt.title('Simple Kriging - Data and Unknown Locations')\n",
" plt.xlim([0,1000])\n",
" plt.ylim([0,1000])\n",
" for i, txt in enumerate(np.round(sk_weights[0],2)):\n",
" plt.annotate('$\\lambda$' + ' ' + '$=$' + str(txt), (x[i]+20, y[i]+20),color = clist[i])\n",
" plt.annotate(i+1, (x[i]+46, y[i]+15),fontsize=6,color = clist[i])\n",
" for i, txt in enumerate(value):\n",
" plt.annotate('$z(\\mathbf{u}$' + ' ' + '$ )$ = ' + str(txt), (x[i]+20, y[i]-40),color = clist[i])\n",
" plt.annotate(i+1, (x[i]+80, y[i]-45),fontsize=6,color = clist[i])\n",
" plt.annotate('$\\sum \\lambda_{\\\\alpha} = $'+ str(np.round(np.sum(sk_weights[0]),2)), (xu+20, yu+20))\n",
" plt.annotate('$z^*(\\mathbf{u}_0)$ = '+ str(np.round(sk_est[0],2)), (xu+20, yu-40))\n",
" plt.annotate('Mean Weight = ' + str(np.round(1.0 - np.sum(sk_weights[0]),2)), (20, 20))\n",
" plt.annotate('?', (xu-20, yu + 30))\n",
"\n",
" ax = plt.gca()\n",
" ellipse = Ellipse((xu, yu),width=hmin1*2.0,height=hmaj1*2.0,angle = 360-azi,facecolor='gray',alpha = 0.1,edgecolor='black',zorder=10)\n",
" ax.add_patch(ellipse)\n",
" ellipse = Ellipse((xu, yu),width=hmin1*2.0,height=hmaj1*2.0,angle = 360-azi,facecolor='none',alpha = 1.0,edgecolor='black',zorder=10)\n",
" ax.add_patch(ellipse)\n",
" #ellipse = Ellipse((x1, y1),width=hmin1*2.0,height=hmaj1*2.0,angle = 360-azi,facecolor='blue',alpha = 0.1,zorder=10)\n",
" ax.add_patch(ellipse)\n",
" #ellipse = Ellipse((x1, y1),width=hmin1*2.0,height=hmaj1*2.0,angle = 360-azi,facecolor='none',alpha = 1.0,edgecolor='blue',zorder=10)\n",
" ax.add_patch(ellipse)\n",
" #ellipse = Ellipse((x2, y2),width=hmin1*2.0,height=hmaj1*2.0,angle = 360-azi,facecolor='red',alpha = 0.1,zorder=10)\n",
" ax.add_patch(ellipse)\n",
" #ellipse = Ellipse((x2, y2),width=hmin1*2.0,height=hmaj1*2.0,angle = 360-azi,facecolor='none',alpha = 1.0,edgecolor='red',zorder=10)\n",
" ax.add_patch(ellipse)\n",
" #ellipse = Ellipse((x3, y3),width=hmin1*2.0,height=hmaj1*2.0,angle = 360-azi,facecolor='green',alpha = 0.1,zorder=10)\n",
" ax.add_patch(ellipse)\n",
" #ellipse = Ellipse((x3, y3),width=hmin1*2.0,height=hmaj1*2.0,angle = 360-azi,facecolor='none',alpha = 1.0,edgecolor='green',zorder=10)\n",
" ax.add_patch(ellipse)\n",
" \n",
" if sk_weights[0,0] > 0.01:\n",
" plt.scatter(x1,y1,color = 'blue', edgecolors = 'black', s = sk_weights[0,0]*1000, alpha = 0.3,zorder=100)\n",
" else:\n",
" plt.scatter(x1,y1,color = 'blue', edgecolors = 'black', marker = 'x', alpha = 0.3,zorder=100)\n",
" if sk_weights[0,1] > 0.01: \n",
" plt.scatter(x2,y2,color = 'red', edgecolors = 'black', s = sk_weights[0,1]*1000,alpha = 0.3,zorder=100)\n",
" else:\n",
" plt.scatter(x2,y2,color = 'red', edgecolors = 'black', marker = 'x',alpha = 0.3,zorder=100)\n",
" if sk_weights[0,2] > 0.01:\n",
" plt.scatter(x3,y3,color = 'green', edgecolors = 'black', s = sk_weights[0,2]*1000, alpha = 0.3,zorder=100)\n",
" else:\n",
" plt.scatter(x3,y3,color = 'green', edgecolors = 'black', marker = 'x', alpha = 0.3,zorder=100)\n",
" \n",
" if (1-sk_std) > 0.01:\n",
" scatter = plt.scatter(xu,yu,color = 'gray', edgecolors = 'black', s = (1-sk_std)*1000,alpha = 0.3,zorder=100)\n",
" else: \n",
" scatter = plt.scatter(xu,yu,color = 'black', edgecolors = 'black', marker = 'x', alpha = 0.3,zorder=100)\n",
"\n",
" samples = norm.rvs(sk_est[0],math.sqrt(sk_var[0]),1000,random_state=73073) \n",
" plt.subplot(1,3,3)\n",
" plt.hist(samples,histtype = 'stepfilled',cumulative = True, bins = np.linspace(vmin,vmax,200),alpha=0.8,color=\"darkorange\",edgecolor='black',density=True)\n",
" plt.xlim([vmin,vmax]); plt.ylim([0,1.0])\n",
" plt.title('Kriging Uncertainty Model at Unknown Location')\n",
" plt.xlabel('Value'); plt.ylabel('Frequency')\n",
" \n",
" ax = plt.gca()\n",
" ax.annotate(r'$z^*(\\mathbf{u}_0)$ = ' + str(np.round(sk_est[0],2)), (0.05*(vmax-vmin)+vmin, 0.9))\n",
" ax.annotate(r'$\\sigma_z^2(\\mathbf{u}_0)$ = ' + str(np.round(sk_var[0],2)), (0.05*(vmax-vmin)+vmin, 0.83))\n",
" ax.annotate(r'$P10_z(\\mathbf{u}_0)$ = ' + str(np.round(np.percentile(samples,10),2)), (0.05*(vmax-vmin)+vmin, 0.76))\n",
" ax.annotate(r'$P90_z(\\mathbf{u}_0)$ = ' + str(np.round(np.percentile(samples,90),2)), (0.05*(vmax-vmin)+vmin, 0.69))\n",
" plt.subplots_adjust(left=0.0, bottom=0.0, right=2.2, top=0.9, wspace=0.3, hspace=0.3)\n",
" plt.show()\n",
" \n",
"# connect the function to make the samples and plot to the widgets \n",
"interactive_plot = widgets.interactive_output(f_make_krige, {'nug':nug, 'it1':it1, 'azi':azi, 'hmaj1':hmaj1, 'hmin1':hmin1, \n",
" 'x1':x1, 'y1':y1, 'x2':x2, 'y2':y2, 'x3':x3, 'y3':y3, 'xu':xu, 'yu':yu})\n",
"interactive_plot.clear_output(wait = True) # reduce flickering by delaying plot updating"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Interactive Simple Kriging Demostration\n",
"\n",
"* select the variogram model and the data locations and observe the outputs from simple kriging \n",
"\n",
"#### Michael Pyrcz, Associate Professor, University of Texas at Austin \n",
"\n",
"##### [Twitter](https://twitter.com/geostatsguy) | [GitHub](https://github.com/GeostatsGuy) | [Website](http://michaelpyrcz.com) | [GoogleScholar](https://scholar.google.com/citations?user=QVZ20eQAAAAJ&hl=en&oi=ao) | [Book](https://www.amazon.com/Geostatistical-Reservoir-Modeling-Michael-Pyrcz/dp/0199731446) | [YouTube](https://www.youtube.com/channel/UCLqEr-xV-ceHdXXXrTId5ig) | [LinkedIn](https://www.linkedin.com/in/michael-pyrcz-61a648a1) | [GeostatsPy](https://github.com/GeostatsGuy/GeostatsPy)\n",
"\n",
"### The Inputs\n",
"\n",
"Select the variogram model and the data locations:\n",
"\n",
"* $c_{nug}$, $C_1 = 1.0 - c_{nug}$, contributions of the sill\n",
"\n",
"* **hmaj1 / hmin1 **: range in the major and minor direction\n",
"\n",
"* **(x1, y1),...(x3,y3) **: spatial data locations "
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "96ddda58f25b4147993ca83720330b64",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"VBox(children=(Text(value=' Simple Kriging, Michael Pyrcz, Associ…"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "b9e2836f1b1441778a36a4519b62af0a",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Output(outputs=({'output_type': 'display_data', 'data': {'text/plain': '', 'i…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"display(uik, interactive_plot) # display the interactive plot"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Simplified Plot of the Estimation Problem\n",
"\n",
"Here's a simplified plot of the estimation problem."
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"image/png": "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+qzTmVntcmBWIrlTy8YKrUHExlq/i8ubb75J06ZN6dChA1dddRUdO3bkpZdeYtOmTZSUlFQ6z0033ZRpOjOrXT6GWYlzzjmVFi1uAHL/id7ddOq0O927d6+19SxdupTzzjuP888/H0msWLGCTp060aRJE+666y42bkxCu1WrVqxatWrLfFVNZ2Z1y1uYlRg9+lymTHmCp58+kHXrjqekZBHNm7/IQw9N/dzHL9euXUvfvn1Zv349zZo143vf+x4/+clPAPjhD3/I8OHDeeCBB/ja177GrrvuCsDBBx9Ms2bN6NOnD6NGjapyOjOrWw7MSjRv3pwpUx5g5syZ/O1vf+MLX+jPSSfdVyvBVN3WYPfu3Xn55Ze3vL722mu31PPnP/95q8sJK5vOzOqWA7MKkjjssMM47LDD8l2KmTUQPoZpZpaRA9PMLCMHpplZRg5MM7OMHJhmZhk5MOtRWVkZBx209b8nGjt2LDfccEO18/3xj3/k4osvrsvStkuWmnfUww8/zPz587e8vuKKK3j88cfrZF1m28uBaQ1KxcD8xS9+wdFHH53Hisw+48CsQps2bZC0zaNNmzZ1ts4hQ4bw85//nAEDBtCjRw9mzJixzTRTpkxh4MCBfPDBB4waNYoLLriAww47jH333ZcHH3wQSG7mcckll3DQQQfRu3dv7r//fiC5kmjy5MkAfPvb3+ass84CYPz48Vx++eWUlZVxwAEHcO6553LggQdyzDHHsHbt2ky1V7VOgOuvv57evXvTp08fxowZA8Btt93Gl7/8Zfr06cPw4cNZs2YNf//735k8eTKXXHIJffv25Y033mDUqFFb+jV9+nT69etH7969Oeuss1i3bh0AXbt25corr6R///707t2bV199dUfefrMa+YvrVVixYgVjx47dpr2yttq0YcMGnnvuOaZOncpVV1211e7on/70J2688UamTp1K27ZtAVi8eDHPPPMMr776KsOGDePkk09m0qRJzJkzh5deeokPPviAL3/5ywwePJjBgwczY8YMhg0bxrvvvsvixYsBeOaZZxgxYgQAr7/+Ovfeey+33XYbp556Kg899BCnn356jXVXtc45c+bw8MMPM2vWLFq0aMGHH34IwEknncS5554LwOWXX8748eP58Y9/zLBhwzj++OM5+eSTt1r+J598wqhRo5g+fTo9evTgjDPO4He/+x0XXXQRAHvssQcvvvgit956KzfccAO333775/sgzCrhLcx6VNV16LntJ510EgBf+tKXKCsr29I+Y8YMfvWrXzFlypQtYQlw4okn0qRJE3r16sX7778PJAF42mmn0bRpUzp27MgRRxzB888/z6BBg5gxYwbz58+nV69edOzYkcWLFzNz5swtVzR169aNvn37VlpDdapa5+OPP86ZZ55JixYtALbctX7u3LkMGjSI3r17M2HCBObNm1ft8hcuXEi3bt3o0aMHACNHjuTpp5+u8X0zq00OzHq0++6789FHH23V9uGHH7LHHntseb3zzjsDyf/+2bBhw5b2rl27snLlym3ufbl5evjsvpqbnyvq3LkzH330EdOmTWPw4MEMGjSIiRMn0rJlyy3Xqecur2IN1alqnRFR6R+KUaNGccstt/DKK69w5ZVX1vhfHata/mZVvW9mtcmBWY9atmxJp06dmD59OpCE5bRp0zj88MNrnHevvfZi0qRJnHHGGTVujQ0ePJj777+fjRs3snTpUp5++mkGDBgAwMCBA7n55pu3BOYNN9zAoEGDPnffqlrnMcccw+9//3vWJLet37JLvnLlSjp16sT69euZMGHCluW0atWKlStXbrP8/fffn7KyMhYtWgTAXXfdxRFHHPG56zbbHg7MenbnnXdy9dVX07dvX4488kiuvPJKvvjFL2aat2fPnkyYMIFTTjmFN954o8rpvv3tb3PwwQfTp08fjjzySK6//nq+8IUvADBo0CA2bNjAfvvtR//+/fnwww93KDCvvvpqunTpsuVR1TqHDh3KsGHDOOSQQ+jbt++WryP98pe/5Ctf+Qpf//rXt7qD/YgRI/j1r39Nv379tupjSUkJf/jDHzjllFPo3bs3TZo04bzzztvuus0+D9W0q1OoevbsGQsXLtyqbcGCBRxwwAGZ5m/Tpg0rVqzYpr1169YsX768NkrcLitXrtzq9m6FLB992Z7PfnuVlpYyZMiQOll2PhRbfyS9EBGH1MayfJa8CvkIRTNr2LxLbmaWkQPTzCyjRheYxXrM1qrmz9xqS6MKzJKSEpYtW+ZfoEYkIli2bJn/FbHVikZ10qdLly6Ul5ezdOnSfJey3T755JOi+aWv776UlJTQpUuXelufFa9GFZjNmzenW7du+S5jh5SWltKvX798l1Eriqkv1rg0ql1yM7PPw4Fp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\n",
"text/plain": [
""
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.subplot(111)\n",
"plt.scatter([x1.value,x2.value,x3.value],[y1.value,y2.value,y3.value],color = ['blue','red','green'],edgecolor='black',label='Data')\n",
"plt.scatter([xu.value],[yu.value],color='grey',edgecolor='black',marker='s',label='Unknown Location')\n",
"plt.xlim([0,1000]); plt.ylim([0,1000]); plt.xlabel('X (m)'); plt.ylabel('Y (m)'); plt.title('Data and Unknown Location')\n",
"plt.legend(loc='upper left'); plt.grid()\n",
"\n",
"plt.subplots_adjust(left=0.0, bottom=0.0, right=0.6, top=0.9, wspace=0.3, hspace=0.3); plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Comments\n",
"\n",
"This was an interactive demonstration of simple kriging for spatial data analytics. Much more could be done, I have other demonstrations on the basics of working with DataFrames, ndarrays, univariate statistics, plotting data, declustering, data transformations and many other workflows available at https://github.com/GeostatsGuy/PythonNumericalDemos and https://github.com/GeostatsGuy/GeostatsPy. \n",
" \n",
"#### The Author:\n",
"\n",
"### Michael Pyrcz, Associate Professor, University of Texas at Austin \n",
"*Novel Data Analytics, Geostatistics and Machine Learning Subsurface Solutions*\n",
"\n",
"With over 17 years of experience in subsurface consulting, research and development, Michael has returned to academia driven by his passion for teaching and enthusiasm for enhancing engineers' and geoscientists' impact in subsurface resource development. \n",
"\n",
"For more about Michael check out these links:\n",
"\n",
"#### [Twitter](https://twitter.com/geostatsguy) | [GitHub](https://github.com/GeostatsGuy) | [Website](http://michaelpyrcz.com) | [GoogleScholar](https://scholar.google.com/citations?user=QVZ20eQAAAAJ&hl=en&oi=ao) | [Book](https://www.amazon.com/Geostatistical-Reservoir-Modeling-Michael-Pyrcz/dp/0199731446) | [YouTube](https://www.youtube.com/channel/UCLqEr-xV-ceHdXXXrTId5ig) | [LinkedIn](https://www.linkedin.com/in/michael-pyrcz-61a648a1)\n",
"\n",
"#### Want to Work Together?\n",
"\n",
"I hope this content is helpful to those that want to learn more about subsurface modeling, data analytics and machine learning. Students and working professionals are welcome to participate.\n",
"\n",
"* Want to invite me to visit your company for training, mentoring, project review, workflow design and / or consulting? I'd be happy to drop by and work with you! \n",
"\n",
"* Interested in partnering, supporting my graduate student research or my Subsurface Data Analytics and Machine Learning consortium (co-PIs including Profs. Foster, Torres-Verdin and van Oort)? My research combines data analytics, stochastic modeling and machine learning theory with practice to develop novel methods and workflows to add value. We are solving challenging subsurface problems!\n",
"\n",
"* I can be reached at mpyrcz@austin.utexas.edu.\n",
"\n",
"I'm always happy to discuss,\n",
"\n",
"*Michael*\n",
"\n",
"Michael Pyrcz, Ph.D., P.Eng. Associate Professor The Hildebrand Department of Petroleum and Geosystems Engineering, Bureau of Economic Geology, The Jackson School of Geosciences, The University of Texas at Austin\n",
"\n",
"#### More Resources Available at: [Twitter](https://twitter.com/geostatsguy) | [GitHub](https://github.com/GeostatsGuy) | [Website](http://michaelpyrcz.com) | [GoogleScholar](https://scholar.google.com/citations?user=QVZ20eQAAAAJ&hl=en&oi=ao) | [Book](https://www.amazon.com/Geostatistical-Reservoir-Modeling-Michael-Pyrcz/dp/0199731446) | [YouTube](https://www.youtube.com/channel/UCLqEr-xV-ceHdXXXrTId5ig) | [LinkedIn](https://www.linkedin.com/in/michael-pyrcz-61a648a1) \n",
" "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.12"
}
},
"nbformat": 4,
"nbformat_minor": 2
}