#!/usr/bin/env python

import sys
import argparse
import pickle
import warnings
import exceptions
import numpy
try:
    from matplotlib import pyplot
except ImportError as import_error:
    warnings.warn("Can't use this script without matplotlib.")
    pyplot = None

from pylearn2.datasets import norb

warnings.warn("This script is deprecated. Please use ./browse_norb.py "
              "instead. It is kept around as a tester for deprecated class "
              "datasets.norb.SmallNORB",
              exceptions.DeprecationWarning)

def main():
    def parse_args():
        parser = argparse.ArgumentParser(
            description="Browser for SmallNORB dataset.")

        parser.add_argument('--which_set',
                            default='train',
                            help="'train', 'test', or the path to a .pkl file")

        parser.add_argument('--zca',
                            default=None,
                            help=("if --which_set points to a .pkl "
                                  "file storing a ZCA-preprocessed "
                                  "NORB dataset, you can optionally "
                                  "enter the preprocessor's .pkl "
                                  "file path here to undo the "
                                  "ZCA'ing for visualization "
                                  "purposes."))

        return parser.parse_args()

    def get_data(args):
        if args.which_set in ('train', 'test'):
            dataset = norb.SmallNORB(args.which_set, True)
        else:
            with open(args.which_set) as norb_file:
                dataset = pickle.load(norb_file)
                if len(dataset.y.shape) < 2 or dataset.y.shape[1] == 1:
                    print("This viewer does not support NORB datasets that "
                          "only have classification labels.")
                    sys.exit(1)

            if args.zca is not None:
                with open(args.zca) as zca_file:
                    zca = pickle.load(zca_file)
                    dataset.X = zca.inverse(dataset.X)

        num_examples = dataset.X.shape[0]

        topo_shape = ((num_examples, ) +
                      tuple(dataset.view_converter.shape))
        assert topo_shape[-1] == 1
        topo_shape = topo_shape[:-1]
        values = dataset.X.reshape(topo_shape)
        labels = numpy.array(dataset.y, 'int')
        return values, labels, dataset.which_set

    args = parse_args()
    values, labels, which_set = get_data(args)

    # For programming convenience, internally remap the instance labels to be
    # 0-4, and the azimuth labels to be 0-17. The user will still only see the
    # original, unmodified label values.

    instance_index = norb.SmallNORB.label_type_to_index['instance']

    def remap_instances(which_set, labels):
        if which_set == 'train':
            new_to_old_instance = [4, 6, 7, 8, 9]
        elif which_set == 'test':
            new_to_old_instance = [0, 1, 2, 3, 5]

        num_instances = len(new_to_old_instance)
        old_to_new_instance = numpy.ndarray(10, 'int')
        old_to_new_instance.fill(-1)
        old_to_new_instance[new_to_old_instance] = numpy.arange(num_instances)

        instance_slice = numpy.index_exp[:, instance_index]
        old_instances = labels[instance_slice]

        new_instances = old_to_new_instance[old_instances]
        labels[instance_slice] = new_instances

        azimuth_index = norb.SmallNORB.label_type_to_index['azimuth']
        azimuth_slice = numpy.index_exp[:, azimuth_index]
        labels[azimuth_slice] = labels[azimuth_slice] / 2

        return new_to_old_instance

    new_to_old_instance = remap_instances(which_set, labels)

    def get_new_azimuth_degrees(scalar_label):
        return 20 * scalar_label

    # Maps a label vector to the corresponding index in <values>
    num_labels_by_type = numpy.array(norb.SmallNORB.num_labels_by_type, 'int')
    num_labels_by_type[instance_index] = len(new_to_old_instance)

    label_to_index = numpy.ndarray(num_labels_by_type, 'int')
    label_to_index.fill(-1)

    for i, label in enumerate(labels):
        label_to_index[tuple(label)] = i

    assert not numpy.any(label_to_index == -1)  # all elements have been set

    figure, axes = pyplot.subplots(1, 2, squeeze=True)

    figure.canvas.set_window_title('Small NORB dataset (%sing set)' %
                                   which_set)

    # shift subplots down to make more room for the text
    figure.subplots_adjust(bottom=0.05)

    num_label_types = len(norb.SmallNORB.num_labels_by_type)
    current_labels = numpy.zeros(num_label_types, 'int')
    current_label_type = [0, ]

    label_text = figure.suptitle("title text",
                                 x=0.1,
                                 horizontalalignment="left")

    def redraw(redraw_text, redraw_images):
        if redraw_text:
            cl = current_labels

            lines = [
                'category: %s' % norb.SmallNORB.get_category(cl[0]),
                'instance: %d' % new_to_old_instance[cl[1]],
                'elevation: %d' % norb.SmallNORB.get_elevation_degrees(cl[2]),
                'azimuth: %d' % get_new_azimuth_degrees(cl[3]),
                'lighting: %d' % cl[4]]

            lt = current_label_type[0]
            lines[lt] = '==> ' + lines[lt]
            text = ('Up/down arrows choose label, left/right arrows change it'
                    '\n\n' +
                    '\n'.join(lines))
            label_text.set_text(text)

        if redraw_images:
            index = label_to_index[tuple(current_labels)]

            image_pair = values[index, :, :, :]
            for i in range(2):
                axes[i].imshow(image_pair[i, :, :], cmap='gray')

        figure.canvas.draw()

    def on_key_press(event):

        def add_mod(arg, step, size):
            return (arg + size + step) % size

        def incr_label_type(step):
            current_label_type[0] = add_mod(current_label_type[0],
                                            step,
                                            num_label_types)

        def incr_label(step):
            lt = current_label_type[0]
            num_labels = num_labels_by_type[lt]
            current_labels[lt] = add_mod(current_labels[lt], step, num_labels)

        if event.key == 'up':
            incr_label_type(-1)
            redraw(True, False)
        elif event.key == 'down':
            incr_label_type(1)
            redraw(True, False)
        elif event.key == 'left':
            incr_label(-1)
            redraw(True, True)
        elif event.key == 'right':
            incr_label(1)
            redraw(True, True)
        elif event.key == 'q':
            sys.exit(0)

    figure.canvas.mpl_connect('key_press_event', on_key_press)
    redraw(True, True)

    pyplot.show()

if __name__ == '__main__':
    main()


# coding=utf-8
import numpy as np
from scipy import integrate as intgrt
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from math import sqrt

# 计算半球的体积
def ballVolume():
	def halfBall(x, y):
		return sqrt(1 - x**2 - y**2)
	def halfCircle(x):
		return sqrt(1 - x**2)
	(vol, error) = intgrt.dblquad(halfBall, -1, 1, lambda x: -halfCircle(x), lambda x: halfCircle(x))
	print ("vol =", vol)

# 对常微分方程组积分
# 计算洛伦茨吸引子的轨迹
def LorenzAttactor():
	# 给出位置矢量 w 和三个参数 sigma rho beta 计算出速度矢量 dx dy dz
	def lorenz(w, t, sigma, rho, beta):
		 (x, y, z) = w.tolist()
		 return (sigma * (y - x), x * (rho - z), x * y - beta * z)
	t = np.arange(0, 20, 0.01) # 创建时间点
	# 调用 ode 对 lorenz 进行求解 用两个不同的初始值
	track1 = intgrt.odeint(lorenz, (0.0, 1.0, 0.0), t, args=(10.0, 28.0, 2.7))
	track2 = intgrt.odeint(lorenz, (0.0, 1.01, 0.0), t, args=(10.0, 28.0, 2.7))
	# 绘图
	fig = plt.figure()
	ax = Axes3D(fig)
	ax.plot(track1[:, 0], track1[:, 1], track1[:, 2], label="$y=1.0$")
	ax.plot(track2[:, 0], track2[:, 1], track2[:, 2], label="$y=1.01$")
	plt.legend(loc="best")
	plt.show()

# 质量-弹簧-阻尼系统
# Mx'' + bx' + kx = F
def msd(xu, t, M, k, b, F):
	(x, u) = xu.tolist()
	dx = u
	du = (F - k * x - b * u) / M
	return (dx, du)

def msdDemo():
	# 初始滑块在位移 x = -1.0 处 起始速度为 0 外部控制力恒为 1.0
	initxu = (-1.0, 0.0)
	(M, k, b, F) = (1.0, 0.5, 0.2, 1.0)
	t = np.arange(0, 40, 0.02)
	rst = intgrt.odeint(msd, initxu, t, args=(M, k, b, F))
	(fig, (ax1, ax2)) = plt.subplots(2, 1)
	ax1.plot(t, rst[:, 0], label=u"位移 x")
	ax2.plot(t, rst[:, 1], label=u"速度 u")
	ax1.legend(); ax2.legend()
	plt.show()

# 质量-弹簧-阻尼系统
class MassSpringDamper(object):
	def __init__(self, M, k, b, F):
		(self.M, self.k, self.b, self.F) = (M, k, b, F)

	# 求导函数
	def dee(self, t, xu):
		(x, u) = xu.tolist()
		dx = u
		du = (self.F - self.k * x - self.b * u) / self.M
		return [dx, du] # 要求返回列表而不是元组

# 采用 PID 控制器
class PID(object):
	def __init__(self, kp, ki, kd, dt):
		(self.kp, self.ki, self.kd, self.dt) = (kp, ki, kd, dt)
		self.lastErr = None
		self.x = 0.0
	def update(self, err):
		p = self.kp * err
		i = self.ki * self.x
		if self.lastErr is None:
			d = 0.0
		else:
			d = self.kd * (err - self.lastErr) / self.dt
		self.x += err * self.dt
		self.lastErr = err
		return p + i + d

# 控制外力 F 使滑块更迅速地停止在位移 2.0 处
def msdPID(kp, ki, kd, dt):
	stm = MassSpringDamper(M=1.0, k=0.5, b=0.2, F=1.0)
	initxu = (-1.0, 0.0)
	pid = PID(kp, ki, kd, dt)
	r = intgrt.ode(stm.dee)
	r.set_integrator("vode", method="bdf")
	r.set_initial_value(initxu, 0)
	t = list(); rst = list(); FArr = list()
	while (r.successful() and (r.t + dt < 3)):
		r.integrate(r.t + dt)
		t.append(r.t)
		rst.append(r.y)
		err = 2.0 - r.y[0]
		F = pid.update(err)
		stm.F = F
		FArr.append(F)
	rst = np.array(rst)
	t = np.array(t)
	FArr = np.array(FArr)
	(fig, (ax1, ax2, ax3)) = plt.subplots(3, 1)
	ax1.plot(t, rst[:, 0], label=u"位移 x")
	ax2.plot(t, rst[:, 1], label=u"速度 u")
	ax3.plot(t, FArr, label=u"控制力 F")
	ax1.legend(); ax2.legend(); ax3.legend()
	plt.show()

if (__name__ == "__main__"):
	# ballVolume()
	LorenzAttactor()
	# msdDemo()
	# msdPID(19.29, 1.41, 6.25, 0.02) # 最优的一组数


from __future__ import print_function
from __future__ import division
from future import standard_library
standard_library.install_aliases()
from builtins import range, zip
from past.utils import old_div
import urllib.parse

import future
import future.utils

import numpy as np
import pandas as pd
from pyquery import PyQuery as pq

import sportsref

