[plotting] library is unfolding and should be working tonight

This commit is contained in:
mzwiessele 2015-10-03 13:59:01 +01:00
parent a6c0d82ef7
commit c3afb4eaaf
13 changed files with 648 additions and 263 deletions

View file

@ -2,14 +2,23 @@
# Licensed under the BSD 3-clause license (see LICENSE.txt)
try:
#===========================================================================
# Load in your plotting library here and
# save it under the name plotting_library!
# This is hooking the library in
# for the usage in GPy:
from ..util.config import config
lib = config.get('plotting', 'library')
if lib == 'matplotlib':
import matplotlib
from . import matplot_dep as plotting_library
from .matplot_dep import plot_definitions
plotting_library = plot_definitions.MatplotlibPlots()
#===========================================================================
except (ImportError, NameError):
raise
import warnings
warnings.warn(ImportWarning("{} not available, install newest version of {} for plotting").format(lib, lib))
warnings.warn(ImportWarning("{} not available, install newest version of {} for plotting".format(lib, lib)))
config.set('plotting', 'library', 'none')
if config.get('plotting', 'library') is not 'none':
@ -20,12 +29,15 @@ if config.get('plotting', 'library') is not 'none':
from ..core import GP
GP.plot_data = gpy_plot.data_plots.plot_data
GP.plot_mean = gpy_plot.gp_plots.plot_mean
GP.plot_confidence = gpy_plot.gp_plots.plot_confidence
from . import matplot_dep
# Still to convert to new style:
GP.plot = plotting_library.models_plots.plot_fit
GP.plot_f = plotting_library.models_plots.plot_fit_f
GP.plot_density = plotting_library.models_plots.plot_density
GP.plot = matplot_dep.models_plots.plot_fit
GP.plot_f = matplot_dep.models_plots.plot_fit_f
GP.plot_density = matplot_dep.models_plots.plot_density
GP.plot_errorbars_trainset = plotting_library.models_plots.plot_errorbars_trainset
GP.plot_magnification = plotting_library.dim_reduction_plots.plot_magnification
GP.plot_errorbars_trainset = matplot_dep.models_plots.plot_errorbars_trainset
GP.plot_magnification = matplot_dep.dim_reduction_plots.plot_magnification

View file

@ -0,0 +1,145 @@
#===============================================================================
# Copyright (c) 2015, Max Zwiessele
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# * Neither the name of GPy.plotting.abstract_plotting_library nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#===============================================================================
#===============================================================================
# Make sure that the necessary files and functions are
# defined in the plotting library:
class AbstractPlottingLibrary(object):
def __init__(self):
"""
Set the defaults dictionary in the _defaults variable:
E.g. for matplotlib we define a file defaults.py and
set the dictionary of it here:
from . import defaults
_defaults = defaults.__dict__
"""
self._defaults = {}
self.__defaults = None
@property
def defaults(self):
#===============================================================================
if self.__defaults is None:
from collections import defaultdict
class defaultdict(defaultdict):
def __getattr__(self, *args, **kwargs):
return defaultdict.__getitem__(self, *args, **kwargs)
self.__defaults = defaultdict(dict, self._defaults)
return self.__defaults
#===============================================================================
def get_new_canvas(self, **kwargs):
"""
Return a canvas, kwargupdate for your plotting library.
This method does two things, it creates an empty canvas
and updates the kwargs (deletes the unnecessary kwargs)
for further usage in normal plotting.
E.g. in matplotlib this means it deletes references to ax, as
plotting is done on the axis itself and is not a kwarg.
"""
raise NotImplementedError("Implement all plot functions in AbstractPlottingLibrary in order to use your own plotting library")
def show_canvas(self, canvas, plots):
"""
Show the canvas given.
plots is either a list of plots or a dictionary with the plots
as the items.
E.g. in matplotlib this does not have to do anything, we make the tight plot, though.
"""
raise NotImplementedError("Implement all plot functions in AbstractPlottingLibrary in order to use your own plotting library")
def plot(self, cavas, X, Y, **kwargs):
"""
Make a line plot from for Y on X (Y = f(X)) on the canvas.
the kwargs are plotting library specific kwargs!
"""
raise NotImplementedError("Implement all plot functions in AbstractPlottingLibrary in order to use your own plotting library")
def scatter(self, canvas, X, Y, **kwargs):
"""
Make a scatter plot between X and Y on the canvas given.
the kwargs are plotting library specific kwargs!
"""
raise NotImplementedError("Implement all plot functions in AbstractPlottingLibrary in order to use your own plotting library")
def xerrorbar(self, canvas, X, Y, error, **kwargs):
"""
Make an errorbar along the xaxis for points at (X,Y) on the canvas.
the kwargs are plotting library specific kwargs!
"""
raise NotImplementedError("Implement all plot functions in AbstractPlottingLibrary in order to use your own plotting library")
def yerrorbar(self, canvas, X, Y, error, **kwargs):
"""
Make errorbars along the yaxis on the canvas given.
the kwargs are plotting library specific kwargs!
"""
raise NotImplementedError("Implement all plot functions in AbstractPlottingLibrary in order to use your own plotting library")
def imshow(self, canvas, X, **kwargs):
"""
Show the image stored in X on the canvas/
the kwargs are plotting library specific kwargs!
"""
raise NotImplementedError("Implement all plot functions in AbstractPlottingLibrary in order to use your own plotting library")
def contour(self, canvas, X, Y, C, **kwargs):
"""
Make a contour plot at (X, Y) with heights stored in C on the canvas.
the kwargs are plotting library specific kwargs!
"""
raise NotImplementedError("Implement all plot functions in AbstractPlottingLibrary in order to use your own plotting library")
def fill_between(self, canvas, X, lower, upper, **kwargs):
"""
Fill along the xaxis between lower and upper.
the kwargs are plotting library specific kwargs!
"""
raise NotImplementedError("Implement all plot functions in AbstractPlottingLibrary in order to use your own plotting library")
def fill_gradient(self, canvas, X, percentiles, **kwargs):
"""
Plot a gradient (in alpha values) for the given percentiles.
the kwargs are plotting library specific kwargs!
"""
raise NotImplementedError("Implement all plot functions in AbstractPlottingLibrary in order to use your own plotting library")

