Skip to content

Commit

Permalink
end plots
Browse files Browse the repository at this point in the history
  • Loading branch information
leliel12 committed Jun 12, 2017
1 parent a0b9412 commit 711cd27
Show file tree
Hide file tree
Showing 8 changed files with 308 additions and 239 deletions.
207 changes: 0 additions & 207 deletions Untitled.ipynb

This file was deleted.

19 changes: 0 additions & 19 deletions coso.py

This file was deleted.

6 changes: 5 additions & 1 deletion skcriteria/plot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
from .. import norm
from .radar import radar_plot
from .multihist import multihist_plot
from .scmtx import scmtx_plot


# =============================================================================
Expand Down Expand Up @@ -89,7 +90,7 @@ def __str__(self):
def __repr__(self):
return str(self)

def __call__(self, plotname="radar", **kwargs):
def __call__(self, plotname="scatter_matrix", **kwargs):
method = getattr(self, plotname)
return method(**kwargs)

Expand Down Expand Up @@ -118,3 +119,6 @@ def radar(self, **kwargs):

def hist(self, **kwargs):
self.plot(multihist_plot, **kwargs)

def scatter_matrix(self, **kwargs):
self.plot(scmtx_plot, **kwargs)
38 changes: 28 additions & 10 deletions skcriteria/plot/multihist.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,10 @@
import numpy as np

import matplotlib.pyplot as plt
from matplotlib.path import Path
from matplotlib.spines import Spine
from matplotlib.projections.polar import PolarAxes
from matplotlib.projections import register_projection
from matplotlib import cm

from six.moves import zip

from .. import norm, util

# =============================================================================
# FUNCTIONS
Expand All @@ -60,19 +55,42 @@
def multihist_plot(
mtx, criteria, weights, anames, cnames,
weighted=True, cmap=None, ax=None,
histtype="stepfilled", alpha=0.8, **kwargs):
subplots_kwargs=None, hist_kwargs=None):

# create ax if necesary
if ax is None:
ax = plt.subplots()[-1]
subplots_kwargs = subplots_kwargs or {}
ax = plt.subplots(**subplots_kwargs)[-1]

# colors
cmap = cm.get_cmap(name=cmap)
colors = cmap(np.linspace(0, 1, mtx.shape[1]))

for arr, col in zip(mtx.T, colors):
ax.hist(arr, color=col, histtype=histtype, alpha=alpha, **kwargs)
# weight the data
if weighted and weights is not None:
wdata = np.multiply(mtx, weights)
else:
wdata = mtx

ax.legend(cnames, loc="best")
# histogram
hist_kwargs = hist_kwargs or {}
hist_kwargs.setdefault("histtype", "stepfilled")
hist_kwargs.setdefault("alpha", 0.8)

for arr, col in zip(wdata.T, colors):
ax.hist(arr, color=col, **hist_kwargs)

ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)

# labels for criteria
if weights is not None:
clabels = [
"{} (w.{:.2f})".format(cn, cw)
for cn, cw in zip(cnames, weights)]
else:
clabels = ["{}".format(cn) for cn in cnames]

ax.legend(clabels, loc="best")

return ax
7 changes: 5 additions & 2 deletions skcriteria/plot/radar.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,17 @@ def unit_poly_verts(theta):


def radar_plot(mtx, criteria, weights, anames, cnames, weighted=True,
frame="polygon", cmap=None, ax=None, labelrow=5):
frame="polygon", cmap=None, ax=None, labelrow=5,
subplots_kwargs=None):

# register radar
theta = radar_factory(len(criteria), frame=frame)

# create ax if necesary
if ax is None:
ax = plt.subplots(subplot_kw=dict(projection='radar'))[-1]
subplots_kwargs = subplots_kwargs or {}
subplots_kwargs.setdefault("subplot_kw", {"projection": "radar"})
ax = plt.subplots(**subplots_kwargs)[-1]
figure = ax.get_figure()

# invert the miniun criteria
Expand Down
177 changes: 177 additions & 0 deletions skcriteria/plot/scmtx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Copyright (c) 2016-2017, Cabral, Juan; Luczywo, Nadia
# 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 the copyright holder 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.

from __future__ import division, print_function


# =============================================================================
# META
# =============================================================================

__doc__ = """ Create a scatter-plot matrix using Matplotlib. """

__author__ = "adrn <adrn@astro.columbia.edu>"


# =============================================================================
# IMPORTS
# =============================================================================

import numpy as np

import matplotlib.pyplot as plt
from matplotlib import cm

from six.moves import range, zip


# =============================================================================
# FUNCTIONS
# =============================================================================