class Season(future.utils.with_metaclass(sportsref.decorators.Cached, object)):

    """Object representing a given NBA season."""

    def __init__(self, year):
        """Initializes a Season object for an NBA season.

        :year: The year of the season we want.
        """
        self.yr = int(year)

    def __eq__(self, other):
        return (self.yr == other.yr)

    def __hash__(self):
        return hash(self.yr)

    def __repr__(self):
        return 'Season({})'.format(self.yr)

    def _subpage_url(self, page):
        return (sportsref.nba.BASE_URL +
                '/leagues/NBA_{}_{}.html'.format(self.yr, page))

    @sportsref.decorators.memoize
    def get_main_doc(self):
        """Returns PyQuery object for the main season URL.
        :returns: PyQuery object.
        """
        url = (sportsref.nba.BASE_URL +
               '/leagues/NBA_{}.html'.format(self.yr))
        return pq(sportsref.utils.get_html(url))

    @sportsref.decorators.memoize
    def get_sub_doc(self, subpage):
        """Returns PyQuery object for a given subpage URL.
        :subpage: The subpage of the season, e.g. 'per_game'.
        :returns: PyQuery object.
        """
        html = sportsref.utils.get_html(self._subpage_url(subpage))
        return pq(html)

    @sportsref.decorators.memoize
    def get_team_ids(self):
        """Returns a list of the team IDs for the given year.
        :returns: List of team IDs.
        """
        df = self.team_stats_per_game()
        if not df.empty:
            return df.index.tolist()
        else:
            print('ERROR: no teams found')
            return []

    @sportsref.decorators.memoize
    def team_ids_to_names(self):
        """Mapping from 3-letter team IDs to full team names.
        :returns: Dictionary with team IDs as keys and full team strings as
        values.
        """
        doc = self.get_main_doc()
        table = doc('table#team-stats-per_game')
        flattened = sportsref.utils.parse_table(table, flatten=True)
        unflattened = sportsref.utils.parse_table(table, flatten=False)
        team_ids = flattened['team_id']
        team_names = unflattened['team_name']
        if len(team_names) != len(team_ids):
            raise Exception("team names and team IDs don't align")
        return dict(zip(team_ids, team_names))

    @sportsref.decorators.memoize
    def team_names_to_ids(self):
        """Mapping from full team names to 3-letter team IDs.
        :returns: Dictionary with tean names as keys and team IDs as values.
        """
        d = self.team_ids_to_names()
        return {v: k for k, v in d.items()}

    @sportsref.decorators.memoize
    @sportsref.decorators.kind_rpb(include_type=True)
    def schedule(self, kind='R'):
        """Returns a list of BoxScore IDs for every game in the season.
        Only needs to handle 'R' or 'P' options because decorator handles 'B'.

        :param kind: 'R' for regular season, 'P' for playoffs, 'B' for both.
            Defaults to 'R'.
        :returns: DataFrame of schedule information.
        :rtype: pd.DataFrame
        """
        kind = kind.upper()[0]
        dfs = []

        # get games from each month
        for month in ('october', 'november', 'december', 'january', 'february',
                      'march', 'april', 'may', 'june'):
            try:
                doc = self.get_sub_doc('games-{}'.format(month))
            except ValueError:
                continue
            table = doc('table#schedule')
            df = sportsref.utils.parse_table(table)
            dfs.append(df)
        df = pd.concat(dfs).reset_index(drop=True)

        # figure out how many regular season games
        try:
            sportsref.utils.get_html('{}/playoffs/NBA_{}.html'.format(
                sportsref.nba.BASE_URL, self.yr)
            )
            is_past_season = True
        except ValueError:
            is_past_season = False

        if is_past_season:
            team_per_game = self.team_stats_per_game()
            n_reg_games = int(team_per_game.g.sum() // 2)
        else:
            n_reg_games = len(df)

        # subset appropriately based on `kind`
        if kind == 'P':
            return df.iloc[n_reg_games:]
        else:
            return df.iloc[:n_reg_games]

    def finals_winner(self):
        """Returns the team ID for the winner of that year's NBA Finals.
        :returns: 3-letter team ID for champ.
        """
        raise NotImplementedError('nba.Season.finals_winner')

    def finals_loser(self):
        """Returns the team ID for the loser of that year's NBA Finals.
        :returns: 3-letter team ID for runner-up.
        """
        raise NotImplementedError('nba.Season.finals_loser')

    def standings(self):
        """Returns a DataFrame containing standings information."""
        doc = self.get_sub_doc('standings')

        east_table = doc('table#divs_standings_E')
        east_df = pd.DataFrame(sportsref.utils.parse_table(east_table))
        east_df.sort_values('wins', ascending=False, inplace=True)
        east_df['seed'] = range(1, len(east_df) + 1)
        east_df['conference'] = 'E'

        west_table = doc('table#divs_standings_W')
        west_df = sportsref.utils.parse_table(west_table)
        west_df.sort_values('wins', ascending=False, inplace=True)
        west_df['seed'] = range(1, len(west_df) + 1)
        west_df['conference'] = 'W'

        full_df = pd.concat([east_df, west_df], axis=0).reset_index(drop=True)
        full_df['team_id'] = full_df.team_id.str.extract(r'(\w+)\W*\(\d+\)', expand=False)
        full_df['gb'] = [gb if isinstance(gb, int) or isinstance(gb, float) else 0
                         for gb in full_df['gb']]
        full_df = full_df.drop('has_class_full_table', axis=1)

        expanded_table = doc('table#expanded_standings')
        expanded_df = sportsref.utils.parse_table(expanded_table)

        full_df = pd.merge(full_df, expanded_df, on='team_id')
        return full_df

    @sportsref.decorators.memoize
    def _get_team_stats_table(self, selector):
        """Helper function for stats tables on season pages. Returns a
        DataFrame."""
        doc = self.get_main_doc()
        table = doc(selector)
        df = sportsref.utils.parse_table(table)
        df.set_index('team_id', inplace=True)
        return df

    def team_stats_per_game(self):
        """Returns a Pandas DataFrame of each team's basic per-game stats for
        the season."""
        return self._get_team_stats_table('table#team-stats-per_game')

    def opp_stats_per_game(self):
        """Returns a Pandas DataFrame of each team's opponent's basic per-game
        stats for the season."""
        return self._get_team_stats_table('table#opponent-stats-per_game')

    def team_stats_totals(self):
        """Returns a Pandas DataFrame of each team's basic stat totals for the
        season."""
        return self._get_team_stats_table('table#team-stats-base')

    def opp_stats_totals(self):
        """Returns a Pandas DataFrame of each team's opponent's basic stat
        totals for the season."""
        return self._get_team_stats_table('table#opponent-stats-base')

    def misc_stats(self):
        """Returns a Pandas DataFrame of miscellaneous stats about each team's
        season."""
        return self._get_team_stats_table('table#misc_stats')

    def team_stats_shooting(self):
        """Returns a Pandas DataFrame of each team's shooting stats for the
        season."""
        return self._get_team_stats_table('table#team_shooting')

    def opp_stats_shooting(self):
        """Returns a Pandas DataFrame of each team's opponent's shooting stats
        for the season."""
        return self._get_team_stats_table('table#opponent_shooting')

    @sportsref.decorators.memoize
    def _get_player_stats_table(self, identifier):
        """Helper function for player season stats.

        :identifier: string identifying the type of stat, e.g. 'per_game'.
        :returns: A DataFrame of stats.
        """
        doc = self.get_sub_doc(identifier)
        table = doc('table#{}_stats'.format(identifier))
        df = sportsref.utils.parse_table(table)
        return df

    def player_stats_per_game(self):
        """Returns a DataFrame of per-game player stats for a season."""
        return self._get_player_stats_table('per_game')

    def player_stats_totals(self):
        """Returns a DataFrame of player stat totals for a season."""
        return self._get_player_stats_table('totals')

    def player_stats_per36(self):
        """Returns a DataFrame of player per-36 min stats for a season."""
        return self._get_player_stats_table('per_minute')

    def player_stats_per100(self):
        """Returns a DataFrame of player per-100 poss stats for a season."""
        return self._get_player_stats_table('per_poss')

    def player_stats_advanced(self):
        """Returns a DataFrame of player per-100 poss stats for a season."""
        return self._get_player_stats_table('advanced')

    def mvp_voting(self):
        """Returns a DataFrame containing information about MVP voting."""
        raise NotImplementedError('nba.Season.mvp_voting')

    def roy_voting(self):
        """Returns a DataFrame containing information about ROY voting."""
        url = '{}/awards/awards_{}.html'.format(sportsref.nba.BASE_URL, self.yr)
        doc = pq(sportsref.utils.get_html(url))
        table = doc('table#roy')
        df = sportsref.utils.parse_table(table)
        return df


"""
Benchmark scikit-learn's Ward implement compared to SciPy's
"""

import time

import numpy as np
from scipy.cluster import hierarchy
import pylab as pl

from sklearn.cluster import AgglomerativeClustering

ward = AgglomerativeClustering(n_clusters=3, linkage='ward')

n_samples = np.logspace(.5, 3, 9)
n_features = np.logspace(1, 3.5, 7)
N_samples, N_features = np.meshgrid(n_samples,
                                    n_features)
scikits_time = np.zeros(N_samples.shape)
scipy_time = np.zeros(N_samples.shape)

for i, n in enumerate(n_samples):
    for j, p in enumerate(n_features):
        X = np.random.normal(size=(n, p))
        t0 = time.time()
        ward.fit(X)
        scikits_time[j, i] = time.time() - t0
        t0 = time.time()
        hierarchy.ward(X)
        scipy_time[j, i] = time.time() - t0

ratio = scikits_time / scipy_time

pl.figure("scikit-learn Ward's method benchmark results")
pl.imshow(np.log(ratio), aspect='auto', origin="lower")
pl.colorbar()
pl.contour(ratio, levels=[1, ], colors='k')
pl.yticks(range(len(n_features)), n_features.astype(np.int))
pl.ylabel('N features')
pl.xticks(range(len(n_samples)), n_samples.astype(np.int))
pl.xlabel('N samples')
pl.title("Scikit's time, in units of scipy time (log)")
pl.show()


#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

import base64
from distutils.version import LooseVersion
from io import BytesIO
import unittest

import pandas as pd
import numpy as np

from pyspark import pandas as ps
from pyspark.pandas.config import set_option, reset_option
from pyspark.testing.pandasutils import (
    have_matplotlib,
    matplotlib_requirement_message,
    PandasOnSparkTestCase,
    TestUtils,
)

if have_matplotlib:
    import matplotlib
    from matplotlib import pyplot as plt

    matplotlib.use("agg")

@unittest.skipIf(not have_matplotlib, matplotlib_requirement_message)
class DataFramePlotMatplotlibTest(PandasOnSparkTestCase, TestUtils):
    sample_ratio_default = None

    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        if LooseVersion(pd.__version__) >= LooseVersion("0.25"):
            pd.set_option("plotting.backend", "matplotlib")
        set_option("plotting.backend", "matplotlib")
        set_option("plotting.max_rows", 2000)
        set_option("plotting.sample_ratio", None)

    @classmethod
    def tearDownClass(cls):
        if LooseVersion(pd.__version__) >= LooseVersion("0.25"):
            pd.reset_option("plotting.backend")
        reset_option("plotting.backend")
        reset_option("plotting.max_rows")
        reset_option("plotting.sample_ratio")
        super().tearDownClass()

    @property
    def pdf1(self):
        return pd.DataFrame(
            {"a": [1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 50], "b": [2, 3, 4, 5, 7, 9, 10, 15, 34, 45, 49]},
            index=[0, 1, 3, 5, 6, 8, 9, 9, 9, 10, 10],
        )

    @property
    def psdf1(self):
        return ps.from_pandas(self.pdf1)

    @staticmethod
    def plot_to_base64(ax):
        bytes_data = BytesIO()
        ax.figure.savefig(bytes_data, format="png")
        bytes_data.seek(0)
        b64_data = base64.b64encode(bytes_data.read())
        plt.close(ax.figure)
        return b64_data

    def test_line_plot(self):
        def check_line_plot(pdf, psdf):
            ax1 = pdf.plot(kind="line", colormap="Paired")
            bin1 = self.plot_to_base64(ax1)
            ax2 = psdf.plot(kind="line", colormap="Paired")
            bin2 = self.plot_to_base64(ax2)
            self.assertEqual(bin1, bin2)

            ax3 = pdf.plot.line(colormap="Paired")
            bin3 = self.plot_to_base64(ax3)
            ax4 = psdf.plot.line(colormap="Paired")
            bin4 = self.plot_to_base64(ax4)
            self.assertEqual(bin3, bin4)

        pdf1 = self.pdf1
        psdf1 = self.psdf1
        check_line_plot(pdf1, psdf1)

        # multi-index columns
        columns = pd.MultiIndex.from_tuples([("x", "a"), ("y", "b")])
        pdf1.columns = columns
        psdf1.columns = columns
        check_line_plot(pdf1, psdf1)

    def test_area_plot(self):
        def check_area_plot(pdf, psdf):
            ax1 = pdf.plot(kind="area", colormap="Paired")
            bin1 = self.plot_to_base64(ax1)
            ax2 = psdf.plot(kind="area", colormap="Paired")
            bin2 = self.plot_to_base64(ax2)
            self.assertEqual(bin1, bin2)

            ax3 = pdf.plot.area(colormap="Paired")
            bin3 = self.plot_to_base64(ax3)
            ax4 = psdf.plot.area(colormap="Paired")
            bin4 = self.plot_to_base64(ax4)
            self.assertEqual(bin3, bin4)

        pdf = self.pdf1
        psdf = self.psdf1
        check_area_plot(pdf, psdf)

        # multi-index columns
        columns = pd.MultiIndex.from_tuples([("x", "a"), ("y", "b")])
        pdf.columns = columns
        psdf.columns = columns
        check_area_plot(pdf, psdf)

    def test_area_plot_stacked_false(self):
        def check_area_plot_stacked_false(pdf, psdf):
            ax1 = pdf.plot.area(stacked=False)
            bin1 = self.plot_to_base64(ax1)
            ax2 = psdf.plot.area(stacked=False)
            bin2 = self.plot_to_base64(ax2)
            self.assertEqual(bin1, bin2)

            # test if frame area plot is correct when stacked=False because default is True

        pdf = pd.DataFrame(
            {
                "sales": [3, 2, 3, 9, 10, 6],
                "signups": [5, 5, 6, 12, 14, 13],
                "visits": [20, 42, 28, 62, 81, 50],
            },
            index=pd.date_range(start="2018/01/01", end="2018/07/01", freq="M"),
        )
        psdf = ps.from_pandas(pdf)
        check_area_plot_stacked_false(pdf, psdf)

        # multi-index columns
        columns = pd.MultiIndex.from_tuples([("x", "sales"), ("x", "signups"), ("y", "visits")])
        pdf.columns = columns
        psdf.columns = columns
        check_area_plot_stacked_false(pdf, psdf)

    def test_area_plot_y(self):
        def check_area_plot_y(pdf, psdf, y):
            ax1 = pdf.plot.area(y=y)
            bin1 = self.plot_to_base64(ax1)
            ax2 = psdf.plot.area(y=y)
            bin2 = self.plot_to_base64(ax2)
            self.assertEqual(bin1, bin2)

        # test if frame area plot is correct when y is specified
        pdf = pd.DataFrame(
            {
                "sales": [3, 2, 3, 9, 10, 6],
                "signups": [5, 5, 6, 12, 14, 13],
                "visits": [20, 42, 28, 62, 81, 50],
            },
            index=pd.date_range(start="2018/01/01", end="2018/07/01", freq="M"),
        )
        psdf = ps.from_pandas(pdf)
        check_area_plot_y(pdf, psdf, y="sales")

        # multi-index columns
        columns = pd.MultiIndex.from_tuples([("x", "sales"), ("x", "signups"), ("y", "visits")])
        pdf.columns = columns
        psdf.columns = columns
        check_area_plot_y(pdf, psdf, y=("x", "sales"))

    def test_barh_plot_with_x_y(self):
        def check_barh_plot_with_x_y(pdf, psdf, x, y):
            ax1 = pdf.plot(kind="barh", x=x, y=y, colormap="Paired")
            bin1 = self.plot_to_base64(ax1)
            ax2 = psdf.plot(kind="barh", x=x, y=y, colormap="Paired")
            bin2 = self.plot_to_base64(ax2)
            self.assertEqual(bin1, bin2)

            ax3 = pdf.plot.barh(x=x, y=y, colormap="Paired")
            bin3 = self.plot_to_base64(ax3)
            ax4 = psdf.plot.barh(x=x, y=y, colormap="Paired")
            bin4 = self.plot_to_base64(ax4)
            self.assertEqual(bin3, bin4)

        # this is testing plot with specified x and y
        pdf1 = pd.DataFrame({"lab": ["A", "B", "C"], "val": [10, 30, 20]})
        psdf1 = ps.from_pandas(pdf1)
        check_barh_plot_with_x_y(pdf1, psdf1, x="lab", y="val")

        # multi-index columns
        columns = pd.MultiIndex.from_tuples([("x", "lab"), ("y", "val")])
        pdf1.columns = columns
        psdf1.columns = columns
        check_barh_plot_with_x_y(pdf1, psdf1, x=("x", "lab"), y=("y", "val"))

    def test_barh_plot(self):
        def check_barh_plot(pdf, psdf):
            ax1 = pdf.plot(kind="barh", colormap="Paired")
            bin1 = self.plot_to_base64(ax1)
            ax2 = psdf.plot(kind="barh", colormap="Paired")
            bin2 = self.plot_to_base64(ax2)
            self.assertEqual(bin1, bin2)

            ax3 = pdf.plot.barh(colormap="Paired")
            bin3 = self.plot_to_base64(ax3)
            ax4 = psdf.plot.barh(colormap="Paired")
            bin4 = self.plot_to_base64(ax4)
            self.assertEqual(bin3, bin4)

        # this is testing when x or y is not assigned
        pdf1 = pd.DataFrame({"lab": ["A", "B", "C"], "val": [10, 30, 20]})
        psdf1 = ps.from_pandas(pdf1)
        check_barh_plot(pdf1, psdf1)

        # multi-index columns
        columns = pd.MultiIndex.from_tuples([("x", "lab"), ("y", "val")])
        pdf1.columns = columns
        psdf1.columns = columns
        check_barh_plot(pdf1, psdf1)

    def test_bar_plot(self):
        def check_bar_plot(pdf, psdf):
            ax1 = pdf.plot(kind="bar", colormap="Paired")
            bin1 = self.plot_to_base64(ax1)
            ax2 = psdf.plot(kind="bar", colormap="Paired")
            bin2 = self.plot_to_base64(ax2)
            self.assertEqual(bin1, bin2)

            ax3 = pdf.plot.bar(colormap="Paired")
            bin3 = self.plot_to_base64(ax3)
            ax4 = psdf.plot.bar(colormap="Paired")
            bin4 = self.plot_to_base64(ax4)
            self.assertEqual(bin3, bin4)

        pdf1 = self.pdf1
        psdf1 = self.psdf1
        check_bar_plot(pdf1, psdf1)

        # multi-index columns
        columns = pd.MultiIndex.from_tuples([("x", "lab"), ("y", "val")])
        pdf1.columns = columns
        psdf1.columns = columns
        check_bar_plot(pdf1, psdf1)

    def test_bar_with_x_y(self):
        # this is testing plot with specified x and y
        pdf = pd.DataFrame({"lab": ["A", "B", "C"], "val": [10, 30, 20]})
        psdf = ps.from_pandas(pdf)

        ax1 = pdf.plot(kind="bar", x="lab", y="val", colormap="Paired")
        bin1 = self.plot_to_base64(ax1)
        ax2 = psdf.plot(kind="bar", x="lab", y="val", colormap="Paired")
        bin2 = self.plot_to_base64(ax2)
        self.assertEqual(bin1, bin2)

        ax3 = pdf.plot.bar(x="lab", y="val", colormap="Paired")
        bin3 = self.plot_to_base64(ax3)
        ax4 = psdf.plot.bar(x="lab", y="val", colormap="Paired")
        bin4 = self.plot_to_base64(ax4)
        self.assertEqual(bin3, bin4)

        # multi-index columns
        columns = pd.MultiIndex.from_tuples([("x", "lab"), ("y", "val")])
        pdf.columns = columns
        psdf.columns = columns

        ax5 = pdf.plot(kind="bar", x=("x", "lab"), y=("y", "val"), colormap="Paired")
        bin5 = self.plot_to_base64(ax5)
        ax6 = psdf.plot(kind="bar", x=("x", "lab"), y=("y", "val"), colormap="Paired")
        bin6 = self.plot_to_base64(ax6)
        self.assertEqual(bin5, bin6)

        ax7 = pdf.plot.bar(x=("x", "lab"), y=("y", "val"), colormap="Paired")
        bin7 = self.plot_to_base64(ax7)
        ax8 = psdf.plot.bar(x=("x", "lab"), y=("y", "val"), colormap="Paired")
        bin8 = self.plot_to_base64(ax8)
        self.assertEqual(bin7, bin8)

    def test_pie_plot(self):
        def check_pie_plot(pdf, psdf, y):
            ax1 = pdf.plot.pie(y=y, figsize=(5, 5), colormap="Paired")
            bin1 = self.plot_to_base64(ax1)
            ax2 = psdf.plot.pie(y=y, figsize=(5, 5), colormap="Paired")
            bin2 = self.plot_to_base64(ax2)
            self.assertEqual(bin1, bin2)

            ax1 = pdf.plot(kind="pie", y=y, figsize=(5, 5), colormap="Paired")
            bin1 = self.plot_to_base64(ax1)
            ax2 = psdf.plot(kind="pie", y=y, figsize=(5, 5), colormap="Paired")
            bin2 = self.plot_to_base64(ax2)
            self.assertEqual(bin1, bin2)

            ax11, ax12 = pdf.plot.pie(figsize=(5, 5), subplots=True, colormap="Paired")
            bin11 = self.plot_to_base64(ax11)
            bin12 = self.plot_to_base64(ax12)
            self.assertEqual(bin11, bin12)

            ax21, ax22 = psdf.plot.pie(figsize=(5, 5), subplots=True, colormap="Paired")
            bin21 = self.plot_to_base64(ax21)
            bin22 = self.plot_to_base64(ax22)
            self.assertEqual(bin21, bin22)

            ax11, ax12 = pdf.plot(kind="pie", figsize=(5, 5), subplots=True, colormap="Paired")
            bin11 = self.plot_to_base64(ax11)
            bin12 = self.plot_to_base64(ax12)
            self.assertEqual(bin11, bin12)

            ax21, ax22 = psdf.plot(kind="pie", figsize=(5, 5), subplots=True, colormap="Paired")
            bin21 = self.plot_to_base64(ax21)
            bin22 = self.plot_to_base64(ax22)
            self.assertEqual(bin21, bin22)

        pdf1 = pd.DataFrame(
            {"mass": [0.330, 4.87, 5.97], "radius": [2439.7, 6051.8, 6378.1]},
            index=["Mercury", "Venus", "Earth"],
        )
        psdf1 = ps.from_pandas(pdf1)
        check_pie_plot(pdf1, psdf1, y="mass")

        # multi-index columns
        columns = pd.MultiIndex.from_tuples([("x", "mass"), ("y", "radius")])
        pdf1.columns = columns
        psdf1.columns = columns
        check_pie_plot(pdf1, psdf1, y=("x", "mass"))

    def test_pie_plot_error_message(self):
        # this is to test if error is correctly raising when y is not specified
        # and subplots is not set to True
        pdf = pd.DataFrame(
            {"mass": [0.330, 4.87, 5.97], "radius": [2439.7, 6051.8, 6378.1]},
            index=["Mercury", "Venus", "Earth"],
        )
        psdf = ps.from_pandas(pdf)

        with self.assertRaises(ValueError) as context:
            psdf.plot.pie(figsize=(5, 5), colormap="Paired")
        error_message = "pie requires either y column or 'subplots=True'"
        self.assertTrue(error_message in str(context.exception))

    def test_scatter_plot(self):
        def check_scatter_plot(pdf, psdf, x, y, c):
            ax1 = pdf.plot.scatter(x=x, y=y)
            bin1 = self.plot_to_base64(ax1)
            ax2 = psdf.plot.scatter(x=x, y=y)
            bin2 = self.plot_to_base64(ax2)
            self.assertEqual(bin1, bin2)

            ax1 = pdf.plot(kind="scatter", x=x, y=y)
            bin1 = self.plot_to_base64(ax1)
            ax2 = psdf.plot(kind="scatter", x=x, y=y)
            bin2 = self.plot_to_base64(ax2)
            self.assertEqual(bin1, bin2)

            # check when keyword c is given as name of a column
            ax1 = pdf.plot.scatter(x=x, y=y, c=c, s=50)
            bin1 = self.plot_to_base64(ax1)
            ax2 = psdf.plot.scatter(x=x, y=y, c=c, s=50)
            bin2 = self.plot_to_base64(ax2)
            self.assertEqual(bin1, bin2)

        # Use pandas scatter plot example
        pdf1 = pd.DataFrame(np.random.rand(50, 4), columns=["a", "b", "c", "d"])
        psdf1 = ps.from_pandas(pdf1)
        check_scatter_plot(pdf1, psdf1, x="a", y="b", c="c")

        # multi-index columns
        columns = pd.MultiIndex.from_tuples([("x", "a"), ("x", "b"), ("y", "c"), ("z", "d")])
        pdf1.columns = columns
        psdf1.columns = columns
        check_scatter_plot(pdf1, psdf1, x=("x", "a"), y=("x", "b"), c=("y", "c"))

    def test_hist_plot(self):
        def check_hist_plot(pdf, psdf):
            _, ax1 = plt.subplots(1, 1)
            ax1 = pdf.plot.hist()
            bin1 = self.plot_to_base64(ax1)
            _, ax2 = plt.subplots(1, 1)
            ax2 = psdf.plot.hist()
            bin2 = self.plot_to_base64(ax2)
            self.assertEqual(bin1, bin2)

            ax1 = pdf.plot.hist(bins=15)
            bin1 = self.plot_to_base64(ax1)
            ax2 = psdf.plot.hist(bins=15)
            bin2 = self.plot_to_base64(ax2)
            self.assertEqual(bin1, bin2)

            ax1 = pdf.plot(kind="hist", bins=15)
            bin1 = self.plot_to_base64(ax1)
            ax2 = psdf.plot(kind="hist", bins=15)
            bin2 = self.plot_to_base64(ax2)
            self.assertEqual(bin1, bin2)

            ax1 = pdf.plot.hist(bins=3, bottom=[2, 1, 3])
            bin1 = self.plot_to_base64(ax1)
            ax2 = psdf.plot.hist(bins=3, bottom=[2, 1, 3])
            bin2 = self.plot_to_base64(ax2)
            self.assertEqual(bin1, bin2)

            non_numeric_pdf = self.pdf1.copy()
            non_numeric_pdf.c = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]
            non_numeric_psdf = ps.from_pandas(non_numeric_pdf)
            ax1 = non_numeric_pdf.plot.hist(
                x=non_numeric_pdf.columns[0], y=non_numeric_pdf.columns[1], bins=3
            )
            bin1 = self.plot_to_base64(ax1)
            ax2 = non_numeric_psdf.plot.hist(
                x=non_numeric_pdf.columns[0], y=non_numeric_pdf.columns[1], bins=3
            )
            bin2 = self.plot_to_base64(ax2)
            self.assertEqual(bin1, bin2)

        pdf1 = self.pdf1
        psdf1 = self.psdf1
        check_hist_plot(pdf1, psdf1)

        # multi-index columns
        columns = pd.MultiIndex.from_tuples([("x", "a"), ("y", "b")])
        pdf1.columns = columns
        psdf1.columns = columns
        check_hist_plot(pdf1, psdf1)

    def test_kde_plot(self):
        def moving_average(a, n=10):
            ret = np.cumsum(a, dtype=float)
            ret[n:] = ret[n:] - ret[:-n]
            return ret[n - 1 :] / n

        def check_kde_plot(pdf, psdf, *args, **kwargs):
            _, ax1 = plt.subplots(1, 1)
            ax1 = pdf.plot.kde(*args, **kwargs)
            _, ax2 = plt.subplots(1, 1)
            ax2 = psdf.plot.kde(*args, **kwargs)

            try:
                for i, (line1, line2) in enumerate(zip(ax1.get_lines(), ax2.get_lines())):
                    expected = line1.get_xydata().ravel()
                    actual = line2.get_xydata().ravel()
                    # TODO: Due to implementation difference, the output is different comparing
                    # to pandas'. We should identify the root cause of difference, and reduce
                    # the diff.

                    # Note: Data is from 1 to 50. So, it smooths them by moving average and compares
                    # both.
                    self.assertTrue(
                        np.allclose(moving_average(actual), moving_average(expected), rtol=3.0)
                    )
            finally:
                ax1.cla()
                ax2.cla()

        pdf1 = self.pdf1
        psdf1 = self.psdf1
        check_kde_plot(pdf1, psdf1, bw_method=0.3)
        check_kde_plot(pdf1, psdf1, ind=[1, 2, 3], bw_method=3.0)

        # multi-index columns
        columns = pd.MultiIndex.from_tuples([("x", "a"), ("y", "b")])
        pdf1.columns = columns
        pdf1.columns = columns
        check_kde_plot(pdf1, psdf1, bw_method=0.3)
        check_kde_plot(pdf1, psdf1, ind=[1, 2, 3], bw_method=3.0)