View file

@ -1,29 +1,3 @@
def update_not_existing_kwargs(to_update, update_from):
return to_update.update({k:v for k,v in update_from.items() if k not in to_update})
#===============================================================================
# Implement library specific defaults in the specific plotting librarys defaults.py file.
# The following lines ensure, that an empty kwarg gets returned, when accessing a not
# existing default
from .. import plotting_library as pl
from collections import defaultdict
class defaultdict(defaultdict):
def __getattr__(self, *args, **kwargs):
return defaultdict.__getitem__(self, *args, **kwargs)
defaults = defaultdict(dict, **pl.defaults.__dict__)
pl.defaults = defaults
#===============================================================================
#===============================================================================
# Make sure that the necessary files and functions are
# defined in the plotting library:
assert hasattr(pl, 'get_new_canvas'), "Please implement a function to get a new canvas for the specific library in plotting_library.get_new_canvas(**kwargs)"
assert hasattr(pl, 'plot'), "Please implement a function to plot a simple line"
assert hasattr(pl, 'scatter'), "Please implement a function to plot a simple scatterplot"
#assert hasattr(pl, 'xerrorbar'), "Please implement a function to plot an errorbar along the xaxis"
#assert hasattr(pl, 'xerrorbar'), "Please implement a function to plot an errorbar along the yaxis"
#assert hasattr(pl, 'fill'), "Please implement a function to fill a section between points"
#assert hasattr(pl, 'imshow'), "Please implement a function to plot an image in the given boundaries"
#===============================================================================
from . import data_plots, gp_plots

View file

