from __future__ import print_function
from ipywidgets import interact, interactive, fixed, interact_manual
from ipywidgets import GridspecLayout
import ipywidgets as widgets
from IPython.display import display
from IPython.display import clear_output
from plotly.subplots import make_subplots
import plotly.express as px
import plotly.offline as pyo
import plotly.io as pio
import plotly.express as px
import plotly.graph_objects as go
import matplotlib.pyplot as plt
from matplotlib import colors,ticker,cm
import matplotlib
from sklearn import datasets, linear_model
from _plotly_future_ import v4_subplots
import plotly.offline as pyo
import plotly.graph_objs as go
import plotly
import numpy as np
from scipy.stats import gaussian_kde
from scipy import stats
import pandas as pd
from pyLPM import utils
import math
#############################################################################################################
def plot_experimental_variogram(dfs, azm,dip):
size_row = 1 if len(azm) < 4 else int(math.ceil(len(azm)/4))
size_cols = 4 if len(azm) >= 4 else int(len(azm))
titles = ["Azimuth {} - Dip {}".format(azm[j], dip[j]) for j in range(len(azm))]
fig = make_subplots(rows=size_row, cols=size_cols, subplot_titles=titles)
count_row = 1
count_cols = 1
for j, i in enumerate(dfs):
fig.add_trace(go.Scatter(x=i['Average distance'], y=i['Spatial continuity'],
mode='markers',
name='Experimental' ,
marker= dict(color =i['Number of pairs']),
text =i['Number of pairs'],
textposition='bottom center') , row=count_row, col=count_cols)
fig.update_xaxes(title_text="Distance", row=count_row, col=count_cols, automargin = True)
fig.update_yaxes(title_text="Variogram", row=count_row, col=count_cols, automargin=True)
fig.update_layout(autosize=True)
count_cols += 1
if count_cols > 4:
count_cols = 1
count_row += 1
fig.show()
return (dfs)
#############################################################################################################
def plot_hscat(store, lagsize, lagmultiply, figsize):
"""Plots h scatterplot
Args:
store ([type]): [description]
lagsize (float): lag size
lagmultiply (int): how many lags to plot
"""
distance =[i*lagsize for i in lagmultiply]
fig = go.Figure()
statitics = ""
annotations = []
for j, i in enumerate(store):
# Create linear regression object
if len(i[0]) != 0:
slope, intercept, r_value, p_value, std_err = stats.linregress(i[0],i[1])
statitics = statitics +''' rho ({}) / distance {} <br />'''.format(str(np.round(r_value,2)), str(distance[j]))
x_val = np.linspace(0, np.max(i[0]), 100)
y_val = slope*x_val + intercept
else:
x_val = []
y_val =[]
fig.add_trace(go.Scatter(x=i[0], y=i[1],
mode='markers',
name='Hscatter - distance {}'.format(str(distance[j]))))
fig.add_trace(go.Scatter(x=x_val, y=y_val,
mode= 'lines',
name = 'Regression - distance {}'.format(str(distance[j])),
line= dict(width=3)))
fig.layout = {
'title':'Hscatter plots',
'xaxis':{'title':'Z(x)','zeroline':True,'autorange':True},
'yaxis':{'title':'Z(x+h)','zeroline':True,'autorange':True},
'annotations':[{'text':statitics,'showarrow':False,'x':0.98,'y':0.98,'xref':'paper','yref':'paper','align':'left','yanchor':'top','bgcolor':'white','bordercolor':'black'}],
'width':figsize[0],
'height':figsize[1],
}
fig['layout'].update(annotations =annotations)
fig.show()
#############################################################################################################
def weighted_avg_and_var(values, weights):
"""Calculates weighted average and variance
Args:
values (array): data values array
weights (array): weight values array
Returns:
array: average, variance
"""
average = np.average(values, weights=weights)
# Fast and numerically precise:
variance = np.average((values-average)**2, weights=weights)
return average, variance
def isotopic_arrays(arrays):
"""Extract isotopic group from arrays
Args:
arrays (array): data values nd array
Returns:
arrays: nd idotopic arrays
"""
masks = []
for array in arrays:
masks.append(np.isnan(array))
mask = sum(masks)
masked_arrays = []
for array in arrays:
masked_var = np.ma.array(array, mask=mask).compressed()
masked_arrays.append(masked_var)
return masked_arrays
#############################################################################################################
[docs]def locmap(x, y, variable, categorical=False, title='', x_axis='Easting (m)', y_axis='Northing (m)', pointsize=8, colorscale='Jet', colorbartitle='', figsize=(700,700)):
"""Plots a location map for samples
Args:
x (array): x values array
y (array): y values array
variable (array): variables values array
categorical (bool, optional): Categorical variable flag. Defaults to False.
title (str, optional): Plot title. Defaults to ''.
x_axis (str, optional): x axis title. Defaults to 'Easting (m)'.
y_axis (str, optional): y axis title. Defaults to 'Northing (m)'.
pointsize (int, optional): point size. Defaults to 8.
colorscale (str, optional): color scale. Defaults to 'Jet'.
colorbartitle (str, optional): colorbar title. Defaults to ''.
figsize (tuple, optional): figure size. Defaults to (700,700).
Returns:
iplot: Location map
"""
variable = np.where(variable == -999.0, float('nan'), variable)
traces = []
if categorical == True:
cats = np.unique(variable[~np.isnan(variable)])
for cat in cats:
mask = variable == cat
trace = {
'type':'scatter',
'mode':'markers',
'x':x[mask],
'y':y[mask],
'marker':{'size':pointsize},
'text':variable[mask],
'name':str(int(cat)),
}
traces.append(trace)
else:
trace = {
'type':'scatter',
'mode':'markers',
'x':x,
'y':y,
'marker':{'size':pointsize,'color':variable,'colorscale':colorscale,'showscale':True,'colorbar':{'title':colorbartitle}},
'text':variable
}
traces.append(trace)
layout = {
'title':title,
'xaxis':{'title':x_axis,'scaleanchor':'y','zeroline':False},
'yaxis':{'title':y_axis,'zeroline':False},
'width':figsize[0],
'height':figsize[1],
}
fig = go.Figure(traces, layout)
return pyo.iplot(fig)
[docs]def histogram(data, n_bins=20, wt=None, title='', x_axis='', y_axis='', cdf=False, figsize=(700,700)):
"""Histogram plot
Args:
data (array): data values array
n_bins (int, optional): number of bins. Defaults to 20.
wt (array, optional): weights values array. Defaults to None.
title (str, optional): plot title. Defaults to ''.
x_axis (str, optional): x axis title. Defaults to ''.
y_axis (str, optional): y axis title. Defaults to ''.
cdf (bool, optional): cdf flag. Defaults to False.
figsize (tuple, optional): figure size. Defaults to (700,700).
Returns:
iplot: histogram plot
"""
dataf = np.where(data == -999.0, float('nan'), data)
dataf = data[~np.isnan(data)]
statistics = '''
n {} <br />
min {} <br />
max {} <br />
mean {} <br />
stdev {} <br />
cv {}
'''.format(round(len(dataf),0), round(dataf.min(),2), round(dataf.max(),2), round(dataf.mean(),2), round(np.sqrt(dataf.var()),2), round(np.sqrt(dataf.var())/dataf.mean(),2))
if wt is not None:
mean, var = weighted_avg_and_var(dataf, wt)
statistics = '''
n {} <br />
min {} <br />
max {} <br />
mean {} <br />
stdev {} <br />
cv {} <br />
weighted
'''.format(round(len(dataf),0), round(dataf.min(),2), round(dataf.max(),2), round(mean,2), round(np.sqrt(var),2), round(np.sqrt(var)/mean),2)
traces = []
hist, bin_edges = np.histogram(dataf, bins=n_bins, weights=wt, density=True)
hist = hist*np.diff(bin_edges)
trace = {
'type':'bar',
'x':bin_edges,
'y':hist,
'name':'pdf'
}
traces.append(trace)
if cdf == True:
hist = np.cumsum(hist)
trace = {
'type':'bar',
'x':bin_edges,
'y':hist,
'name':'cdf'
}
traces.append(trace)
layout = {
'title':title,
'xaxis':{'title':x_axis},
'yaxis':{'title':y_axis},
'width':figsize[0],
'height':figsize[1],
'barmode':'group',
'annotations':[{'text':statistics,'showarrow':False,'x':0.98,'y':0.98,'xref':'paper','yref':'paper','align':'left','yanchor':'top','bgcolor':'white','bordercolor':'black'}]
}
fig = go.Figure(traces, layout)
return pyo.iplot(fig)
[docs]def scatter2d(x, y, variable='kernel density', xy_line = True, best_fit_line=True, title='', x_axis='', y_axis='', pointsize=8, colorscale='Viridis', colorbartitle='', figsize=(700,700)):
"""2D scatter plot
Args:
x (array): x variable data array
y (array): y variable data array
variable (str, optional): variable to color points. Defaults to 'kernel density'.
xy_line (bool, optional): x=y line flag. Defaults to True.
best_fit_line (bool, optional): best fit line flag. Defaults to True.
title (str, optional): plot title. Defaults to ''.
x_axis (str, optional): x axis title. Defaults to ''.
y_axis (str, optional): y axis title. Defaults to ''.
pointsize (int, optional): point size. Defaults to 8.
colorscale (str, optional): color scale. Defaults to 'Viridis'.
colorbartitle (str, optional): color bar title. Defaults to ''.
figsize (tuple, optional): figure size. Defaults to (700,700).
Returns:
iplot: 2D scatter plot
"""
x = np.where(x == -999.0, float('nan'), x)
y = np.where(y == -999.0, float('nan'), y)
x, y = isotopic_arrays([x,y])[0], isotopic_arrays([x,y])[1]
statistics = '''
n {} <br />
rho {}
'''.format(round(len(x),0), round(np.corrcoef([x,y])[1,0],2))
if best_fit_line == True:
slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
statistics = '''
n {} <br />
rho {} <br />
slope {} <br />
intercept {}
'''.format(round(len(x),0), round(np.corrcoef([x,y])[1,0],2), round(slope,2), round(intercept,2))
if type(variable) is not str:
variable = np.where(variable == -999.0, float('nan'), variable)
else:
xy = np.vstack([x,y])
variable = gaussian_kde(xy)(xy)
traces = []
trace = {
'type':'scatter',
'mode':'markers',
'x':x,
'y':y,
'marker':{'size':pointsize,'color':variable,'colorscale':colorscale,'showscale':False,'colorbar':{'title':colorbartitle}},
'text':variable,
'name':'Scatter'
}
traces.append(trace)
if xy_line == True:
maxxy = [max(x), max(y)]
trace = {
'type':'scatter',
'mode':'lines',
'x':[0,max(maxxy)],
'y':[0,max(maxxy)],
'name':'x=y line',
'line':{'dash':'dot','color':'red'}
}
traces.append(trace)
if best_fit_line == True:
maxxy = [max(x), max(y)]
minxy = [min(x), min(y)]
vals = np.arange(min(minxy),max(maxxy))
trace = {
'type':'scatter',
'mode':'lines',
'x':vals,
'y':slope*vals+intercept,
'name':'best fit line',
'line':{'dash':'dot','color':'grey'}
}
traces.append(trace)
layout = {
'title':title,
'xaxis':{'title':x_axis,'zeroline':True,'autorange':True},
'yaxis':{'title':y_axis,'zeroline':True,'autorange':True},
'width':figsize[0],
'height':figsize[1],
'annotations':[{'text':statistics,'showarrow':False,'x':0.98,'y':0.98,'xref':'paper','yref':'paper','align':'left','yanchor':'top','bgcolor':'white','bordercolor':'black'}],
}
fig = go.Figure(traces, layout)
return pyo.iplot(fig)
def cell_declus_sum(cell_size, mean, title='Cell declus summary', pointsize=8, figsize=(600,600)):
"""Cell declustering summary plot
Args:
cell_size (array): cell sizes values array
mean (array): mean values array
title (str, optional): plt title. Defaults to 'Cell declus summary'.
pointsize (int, optional): point size. Defaults to 8.
figsize (tuple, optional): figure size. Defaults to (600,600).
Returns:
iplot: cell declus summary plot
"""
index = np.where(mean == min(mean))[0][0]
text_annotation = '''
cell size {} <br />
mean {}
'''.format(round(cell_size[index],2), round(min(mean),2))
trace = {
'type':'scatter',
'mode':'markers',
'x':cell_size,
'y':mean,
'marker':{'size':pointsize},
}
layout = {
'title':title,
'xaxis':{'title':'cell size','zeroline':True,'autorange':True},
'yaxis':{'title':'mean','zeroline':True,'autorange':True},
'width':figsize[0],
'height':figsize[1],
'annotations':[{'text':text_annotation,'showarrow':True,'arrowhead':7,'ax':0,'ay':-0.5*min(mean),'x':cell_size[index],'y':min(mean),'xref':'x','yref':'y','align':'left','yanchor':'top','bgcolor':'white','bordercolor':'black'}],
}
fig = go.Figure([trace], layout)
return pyo.iplot(fig)
[docs]def pixelplot(grid_dic, variable, categorical=False, points=None, gap=0, title='', x_axis='Easting (m)', y_axis='Northing (m)', colorscale='Jet', colorbartitle='', figsize=(700,700)):
"""Pixel plot for gridded data
Args:
grid_dic (dict): grid definitions dictionary
variable (array): data values array
categorical (bool, optional): categorical data flag. Defaults to False.
points (lst, optional): [x,y,z,var] list to plot points on top of grid. Defaults to None.
gap (int, optional): gap between blocks. Defaults to 0.
title (str, optional): plt title. Defaults to ''.
x_axis (str, optional): x axis title. Defaults to 'Easting (m)'.
y_axis (str, optional): y axis title. Defaults to 'Northing (m)'.
colorscale (str, optional): color scale. Defaults to 'Jet'.
colorbartitle (str, optional): color bar title. Defaults to ''.
figsize (tuple, optional):figure size. Defaults to (700,700).
Returns:
iplot: pixel plot
"""
variable = np.where(variable == -999, float('nan'), variable)
traces = []
x = np.array([(grid_dic['ox']+i*grid_dic['sx']) for i in range(grid_dic['nx'])])
y = np.array([(grid_dic['oy']+j*grid_dic['sy']) for j in range(grid_dic['ny'])])
trace = {
'type':'heatmap',
'z':variable.reshape(grid_dic['ny'], grid_dic['nx']),
'x':x,
'y':y,
'colorscale':colorscale,
'xgap':gap,
'ygap':gap
}
traces.append(trace)
if points is not None:
trace = {
'type':'scatter',
'mode':'markers',
'x':points[0],
'y':points[1],
'marker':{'colorscale':colorscale,'size':6,'color':points[2],'line':{'color':'black','width':1}},
'text':variable}
traces.append(trace)
layout = {
'title':title,
'xaxis':{'title':x_axis,'zeroline':False,'scaleanchor':'y'},
'yaxis':{'title':y_axis,'zeroline':False},
'width':figsize[0],
'height':figsize[1],
}
fig = go.Figure(traces, layout)
return pyo.iplot(fig)
[docs]def qqplot(x,y, dicretization=100, title='', x_axis='', y_axis='', pointsize=8, figsize=(700,700)):
"""QQ plot
Args:
x (array): x variable data array
y (array): y variable data array
dicretization (int, optional): number of quantiles to plot. Defaults to 100.
title (str, optional): plot title. Defaults to ''.
x_axis (str, optional): x axis title. Defaults to ''.
y_axis (str, optional): y axis title. Defaults to ''.
pointsize (int, optional): point size. Defaults to 8.
figsize (tuple, optional): figure size. Defaults to (700,700).
Returns:
iplot: QQ plot
"""
x = np.where(x == -999.0, float('nan'), x)
y = np.where(y == -999.0, float('nan'), y)
x_quant = [np.nanquantile(np.array(x), q) for q in np.linspace(0,1,dicretization)]
y_quant = [np.nanquantile(np.array(y), q) for q in np.linspace(0,1,dicretization)]
traces = []
maxxy = [max(x_quant), max(y_quant)]
minxy = [min(x_quant), min(y_quant)]
trace = {
'type':'scatter',
'mode':'lines',
'x':[min(minxy),max(maxxy)],
'y':[min(minxy),max(maxxy)],
'name':'reference',
'line':{'dash':'dot','color':'grey'}
}
traces.append(trace)
trace = {
'type':'scatter',
'mode':'lines',
'x':x_quant,
'y':y_quant,
'name':'qq',
#'line':{'dash':'dot','color':'grey'}
}
traces.append(trace)
layout = {
'title':title,
'xaxis':{'title':x_axis,'zeroline':True,'autorange':False,'range':[min(minxy),max(maxxy)]},
'yaxis':{'title':y_axis,'zeroline':True,'autorange':False,'range':[min(minxy),max(maxxy)]},
'width':figsize[0],
'height':figsize[1],
#'annotations':[{'text':statistics,'showarrow':False,'x':0.98,'y':0.98,'xref':'paper','yref':'paper','align':'left','yanchor':'top','bgcolor':'white','bordercolor':'black'}],
}
fig = go.Figure(traces, layout)
return pyo.iplot(fig)
def xval(real, estimate, error, pointsize=8, figsize=(500,900)):
"""Cross validation results summary
Args:
real (array): true values array
estimate (array): estimated values array
error (array): real - estimates array
pointsize (int, optional): point size. Defaults to 8.
figsize (tuple, optional): figure size. Defaults to (500,900).
Returns:
iplot: cross validation summary
"""
fig = plotly.subplots.make_subplots(rows=1, cols=3)
real = np.where(real == -999.0, float('nan'), real)
estimate = np.where(estimate == -999.0, float('nan'), estimate)
slope, intercept, r_value, p_value, std_err = stats.linregress(real,estimate)
trace = {
'type':'scatter',
'mode':'markers',
'x':real,
'y':estimate,
'marker':{'size':pointsize},
'name':'True x Estimates'
}
fig.append_trace(trace, 1, 1)
maxxy = [max(real), max(estimate)]
minxy = [min(real), min(estimate)]
vals = np.arange(min(minxy),max(maxxy))
trace = {
'type':'scatter',
'mode':'lines',
'x':vals,
'y':slope*vals+intercept,
'name':'best fit line',
'line':{'dash':'dot','color':'grey'}
}
fig.append_trace(trace, 1, 1)
maxxy = [max(real), max(estimate)]
trace = {
'type':'scatter',
'mode':'lines',
'x':[0,max(maxxy)],
'y':[0,max(maxxy)],
'name':'x=y line',
'line':{'dash':'dot','color':'red'}
}
fig.append_trace(trace, 1, 1)
hist, bin_edges = np.histogram(error, bins=20, density=True)
hist = hist*np.diff(bin_edges)
trace = {
'type':'bar',
'x':bin_edges,
'y':hist,
'name':'error histogram'
}
fig.append_trace(trace, 1, 2)
trace = {
'type':'scatter',
'mode':'markers',
'x':real,
'y':error,
'marker':{'size':pointsize},
'name':'True x Error'
}
fig.append_trace(trace, 1, 3)
statistics = '''
n {} <br />
min {} <br />
max {} <br />
mean {} <br />
stdev {} <br />
cv {} <br />
rho {} <br />
slope {}
'''.format(round(len(error),0), round(error.min(),2), round(error.max(),2), round(error.mean(),2), round(np.sqrt(error.var()),2), round(np.sqrt(error.var())/error.mean(),2), round(np.corrcoef([real,estimate])[1,0],2), round(slope,2))
fig.layout.update(annotations=[{'text':statistics,'showarrow':False,'x':0.98,'y':0.98,'xref':'paper','yref':'paper','align':'left','yanchor':'top','bgcolor':'white','bordercolor':'black'}])
fig.layout.update(title='Cross validation results')
return pyo.iplot(fig)
[docs]def swath_plots(x,y,z,point_var,grid,grid_var,n_bins=10):
"""Swath plots in x, y and z
Args:
x (array): x coordinates array
y (array): y coordinates array
z (array): z coordinates array
point_var (array): point variable array
grid (dict): grid definitions dictionary
grid_var (array): gridded variable array
n_bins (int, optional): number of bins. Defaults to 10.
Returns:
iplot: swath plots
"""
mask_pt = np.isfinite(point_var)
mask_grid = np.isfinite(grid_var)
if z is None:
z = np.zeros(len(x))
x, y, z = np.array(x)[mask_pt], np.array(y)[mask_pt], np.array(z)[mask_pt]
point_var, grid_var = np.array(point_var)[mask_pt], np.array(grid_var)
points_df = pd.DataFrame(columns=['x','y','z','var'])
points_df['x'], points_df['y'], points_df['z'], points_df['var'] = x, y, z, point_var
grid_df = pd.DataFrame(columns=['x','y','z'], data=utils.add_coord(grid))
#grid_df.sort_values(by=['z','y','x'], inplace=True)
grid_df['var'] = grid_var
girf_df = grid_df.dropna()
x_linspace, y_linspace, z_linspace = np.linspace(min(grid_df['x']), max(grid_df['x']), n_bins), np.linspace(min(grid_df['y']), max(grid_df['y']), n_bins), np.linspace(min(grid_df['z']), max(grid_df['z']), n_bins)
x_grades_pts = []
x_grades_grid = []
x_n_pts = []
for idx, slice in enumerate(x_linspace):
if idx != 0:
pts_df_filter = (points_df['x'] >= x_linspace[idx-1]) & (points_df['x'] <= x_linspace[idx])
grid_df_filter = (grid_df['x'] >= x_linspace[idx-1]) & (grid_df['x'] <= x_linspace[idx])
x_grades_pts.append(np.mean(points_df[pts_df_filter]['var']))
x_grades_grid.append(np.mean(grid_df[grid_df_filter]['var']))
x_n_pts.append(len(points_df[pts_df_filter]['var']))
y_grades_pts = []
y_grades_grid = []
y_n_pts = []
for idx, slice in enumerate(y_linspace):
if idx != 0:
pts_df_filter = (points_df['y'] >= y_linspace[idx-1]) & (points_df['y'] <= y_linspace[idx])
grid_df_filter = (grid_df['y'] >= y_linspace[idx-1]) & (grid_df['y'] <= y_linspace[idx])
y_grades_pts.append(np.mean(points_df[pts_df_filter]['var']))
y_grades_grid.append(np.mean(grid_df[grid_df_filter]['var']))
y_n_pts.append(len(points_df[pts_df_filter]['var']))
z_grades_pts = []
z_grades_grid = []
z_n_pts = []
for idx, slice in enumerate(z_linspace):
if idx != 0:
pts_df_filter = (points_df['z'] >= z_linspace[idx-1]) & (points_df['z'] <= z_linspace[idx])
grid_df_filter = (grid_df['z'] >= z_linspace[idx-1]) & (grid_df['z'] <= z_linspace[idx])
z_grades_pts.append(np.mean(points_df[pts_df_filter]['var']))
z_grades_grid.append(np.mean(grid_df[grid_df_filter]['var']))
z_n_pts.append(len(points_df[pts_df_filter]['var']))
if sum(z) == 0:
fig = plotly.subplots.make_subplots(rows=2, cols=1)
tracepts = {
'type':'scatter',
'mode':'lines',
'x':x_linspace,
'y':x_grades_pts,
'name':'points in x',
'line':{'dash':'solid','color':'red'},
}
tracegrid = {
'type':'scatter',
'mode':'lines',
'x':x_linspace,
'y':x_grades_grid,
'name':'grid in x',
'line':{'dash':'solid','color':'blue'},
}
tracenpts = {
'type':'bar',
'x':x_linspace,
'y':np.array(x_n_pts)/max(x_n_pts)*max(x_grades_grid),
'name':'number of points in x',
'hovertext':x_n_pts
}
fig.append_trace(tracepts, 1, 1)
fig.append_trace(tracegrid, 1, 1)
fig.append_trace(tracenpts, 1, 1)
tracepts = {
'type':'scatter',
'mode':'lines',
'x':y_linspace,
'y':y_grades_pts,
'name':'points in y',
'line':{'dash':'solid','color':'red'},
}
tracegrid = {
'type':'scatter',
'mode':'lines',
'x':y_linspace,
'y':y_grades_grid,
'name':'grid in y',
'line':{'dash':'solid','color':'blue'},
}
tracenpts = {
'type':'bar',
'x':y_linspace,
'y':np.array(y_n_pts)/max(y_n_pts)*max(y_grades_grid),
'name':'number of points in y',
'hovertext':y_n_pts
}
fig.append_trace(tracepts, 2, 1)
fig.append_trace(tracegrid, 2, 1)
fig.append_trace(tracenpts, 2, 1)
fig.layout.update(title='Swath plots')
return pyo.iplot(fig)