if __name__ == "__main__":
    from pyspark.pandas.tests.plot.test_frame_plot_matplotlib import *  # noqa: F401

    try:
        import xmlrunner  # type: ignore[import]

        testRunner = xmlrunner.XMLTestRunner(output="target/test-reports", verbosity=2)
    except ImportError:
        testRunner = None
    unittest.main(testRunner=testRunner, verbosity=2)


"""Joblib is a set of tools to provide **lightweight pipelining in
Python**. In particular, joblib offers:

1. transparent disk-caching of the output values and lazy re-evaluation
   (memoize pattern)

2. easy simple parallel computing

3. logging and tracing of the execution

Joblib is optimized to be **fast** and **robust** in particular on large
data and has specific optimizations for `numpy` arrays. It is
**BSD-licensed**.

    ========================= ================================================
    **User documentation:**        http://pythonhosted.org/joblib

    **Download packages:**         http://pypi.python.org/pypi/joblib#downloads

    **Source code:**               http://github.com/joblib/joblib

    **Report issues:**             http://github.com/joblib/joblib/issues
    ========================= ================================================

Vision
--------

The vision is to provide tools to easily achieve better performance and
reproducibility when working with long running jobs.

 *  **Avoid computing twice the same thing**: code is rerun over an
    over, for instance when prototyping computational-heavy jobs (as in
    scientific development), but hand-crafted solution to alleviate this
    issue is error-prone and often leads to unreproducible results

 *  **Persist to disk transparently**: persisting in an efficient way
    arbitrary objects containing large data is hard. Using
    joblib's caching mechanism avoids hand-written persistence and
    implicitly links the file on disk to the execution context of
    the original Python object. As a result, joblib's persistence is
    good for resuming an application status or computational job, eg
    after a crash.

Joblib strives to address these problems while **leaving your code and
your flow control as unmodified as possible** (no framework, no new
paradigms).

Main features
------------------

1) **Transparent and fast disk-caching of output value:** a memoize or
   make-like functionality for Python functions that works well for
   arbitrary Python objects, including very large numpy arrays. Separate
   persistence and flow-execution logic from domain logic or algorithmic
   code by writing the operations as a set of steps with well-defined
   inputs and  outputs: Python functions. Joblib can save their
   computation to disk and rerun it only if necessary::

      >>> from sklearn.externals.joblib import Memory
      >>> mem = Memory(cachedir='/tmp/joblib')
      >>> import numpy as np
      >>> a = np.vander(np.arange(3)).astype(np.float)
      >>> square = mem.cache(np.square)
      >>> b = square(a)                                   # doctest: +ELLIPSIS
      ________________________________________________________________________________
      [Memory] Calling square...
      square(array([[ 0.,  0.,  1.],
             [ 1.,  1.,  1.],
             [ 4.,  2.,  1.]]))
      ___________________________________________________________square - 0...s, 0.0min

      >>> c = square(a)
      >>> # The above call did not trigger an evaluation

2) **Embarrassingly parallel helper:** to make it easy to write readable
   parallel code and debug it quickly::

      >>> from sklearn.externals.joblib import Parallel, delayed
      >>> from math import sqrt
      >>> Parallel(n_jobs=1)(delayed(sqrt)(i**2) for i in range(10))
      [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]

3) **Logging/tracing:** The different functionalities will
   progressively acquire better logging mechanism to help track what
   has been ran, and capture I/O easily. In addition, Joblib will
   provide a few I/O primitives, to easily define logging and
   display streams, and provide a way of compiling a report.
   We want to be able to quickly inspect what has been run.

4) **Fast compressed Persistence**: a replacement for pickle to work
   efficiently on Python objects containing large data (
   *joblib.dump* & *joblib.load* ).

..
    >>> import shutil ; shutil.rmtree('/tmp/joblib/')

"""

