Skip to content

Commit

Permalink
added marignal variogram plot
Browse files Browse the repository at this point in the history
  • Loading branch information
mmaelicke committed Feb 8, 2021
1 parent 3a3f92f commit 784b929
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 67 deletions.
93 changes: 26 additions & 67 deletions skgstat/SpaceTimeVariogram.py
Original file line number Diff line number Diff line change
Expand Up @@ -1096,7 +1096,7 @@ def _get_member(self, xlag, tlag):
# ------------------------------------------------------------------------ #
# PLOTTING #
# ------------------------------------------------------------------------ #
def plot(self, kind='scatter', ax=None, **kwargs):
def plot(self, kind='scatter', ax=None, **kwargs): # pragma: no cover
"""Plot the experimental variogram
At the current version the SpaceTimeVariogram class is not capable of
Expand Down Expand Up @@ -1161,7 +1161,7 @@ def plot(self, kind='scatter', ax=None, **kwargs):
raise ValueError('kind %s is not a valid value.')

def scatter(self, ax=None, elev=30, azim=220, c='blue',
depthshade=True, **kwargs):
depthshade=True, **kwargs): # pragma: no cover
"""3D Scatter Variogram
Plot the experimental variogram into a 3D matplotlib.Figure. The two
Expand Down Expand Up @@ -1217,7 +1217,7 @@ def scatter(self, ax=None, elev=30, azim=220, c='blue',
c=c, depthshade=depthshade, **kwargs)

def surface(self, ax=None, elev=30, azim=220, color='blue',
alpha=0.5, **kwargs):
alpha=0.5, **kwargs): # pragma: no cover
"""3D Scatter Variogram
Plot the experimental variogram into a 3D matplotlib.Figure. The two
Expand Down Expand Up @@ -1288,7 +1288,7 @@ def _plot3d(self, kind='scatter', ax=None, elev=30, azim=220, **kwargs): # prag
raise ValueError('The plotting backend has an undefined state.')

def contour(self, ax=None, zoom_factor=100., levels=10, colors='k',
linewidths=0.3, method="fast", **kwargs):
linewidths=0.3, method="fast", **kwargs): # pragma: no cover
"""Variogram 2D contour plot
Plot a 2D contour plot of the experimental variogram. The
Expand Down Expand Up @@ -1345,7 +1345,7 @@ def contour(self, ax=None, zoom_factor=100., levels=10, colors='k',
linewidths=linewidths, **kwargs)