@ -27,16 +27,51 @@
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#===============================================================================
from . import pl
from . import update_not_existing_kwargs
from . import defaults
from functools import wraps
from . import pl
import numpy as np
from .plot_util import get_x_y_var, get_free_dims, get_which_data_ycols,\
get_which_data_rows, update_not_existing_kwargs
def _plot_data(self, canvas, which_data_rows='all',
which_data_ycols='all', visible_dims=None,
error_kwargs=None, **plot_kwargs):
if error_kwargs is None:
error_kwargs = {}
ycols = get_which_data_ycols(self, which_data_ycols)
rows = get_which_data_rows(self, which_data_rows)
X, X_variance, Y = get_x_y_var(self)
free_dims = get_free_dims(self, visible_dims, None)
plots = {}
plots['dataplot'] = []
plots['xerrorplot'] = []
#one dimensional plotting
if len(free_dims) == 1:
for d in ycols:
update_not_existing_kwargs(plot_kwargs, pl.defaults.data_1d)
plots['dataplot'].append(pl.scatter(canvas, X[rows, free_dims], Y[rows, d], **plot_kwargs))
if X_variance is not None:
update_not_existing_kwargs(error_kwargs, pl.defaults.xerrorbar)
plots['xerrorplot'].append(pl.xerrorbar(canvas, X[rows, free_dims].flatten(), Y[rows, d].flatten(),
2 * np.sqrt(X_variance[rows, free_dims].flatten()),
**error_kwargs))
#2D plotting
elif len(free_dims) == 2:
for d in ycols:
update_not_existing_kwargs(plot_kwargs, pl.defaults.data_2d)
plots['dataplot'].append(pl.scatter(canvas, X[rows, free_dims[0]], X[rows, free_dims[1]],
c=Y[rows, d], vmin=Y.min(), vmax=Y.max(), **plot_kwargs))
else:
raise NotImplementedError("Cannot plot in more then two dimensions")
return plots
def plot_data(self, which_data_rows='all',
which_data_ycols='all', visible_dims=None,
error_kwargs=None, **plot_kwargs):
"""
Plot the training data
- For higher dimensions than two, use fixed_inputs to plot the data points with some of the inputs fixed.
@ -52,53 +87,9 @@ def _plot_data(self, canvas, which_data_rows='all',
:type visible_dims: a numpy array
:param dict error_kwargs: kwargs for the error plot for the plotting library you are using
:param kwargs plot_kwargs: kwargs for the data plot for the plotting library you are using
"""
#deal with optional arguments
if which_data_rows == 'all':
which_data_rows = slice(None)
if which_data_ycols == 'all':
which_data_ycols = np.arange(self.output_dim)
if error_kwargs is None:
error_kwargs = {}
if hasattr(self, 'has_uncertain_inputs') and self.has_uncertain_inputs():
X = self.X.mean
X_variance = self.X.variance
else:
X = self.X
X_variance = None
Y = self.Y
#work out what the inputs are for plotting (1D or 2D)
if visible_dims is None:
visible_dims = np.arange(self.input_dim)
assert visible_dims.size <= 2, "Visible inputs cannot be larger than two"
free_dims = visible_dims
#one dimensional plotting
if len(free_dims) == 1:
for d in which_data_ycols:
update_not_existing_kwargs(plot_kwargs, defaults.data_1d)
canvas.append(pl.scatter(canvas, X[which_data_rows, free_dims], Y[which_data_rows, d], **plot_kwargs))
if X_variance is not None:
update_not_existing_kwargs(error_kwargs, defaults.xerrorbar)
canvas.append(pl.xerrorbar(canvas, X[which_data_rows, free_dims].flatten(), Y[which_data_rows, d].flatten(),
2 * np.sqrt(X_variance[which_data_rows, free_dims].flatten()),
**error_kwargs))
#2D plotting
elif len(free_dims) == 2:
for d in which_data_ycols:
update_not_existing_kwargs(plot_kwargs, defaults.data_2d)
canvas = pl.scatter(canvas, X[which_data_rows, free_dims[0]], X[which_data_rows, free_dims[1]],
c=Y[which_data_rows, d], vmin=Y.min(), vmax=Y.max(), **plot_kwargs)
else:
raise NotImplementedError("Cannot plot in more then two dimensions")
return canvas
@wraps(_plot_data)
def plot_data(self, which_data_rows='all',
which_data_ycols='all', visible_dims=None,
error_kwargs=None, **plot_kwargs):
:returns list: of plots created.
"""
canvas, kwargs = pl.get_new_canvas(plot_kwargs)
_plot_data(self, canvas, which_data_rows, which_data_ycols, visible_dims, error_kwargs, **kwargs)
return pl.show_canvas(canvas)
plots = _plot_data(self, canvas, which_data_rows, which_data_ycols, visible_dims, error_kwargs, **kwargs)
return pl.show_canvas(canvas, plots)

View file

@ -28,78 +28,140 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#===============================================================================
from . import pl
from . import update_not_existing_kwargs, defaults
from .util import x_frame1D
from scipy import sparse
import numpy as np
from functools import wraps
def plot_mean(self, plot_limits=None, fixed_inputs=[],
from . import pl
from .plot_util import get_x_y_var, get_fixed_dims, get_free_dims, \
x_frame1D, x_frame2D, update_not_existing_kwargs, \
helper_predict_with_model
def _helper_for_plots(self, plot_limits, fixed_inputs, resolution):
"""
Figure out the data, free_dims and create an Xgrid for
the prediction.
"""
X, Xvar, Y = get_x_y_var(self)
#work out what the inputs are for plotting (1D or 2D)
fixed_dims = get_fixed_dims(self, fixed_inputs)
free_dims = get_free_dims(self, None, fixed_dims)
if len(free_dims) == 1:
#define the frame on which to plot
resolution = resolution or 200
Xnew, xmin, xmax = x_frame1D(X[:,free_dims], plot_limits=plot_limits, resolution=resolution)
Xgrid = np.empty((Xnew.shape[0],self.input_dim))
Xgrid[:,free_dims] = Xnew
for i,v in fixed_dims:
Xgrid[:,i] = v
x = Xgrid
y = None
elif len(free_dims) == 2:
#define the frame for plotting on
resolution = resolution or 50
Xnew, x, y, xmin, xmax = x_frame2D(X[:,free_dims], plot_limits, resolution)
Xgrid = np.empty((Xnew.shape[0],self.input_dim))
Xgrid[:,free_dims] = Xnew
for i,v in fixed_dims:
Xgrid[:,i] = v
return X, Xvar, Y, fixed_dims, free_dims, Xgrid, x, y, xmin, xmax, resolution
def plot_mean(self, plot_limits=None, fixed_inputs=None,
resolution=None, plot_raw=False,
Y_metadata=None, apply_link=False,
plot_uncertain_inputs=True, predict_kw=None,
which_data_ycols='all',
levels=20,
predict_kw=None,
**kwargs):
"""
Plot the mean of a GP.
Plot the mean of the GP.
:param plot_limits: The limits of the plot. If 1D [xmin,xmax], if 2D [[xmin,ymin],[xmax,ymax]]. Defaluts to data limits
:type plot_limits: np.array
:param fixed_inputs: a list of tuple [(i,v), (i,v)...], specifying that input index i should be set to value v.
:param fixed_inputs: a list of tuple [(i,v), (i,v)...], specifying that input dimension i should be set to value v.
:type fixed_inputs: a list of tuples
:param levels: for 2D plotting, the number of contour levels to use is ax is None, create a new figure
:type levels: int
:param int resolution: The resolution of the prediction [defaults are 1D:200, 2D:50]
:param bool plot_raw: plot the latent function (usually denoted f) only?
:param dict Y_metadata: the Y_metadata (for e.g. heteroscedastic GPs)
:param bool apply_link: whether to apply the link function of the GP to the raw prediction.
:param array-like which_data_ycols: which columns of y to plot (array-like or list of ints)
:param dict predict_kw: the keyword arguments for the prediction. If you want to plot a specific kernel give dict(kern=<specific kernel>) in here
:param int levels: for 2D plotting, the number of contour levels to use is
"""
if hasattr(self, 'has_uncertain_inputs') and self.has_uncertain_inputs():
X = self.X.mean
X_variance = self.X.variance
else:
X = self.X
Y = self.Y
if sparse.issparse(Y): Y = Y.todense().view(np.ndarray)
canvas, kwargs = pl.get_new_canvas(kwargs)
plots = _plot_mean(self, canvas, plot_limits, fixed_inputs, resolution, plot_raw, Y_metadata, apply_link, which_data_ycols, levels, predict_kw, **kwargs)
return pl.show_canvas(canvas, plots)
@wraps(plot_mean)
def _plot_mean(self, canvas, plot_limits=None, fixed_inputs=None,
resolution=None, plot_raw=False,
Y_metadata=None, apply_link=False,
which_data_ycols=None,
levels=20,
predict_kw=None, **kwargs):
if predict_kw is None:
predict_kw = {}
#work out what the inputs are for plotting (1D or 2D)
fixed_dims = np.array([i for i,v in fixed_inputs])
free_dims = np.setdiff1d(np.arange(self.input_dim),fixed_dims)
_, _, _, _, free_dims, Xgrid, x, y, _, _, resolution = _helper_for_plots(self, plot_limits, fixed_inputs, resolution)
if len(free_dims<=2):
which_data_ycols = get_which_data_ycols(self, which_data_ycols)
mu, _ = helper_predict_with_model(self, Xgrid, plot_raw, apply_link, None, which_data_ycols, **predict_kw)
if len(free_dims)==1:
# 1D plotting:
update_not_existing_kwargs(kwargs, pl.defaults.meanplot_1d)
return dict(gpmean=[pl.plot(canvas, Xgrid, mu, **kwargs)])
else:
update_not_existing_kwargs(kwargs, pl.defaults.meanplot_2d)
return dict(gpmean=[pl.contour(canvas, x, y,
mu.reshape(resolution, resolution),
levels=levels, **kwargs)])
def plot_confidence(self, lower=2.5, upper=97.5, plot_limits=None, fixed_inputs=None,
resolution=None, plot_raw=False,
Y_metadata=None, apply_link=False,
which_data_ycols='all',
predict_kw=None,
**kwargs):
"""
Plot the confidence interval between the percentiles lower and upper.
E.g. the 95% confidence interval is $2.5, 97.5$.
Note: Only implemented for one dimension!
#define the frame on which to plot
Xnew, xmin, xmax = x_frame1D(X[:,free_dims], plot_limits=plot_limits, resolution=resolution or 200)
Xgrid = np.empty((Xnew.shape[0],self.input_dim))
Xgrid[:,free_dims] = Xnew
for i,v in fixed_inputs:
Xgrid[:,i] = v
:param plot_limits: The limits of the plot. If 1D [xmin,xmax], if 2D [[xmin,ymin],[xmax,ymax]]. Defaluts to data limits
:type plot_limits: np.array
:param fixed_inputs: a list of tuple [(i,v), (i,v)...], specifying that input dimension i should be set to value v.
:type fixed_inputs: a list of tuples
:param int resolution: The resolution of the prediction [default:200]
:param bool plot_raw: plot the latent function (usually denoted f) only?
:param dict Y_metadata: the Y_metadata (for e.g. heteroscedastic GPs)
:param bool apply_link: whether to apply the link function of the GP to the raw prediction.
:param array-like which_data_ycols: which columns of y to plot (array-like or list of ints)
:param dict predict_kw: the keyword arguments for the prediction. If you want to plot a specific kernel give dict(kern=<specific kernel>) in here
"""
canvas, kwargs = pl.get_new_canvas(kwargs)
plots = _plot_confidence(self, canvas, lower, upper, plot_limits,
fixed_inputs, resolution, plot_raw, Y_metadata,
apply_link, which_data_ycols,
predict_kw, **kwargs)
return pl.show_canvas(canvas, plots)
if plot_raw:
mu = self._raw_predict(Xgrid)[0]
update_not_existing_kwargs(kwargs, defaults.meanplot)
return pl.plot(Xgrid, mu, **kwargs)
def _plot_confidence(self, canvas, lower, upper, plot_limits=None, fixed_inputs=None,
resolution=None, plot_raw=False,
Y_metadata=None, apply_link=False,
which_data_ycols=None,
predict_kw=None,
**kwargs):
if predict_kw is None:
predict_kw = {}
_, _, _, _, _, Xgrid, _, _, _, _, _ = _helper_for_plots(self, plot_limits, fixed_inputs, resolution)
def gpplot(x, mu, lower, upper, edgecol='#3300FF', fillcol='#33CCFF', ax=None, fignum=None, **kwargs):
_, axes = ax_default(fignum, ax)
update_not_existing_kwargs(kwargs, pl.defaults.confidence_interval)
_, percs = helper_predict_with_model(self, Xgrid, plot_raw, apply_link, (lower, upper), which_data_ycols, **predict_kw)
mu = mu.flatten()
x = x.flatten()
lower = lower.flatten()
upper = upper.flatten()
return dict(gpconfidence=pl.fill_between(canvas, Xgrid, percs[0], percs[1], **kwargs))
plots = []
#here's the mean
plots.append(meanplot(x, mu, edgecol, axes))
#here's the box
kwargs['linewidth']=0.5
if not 'alpha' in kwargs.keys():
kwargs['alpha'] = 0.3
plots.append(axes.fill(np.hstack((x,x[::-1])),np.hstack((upper,lower[::-1])),color=fillcol,**kwargs))
#this is the edge:
plots.append(meanplot(x, upper,color=edgecol, linewidth=0.2, ax=axes))
plots.append(meanplot(x, lower,color=edgecol, linewidth=0.2, ax=axes))
return plots

View file

@ -27,3 +27,145 @@
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#===============================================================================
import numpy as np
from scipy import sparse
def helper_predict_with_model(self, Xgrid, plot_raw, apply_link, which_data_ycols, percentiles, **predict_kw):
"""
Make the right decisions for prediction with a model
based on the standard arguments of plotting.
This is quite complex and will take a while to understand,
so do not change anything in here lightly!!!
"""
if 'likelihood' not in predict_kw:
if plot_raw:
from ...likelihoods import Gaussian
lik = Gaussian(0) # Make the likelihood not add any noise
else:
lik = None
predict_kw['likelihood'] = lik
mu, _ = self.predict(Xgrid, **predict_kw)
if percentiles is not None:
percentiles = self.predict_quantiles(Xgrid, quantiles=percentiles, **predict_kw)
else: percentiles = {}
retmu = np.empty((Xgrid.shape[0], len(ycols)))
if plot_raw and apply_link:
for i, d in enumerate(ycols):
retmu = self.likelihood.gp_link.transf(mu[:, [i]])
for perc in percentiles:
perc[:, [i]] = self.likelihood.gp_link.transf(perc[:, [i]])
return mu, percentiles
def update_not_existing_kwargs(to_update, update_from):
"""
This function updates the keyword aguments from update_from in
to_update, only if the keys are not set in to_update.
This is used for updated kwargs from the default dicts.
"""
return to_update.update({k:v for k,v in update_from.items() if k not in to_update})
def get_x_y_var(model):
"""
The the data from a model as
X the inputs,
X_variance the variance of the inputs ([default: None])
and Y the outputs
:returns: (X, X_variance, Y)
"""
if hasattr(model, 'has_uncertain_inputs') and model.has_uncertain_inputs():
X = model.X.mean
X_variance = model.X.variance
else:
X = model.X
X_variance = None
Y = model.Y
if sparse.issparse(Y): Y = Y.todense().view(np.ndarray)
return X, X_variance, Y
def get_free_dims(model, visible_dims, fixed_dims):
"""
work out what the inputs are for plotting (1D or 2D)
The visible dimensions are the dimensions, which are visible.
the fixed_dims are the fixed dimensions for this.
The free_dims are then the visible dims without the fixed dims.
"""
if visible_dims is None:
visible_dims = np.arange(model.input_dim)
assert visible_dims.size <= 2, "Visible inputs cannot be larger than two"
if fixed_dims is None:
return visible_dims
else:
return np.setdiff1d(visible_dims, fixed_dims)
def get_fixed_dims(model, fixed_inputs):
"""
Work out the fixed dimensions from the fixed_inputs list of tuples.
"""
if fixed_inputs is None:
fixed_inputs = []
return np.array([i for i,_ in fixed_inputs])
def get_which_data_ycols(model, which_data_ycols):
"""
Helper to get the data columns to plot.
"""
if which_data_ycols == 'all' or which_data_ycols is None:
return np.arange(model.output_dim)
return which_data_ycols
def get_which_data_rows(model, which_data_rows):
"""
Helper to get the data rows to plot.
"""
if which_data_rows == 'all' or which_data_rows is None:
return slice(None)
return which_data_rows
def x_frame1D(X,plot_limits=None,resolution=None):
"""
Internal helper function for making plots, returns a set of input values to plot as well as lower and upper limits
"""
assert X.shape[1] ==1, "x_frame1D is defined for one-dimensional inputs"
if plot_limits is None:
from ...core.parameterization.variational import VariationalPosterior
if isinstance(X, VariationalPosterior):
xmin,xmax = X.mean.min(0),X.mean.max(0)
else:
xmin,xmax = X.min(0),X.max(0)
xmin, xmax = xmin-0.2*(xmax-xmin), xmax+0.2*(xmax-xmin)
elif len(plot_limits)==2:
xmin, xmax = plot_limits
else:
raise ValueError("Bad limits for plotting")
Xnew = np.linspace(xmin,xmax,resolution or 200)[:,None]
return Xnew, xmin, xmax
def x_frame2D(X,plot_limits=None,resolution=None):
"""
Internal helper function for making plots, returns a set of input values to plot as well as lower and upper limits
"""
assert X.shape[1] ==2, "x_frame2D is defined for two-dimensional inputs"
if plot_limits is None:
xmin,xmax = X.min(0),X.max(0)
xmin, xmax = xmin-0.2*(xmax-xmin), xmax+0.2*(xmax-xmin)
elif len(plot_limits)==2:
xmin, xmax = plot_limits
else:
raise ValueError("Bad limits for plotting")
resolution = resolution or 50
xx, yy = np.mgrid[xmin[0]:xmax[0]:1j*resolution,xmin[1]:xmax[1]:1j*resolution]
Xnew = np.vstack((xx.flatten(),yy.flatten())).T
return Xnew, xx, yy, xmin, xmax

View file

@ -1,68 +0,0 @@
#===============================================================================
# Copyright (c) 2012-2015 GPy Authors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# * Neither the name of GPy nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#===============================================================================
import numpy as np
def x_frame1D(X,plot_limits=None,resolution=None):
"""
Internal helper function for making plots, returns a set of input values to plot as well as lower and upper limits
"""
assert X.shape[1] ==1, "x_frame1D is defined for one-dimensional inputs"
if plot_limits is None:
from ...core.parameterization.variational import VariationalPosterior
if isinstance(X, VariationalPosterior):
xmin,xmax = X.mean.min(0),X.mean.max(0)
else:
xmin,xmax = X.min(0),X.max(0)
xmin, xmax = xmin-0.2*(xmax-xmin), xmax+0.2*(xmax-xmin)
elif len(plot_limits)==2:
xmin, xmax = plot_limits
else:
raise ValueError("Bad limits for plotting")
Xnew = np.linspace(xmin,xmax,resolution or 200)[:,None]
return Xnew, xmin, xmax
def x_frame2D(X,plot_limits=None,resolution=None):
"""
Internal helper function for making plots, returns a set of input values to plot as well as lower and upper limits
"""
assert X.shape[1] ==2, "x_frame2D is defined for two-dimensional inputs"
if plot_limits is None:
xmin,xmax = X.min(0),X.max(0)
xmin, xmax = xmin-0.2*(xmax-xmin), xmax+0.2*(xmax-xmin)
elif len(plot_limits)==2:
xmin, xmax = plot_limits
else:
raise ValueError("Bad limits for plotting")
resolution = resolution or 50
xx,yy = np.mgrid[xmin[0]:xmax[0]:1j*resolution,xmin[1]:xmax[1]:1j*resolution]
Xnew = np.vstack((xx.flatten(),yy.flatten())).T
return Xnew, xx, yy, xmin, xmax

View file

@ -1,54 +1,6 @@
# Copyright (c) 2014, GPy authors (see AUTHORS.txt).
# Licensed under the BSD 3-clause license (see LICENSE.txt)
from matplotlib import pyplot as plt
from . import defaults
def get_new_canvas(kwargs):
"""
Return a canvas, kwargupdate for matplotlib. This just a
dictionary for the collection and we add the an axis to kwarg.
This method does two things, it creates an empty canvas
and updates the kwargs (deletes the unnecessary kwargs)
for further usage in normal plotting.
in matplotlib this means it deletes references to ax, as
plotting is done on the axis itself and is not a kwarg.
"""
if 'ax' in kwargs:
ax = kwargs.pop('ax')
elif 'num' in kwargs and 'figsize' in kwargs:
ax = plt.figure(num=kwargs.pop('num'), figsize=kwargs.pop('figsize')).add_subplot(111)
elif 'num' in kwargs:
ax = plt.figure(num=kwargs.pop('num')).add_subplot(111)
elif 'figsize' in kwargs:
ax = plt.figure(figsize=kwargs.pop('figsize')).add_subplot(111)
else:
ax = plt.figure().add_subplot(111)
# Add ax to kwargs to add all subsequent plots to this axis:
#kwargs['ax'] = ax
return ax, kwargs
def show_canvas(canvas):
try:
canvas.figure.canvas.draw()
canvas.figure.tight_layout()
except:
pass
return canvas
def scatter(ax, *args, **kwargs):
ax.scatter(*args, **kwargs)
def plot(ax, *args, **kwargs):
ax.plot(*args, **kwargs)
def imshow(ax, *args, **kwargs):
ax.imshow(*args, **kwargs)
from . import base_plots
from . import models_plots
from . import priors_plots

View file

@ -39,12 +39,15 @@ it gives back an empty default, when defaults are not defined.
'''
from matplotlib import cm
from . import Tango
# Data:
data_1d = dict(lw=1.5, marker='x', edgecolor='k')
data_2d = dict(s=35, edgecolors='none', linewidth=0., cmap=cm.get_cmap('hot'))
xerrorbar = dict(ecolor='k', fmt='none', elinewidth=.5, alpha=.5)
yerrorbar = dict(ecolor='darkred', fmt='none', elinewidth=.5, alpha=.5)
yerrorbar = dict(ecolor=Tango.colorsHex['darkBlue'], fmt='none', elinewidth=.5, alpha=.5)
# GP plots
meanplot = dict(color='#3300FF', linewidth=2)
meanplot_1d = dict(color=Tango.colorsHex['mediumBlue'], linewidth=2)
meanplot_2d = dict(cmap='hot', linewidth=.5)
confidence_interval = dict(linecolor=Tango.colorsHex['darkBlue'],fillcolor=Tango.colorsHex['lightBlue'])

View file

@ -259,12 +259,12 @@ def plot_fit(self, plot_limits=None, which_data_rows='all',
#define the frame for plotting on
resolution = resolution or 50
Xnew, _, _, xmin, xmax = x_frame2D(X[:,free_dims], plot_limits, resolution)
Xnew, x, y, xmin, xmax = x_frame2D(X[:,free_dims], plot_limits, resolution)
Xgrid = np.empty((Xnew.shape[0],self.input_dim))
Xgrid[:,free_dims] = Xnew
for i,v in fixed_inputs:
Xgrid[:,i] = v
x, y = np.linspace(xmin[0], xmax[0], resolution), np.linspace(xmin[1], xmax[1], resolution)
#x, y = np.linspace(xmin[0], xmax[0], resolution), np.linspace(xmin[1], xmax[1], resolution)
#predict on the frame and plot
if plot_raw:

View file

@ -0,0 +1,166 @@
#===============================================================================
# Copyright (c) 2015, Max Zwiessele
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# * Neither the name of GPy.plotting.matplot_dep.plot_definitions nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#===============================================================================
import numpy as np
from matplotlib import pyplot as plt
from ..abstract_plotting_library import AbstractPlottingLibrary
from . import defaults
class MatplotlibPlots(AbstractPlottingLibrary):
def __init__(self):
super(MatplotlibPlots, self).__init__()
self._defaults = defaults.__dict__
def get_new_canvas(self, kwargs):
if 'ax' in kwargs:
ax = kwargs.pop('ax')
elif 'num' in kwargs and 'figsize' in kwargs:
ax = plt.figure(num=kwargs.pop('num'), figsize=kwargs.pop('figsize')).add_subplot(111)
elif 'num' in kwargs:
ax = plt.figure(num=kwargs.pop('num')).add_subplot(111)
elif 'figsize' in kwargs:
ax = plt.figure(figsize=kwargs.pop('figsize')).add_subplot(111)
else:
ax = plt.figure().add_subplot(111)
# Add ax to kwargs to add all subsequent plots to this axis:
#kwargs['ax'] = ax
return ax, kwargs
def show_canvas(self, ax, plots):
try:
ax.autoscale_view()
ax.figure.canvas.draw()
ax.figure.tight_layout()
except:
pass
return ax
def scatter(self, ax, X, Y, **kwargs):
return ax.scatter(X, Y, **kwargs)
def plot(self, ax, X, Y, **kwargs):
return ax.plot(X, Y, **kwargs)
def xerrorbar(self, ax, X, Y, error, **kwargs):
if not('linestyle' in kwargs or 'ls' in kwargs):
kwargs['ls'] = 'none'
return ax.errorbar(X, Y, xerr=error, **kwargs)
def yerrorbar(self, ax, X, Y, error, **kwargs):
if not('linestyle' in kwargs or 'ls' in kwargs):
kwargs['ls'] = 'none'
return ax.errorbar(X, Y, yerr=error, **kwargs)
def imshow(self, ax, X, **kwargs):
return ax.imshow(**kwargs)
def contour(self, ax, X, Y, C, levels=20, **kwargs):
return ax.contour(X, Y, C, levels=np.linspace(C.min(), C.max(), levels), **kwargs)
def fill_between(self, ax, X, lower, upper, **kwargs):
return ax.fill_between(X.flatten(), lower.flatten(), upper.flatten(), **kwargs)
def fill_gradient(self, canvas, X, percentiles, **kwargs):
ax = canvas
plots = []
if not 'alpha' in kwargs.keys():
kwargs['alpha'] = 1./(len(percentiles))
# pop where from kwargs
where = kwargs.pop('where') if 'where' in kwargs else None
# pop interpolate, which we actually do not do here!
if 'interpolate' in kwargs: kwargs.pop('interpolate')
def pairwise(inlist):
l = len(inlist)
for i in range(int(np.ceil(l/2.))):
yield inlist[:][i], inlist[:][(l-1)-i]
polycol = []
for y1, y2 in pairwise(percentiles):
import matplotlib.mlab as mlab
# Handle united data, such as dates
ax._process_unit_info(xdata=X, ydata=y1)
ax._process_unit_info(ydata=y2)
# Convert the arrays so we can work with them
from numpy import ma
x = ma.masked_invalid(ax.convert_xunits(X))
y1 = ma.masked_invalid(ax.convert_yunits(y1))
y2 = ma.masked_invalid(ax.convert_yunits(y2))
if y1.ndim == 0:
y1 = np.ones_like(x) * y1
if y2.ndim == 0:
y2 = np.ones_like(x) * y2
if where is None:
where = np.ones(len(x), np.bool)
else:
where = np.asarray(where, np.bool)
if not (x.shape == y1.shape == y2.shape == where.shape):
raise ValueError("Argument dimensions are incompatible")
mask = reduce(ma.mask_or, [ma.getmask(a) for a in (x, y1, y2)])
if mask is not ma.nomask:
where &= ~mask
polys = []
for ind0, ind1 in mlab.contiguous_regions(where):
xslice = x[ind0:ind1]
y1slice = y1[ind0:ind1]
y2slice = y2[ind0:ind1]
if not len(xslice):
continue
N = len(xslice)
X = np.zeros((2 * N + 2, 2), np.float)
# the purpose of the next two lines is for when y2 is a
# scalar like 0 and we want the fill to go all the way
# down to 0 even if none of the y1 sample points do
start = xslice[0], y2slice[0]
end = xslice[-1], y2slice[-1]
X[0] = start
X[N + 1] = end
X[1:N + 1, 0] = xslice
X[1:N + 1, 1] = y1slice
X[N + 2:, 0] = xslice[::-1]
X[N + 2:, 1] = y2slice[::-1]
polys.append(X)
polycol.extend(polys)
from matplotlib.collections import PolyCollection
plots.append(PolyCollection(polycol, **kwargs))
ax.add_collection(plots[-1], autolim=True)
ax.autoscale_view()
return plots