# PEP0440 compatible formatted version, see:
# https://www.python.org/dev/peps/pep-0440/
#
# Generic release markers:
# X.Y
# X.Y.Z # For bugfix releases
#
# Admissible pre-release markers:
# X.YaN # Alpha release
# X.YbN # Beta release
# X.YrcN # Release Candidate
# X.Y # Final release
#
# Dev branch marker is: 'X.Y.dev' or 'X.Y.devN' where N is an integer.
# 'X.Y.dev0' is the canonical version of 'X.Y.dev'
#
__version__ = '0.11'

from .memory import Memory, MemorizedResult
from .logger import PrintTime
from .logger import Logger
from .hashing import hash
from .numpy_pickle import dump
from .numpy_pickle import load
from .parallel import Parallel
from .parallel import delayed
from .parallel import cpu_count
from .parallel import register_parallel_backend
from .parallel import parallel_backend
from .parallel import effective_n_jobs

__all__ = ['Memory', 'MemorizedResult', 'PrintTime', 'Logger', 'hash', 'dump',
           'load', 'Parallel', 'delayed', 'cpu_count', 'effective_n_jobs',
           'register_parallel_backend', 'parallel_backend']


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from mpl_toolkits.axes_grid.parasite_axes import SubplotHost
from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as AA

def plot(srv_app, srv_lwip, cli_app, cli_lwip):

	#srv_app = {0:[],1:[],2:[]}
	#srv_lwip = {0:[],1:[],2:[]}
	#cli_app = {0:[],1:[],2:[]}
	#cli_lwip = {0:[],1:[],2:[]}

	O2lwip=cli_lwip[2]
	O2comp=cli_app[2]

	O1lwip=cli_lwip[1]
	O1comp=cli_app[1]

	O0lwip=cli_lwip[0]
	O0comp=cli_app[0]

	colorsred = ['brown', 'red', 'tomato', 'lightsalmon']
	colorsgreen = ['darkgreen', 'seagreen', 'limegreen', 'springgreen']
	colorsblue =['navy', 'blue', 'steelblue', 'lightsteelblue']

	hatches = ['//', '++', 'xxx',  'oo','\\\\\\', 'OO', '..' , '---', "**"]
	label_size=15
	font_size=15

	#client

	N = 3
	width = 0.25       # the width of the bars
	xtra_space = 0.02
	ind = np.arange(N) + 2 - (width*3+xtra_space*2)/2 # the x locations for the groups

	ind1 = np.arange(N) + 2 - (width*3+xtra_space*2)/2 # the x locations for the groups
	ind2 = np.arange(N) + 2+(N+1) - (width*3+xtra_space*2)/2 # the x locations for the groups
	ind3 = np.arange(N) + 2+N+1+N+1 - (width*3+xtra_space*2)/2 # the x locations for the groups
	ind = np.append(ind1, ind2)
	ind = np.append(ind, ind3)
	#ind = np.append(ind, ind4)
	#ind = np.append(ind, ind5)

	fig, ax = plt.subplots(2)

	a1 = ax[0].bar(ind, O2comp, width, color=[0,0.5,1])
	a2 = ax[0].bar(ind, O2lwip, width, fill=False, hatch=hatches[0], edgecolor=[0,0.5,1], bottom=O2comp)

	b1 = ax[0].bar(ind+ width + xtra_space, O1comp, width, color=[0,1,0.5])
	b2 = ax[0].bar(ind+ width + xtra_space, O1lwip, width, fill=False, hatch=hatches[0], edgecolor=[0,1,0.5], bottom=O1comp)

	c1 = ax[0].bar(ind+ 2*(width + xtra_space), O0comp, width, color=[1,0.5,0])
	c2 = ax[0].bar(ind+ 2*(width + xtra_space), O0lwip, width, fill=False, hatch=hatches[0], edgecolor=[1,0.5,0], bottom=O0comp)

	OLevel = ["O-0", "O-1", "O-2", "O-3"]
	channels = ["b@11Mbps", "g@9Mbps", "g@54Mbps"]
	duration_type = [" - lwIP", " - App."]
	legend_size=16
	plt.figlegend(
		    (
		     a1, a2,
		     b1, b2,
		     c1, c2
		    ),
		    (
			OLevel[2]+duration_type[1], OLevel[2]+duration_type[0],
			OLevel[1]+duration_type[1], OLevel[1]+duration_type[0],
			OLevel[0]+duration_type[1], OLevel[0]+duration_type[0]
		    ),
		   scatterpoints=1,
		   loc='upper center',
		   ncol=3,
		   prop={'size':legend_size})

	xticks = [ 2, 2.9, 3, 4,    6, 6.9, 7, 8,    10, 10.9, 11, 12]
	xticks_minor = [ 1,  5, 9, 13 ]#longer
	xlbls = [channels[0], '6-Cli.', channels[1], channels[2],
	channels[0], '4-Cli.', channels[1], channels[2],
	channels[0], '2-Cli.', channels[1], channels[2]]

	ax[0].set_xticks( xticks )
	ax[0].set_xticks( xticks_minor, minor=True )
	ax[0].set_xticklabels( xlbls )
	ax[0].set_xlim( 1, 13 )

	ax[0].grid( 'off', axis='x' )
	ax[0].grid( 'off', axis='x', which='minor' )

	# vertical alignment of xtick labels
	va = [ 0, -.1, 0, 0,   0, -.1, 0, 0,  0, -.1, 0, 0]
	for t, y in zip( ax[0].get_xticklabels( ), va ):
	    t.set_y( y )

	ax[0].tick_params( axis='x', which='minor', direction='out', length=40 , top='off')
	#ax.tick_params( axis='x', which='major', direction='out', length=10 )
	ax[0].tick_params( axis='x', which='major', bottom='off', top='off' )
	vals = ax[0].get_yticks()
	ax[0].set_yticklabels(['{:3.0f}%'.format(x*100) for x in vals])

	#server

	O2lwip=srv_lwip[2]
	O2comp=srv_app[2]

	O1lwip=srv_lwip[1]
	O1comp=srv_app[1]

	O0lwip=srv_lwip[0]
	O0comp=srv_app[0]

	a1 = ax[1].bar(ind, O2comp, width, color=[0,0.5,1])
	a2 = ax[1].bar(ind, O2lwip, width, fill=False, hatch=hatches[0], edgecolor=[0,0.5,1], bottom=O2comp)

	b1 = ax[1].bar(ind+ width + xtra_space, O1comp, width, color=[0,1,0.5])
	b2 = ax[1].bar(ind+ width + xtra_space, O1lwip, width, fill=False, hatch=hatches[0], edgecolor=[0,1,0.5], bottom=O1comp)

	c1 = ax[1].bar(ind+ 2*(width + xtra_space), O0comp, width, color=[1,0.5,0])
	c2 = ax[1].bar(ind+ 2*(width + xtra_space), O0lwip, width, fill=False, hatch=hatches[0], edgecolor=[1,0.5,0], bottom=O0comp)

	channels = ["b@11Mbps", "g@9Mbps", "g@54Mbps"]
	duration_type = [" - Communication", " - Computation"]

	xticks = [ 2, 2.9, 3, 4,    6, 6.9, 7, 8,    10, 10.9, 11, 12]
	xticks_minor = [ 1,  5, 9, 13 ]#longer
	xlbls = [channels[0], '6-Cli.', channels[1], channels[2],
	channels[0], '4-Cli.', channels[1], channels[2],
	channels[0], '2-Cli.', channels[1], channels[2]]

	ax[1].set_xticks( xticks )
	ax[1].set_xticks( xticks_minor, minor=True )
	ax[1].set_xticklabels( xlbls )
	ax[1].set_xlim( 1, 13 )

	ax[1].grid( 'off', axis='x' )
	ax[1].grid( 'off', axis='x', which='minor' )

	va = [ 0, -.1, 0, 0,   0, -.1, 0, 0,  0, -.1, 0, 0]
	for t, y in zip( ax[1].get_xticklabels( ), va ):
	    t.set_y( y )

	ax[1].tick_params( axis='x', which='minor', direction='out', length=40 , top='off')
	ax[1].tick_params( axis='x', which='major', bottom='off', top='off' )

	vals = ax[1].get_yticks()
	ax[1].set_yticklabels(['{:3.0f}%'.format(x*100) for x in vals])

	# add some text for labels, title and axes ticks
	ax[0].set_ylabel('Core Utilization', fontsize=label_size)
	ax[0].set_xlabel('Client', fontsize=label_size)
	ax[1].set_ylabel('Core Utilization', fontsize=label_size)
	ax[1].set_xlabel('Server', fontsize=label_size)

	ax[0].tick_params(axis='y', labelsize=font_size)
	ax[1].tick_params(axis='y', labelsize=font_size)
	ax[0].tick_params(axis='x', labelsize=font_size)
	ax[1].tick_params(axis='x', labelsize=font_size)

	plt.show()