def contourf(self, ax=None, zoom_factor=100., levels=10,
cmap='RdYlBu_r', method="fast", **kwargs):
cmap='RdYlBu_r', method="fast", **kwargs): # pragma: no cover
"""Variogram 2D filled contour plot
Plot a 2D filled contour plot of the experimental variogram. The
Expand Down Expand Up @@ -1400,7 +1400,7 @@ def contourf(self, ax=None, zoom_factor=100., levels=10,
return self._plot2d(kind='contourf', ax=ax, zoom_factor=zoom_factor,
levels=levels, cmap=cmap, method=method, **kwargs)

def _plot2d(self, kind='contour', ax=None, zoom_factor=100., levels=10, method="fast", **kwargs):
def _plot2d(self, kind='contour', ax=None, zoom_factor=100., levels=10, method="fast", **kwargs): # pragma: no cover
# get the backend
used_backend = plotting.backend()

Expand All @@ -1413,7 +1413,7 @@ def _plot2d(self, kind='contour', ax=None, zoom_factor=100., levels=10, method="
raise ValueError('The plotting backend has an undefined state.')

def marginals(self, plot=True, axes=None, sharey=True, include_model=False,
**kwargs):
**kwargs): # pragma: no cover
"""Plot marginal variograms
Plots the two marginal variograms into a new or existing figure. The
Expand All @@ -1426,6 +1426,8 @@ class 0. In case the expected variability is not of same magnitude,
Parameters
----------
plot : bool
.. deprecated:: 0.4
With version 0.4, this parameter will be removed
If set to False, no matplotlib.Figure will be returned. Instead a
tuple of the two marginal experimental variogram values is
returned.
Expand Down Expand Up @@ -1453,64 +1455,21 @@ class 0. In case the expected variability is not of same magnitude,
If plot is True, the matplotlib.Figure will be returned.
"""
# get the marginal space variogram
# vx = self.get_marginal(axis='space', lag=0)
# vy = self.get_marginal(axis='time', lag=0)
vx = self.XMarginal.experimental
vy = self.TMarginal.experimental

# if no plot is desired, return the experimental variograms
# handle plot
if not plot:
return vx, vy

# check if an ax needs to be created
if axes is None:
fig, axes = plt.subplots(1, 2,
figsize=kwargs.get('figsize', (12, 6)),
sharey=sharey
)
else:
if len(axes) != 2:
raise ValueError('axes needs to an array of two AxesSubplot '
'objects')
fig = axes[0].get_figure()

# plot
ax = axes[0]
ax2 = axes[1]
ax3 = ax2.twinx()
ax3.get_shared_y_axes().join(ax3, ax)

if include_model:
# transform
xx = np.linspace(0, self.xbins[-1], 50)
xy = np.linspace(0, self.tbins[-1], 50)
y_vx = self.XMarginal.transform(xx)
y_vy = self.TMarginal.transform(xy)

# plot
ax.plot(self.xbins, vx, 'Db')
ax.plot(xx, y_vx, '-b')
ax3.plot(self.tbins, vy, 'Dg')
ax3.plot(xy, y_vy, '-g')
else:
ax.plot(self.xbins, vx, '-ob')
ax3.plot(self.tbins, vy, '-og')

# set labels
ax.set_xlabel('distance [spatial]')
ax.set_ylabel('semivariance [%s]' % self.estimator.__name__)
ax2.set_xlabel('distance [temporal]')
if not sharey:
ax3.set_ylabel('semivariance [%s]' % self.estimator.__name__)

# set title and grid
ax.set_title('spatial marginal variogram')
ax2.set_title('temporal marginal variogram')

ax.grid(which='major')
ax2.grid(which='major')
plt.tight_layout()

# return
return fig
raise DeprecationWarning('The plot parameter will be removed.')
return (
self.XMarginal.experimental,
self.TMarginal.experimental
)

# backend
used_backend = plotting.backend()

if used_backend == 'matplotlib':
return plotting.matplotlib_marginal(self, axes=axes, sharey=sharey, include_model=include_model, **kwargs)
elif used_backend == 'plotly':
return plotting.plotly_marginal(self, fig=axes, include_model=include_model, **kwargs)

# if we reach this line, somethings wrong with plotting backend
raise ValueError('The plotting backend has an undefined state.')
1 change: 1 addition & 0 deletions skgstat/plotting/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from .directtional_variogram import matplotlib_pair_field, plotly_pair_field
from .stvariogram_plot3d import matplotlib_plot_3d, plotly_plot_3d
from .stvariogram_plot2d import matplotlib_plot_2d, plotly_plot_2d
from .stvariogram_marginal import matplotlib_marginal, plotly_marginal


ALLOWED_BACKENDS = [
Expand Down
154 changes: 154 additions & 0 deletions skgstat/plotting/stvariogram_marginal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import numpy as np
import matplotlib.pyplot as plt

try:
import plotly.graph_objects as go
from plotly.subplots import make_subplots
except ImportError:
pass


def __calc_plot_data(stvariogram, **kwargs):
# get the marginal experimental variograms
vx = stvariogram.XMarginal.experimental
vy = stvariogram.TMarginal.experimental

res = kwargs.get('model_resolution', 100)

# get the model
xx = np.linspace(0, stvariogram.xbins[-1], res)
xy = np.linspace(0, stvariogram.tbins[-1], res)
y_vx = stvariogram.XMarginal.transform(xx)
y_vy = stvariogram.TMarginal.transform(xy)

return xx, xy, y_vx, y_vy


def matplotlib_marginal(stvariogram, axes=None, sharey=True, include_model=False, **kwargs):
# check if an ax needs to be created
if axes is None:
fig, axes = plt.subplots(1, 2, figsize=kwargs.get('figsize', (12, 6)),sharey=sharey)
else:
if len(axes) != 2:
raise ValueError('axes needs to an array of two AxesSubplot objects')
fig = axes[0].get_figure()

# get some settings
x_style = kwargs.get('x_style', 'ok' if include_model else '-ob')
t_style = kwargs.get('t_style', 'ok' if include_model else '-og')

# handle the twin axes
ax = axes[0]
ax2 = axes[1]
ax3 = ax2.twinx()
ax3.get_shared_y_axes().join(ax3, ax)

# plot the marginal experimental variogram
ax.plot(stvariogram.xbins, stvariogram.XMarginal.experimental, x_style)
ax3.plot(stvariogram.tbins, stvariogram.TMarginal.experimental, t_style)

if include_model:
xx, xy, y_vx, y_vy = __calc_plot_data(stvariogram, **kwargs)

# plot
ax.plot(xx, y_vx, '-b')
ax.plot(xy, y_vy, '-g')

# set labels
ax.set_xlabel('distance [spatial]')
ax.set_ylabel('semivariance [%s]' % stvariogram.estimator.__name__)
ax2.set_xlabel('distance [temporal]')
if not sharey:
ax3.set_ylabel('semivariance [%s]' % stvariogram.estimator.__name__)

# set title and grid
ax.set_title('spatial marginal variogram')
ax2.set_title('temporal marginal variogram')

ax.grid(which='major')
ax2.grid(which='major')
plt.tight_layout()

# return
return fig


def plotly_marginal(stvariogram, fig=None, include_model=False, **kwargs):
shared_yaxes = kwargs.get('sharey', kwargs.get('shared_yaxis', True))
# check if a figure needs to be created
if fig is None:
fig = go.Figure()
try:
fig.set_subplots(rows=1, cols=2, shared_yaxes=shared_yaxes)
except ValueError:
# figure has alredy subplots
pass

# get some settings
x_color = kwargs.get('x_color', 'black' if include_model else 'green')
t_color = kwargs.get('t_color', 'black' if include_model else 'blue')

# plot the marginal experimental variogram
fig.add_trace(
go.Scatter(
name='Spatial marginal variogram',
x=stvariogram.xbins,
y=stvariogram.XMarginal.experimental,
mode='markers' if include_model else 'markers+lines',
marker=dict(color=x_color),
line=dict(color=x_color),
), row=1, col=1
)
fig.add_trace(
go.Scatter(
name='Temporal marginal variogram',
x=stvariogram.tbins,
y=stvariogram.TMarginal.experimental,
mode='markers' if include_model else 'markers+lines',
marker=dict(color=t_color),
line=dict(color=t_color)
), row=1, col=2
)

# handle models
if include_model:
xx, yy, y_vx, y_vy = __calc_plot_data(stvariogram, **kwargs)

# add the models
fig.add_trace(
go.Scatter(
name='spatial %s model' % stvariogram.XMarginal.model.__name__,
x=xx,
y=y_vx,
mode='lines',
line=dict(color='blue')
), row=1, col=1
)
fig.add_trace(
go.Scatter(
name='temporal %s model' % stvariogram.TMarginal.model.__name__,
x=yy,
y=y_vy,
mode='lines',
line=dict(color='green')
), row=1, col=2
)

# update the layout
fig.update_xaxes(title_text='distance [spatial]', row=1, col=1)
fig.update_xaxes(title_text='distance [temporal]', row=1, col=2)
fig.update_yaxes(title_text='semivariance [%s]' % stvariogram.estimator.__name__, row=1, col=1)
if not shared_yaxes:
fig.update_yaxes(title_text='semivariance [%s]' % stvariogram.estimator.__name__, row=1, col=2)

fig.update_layout(
legend=dict(
orientation='h',
x=0,
y=1.05,
xanchor='left',
yanchor='bottom'
)
)

return fig

0 comments on commit 784b929

Please sign in to comment.