def scatter_plot_matrix(
data, labels, colors, axes=None,
subplots_kwargs=None, scatter_kwargs=None, hist_kwargs=None):
""" Create a scatter plot matrix from the given data.
Parameters
----------
data : numpy.ndarray
A numpy array containined the scatter data to plot. The data
should be shape MxN where M is the number of dimensions and
with N data points.
labels : numpy.ndarray (optional)
A numpy array of length M containing the axis labels.
axes : matplotlib Axes array (optional)
If you've already created the axes objects, pass this in to
plot the data on that.
subplots_kwargs : dict (optional)
A dictionary of keyword arguments to pass to the
matplotlib.pyplot.subplots call. Note: only relevant if axes=None.
scatter_kwargs : dict (optional)
A dictionary of keyword arguments to pass to the
matplotlib.pyplot.scatter function calls.
hist_kwargs : dict (optional)
A dictionary of keyword arguments to pass to the
matplotlib.pyplot.hist function calls.
"""

M, N = data.shape

if axes is None:
skwargs = subplots_kwargs or {}
skwargs.setdefault("sharex", False)
skwargs.setdefault("sharey", False)
fig, axes = plt.subplots(M, M, **skwargs)

sc_kwargs = scatter_kwargs or {}
sc_kwargs.setdefault("edgecolor", "none")
sc_kwargs.setdefault("s", 10)

hist_kwargs = hist_kwargs or {}
hist_kwargs.setdefault("histtype", "stepfilled")
hist_kwargs.setdefault("alpha", 0.8)

xticks, yticks = None, None

hist_color_idx = int(len(colors) / 2 - 1)
if hist_color_idx < 0:
hist_color_idx = 0
hist_color = colors[hist_color_idx]

icolors, colors_buff = iter(colors), {}

for ii in range(M):
for jj in range(M):
ax = axes[ii, jj]
col = (
colors_buff[(ii, jj)]
if (ii, jj) in colors_buff else
next(icolors))
if ii == jj:
ax.hist(data[ii], color=hist_color, **hist_kwargs)
else:
ax.scatter(data[jj], data[ii], color=col, **sc_kwargs)
colors_buff[(ii, jj)] = col
colors_buff[(jj, ii)] = col

if yticks is None:
yticks = ax.get_yticks()[1: -1]

if xticks is None:
xticks = ax.get_xticks()[1: -1]

# first column
if jj == 0:
ax.set_ylabel(labels[ii])

# Hack so ticklabels don't overlap
ax.yaxis.set_ticks(yticks)

# last row
if ii == M - 1:
ax.set_xlabel(labels[jj])

# Hack so ticklabels don't overlap
ax.xaxis.set_ticks(xticks)

ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)

fig = axes[0, 0].figure
fig.subplots_adjust(hspace=0.25, wspace=0.25, left=0.08,
bottom=0.08, top=0.9, right=0.9)
return axes


def scmtx_plot(mtx, criteria, weights, anames, cnames, weighted=True,
frame="polygon", cmap=None, ax=None, **kwargs):

cmap = cm.get_cmap(name=cmap)
colors = cmap(np.linspace(0, 1, mtx.shape[1] ** 2))

# weight the data
if weighted and weights is not None:
wdata = np.multiply(mtx, weights)
else:
wdata = mtx

# labels for criteria
if weights is not None:
clabels = [
"{} (w.{:.2f})".format(cn, cw)
for cn, cw in zip(cnames, weights)]
else:
clabels = ["{}".format(cn) for cn in cnames]

return scatter_plot_matrix(
wdata.T, labels=clabels, colors=colors, axes=ax, **kwargs)
91 changes: 91 additions & 0 deletions skcriteria/tests/test_plot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Copyright (c) 2016-2017, Cabral, Juan; Luczywo, Nadia
# 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 the copyright holder 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.


# =============================================================================
# FUTURE
# =============================================================================

from __future__ import unicode_literals


# =============================================================================
# DOC
# =============================================================================

__doc__ = """Test normalization functionalities"""


# =============================================================================
# IMPORTS
# =============================================================================

import random

import numpy as np

import mock

from six.moves import range

from . import core

from .. import Data


# =============================================================================
# BASE
# =============================================================================

@mock.patch("matplotlib.pyplot.show")
class PlotTestCase(core.SKCriteriaTestCase):

def setUp(self):
self.alternative_n, self.criteria_n = 5, 3
self.mtx = np.random.rand(self.alternative_n, self.criteria_n)
self.criteria = np.asarray([
random.choice([1, -1]) for n in range(self.criteria_n)])
self.weights = np.random.randint(1, 100, self.criteria_n)
self.data = Data(self.mtx, self.criteria, self.weights)

def test_scattermatrix(self, *args):
self.data.plot()
self.data.plot("scatter_matrix")
self.data.plot.scatter_matrix()

def test_radar(self, *args):
self.data.plot("radar")
self.data.plot.radar()

def test_hist(self, *args):
self.data.plot("hist")
self.data.plot.hist()

0 comments on commit 711cd27

Please sign in to comment.