'''Plot acf and pacf for some ARMA(1,1)

'''

from __future__ import print_function
import numpy as np
import matplotlib.pyplot as plt
import statsmodels.tsa.arima_process as tsp
from statsmodels.sandbox.tsa.fftarma import ArmaFft as FftArmaProcess
import statsmodels.tsa.stattools as tss
from statsmodels.graphics.tsaplots import plotacf

np.set_printoptions(precision=2)

arcoefs = [0.9, 0., -0.5] #[0.9, 0.5, 0.1, 0., -0.5]
macoefs = [0.9, 0., -0.5] #[0.9, 0.5, 0.1, 0., -0.5]
nsample = 1000
nburnin = 1000
sig = 1

fig = plt.figure(figsize=(8, 13))
fig.suptitle('ARMA: Autocorrelation (left) and Partial Autocorrelation (right)')
subplotcount = 1
nrows = 4
for arcoef in arcoefs[:-1]:
    for macoef in macoefs[:-1]:
        ar = np.r_[1., -arcoef]
        ma = np.r_[1.,  macoef]

        #y = tsp.arma_generate_sample(ar,ma,nsample, sig, burnin)
        #armaprocess = FftArmaProcess(ar, ma, nsample) #TODO: make n optional
        #armaprocess.plot4()
        armaprocess = tsp.ArmaProcess(ar, ma)
        acf = armaprocess.acf(20)[:20]
        pacf = armaprocess.pacf(20)[:20]
        ax = fig.add_subplot(nrows, 2, subplotcount)
        plotacf(acf, ax=ax)
##        ax.set_title('Autocorrelation \nar=%s, ma=%rs' % (ar, ma),
##                     size='xx-small')
        ax.text(0.7, 0.6, 'ar =%s \nma=%s' % (ar, ma),
                transform=ax.transAxes,
                horizontalalignment='left', #'right',
                size='xx-small')
        ax.set_xlim(-1,20)
        subplotcount +=1
        ax = fig.add_subplot(nrows, 2, subplotcount)
        plotacf(pacf, ax=ax)
##        ax.set_title('Partial Autocorrelation \nar=%s, ma=%rs' % (ar, ma),
##                     size='xx-small')
        ax.text(0.7, 0.6, 'ar =%s \nma=%s' % (ar, ma),
                transform=ax.transAxes,
                horizontalalignment='left', #'right',
                size='xx-small')
        ax.set_xlim(-1,20)
        subplotcount +=1

axs = fig.axes
### turn of the 2nd column y tick labels
##for ax in axs[1::2]:#[:,1].flat:
##   for label in ax.get_yticklabels(): label.set_visible(False)

# turn off all but the bottom xtick labels
for ax in axs[:-2]:#[:-1,:].flat:
   for label in ax.get_xticklabels(): label.set_visible(False)

# use a MaxNLocator on the first column y axis if you have a bunch of
# rows to avoid bunching; example below uses at most 3 ticks
import matplotlib.ticker as mticker
for ax in axs: #[::2]:#[:,1].flat:
   ax.yaxis.set_major_locator( mticker.MaxNLocator(3 ))

plt.show()


import itertools
import json
import matplotlib.pyplot as plt
from matplotlib import style
import os
style.use('ggplot')
import numpy as np
from pprint import pprint
from os.path import basename

xrange=range

class PsoTools(object):
	def __init__(self):
		pass

	# Convert a data raw file to a json file
	def rawToJson(self, inputFilePath, outputFilePath):

		inFile = open(inputFilePath, mode='r')
		outFile = open(outputFilePath, mode='w')
		meta_data = dict.fromkeys(['nb_customers', 'nb_depots',
		'vehicle_cap', 'vehicle_cost', 'cost_type'])
		cust_dict = dict.fromkeys(['x', 'y', 'demand'])
		dep_dict = dict.fromkeys(['x', 'y', 'capacity'])
		customers = {}
		depots = {}

		# Number of customers and available depots
		nb_customers = int(inFile.readline())
		nb_depots = int(inFile.readline())
		meta_data['nb_customers'] = nb_customers
		meta_data['nb_depots'] = nb_depots
		inFile.readline()	# Empty line

		# Depots cordinates
		for i, line in enumerate(inFile):
			if i < nb_depots:
				x = float(line.split()[0])
				y = float(line.split()[1])
				depots['d'+str(i)] = {}
				depots['d'+str(i)]['x'] = x
				depots['d'+str(i)]['y'] = y
			else:
				i=i-1
				break

		# Customers cordinates and vehicule capacity
		for i, line in enumerate(inFile):
			if i < nb_customers:
				x = float(line.split()[0])
				y = float(line.split()[1])
				customers['c'+str(i)] = {}
				customers['c'+str(i)]['x'] = x
				customers['c'+str(i)]['y'] = y
			else:
				break

		# Vehicules and depots capacity
		for i, line in enumerate(inFile):
			if i == 0:
				vehicle_cap = float(line)
				meta_data['vehicle_cap'] = vehicle_cap
			elif i == 1:
				pass
			elif i < nb_depots+2:
				depot_cap = float(line)
				depots['d'+str(i-2)]['capacity'] = depot_cap
			else:
				break

		# Customers demands
		for i, line in enumerate(inFile):
			if i < nb_customers:
				demand = float(line)
				customers['c'+str(i)]['demand'] = demand
			else:
				break

		# Depots openning costs
		for i, line in enumerate(inFile):
			if i < nb_depots:
				openning_cost = float(line)
				depots['d'+str(i)]['opening_cost'] = openning_cost
			elif i == nb_depots:
				pass
			elif i == nb_depots+1:
				vehicle_cost = float(line)
				meta_data['vehicle_cost'] = vehicle_cost
			elif i == nb_depots+2:
				pass
			elif i == nb_depots+3:
				cost_type = float(line)
				meta_data['cost_type'] = cost_type
			else:
				break

		final_output = {}
		final_output['customers'] = customers
		final_output['depots'] = depots
		final_output['meta_data'] = meta_data

		json.dump(final_output, outFile, indent=4)
		inFile.close()
		outFile.close()

	# Plot the customers on the map
	def plotCustomers(self, jsonInputFile):

		if os.path.isfile(jsonInputFile):

			with open(jsonInputFile) as data_file:
				data = json.load(data_file)

			nb_customers = data['meta_data']['nb_customers']
			coords_cust = np.zeros(shape=(nb_customers,2))

			for i in xrange(nb_customers):
				x = data['customers']['c{0}'.format(i)]['x']
				y = data['customers']['c{0}'.format(i)]['y']
				coords_cust[i] = [x,y]

			plt.scatter(coords_cust[:,0], coords_cust[:,1], marker='P', s=10, linewidth=5)
			plt.show()

	# Plot the depots on the map
	def plotDepots(self, jsonInputFile):

		if os.path.isfile(jsonInputFile):

			with open(jsonInputFile) as data_file:
				data = json.load(data_file)

			nb_depots = data['meta_data']['nb_depots']
			coords_depot = np.zeros(shape=(nb_depots,2))

			for i in xrange(nb_depots):
				x = data['depots']['d{0}'.format(i)]['x']
				y = data['depots']['d{0}'.format(i)]['y']
				coords_depot[i] = [x,y]

			plt.scatter(coords_depot[:,0], coords_depot[:,1], marker='P', s=10, linewidth=5)
			plt.show()

	# Plot both depots and customers on the map
	def plotAll(self, jsonInputFile):

		if os.path.isfile(jsonInputFile):

			with open(jsonInputFile) as data_file:
				data = json.load(data_file)

			nb_customers = data['meta_data']['nb_customers']
			nb_depots = data['meta_data']['nb_depots']
			coords_cust = np.zeros(shape=(nb_customers,2))
			coords_depot = np.zeros(shape=(nb_depots,2))

			for i in xrange(nb_customers):
				x = data['customers']['c{0}'.format(i)]['x']
				y = data['customers']['c{0}'.format(i)]['y']
				coords_cust[i] = [x,y]

			for i in xrange(nb_depots):
				x = data['depots']['d{0}'.format(i)]['x']
				y = data['depots']['d{0}'.format(i)]['y']
				coords_depot[i] = [x,y]

			filename = str(basename(os.path.splitext(jsonInputFile)[0]) + '.pdf')

			plt.scatter(coords_cust[:,0], coords_cust[:,1], marker='s', s=10, linewidth=5)
			plt.scatter(coords_depot[:,0], coords_depot[:,1], marker='8', s=10, linewidth=5)
			plt.savefig(filename, format='pdf')
			#~ plt.show()


"""Timeseries plotting functions."""
from __future__ import division
import numpy as np
import pandas as pd
from scipy import stats, interpolate
import matplotlib as mpl
import matplotlib.pyplot as plt

from .external.six import string_types

from . import utils
from . import algorithms as algo
from .palettes import color_palette

def tsplot(data, time=None, unit=None, condition=None, value=None,
           err_style="ci_band", ci=68, interpolate=True, color=None,
           estimator=np.mean, n_boot=5000, err_palette=None, err_kws=None,
           legend=True, ax=None, **kwargs):
    """Plot one or more timeseries with flexible representation of uncertainty.

    This function is intended to be used with data where observations are
    nested within sampling units that were measured at multiple timepoints.

    It can take data specified either as a long-form (tidy) DataFrame or as an
    ndarray with dimensions (unit, time) The interpretation of some of the
    other parameters changes depending on the type of object passed as data.

    Parameters
    ----------
    data : DataFrame or ndarray
        Data for the plot. Should either be a "long form" dataframe or an
        array with dimensions (unit, time, condition). In both cases, the
        condition field/dimension is optional. The type of this argument
        determines the interpretation of the next few parameters. When
        using a DataFrame, the index has to be sequential.
    time : string or series-like
        Either the name of the field corresponding to time in the data
        DataFrame or x values for a plot when data is an array. If a Series,
        the name will be used to label the x axis.
    unit : string
        Field in the data DataFrame identifying the sampling unit (e.g.
        subject, neuron, etc.). The error representation will collapse over
        units at each time/condition observation. This has no role when data
        is an array.
    value : string
        Either the name of the field corresponding to the data values in
        the data DataFrame (i.e. the y coordinate) or a string that forms
        the y axis label when data is an array.
    condition : string or Series-like
        Either the name of the field identifying the condition an observation
        falls under in the data DataFrame, or a sequence of names with a length
        equal to the size of the third dimension of data. There will be a
        separate trace plotted for each condition. If condition is a Series
        with a name attribute, the name will form the title for the plot
        legend (unless legend is set to False).
    err_style : string or list of strings or None
        Names of ways to plot uncertainty across units from set of
        {ci_band, ci_bars, boot_traces, boot_kde, unit_traces, unit_points}.
        Can use one or more than one method.
    ci : float or list of floats in [0, 100]
        Confidence interval size(s). If a list, it will stack the error
        plots for each confidence interval. Only relevant for error styles
        with "ci" in the name.
    interpolate : boolean
        Whether to do a linear interpolation between each timepoint when
        plotting. The value of this parameter also determines the marker
        used for the main plot traces, unless marker is specified as a keyword
        argument.
    color : seaborn palette or matplotlib color name or dictionary
        Palette or color for the main plots and error representation (unless
        plotting by unit, which can be separately controlled with err_palette).
        If a dictionary, should map condition name to color spec.
    estimator : callable
        Function to determine central tendency and to pass to bootstrap
        must take an ``axis`` argument.
    n_boot : int
        Number of bootstrap iterations.
    err_palette : seaborn palette
        Palette name or list of colors used when plotting data for each unit.
    err_kws : dict, optional
        Keyword argument dictionary passed through to matplotlib function
        generating the error plot,
    legend : bool, optional
        If ``True`` and there is a ``condition`` variable, add a legend to
        the plot.
    ax : axis object, optional
        Plot in given axis; if None creates a new figure
    kwargs :
        Other keyword arguments are passed to main plot() call

    Returns
    -------
    ax : matplotlib axis
        axis with plot data

    Examples
    --------

    Plot a trace with translucent confidence bands:

    .. plot::
        :context: close-figs

        >>> import numpy as np; np.random.seed(22)
        >>> import seaborn as sns; sns.set(color_codes=True)
        >>> x = np.linspace(0, 15, 31)
        >>> data = np.sin(x) + np.random.rand(10, 31) + np.random.randn(10, 1)
        >>> ax = sns.tsplot(data=data)

    Plot a long-form dataframe with several conditions:

    .. plot::
        :context: close-figs

        >>> gammas = sns.load_dataset("gammas")
        >>> ax = sns.tsplot(time="timepoint", value="BOLD signal",
        ...                 unit="subject", condition="ROI",
        ...                 data=gammas)

    Use error bars at the positions of the observations:

    .. plot::
        :context: close-figs

        >>> ax = sns.tsplot(data=data, err_style="ci_bars", color="g")

    Don't interpolate between the observations:

    .. plot::
        :context: close-figs

        >>> import matplotlib.pyplot as plt
        >>> ax = sns.tsplot(data=data, err_style="ci_bars", interpolate=False)

    Show multiple confidence bands:

    .. plot::
        :context: close-figs

        >>> ax = sns.tsplot(data=data, ci=[68, 95], color="m")

    Use a different estimator:

    .. plot::
        :context: close-figs

        >>> ax = sns.tsplot(data=data, estimator=np.median)

    Show each bootstrap resample:

    .. plot::
        :context: close-figs

        >>> ax = sns.tsplot(data=data, err_style="boot_traces", n_boot=500)

    Show the trace from each sampling unit:

    .. plot::
        :context: close-figs

        >>> ax = sns.tsplot(data=data, err_style="unit_traces")

    """
    # Sort out default values for the parameters
    if ax is None:
        ax = plt.gca()

    if err_kws is None:
        err_kws = {}

    # Handle different types of input data
    if isinstance(data, pd.DataFrame):

        xlabel = time
        ylabel = value

        # Condition is optional
        if condition is None:
            condition = pd.Series(np.ones(len(data)))
            legend = False
            legend_name = None
            n_cond = 1
        else:
            legend = True and legend
            legend_name = condition
            n_cond = len(data[condition].unique())

    else:
        data = np.asarray(data)

        # Data can be a timecourse from a single unit or
        # several observations in one condition
        if data.ndim == 1:
            data = data[np.newaxis, :, np.newaxis]
        elif data.ndim == 2:
            data = data[:, :, np.newaxis]
        n_unit, n_time, n_cond = data.shape

        # Units are experimental observations. Maybe subjects, or neurons
        if unit is None:
            units = np.arange(n_unit)
        unit = "unit"
        units = np.repeat(units, n_time * n_cond)
        ylabel = None

        # Time forms the xaxis of the plot
        if time is None:
            times = np.arange(n_time)
        else:
            times = np.asarray(time)
        xlabel = None
        if hasattr(time, "name"):
            xlabel = time.name
        time = "time"
        times = np.tile(np.repeat(times, n_cond), n_unit)

        # Conditions split the timeseries plots
        if condition is None:
            conds = range(n_cond)
            legend = False
            if isinstance(color, dict):
                err = "Must have condition names if using color dict."
                raise ValueError(err)
        else:
            conds = np.asarray(condition)
            legend = True and legend
            if hasattr(condition, "name"):
                legend_name = condition.name
            else:
                legend_name = None
        condition = "cond"
        conds = np.tile(conds, n_unit * n_time)

        # Value forms the y value in the plot
        if value is None:
            ylabel = None
        else:
            ylabel = value
        value = "value"

        # Convert to long-form DataFrame
        data = pd.DataFrame(dict(value=data.ravel(),
                                 time=times,
                                 unit=units,
                                 cond=conds))

    # Set up the err_style and ci arguments for the loop below
    if isinstance(err_style, string_types):
        err_style = [err_style]
    elif err_style is None:
        err_style = []
    if not hasattr(ci, "__iter__"):
        ci = [ci]

    # Set up the color palette
    if color is None:
        current_palette = utils.get_color_cycle()
        if len(current_palette) < n_cond:
            colors = color_palette("husl", n_cond)
        else:
            colors = color_palette(n_colors=n_cond)
    elif isinstance(color, dict):
        colors = [color[c] for c in data[condition].unique()]
    else:
        try:
            colors = color_palette(color, n_cond)
        except ValueError:
            color = mpl.colors.colorConverter.to_rgb(color)
            colors = [color] * n_cond

    # Do a groupby with condition and plot each trace
    for c, (cond, df_c) in enumerate(data.groupby(condition, sort=False)):

        df_c = df_c.pivot(unit, time, value)
        x = df_c.columns.values.astype(np.float)

        # Bootstrap the data for confidence intervals
        boot_data = algo.bootstrap(df_c.values, n_boot=n_boot,
                                   axis=0, func=estimator)
        cis = [utils.ci(boot_data, v, axis=0) for v in ci]
        central_data = estimator(df_c.values, axis=0)

        # Get the color for this condition
        color = colors[c]

        # Use subroutines to plot the uncertainty
        for style in err_style:

            # Allow for null style (only plot central tendency)
            if style is None:
                continue

            # Grab the function from the global environment
            try:
                plot_func = globals()["_plot_%s" % style]
            except KeyError:
                raise ValueError("%s is not a valid err_style" % style)

            # Possibly set up to plot each observation in a different color
            if err_palette is not None and "unit" in style:
                orig_color = color
                color = color_palette(err_palette, len(df_c.values))

            # Pass all parameters to the error plotter as keyword args
            plot_kwargs = dict(ax=ax, x=x, data=df_c.values,
                               boot_data=boot_data,
                               central_data=central_data,
                               color=color, err_kws=err_kws)

            # Plot the error representation, possibly for multiple cis
            for ci_i in cis:
                plot_kwargs["ci"] = ci_i
                plot_func(**plot_kwargs)

            if err_palette is not None and "unit" in style:
                color = orig_color

        # Plot the central trace
        kwargs.setdefault("marker", "" if interpolate else "o")
        ls = kwargs.pop("ls", "-" if interpolate else "")
        kwargs.setdefault("linestyle", ls)
        label = cond if legend else "_nolegend_"
        ax.plot(x, central_data, color=color, label=label, **kwargs)

    # Pad the sides of the plot only when not interpolating
    ax.set_xlim(x.min(), x.max())
    x_diff = x[1] - x[0]
    if not interpolate:
        ax.set_xlim(x.min() - x_diff, x.max() + x_diff)

    # Add the plot labels
    if xlabel is not None:
        ax.set_xlabel(xlabel)
    if ylabel is not None:
        ax.set_ylabel(ylabel)
    if legend:
        ax.legend(loc=0, title=legend_name)

    return ax

# Subroutines for tsplot errorbar plotting
# ----------------------------------------

def _plot_ci_band(ax, x, ci, color, err_kws, **kwargs):
    """Plot translucent error bands around the central tendancy."""
    low, high = ci
    if "alpha" not in err_kws:
        err_kws["alpha"] = 0.2
    ax.fill_between(x, low, high, facecolor=color, **err_kws)

def _plot_ci_bars(ax, x, central_data, ci, color, err_kws, **kwargs):
    """Plot error bars at each data point."""
    for x_i, y_i, (low, high) in zip(x, central_data, ci.T):
        ax.plot([x_i, x_i], [low, high], color=color,
                solid_capstyle="round", **err_kws)

def _plot_boot_traces(ax, x, boot_data, color, err_kws, **kwargs):
    """Plot 250 traces from bootstrap."""
    err_kws.setdefault("alpha", 0.25)
    err_kws.setdefault("linewidth", 0.25)
    if "lw" in err_kws:
        err_kws["linewidth"] = err_kws.pop("lw")
    ax.plot(x, boot_data.T, color=color, label="_nolegend_", **err_kws)

def _plot_unit_traces(ax, x, data, ci, color, err_kws, **kwargs):
    """Plot a trace for each observation in the original data."""
    if isinstance(color, list):
        if "alpha" not in err_kws:
            err_kws["alpha"] = .5
        for i, obs in enumerate(data):
            ax.plot(x, obs, color=color[i], label="_nolegend_", **err_kws)
    else:
        if "alpha" not in err_kws:
            err_kws["alpha"] = .2
        ax.plot(x, data.T, color=color, label="_nolegend_", **err_kws)

def _plot_unit_points(ax, x, data, color, err_kws, **kwargs):
    """Plot each original data point discretely."""
    if isinstance(color, list):
        for i, obs in enumerate(data):
            ax.plot(x, obs, "o", color=color[i], alpha=0.8, markersize=4,
                    label="_nolegend_", **err_kws)
    else:
        ax.plot(x, data.T, "o", color=color, alpha=0.5, markersize=4,
                label="_nolegend_", **err_kws)

def _plot_boot_kde(ax, x, boot_data, color, **kwargs):
    """Plot the kernal density estimate of the bootstrap distribution."""
    kwargs.pop("data")
    _ts_kde(ax, x, boot_data, color, **kwargs)

def _plot_unit_kde(ax, x, data, color, **kwargs):
    """Plot the kernal density estimate over the sample."""
    _ts_kde(ax, x, data, color, **kwargs)

def _ts_kde(ax, x, data, color, **kwargs):
    """Upsample over time and plot a KDE of the bootstrap distribution."""
    kde_data = []
    y_min, y_max = data.min(), data.max()
    y_vals = np.linspace(y_min, y_max, 100)
    upsampler = interpolate.interp1d(x, data)
    data_upsample = upsampler(np.linspace(x.min(), x.max(), 100))
    for pt_data in data_upsample.T:
        pt_kde = stats.kde.gaussian_kde(pt_data)
        kde_data.append(pt_kde(y_vals))
    kde_data = np.transpose(kde_data)
    rgb = mpl.colors.ColorConverter().to_rgb(color)
    img = np.zeros((kde_data.shape[0], kde_data.shape[1], 4))
    img[:, :, :3] = rgb
    kde_data /= kde_data.max(axis=0)
    kde_data[kde_data > 1] = 1
    img[:, :, 3] = kde_data
    ax.imshow(img, interpolation="spline16", zorder=2,
              extent=(x.min(), x.max(), y_min, y_max),
              aspect="auto", origin="lower")


import pandas as pd
import pymongo
from bokeh.plotting import cursession, figure, output_server, push
from bokeh.models.formatters import DatetimeTickFormatter, PrintfTickFormatter
from bokeh.io import vplot
from bokeh import embed
from json import load
from urllib2 import urlopen
import time

client = pymongo.MongoClient()
db = client['bitmicro']
collection = db['btc_predictions']

def get_data():
    cursor = collection.find().limit(3*60*60).sort('_id', pymongo.DESCENDING)
    data = pd.DataFrame(list(cursor))
    data = data.set_index('_id')
    data = data.sort_index(ascending=True)
    timestamps = pd.to_datetime(data.index, unit='s').to_series()
    prices = data.price
    predictions = data.prediction*10000
    returns = (data.position*data.change).cumsum()*10000
    return timestamps, prices, predictions, returns

timestamps, prices, predictions, returns = get_data()
output_server('bitpredict_extended')

background = '#f2f2f2'
ylabel_standoff = 0
xformatter = DatetimeTickFormatter(formats=dict(hours=["%H:%M"]))
yformatter = PrintfTickFormatter(format="%8.1f")
p1 = figure(title=None,
            plot_width=750,
            plot_height=300,
            x_axis_type='datetime',
            min_border_top=10,
            min_border_bottom=33,
            background_fill=background,
            tools='',
            toolbar_location=None)
p1.line(x=timestamps,
        y=prices,
        name='prices',
        color='#4271ae',
        line_width=1,
        legend='Bitcoin Bid/Ask Midpoint',
        line_cap='round',
        line_join='round')
p1.legend.orientation = 'top_left'
p1.legend.border_line_color = background
p1.outline_line_color = None
p1.xgrid.grid_line_color = 'white'
p1.ygrid.grid_line_color = 'white'
p1.axis.axis_line_color = None
p1.axis.major_tick_line_color = None
p1.axis.minor_tick_line_color = None
p1.yaxis.axis_label = 'Price'
p1.yaxis.axis_label_standoff = ylabel_standoff
p1.xaxis.formatter = xformatter
p1.yaxis.formatter = PrintfTickFormatter(format='%8.2f')
p1.yaxis.major_label_text_font = 'courier'
p1.xaxis.major_label_text_font = 'courier'

p2 = figure(title=None,
            plot_width=750,
            plot_height=295,
            x_axis_type='datetime',
            min_border_top=5,
            min_border_bottom=33,
            background_fill=background,
            tools='',
            toolbar_location=None)
p2.line(x=timestamps,
        y=predictions,
        name='predictions',
        color='#c82829',
        line_width=1,
        legend='30 Second Prediction',
        line_cap='round',
        line_join='round')
p2.legend.orientation = 'top_left'
p2.legend.border_line_color = background
p2.outline_line_color = None
p2.xgrid.grid_line_color = 'white'
p2.ygrid.grid_line_color = 'white'
p2.axis.axis_line_color = None
p2.axis.major_tick_line_color = None
p2.axis.minor_tick_line_color = None
p2.yaxis.axis_label = 'Basis Points'
p2.yaxis.axis_label_standoff = ylabel_standoff
p2.xaxis.formatter = xformatter
p2.yaxis.formatter = yformatter
p2.yaxis.major_label_text_font = 'courier'
p2.xaxis.major_label_text_font = 'courier'
p2.x_range = p1.x_range

p3 = figure(title=None,
            plot_width=750,
            plot_height=320,
            x_axis_type='datetime',
            min_border_top=5,
            min_border_bottom=10,
            background_fill=background,
            x_axis_label='Greenwich Mean Time',
            tools='',
            toolbar_location=None)
p3.line(x=timestamps,
        y=returns,
        name='returns',
        color='#8959a8',
        line_width=1,
        legend='Cumulative Return',
        line_cap='round',
        line_join='round')
p3.legend.orientation = 'top_left'
p3.legend.border_line_color = background
p3.outline_line_color = None
p3.xgrid.grid_line_color = 'white'
p3.ygrid.grid_line_color = 'white'
p3.axis.axis_line_color = None
p3.axis.major_tick_line_color = None
p3.axis.minor_tick_line_color = None
p3.yaxis.axis_label = 'Basis Points'
p3.yaxis.axis_label_standoff = ylabel_standoff
p3.xaxis.formatter = xformatter
p3.yaxis.formatter = yformatter
p3.xaxis.axis_label_standoff = 12
p3.yaxis.major_label_text_font = 'courier'
p3.xaxis.major_label_text_font = 'courier'
p3.x_range = p1.x_range

vp = vplot(p1, p2, p3)
push()
ip = load(urlopen('http://jsonip.com'))['ip']
ssn = cursession()
ssn.publish()
tag = embed.autoload_server(vp, ssn, public=True).replace('localhost', ip)
html = """
{%% extends "layout.html" %%}
{%% block bokeh %%}
%s
{%% endblock %%}
""" % tag
with open('templates/extended.html', 'w+') as f:
    f.write(html)

renderer = p1.select(dict(name='prices'))
ds_prices = renderer[0].data_source
renderer = p2.select(dict(name='predictions'))
ds_predictions = renderer[0].data_source
renderer = p3.select(dict(name='returns'))
ds_returns = renderer[0].data_source

while True:
    timestamps, prices, predictions, returns = get_data()
    ds_prices.data['x'] = timestamps
    ds_predictions.data['x'] = timestamps
    ds_returns.data['x'] = timestamps
    ds_prices.data['y'] = prices
    ds_predictions.data['y'] = predictions
    ds_returns.data['y'] = returns
    ssn.store_objects(ds_prices)
    ssn.store_objects(ds_predictions)
    ssn.store_objects(ds_returns)
    time.sleep(60)


#!/usr/bin/env python
import matplotlib as mpl
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d import proj3d
import numpy as np
import matplotlib.pyplot as plt
import csv
import re
import sys

from __tools__ import MyParser

parser=MyParser(description="Tool to visualize kmc trajectory .csv files" )
parser.add_argument("-t","--trajectory",type=str,nargs="+",required=True,help="Files to visualize .csv format")
parser.add_argument("--steps",type=int,default=-1,help="Maximum number of steps to read in. default:-1")
args=parser.parse_args()
#parser.add_argument('-p',"--plot", action='store_const', const=1, default=0,help="Calculate exciton coupling in classical limit")

if type(args.trajectory)==str:
	args.trajectory=[args.trajectory]

class carrierstorage(object):
		numberofobjects= 0
		def __init__(self):
				carrierstorage.numberofobjects+=1
				self.id=carrierstorage.numberofobjects
				self.traj=[]

		def append(self,posvec):
				self.traj.append(posvec)

		def array(self):
				return np.array(self.traj)

		def info(self):
				print "Carrier No",self.id
				print self.array().shape

listofcarriers=[]

for filename in args.trajectory:
	locallistofcarriers=[]
	with open(filename,"r") as f:
		reader = csv.reader(f, dialect="excel-tab")
		conversion=1
		start=2
		for i,row in enumerate(reader):
			#print i
			if args.steps>0 and i>args.steps:
				break
			if i==0:
				commentlinelength=len(row)
				if "carrier" in ''.join(row):
					noofcharges=''.join(row).count("carrier")/3
				else:
					noofcharges=len(row)/3
				print "Found {} carriers in file {}".format(noofcharges,filename)
				if noofcharges==0:
					break
				for i in range(noofcharges):
					newcarrier=carrierstorage()
					listofcarriers.append(newcarrier)
					locallistofcarriers.append(newcarrier)
				continue
			if i==1:
				#print row
				if len(row)!=commentlinelength:
					print "header and trajectory do not have same number of columns. Ignoring steps colum"
					start=1
				nprow=np.array(row,dtype=float)
				firstcoord=nprow[start:start+3]
				if np.sqrt(np.sum(firstcoord**2))<0.0001:
					print "Units is probably meter instead of nm. Old trajectory format"
					conversion=1E9
				else:
					print "Units is probably nm."
			if i>0:
				nprow=np.array(row,dtype=float)
				for j,carrier in enumerate(locallistofcarriers):
					s=start+j*3
					carrier.append(conversion*nprow[s:s+3])

print "Found {} carriers in total".format(len(listofcarriers))
if len(listofcarriers)==0:
	print "No carriers found"
	sys.exit()
fig = plt.figure(1)
ax = fig.gca(projection='3d')
ax.set_xlabel('x [nm]')
ax.set_ylabel('y [nm]')
ax.set_zlabel('z [nm]')

for i in listofcarriers:
	posarray=i.array()
	#print posarray
	ax.plot(posarray[:,0], posarray[:,1], posarray[:,2])
	ax.scatter(posarray[0,0], posarray[0,1], posarray[0,2],s=200,marker="+",c="black")
	ax.scatter(posarray[-1,0], posarray[-1,1], posarray[-1,2],s=400,marker="x",c="black")

max_range = np.array([posarray[:,0].max()-posarray[:,0].min(), posarray[:,1].max()-posarray[:,1].min(), posarray[:,2].max()-posarray[:,2].min()]).max()
Xb = 0.5*max_range*np.mgrid[-1:2:2,-1:2:2,-1:2:2][0].flatten() + 0.5*(posarray[:,0].max()+posarray[:,0].min())
Yb = 0.5*max_range*np.mgrid[-1:2:2,-1:2:2,-1:2:2][1].flatten() + 0.5*(posarray[:,1].max()+posarray[:,1].min())
Zb = 0.5*max_range*np.mgrid[-1:2:2,-1:2:2,-1:2:2][2].flatten() + 0.5*(posarray[:,2].max()+posarray[:,2].min())
for xb, yb, zb in zip(Xb, Yb, Zb):
   ax.plot([xb], [yb], [zb], 'w')

plt.grid()

plt.show()


# coding=utf-8
"""
Copyright 2013 LinkedIn Corp. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""

import numpy
import os
import matplotlib as mpl
mpl.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as AA
import logging
import naarad.naarad_constants as CONSTANTS

logger = logging.getLogger('naarad.graphing.matplotlib')

def convert_to_mdate(date_str):
  mdate = mdates.epoch2num(int(date_str) / 1000)
  return mdate

# MPL-WA-07
# matplotlib does not rotate colors correctly when using multiple y axes. This method fills in that gap.
def get_current_color(index):
  return CONSTANTS.COLOR_PALETTE[index % len(CONSTANTS.COLOR_PALETTE)]

def get_graph_metadata(plots):
  height = 0
  width = 0
  title = ''
  for plot in plots:
    if plot.graph_height > height:
      height = plot.graph_height
    if plot.graph_width > width:
      width = plot.graph_width
    if title == '':
      title = plot.graph_title
    elif title != plot.graph_title:
      title = title + ',' + plot.graph_title
  return height / 80, width / 80, title

def curate_plot_list(plots):
  delete_nodes = []
  for plot in plots:
    if os.path.exists(plot.input_csv):
      if not os.path.getsize(plot.input_csv):
        logger.warning("%s file is empty. No plot corresponding to this file will be generated", plot.input_csv)
        delete_nodes.append(plot)
    else:
      logger.warning("%s file does not exist. No plot corresponding to this file will be generated", plot.input_csv)
      delete_nodes.append(plot)
  for node in delete_nodes:
    plots.remove(node)
  return plots

def highlight_region(plt, start_x, end_x):
  """
  Highlight a region on the chart between the specified start and end x-co-ordinates.
  param pyplot plt: matplotlibk pyplot which contains the charts to be highlighted
  param string start_x : epoch time millis
  param string end_x : epoch time millis
  """
  start_x = convert_to_mdate(start_x)
  end_x = convert_to_mdate(end_x)
  plt.axvspan(start_x, end_x, color=CONSTANTS.HIGHLIGHT_COLOR, alpha=CONSTANTS.HIGHLIGHT_ALPHA)

def graph_data(list_of_plots, output_directory, resource_path, output_filename):
  plots = curate_plot_list(list_of_plots)
  plot_count = len(plots)
  if plot_count == 0:
    return False, None
  graph_height, graph_width, graph_title = get_graph_metadata(list_of_plots)
  current_plot_count = 0
  fig, axis = plt.subplots()
  fig.set_size_inches(graph_width, graph_height)
  if plot_count < 2:
    fig.subplots_adjust(left=CONSTANTS.SUBPLOT_LEFT_OFFSET, bottom=CONSTANTS.SUBPLOT_BOTTOM_OFFSET, right=CONSTANTS.SUBPLOT_RIGHT_OFFSET)
  else:
    fig.subplots_adjust(left=CONSTANTS.SUBPLOT_LEFT_OFFSET, bottom=CONSTANTS.SUBPLOT_BOTTOM_OFFSET,
                        right=CONSTANTS.SUBPLOT_RIGHT_OFFSET - CONSTANTS.Y_AXIS_OFFSET * (plot_count - 2))
  current_axis = axis
  for plot in plots:
    current_plot_count += 1
    logger.info('Processing: ' + plot.input_csv + ' [ ' + output_filename + ' ]')
    timestamp, yval = numpy.loadtxt(plot.input_csv, unpack=True, delimiter=',', converters={0: convert_to_mdate})
    maximum_yvalue = numpy.amax(yval) * (1.0 + CONSTANTS.ZOOM_FACTOR * current_plot_count)
    minimum_yvalue = numpy.amin(yval) * (1.0 - CONSTANTS.ZOOM_FACTOR * current_plot_count)

    if current_plot_count == 0:
      current_axis.yaxis.set_ticks_position('left')
    if current_plot_count > 1:
      current_axis = axis.twinx()
      current_axis.yaxis.grid(False)
      # Set right y-axis for additional plots
      current_axis.yaxis.set_ticks_position('right')
      # Offset the right y axis to avoid overlap
      current_axis.spines['right'].set_position(('axes', 1 + CONSTANTS.Y_AXIS_OFFSET * (current_plot_count - 2)))
      current_axis.spines['right'].set_smart_bounds(False)
      current_axis.spines['right'].set_color(get_current_color(current_plot_count))
      current_axis.set_frame_on(True)
      current_axis.patch.set_visible(False)
    current_axis.set_ylabel(plot.y_label, color=get_current_color(current_plot_count), fontsize=CONSTANTS.Y_LABEL_FONTSIZE)
    current_axis.set_ylim([minimum_yvalue, maximum_yvalue])
    if plot.graph_type == 'line':
      current_axis.plot_date(x=timestamp, y=yval, linestyle='-', marker=None, color=get_current_color(current_plot_count))
    else:
      current_axis.plot_date(x=timestamp, y=yval, marker='.', color=get_current_color(current_plot_count))
    y_ticks = current_axis.get_yticklabels()
    for y_tick in y_ticks:
      y_tick.set_color(get_current_color(current_plot_count))
      y_tick.set_fontsize(CONSTANTS.Y_TICKS_FONTSIZE)
    for x_tick in current_axis.get_xticklabels():
      x_tick.set_fontsize(CONSTANTS.X_TICKS_FONTSIZE)
    if plot.highlight_regions is not None:
      for region in plot.highlight_regions:
        highlight_region(plt, str(region.start_timestamp), str(region.end_timestamp))
  axis.yaxis.grid(True)
  axis.xaxis.grid(True)
  axis.set_title(graph_title)
  axis.set_xlabel('Time')
  x_date_format = mdates.DateFormatter(CONSTANTS.X_TICKS_DATEFORMAT)
  axis.xaxis.set_major_formatter(x_date_format)
  plot_file_name = os.path.join(output_directory, output_filename + ".png")
  fig.savefig(plot_file_name)
  plt.close()
  # Create html fragment to be used for creation of the report
  with open(os.path.join(output_directory, output_filename + '.div'), 'w') as div_file:
    div_file.write('

' + os.path.basename(plot_file_name) +
                   '

')
  return True, os.path.join(output_directory, output_filename + '.div')

def graph_data_on_the_same_graph(list_of_plots, output_directory, resource_path, output_filename):
  """
  graph_data_on_the_same_graph: put a list of plots on the same graph: currently it supports CDF
  """
  maximum_yvalue = -float('inf')
  minimum_yvalue = float('inf')
  plots = curate_plot_list(list_of_plots)
  plot_count = len(plots)
  if plot_count == 0:
    return False, None
  graph_height, graph_width, graph_title = get_graph_metadata(plots)
  current_plot_count = 0
  fig, axis = plt.subplots()
  fig.set_size_inches(graph_width, graph_height)
  if plot_count < 2:
    fig.subplots_adjust(left=CONSTANTS.SUBPLOT_LEFT_OFFSET, bottom=CONSTANTS.SUBPLOT_BOTTOM_OFFSET, right=CONSTANTS.SUBPLOT_RIGHT_OFFSET)
  else:
    fig.subplots_adjust(left=CONSTANTS.SUBPLOT_LEFT_OFFSET, bottom=CONSTANTS.SUBPLOT_BOTTOM_OFFSET,
                        right=CONSTANTS.SUBPLOT_RIGHT_OFFSET - CONSTANTS.Y_AXIS_OFFSET * (plot_count - 2))
  # Generate each plot on the graph
  for plot in plots:
    current_plot_count += 1
    logger.info('Processing: ' + plot.input_csv + ' [ ' + output_filename + ' ]')
    xval, yval = numpy.loadtxt(plot.input_csv, unpack=True, delimiter=',')
    axis.plot(xval, yval, linestyle='-', marker=None, color=get_current_color(current_plot_count), label=plot.plot_label)
    axis.legend()
    maximum_yvalue = max(maximum_yvalue, numpy.amax(yval) * (1.0 + CONSTANTS.ZOOM_FACTOR * current_plot_count))
    minimum_yvalue = min(minimum_yvalue, numpy.amin(yval) * (1.0 - CONSTANTS.ZOOM_FACTOR * current_plot_count))
  # Set properties of the plots
  axis.yaxis.set_ticks_position('left')
  axis.set_xlabel(plots[0].x_label)
  axis.set_ylabel(plots[0].y_label, fontsize=CONSTANTS.Y_LABEL_FONTSIZE)
  axis.set_ylim([minimum_yvalue, maximum_yvalue])
  axis.yaxis.grid(True)
  axis.xaxis.grid(True)
  axis.set_title(graph_title)
  plot_file_name = os.path.join(output_directory, output_filename + ".png")
  fig.savefig(plot_file_name)
  plt.close()
  # Create html fragment to be used for creation of the report
  with open(os.path.join(output_directory, output_filename + '.div'), 'w') as div_file:
    div_file.write('

' + os.path.basename(plot_file_name) + '

')
  return True, os.path.join(output_directory, output_filename + '.div')


import numpy as np
import pandas as pd
from .recmat import recall_matrix
from scipy.spatial.distance import cdist
from ..helpers import check_nan

def lagcrp_helper(egg, match='exact', distance='euclidean',
                  ts=None, features=None):
    """
    Computes probabilities for each transition distance (probability that a word
    recalled will be a given distance--in presentation order--from the previous
    recalled word).

    Parameters
    ----------
    egg : quail.Egg
        Data to analyze

    match : str (exact, best or smooth)
        Matching approach to compute recall matrix.  If exact, the presented and
        recalled items must be identical (default).  If best, the recalled item
        that is most similar to the presented items will be selected. If smooth,
        a weighted average of all presented items will be used, where the
        weights are derived from the similarity between the recalled item and
        each presented item.

    distance : str
        The distance function used to compare presented and recalled items.
        Applies only to 'best' and 'smooth' matching approaches.  Can be any
        distance function supported by numpy.spatial.distance.cdist.

    Returns
    ----------
    prec : numpy array
      each float is the probability of transition distance (distnaces indexed by
      position, from -(n-1) to (n-1), excluding zero

    """

    def lagcrp(rec, lstlen):
        """Computes lag-crp for a given recall list"""

        def check_pair(a, b):
            if (a>0 and b>0) and (a!=b):
                return True
            else:
                return False

        def compute_actual(rec, lstlen):
            arr=pd.Series(data=np.zeros((lstlen)*2),
                          index=list(range(-lstlen,0))+list(range(1,lstlen+1)))
            recalled=[]
            for trial in range(0,len(rec)-1):
                a=rec[trial]
                b=rec[trial+1]
                if check_pair(a, b) and (a not in recalled) and (b not in recalled):
                    arr[b-a]+=1
                recalled.append(a)
            return arr

        def compute_possible(rec, lstlen):
            arr=pd.Series(data=np.zeros((lstlen)*2),
                          index=list(range(-lstlen,0))+list(range(1,lstlen+1)))
            recalled=[]
            for trial in rec:
                if np.isnan(trial):
                    pass
                else:
                    lbound=int(1-trial)
                    ubound=int(lstlen-trial)
                    chances=list(range(lbound,0))+list(range(1,ubound+1))
                    for each in recalled:
                        if each-trial in chances:
                            chances.remove(each-trial)
                    arr[chances]+=1
                    recalled.append(trial)
            return arr

        actual = compute_actual(rec, lstlen)
        possible = compute_possible(rec, lstlen)
        crp = [0.0 if j == 0 else i / j for i, j in zip(actual, possible)]
        crp.insert(int(len(crp) / 2), np.nan)
        return crp

    def nlagcrp(distmat, ts=None):

        def lagcrp_model(s):
            idx = list(range(0, -s, -1))
            return np.array([list(range(i, i+s)) for i in idx])

        # remove nan columns
        distmat = distmat[:,~np.all(np.isnan(distmat), axis=0)].T

        model = lagcrp_model(distmat.shape[1])
        lagcrp = np.zeros(ts * 2)
        for rdx in range(len(distmat)-1):
            item = distmat[rdx, :]
            next_item = distmat[rdx+1, :]
            if not np.isnan(item).any() and not np.isnan(next_item).any():
                outer = np.outer(item, next_item)
                lagcrp += np.array(list(map(lambda lag: np.mean(outer[model==lag]), range(-ts, ts))))
        lagcrp /= ts
        lagcrp = list(lagcrp)
        lagcrp.insert(int(len(lagcrp) / 2), np.nan)
        return np.array(lagcrp)

    def _format(p, r):
        p = np.matrix([np.array(i) for i in p])
        if p.shape[0]==1:
            p=p.T
        r = map(lambda x: [np.nan]*p.shape[1] if check_nan(x) else x, r)
        r = np.matrix([np.array(i) for i in r])
        if r.shape[0]==1:
            r=r.T
        return p, r

    opts = dict(match=match, distance=distance, features=features)
    if match is 'exact':
        opts.update({'features' : 'item'})
    recmat = recall_matrix(egg, **opts)
    if not ts:
        ts = egg.pres.shape[1]
    if match in ['exact', 'best']:
        lagcrp = [lagcrp(lst, egg.list_length) for lst in recmat]
    elif match is 'smooth':
        lagcrp = np.atleast_2d(np.mean([nlagcrp(r, ts=ts) for r in recmat], 0))
    else:
        raise ValueError('Match must be set to exact, best or smooth.')
    return np.nanmean(lagcrp, axis=0)


#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
Created on Thu Jun  8 19:14:33 2017

@author: sbhal
"""

import numpy as np
import pandas as pd
import random
import tensorflow as tf

class qlearningTF:
    def __init__(self, m_criteria, initialWeights=None):
        if initialWeights == None:
            self.weights = np.full(m_criteria, 3) #assign dtype
        else:
            self.weights = initialWeights
        self.weightBins = 3 #.3 .7. .5
        self.e = 0.5
        self.lr = .8
        self.y = .95
        self.m_criteria = m_criteria
        self.actionStatesCount = 3 #+-0
        # initialize Q table
        self.currState = "33"

        self.Qrows = pow(self.weightBins,self.m_criteria)
        self.Qcols = self.m_criteria* self.actionStatesCount

        # These lines establish the feed-forward part of the network used to choose actions
        self.inputs1 = tf.placeholder(shape=[1, self.Qrows], dtype=tf.float32)
        #self.W = tf.Variable(tf.random_uniform([self.Qrows, self.Qcols], 0, 0.01))
        self.W = tf.Variable(tf.random_uniform([self.Qrows, self.Qcols], 0, 0.00))
        self.Qout = tf.matmul(self.inputs1, self.W)
        self.predict = tf.argmax(self.Qout, 1)
        # Below we obtain the loss by taking the sum of squares difference between the target and prediction Q values.
        self.nextQ = tf.placeholder(shape=[1, self.Qcols], dtype=tf.float32)
        loss = tf.reduce_sum(tf.square(self.nextQ - self.Qout))
        trainer = tf.train.GradientDescentOptimizer(learning_rate=0.1)
        self.updateModel = trainer.minimize(loss)
        self.sess = tf.Session()
        self.sess.run(tf.initialize_all_variables())

    def learn(self, s, a, reward, s1): #curState ----action----> finalState (+reward)
        allQ = self.sess.run(self.Qout, feed_dict={self.inputs1: np.identity(self.Qrows)[s:s + 1]})
        value2 = np.max(self.sess.run(self.Qout,feed_dict={self.inputs1:np.identity(self.Qrows)[s1:s1+1]}))
        allQ[0, a] = reward + self.y * value2
        _, W1 = self.sess.run([self.updateModel, self.W], feed_dict={self.inputs1: np.identity(self.Qrows)[s:s + 1], self.nextQ: allQ})

        # print(self.sess.run(self.W), " weight updated @ state", self.currState)
        self.currState = self.state_num_to_string(s1)

    def currToFinalState (self, a, c):
        c_num = list(map(int, c))
        if a[2] == "+":
            c_num[int(a[1])] = min(7, c_num[int(a[1])]+2)
        else:
            c_num[int(a[1])] = max(3, c_num[int(a[1])] - 2)
        return "".join(map(str,c_num))

    def update(self, action, latency):
        reward = 0 if latency==0 else 1/latency
        finalState = self.currToFinalState(action, self.currState)
        s = self.state_string_to_num(self.currState)
        s1 = self.state_string_to_num(finalState)
        a = self.action_string_to_num(action)
        self.learn (s, a, reward, s1)

    def choose_action(self, currState):
        #verify if currState has correct format
        s = self.state_string_to_num(currState)
        if np.random.rand(1) < self.e:
            # print("Random action Chosen")
            return self.action_num_to_string(random.randrange(0, self.Qcols))
        else:
            a = np.argmax(self.sess.run(self.Qout,feed_dict={self.inputs1:np.identity(self.Qrows)[s:s+1]}))
            return self.action_num_to_string(a)
    def state_string_to_num(self, s):
        dict = {'3': 0,
                '5': 1,
                '7': 2}
        sum =0
        for i, c in enumerate(reversed(s)):
            sum += pow(self.weightBins,i) * dict[c]
        return sum

    def state_num_to_string(self, num):
        dict = {'0':'3',
                '1':'5',
                '2':'7'}
        mynum = num
        strr = ""
        string = ""
        for i in reversed(range(0,self.m_criteria)):
            strr += str(mynum // pow(self.weightBins, i))
            mynum = mynum % pow(self.weightBins, i)
        for i,c in enumerate(strr):
            string += dict[strr[i]]
        return string

    def action_num_to_string(self, num):
        dict = {0: "+",
                1: "-",
                2: "0"}
        quotient = num // self.weightBins
        remainder = num % self.weightBins
        return "w"+ str(quotient) + dict[remainder]
    def action_string_to_num(self, s):
        dict = { "+": 0,
                 "-": 1,
                 "0": 2}
        return (int(s[1]) * self.weightBins) + dict[s[2]]

if __name__ == "__main__":
    myIns = qlearningTF(m_criteria=2)
    print (myIns.state_string_to_num("33"))
    print(myIns.state_string_to_num("53"))
    print(myIns.state_string_to_num("77"))
    print(myIns.action_num_to_string(0))
    print(myIns.action_num_to_string(4))

    print(myIns.state_num_to_string(0))
    print(myIns.state_num_to_string(3))
    print(myIns.state_num_to_string(8))

    print("From here:")
    action = myIns.choose_action("33")
    print("Action given is", action)
    myIns.update(action, 300)
    print("new")
    action = myIns.choose_action("77")
    myIns.update(action, 300)
    print(myIns.choose_action("33"))