#!/usr/bin/python
import time
import os
import sys
import pygame
import numpy
from PIL import Image, ImageDraw, ImageChops

print("")
print("")
print(" USE l=3 to take a photo every 3 somethings, try a 1000 or 2")
print("      t  to take triggered photos ")
print("     cap=/home/pi/folder/ to set caps path other than current dir")
print("      ")
pi_paper = False  #updates pi wall paper, use -nopaper to turn it off.

s_val = "10"
c_val = "2"
g_val = "10"
b_val = "15"
x_dim = 1600
y_dim = 896
additonal_commands = "-d/dev/video1 -w"

try:
    cappath = os.getcwd()
    cappath += "/"
except:
    print("  COULD NOT GET CURRENT DIR SET WITH A FLAG ")
    cappath = "./"
    print("  COULD NOT GET CURRENT DIR SET WITH A FLAG ")

loc_settings = "./camera_settings.txt"
try:
    with open(loc_settings, "r") as f:
        for line in f:
            s_item = line.split("=")
            if s_item[0] == "s_val":
                s_val = s_item[1].split("\n")[0]
            elif s_item[0] == "c_val":
                c_val = s_item[1].split("\n")[0]
            elif s_item[0] == "g_val":
                g_val = s_item[1].split("\n")[0]
            elif s_item[0] == "b_val":
                b_val = s_item[1].split("\n")[0]
            elif s_item[0] == "x_dim":
                x_dim = s_item[1].split("\n")[0]
            elif s_item[0] == "y_dim":
                y_dim = s_item[1].split("\n")[0]
            elif s_item[0] == "additonal_commands":
                additonal_commands = s_item[1].split("\n")[0]
except:
    print("No config file for camera, using default")
    print("Run cam_config.py to create one")

def photo():
    # take and save photo
    timenow = time.time()
    timenow = str(timenow)[0:10]
    filename= "cap_"+str(timenow)+".jpg"
    #os.system("uvccapture "+additonal_commands+" -S"+s_val+" -C" + c_val + " -G"+ g_val +" -B"+ b_val +" -x"+str(x_dim)+" -y"+str(y_dim)+" -v -t0 -o"+cappath+filename)
    cmd = str("uvccapture "+additonal_commands+" -x"+str(x_dim)+" -y"+str(y_dim)+" -v -t0 -o"+cappath+filename)
    print("####")
    print("####")
    print cmd
    print("####")
    print("####")
    os.system(cmd)
    print("Image taken and saved to "+cappath+filename)
    if pi_paper == True:
        os.system("export DISPLAY=:0 && pcmanfm --set-wallpaper "+cappath+filename)
    return filename

if 'wp' in sys.argv or 'wallpaper' in sys.argv:
    pi_paper = True
    print(" Going to try changing wall paper")

loop = False
trig = False
for argu in sys.argv[1:]:
    try:
        thearg = str(argu).split('=')[0]
    except:
        thearg = str(argu)
    if thearg == 'cap' or thearg =='cappath':
        cappath = str(argu).split('=')[1]
    elif thearg == 'l' or thearg == 'looped':
        try:
            num = int(str(argu).split('=')[1])
        except:
            print("No speed supplied, taking every 10")
            num = 10
        loop = True
    elif thearg == 't' or thearg == 'TRIGGERED':
        trig = True
print(" Saving files to, " + str(cappath))

pygame.init()
display_width = x_dim
display_height = y_dim
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('Most recent image')
black = (0,0,0)
white = (255,255,255)
clock = pygame.time.Clock()
crashed = False

import matplotlib.pyplot as plt

def show_pic(imgtaken, x=0,y=0):
    gameDisplay.blit(imgtaken, (x,y))

gameDisplay.fill(white)

c_photo = photo()
pil_c_photo = Image.open(c_photo)
numpy_pic = numpy.array(pil_c_photo)

b_photo = photo()
pil_b_photo = Image.open(b_photo)
numpy_pic_b = numpy.array(pil_b_photo)

mask  = numpy_pic_b > numpy_pic + 30 #the +30 gets rid of noise
mask2 = numpy_pic_b < numpy_pic - 30
lol = mask + mask2
e_pic = numpy_pic.copy()

num = 0
while not crashed:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            crashed = True
    timenow = time.time()
    e_photo = str(timenow).split(".")[0]
    e_photo= "numpy_"+str(timenow)+".jpg"
    num = num + 1

    b_photo = c_photo

    c_photo = photo()
    numpy_pic_b = numpy_pic.copy()
    pil_c_photo = Image.open(c_photo)
    numpy_pic = numpy.array(pil_c_photo)

    print numpy_pic.size
    #print len(numpy_pic[3])
    print "###"
    #print numpy_pic[1:,1,1]

    #a = np.arange(100)
    print "##########"
    #numpy_pic[1:500, range(0, len(numpy_pic[2]), 10), 1] = 0
    #for x in numpy_pic[1:500, range(0, len(numpy_pic[2])), 1]:
    #    if x >= 100:
    #        x = 255
    #for x in range(10,170,10):
    #    mask = numpy_pic < x
    #    numpy_pic[mask] = 255-x #numpy_pic[mask] + numpy_pic[mask]
    #for x in range(200,255,5):
    #    mask = numpy_pic > x
    #    numpy_pic[mask] = 0+(x/10) # numpy_pic[mask] / numpy_pic[mask]+(numpy_pic[mask]/numpy_pic[mask])

    #print numpy_pic[1:,1,1]
    #print numpy_pic.min()
    print "###"
    #print numpy_pic.shape #Array dimensions
    #print numpy_pic.ndim #Number of array dimensions
    #print numpy_pic.dtype #Data type of array elements
    #print numpy_pic.dtype.name #Name of data type
    #print numpy_pic.mean()
    #print numpy_pic.max()
    #print numpy_pic.min()
    #print numpy.info(numpy.ndarray.dtype)
    #print numpy_pic.astype(int)

    #mask = numpy_pic > numpy_pic_b
    #mask = numpy_pic[:, :, 2] > 150
    #numpy_pic[mask] = [0, 0, 255]
    #lol = numpy_pic +

    #mask  = numpy_pic_b > numpy_pic + 30 #the +30 gets rid of noise
    #mask2 = numpy_pic_b < numpy_pic - 30
    margin = 20
    maskr = numpy_pic[:, :, 0] < numpy_pic_b[:, :, 0] - margin
    maskg = numpy_pic[:, :, 1] < numpy_pic_b[:, :, 1] - margin
    maskb = numpy_pic[:, :, 2] < numpy_pic_b[:, :, 2] - margin
    maskr2 = numpy_pic[:, :, 0] > numpy_pic_b[:, :, 0] + margin
    maskg2 = numpy_pic[:, :, 1] > numpy_pic_b[:, :, 1] + margin
    maskb2 = numpy_pic[:, :, 2] > numpy_pic_b[:, :, 2] + margin
    #numpy_pic[mask] = [0, 0, 255]

    #lol_old = lol
    #lol = mask + mask2
    #lol = lol + lol_old
    persist = 'ohhh'
    if persist == 'True':
        numpy_pic[maskr] = [255, 0, 0]
        numpy_pic[maskg] = [0, 255, 0]
        numpy_pic[maskb] = [0, 0, 255]
        numpy_pic[maskb2] = [0, 0, 100]
        numpy_pic[maskr2] = [100, 0, 0]
        numpy_pic[maskg2] = [0, 100, 0]
        Image.fromarray(numpy_pic).save(e_photo)
    elif persist == 'False':
        old_e = e_pic
        e_pic = numpy_pic.copy()
        e_pic[maskr] = [255, 0, 0]
        e_pic[maskg] = [0, 255, 0]
        e_pic[maskb] = [0, 0, 255]
        e_pic[maskr2] = [100, 0, 0]
        e_pic[maskg2] = [0, 100, 0]
        e_pic[maskb2] = [0, 0, 100]
        show1 = 'waa'
        if show1 == '1':
            e_pic = ((e_pic/4) - (numpy_pic))*3
            e_pic = e_pic / 3 + old_e / 2
        elif show1 == 'tripsy':
            e_pic = ((e_pic/4) - (numpy_pic))*3
            e_pic = e_pic - old_e / 2
        elif show1 == 'waa':
            e_pic = ((e_pic/4) - (numpy_pic))*3
            #e_pic = old_e * 0.8 + e_pic * 0.2
        Image.fromarray(e_pic).save(e_photo)

    elif persist == 'ohhh':
        old_e = e_pic.copy()
        mask_b_pic = numpy_pic.copy()
        mask_d_pic = numpy_pic.copy()
        mask_b_pic[maskr] = [255, 255, 255]
        mask_b_pic[maskg] = [255, 255, 255]
        mask_b_pic[maskb] = [255, 255, 255]
        mask_d_pic[maskr2] = [0, 0, 0]
        mask_d_pic[maskg2] = [0, 0, 0]
        mask_d_pic[maskb2] = [0, 0, 0]
        #e_pic = e_pic/6 + old_e
        e_pic = [200, 200, 0]
        #e_pic = e_pic/2 - ((mask_d_pic) + (mask_b_pic))
        #e_pic = e_pic/2 + ((mask_d_pic) + (mask_b_pic))
                                      #choose one of the following
        #e_pic = mask_d_pic               #shows when pixel is darker than it was
        #e_pic = mask_b_pic              #shows when pixel is lighter than prior
        e_pic = mask_d_pic - mask_b_pic  #black execpt for movement
        e_pic = mask_b_pic / (mask_d_pic / 100)  #black execpt for movement
        #e_pic = mask_d_pic + mask_b_pic  #looks odd

        Image.fromarray(e_pic).save(e_photo)

    #plt.imshow(lol)
    #plt.show()
    #Image.fromarray(numpy_pic).save(e_photo)
    onscreen = pygame.image.load(e_photo)
    gameDisplay.blit(onscreen, (0,0))
    pygame.display.update()

    if trig == True:
        print("Waiting for input before taking next image...")
        tp = raw_input("press return to take picture; ")
        if tp == "q":
            print("---bye!")
            exit()
        clock.tick(20)
    if loop == True:
        pygame.time.wait(num)
        clock.tick(20)
    elif trig == False and loop == False:
        crashed = True

#while True:
    #pygame.time.wait(1000)
    #clock.tick(20)

pygame.quit()
quit()


"""
Author: John Hwang <<hwangjt@umich.edu>>

This package is distributed under New BSD license.
"""

import unittest

import matplotlib

matplotlib.use("Agg")

try:
    from smt.surrogate_models import IDW, RBF, RMTB, RMTC

    compiled_available = True
except:
    compiled_available = False

class Test(unittest.TestCase):
    @unittest.skipIf(not compiled_available, "C compilation failed")
    def test_idw(self):
        import numpy as np
        import matplotlib.pyplot as plt

        from smt.surrogate_models import IDW

        xt = np.array([0.0, 1.0, 2.0, 3.0, 4.0])
        yt = np.array([0.0, 1.0, 1.5, 0.9, 1.0])

        sm = IDW(p=2)
        sm.set_training_values(xt, yt)
        sm.train()

        num = 100
        x = np.linspace(0.0, 4.0, num)
        y = sm.predict_values(x)

        plt.plot(xt, yt, "o")
        plt.plot(x, y)
        plt.xlabel("x")
        plt.ylabel("y")
        plt.legend(["Training data", "Prediction"])
        plt.show()

    @unittest.skipIf(not compiled_available, "C compilation failed")
    def test_rbf(self):
        import numpy as np
        import matplotlib.pyplot as plt

        from smt.surrogate_models import RBF

        xt = np.array([0.0, 1.0, 2.0, 3.0, 4.0])
        yt = np.array([0.0, 1.0, 1.5, 0.9, 1.0])

        sm = RBF(d0=5)
        sm.set_training_values(xt, yt)
        sm.train()

        num = 100
        x = np.linspace(0.0, 4.0, num)
        y = sm.predict_values(x)

        plt.plot(xt, yt, "o")
        plt.plot(x, y)
        plt.xlabel("x")
        plt.ylabel("y")
        plt.legend(["Training data", "Prediction"])
        plt.show()

    @unittest.skipIf(not compiled_available, "C compilation failed")
    def test_rmtb(self):
        import numpy as np
        import matplotlib.pyplot as plt

        from smt.surrogate_models import RMTB

        xt = np.array([0.0, 1.0, 2.0, 3.0, 4.0])
        yt = np.array([0.0, 1.0, 1.5, 0.9, 1.0])

        xlimits = np.array([[0.0, 4.0]])

        sm = RMTB(
            xlimits=xlimits,
            order=4,
            num_ctrl_pts=20,
            energy_weight=1e-15,
            regularization_weight=0.0,
        )
        sm.set_training_values(xt, yt)
        sm.train()

        num = 100
        x = np.linspace(0.0, 4.0, num)
        y = sm.predict_values(x)

        plt.plot(xt, yt, "o")
        plt.plot(x, y)
        plt.xlabel("x")
        plt.ylabel("y")
        plt.legend(["Training data", "Prediction"])
        plt.show()

    @unittest.skipIf(not compiled_available, "C compilation failed")
    def test_rmtc(self):
        import numpy as np
        import matplotlib.pyplot as plt

        from smt.surrogate_models import RMTC

        xt = np.array([0.0, 1.0, 2.0, 3.0, 4.0])
        yt = np.array([0.0, 1.0, 1.5, 0.9, 1.0])

        xlimits = np.array([[0.0, 4.0]])

        sm = RMTC(
            xlimits=xlimits,
            num_elements=20,
            energy_weight=1e-15,
            regularization_weight=0.0,
        )
        sm.set_training_values(xt, yt)
        sm.train()

        num = 100
        x = np.linspace(0.0, 4.0, num)
        y = sm.predict_values(x)

        plt.plot(xt, yt, "o")
        plt.plot(x, y)
        plt.xlabel("x")
        plt.ylabel("y")
        plt.legend(["Training data", "Prediction"])
        plt.show()

    def test_ls(self):
        import numpy as np
        import matplotlib.pyplot as plt

        from smt.surrogate_models import LS

        xt = np.array([0.0, 1.0, 2.0, 3.0, 4.0])
        yt = np.array([0.0, 1.0, 1.5, 0.9, 1.0])

        sm = LS()
        sm.set_training_values(xt, yt)
        sm.train()

        num = 100
        x = np.linspace(0.0, 4.0, num)
        y = sm.predict_values(x)

        plt.plot(xt, yt, "o")
        plt.plot(x, y)
        plt.xlabel("x")
        plt.ylabel("y")
        plt.legend(["Training data", "Prediction"])
        plt.show()

    def test_qp(self):
        import numpy as np
        import matplotlib.pyplot as plt

        from smt.surrogate_models import QP

        xt = np.array([[0.0, 1.0, 2.0, 3.0, 4.0]]).T
        yt = np.array([[0.2, 1.4, 1.5, 0.9, 1.0], [0.0, 1.0, 2.0, 4, 3]]).T

        sm = QP()
        sm.set_training_values(xt, yt)
        sm.train()

        num = 100
        x = np.linspace(0.0, 4.0, num)
        y = sm.predict_values(x)

        t1, _ = plt.plot(xt, yt[:, 0], "o", "C0")
        p1 = plt.plot(x, y[:, 0], "C0", label="Prediction 1")
        t2, _ = plt.plot(xt, yt[:, 1], "o", "C1")
        p2 = plt.plot(x, y[:, 1], "C1", label="Prediction 2")
        plt.xlabel("x")
        plt.ylabel("y")
        plt.legend()
        plt.show()

    def test_krg(self):
        import numpy as np
        import matplotlib.pyplot as plt

        from smt.surrogate_models import KRG

        xt = np.array([0.0, 1.0, 2.0, 3.0, 4.0])
        yt = np.array([0.0, 1.0, 1.5, 0.9, 1.0])

        sm = KRG(theta0=[1e-2])
        sm.set_training_values(xt, yt)
        sm.train()

        num = 100
        x = np.linspace(0.0, 4.0, num)
        y = sm.predict_values(x)
        # estimated variance
        s2 = sm.predict_variances(x)
        # derivative according to the first variable
        dydx = sm.predict_derivatives(xt, 0)
        fig, axs = plt.subplots(1)

        # add a plot with variance
        axs.plot(xt, yt, "o")
        axs.plot(x, y)
        axs.fill_between(
            np.ravel(x),
            np.ravel(y - 3 * np.sqrt(s2)),
            np.ravel(y + 3 * np.sqrt(s2)),
            color="lightgrey",
        )
        axs.set_xlabel("x")
        axs.set_ylabel("y")
        axs.legend(
            ["Training data", "Prediction", "Confidence Interval 99%"],
            loc="lower right",
        )

        plt.show()

    def test_mixed_int_krg(self):
        import numpy as np
        import matplotlib.pyplot as plt

        from smt.surrogate_models import KRG
        from smt.applications.mixed_integer import MixedIntegerSurrogateModel, INT

        xt = np.array([0.0, 2.0, 3.0])
        yt = np.array([0.0, 1.5, 0.9])

        # xtypes = [FLOAT, INT, (ENUM, 3), (ENUM, 2)]
        # FLOAT means x1 continuous
        # INT means x2 integer
        # (ENUM, 3) means x3, x4 & x5 are 3 levels of the same categorical variable
        # (ENUM, 2) means x6 & x7 are 2 levels of the same categorical variable

        sm = MixedIntegerSurrogateModel(
            xtypes=[INT], xlimits=[[0, 4]], surrogate=KRG(theta0=[1e-2])
        )
        sm.set_training_values(xt, yt)
        sm.train()

        num = 500
        x = np.linspace(0.0, 4.0, num)
        y = sm.predict_values(x)
        # estimated variance
        s2 = sm.predict_variances(x)

        fig, axs = plt.subplots(1)
        axs.plot(xt, yt, "o")
        axs.plot(x, y)
        axs.fill_between(
            np.ravel(x),
            np.ravel(y - 3 * np.sqrt(s2)),
            np.ravel(y + 3 * np.sqrt(s2)),
            color="lightgrey",
        )
        axs.set_xlabel("x")
        axs.set_ylabel("y")
        axs.legend(
            ["Training data", "Prediction", "Confidence Interval 99%"],
            loc="lower right",
        )

        plt.show()

    def test_mixed_gower_krg(self):
        import numpy as np
        import matplotlib.pyplot as plt
        from smt.surrogate_models import KRG
        from smt.applications.mixed_integer import MixedIntegerSurrogateModel
        from smt.applications.mixed_integer import ENUM

        # xtypes = [FLOAT, INT, (ENUM, 3), (ENUM, 2)]
        # FLOAT means x1 continuous
        # INT means x2 integer
        # (ENUM, 3) means x3, x4 & x5 are 3 levels of the same categorical variable
        # (ENUM, 2) means x6 & x7 are 2 levels of the same categorical variable

        xt = np.linspace(1.0, 5.0, 5)
        x_train = np.array(["%.2f" % i for i in xt], dtype=object)
        yt = np.array([0.0, 1.0, 1.5, 0.5, 1.0])

        xlimits = [["0.0", "1.0", " 2.0", "3.0", "4.0"]]

        sm = MixedIntegerSurrogateModel(
            use_gower_distance=True,
            xtypes=[(ENUM, 5)],
            xlimits=xlimits,
            surrogate=KRG(theta0=[1e-2]),
        )
        sm.set_training_values(x_train, yt)
        sm.train()

        num = 101
        x = np.linspace(0, 5, num)
        x_pred = np.array(["%.2f" % i for i in x], dtype=object)

        y = sm.predict_values(x_pred)

        plt.plot(xt, yt, "o")
        plt.plot(x, y)
        plt.xlabel("x")
        plt.ylabel("y")
        plt.legend(["Training data", "Prediction"])
        plt.show()

    def test_kpls(self):
        import numpy as np
        import matplotlib.pyplot as plt

        from smt.surrogate_models import KPLS

        xt = np.array([0.0, 1.0, 2.0, 3.0, 4.0])
        yt = np.array([0.0, 1.0, 1.5, 0.9, 1.0])

        sm = KPLS(theta0=[1e-2])
        sm.set_training_values(xt, yt)
        sm.train()

        num = 100
        x = np.linspace(0.0, 4.0, num)
        y = sm.predict_values(x)
        # estimated variance
        s2 = sm.predict_variances(x)
        # to compute the derivative according to the first variable
        dydx = sm.predict_derivatives(xt, 0)

        plt.plot(xt, yt, "o")
        plt.plot(x, y)
        plt.xlabel("x")
        plt.ylabel("y")
        plt.legend(["Training data", "Prediction"])
        plt.show()

        # add a plot with variance
        plt.plot(xt, yt, "o")
        plt.plot(x, y)
        plt.fill_between(
            np.ravel(x),
            np.ravel(y - 3 * np.sqrt(s2)),
            np.ravel(y + 3 * np.sqrt(s2)),
            color="lightgrey",
        )
        plt.xlabel("x")
        plt.ylabel("y")
        plt.legend(["Training data", "Prediction", "Confidence Interval 99%"])
        plt.show()

    def test_kplsk(self):
        import numpy as np
        import matplotlib.pyplot as plt

        from smt.surrogate_models import KPLSK

        xt = np.array([0.0, 1.0, 2.0, 3.0, 4.0])
        yt = np.array([0.0, 1.0, 1.5, 0.9, 1.0])

        sm = KPLSK(theta0=[1e-2])
        sm.set_training_values(xt, yt)
        sm.train()

        num = 100
        x = np.linspace(0.0, 4.0, num)
        y = sm.predict_values(x)
        # estimated variance
        s2 = sm.predict_variances(x)
        # derivative according to the first variable
        dydx = sm.predict_derivatives(xt, 0)

        plt.plot(xt, yt, "o")
        plt.plot(x, y)
        plt.xlabel("x")
        plt.ylabel("y")
        plt.legend(["Training data", "Prediction"])
        plt.show()

        # add a plot with variance
        plt.plot(xt, yt, "o")
        plt.plot(x, y)
        plt.fill_between(
            np.ravel(x),
            np.ravel(y - 3 * np.sqrt(s2)),
            np.ravel(y + 3 * np.sqrt(s2)),
            color="lightgrey",
        )
        plt.xlabel("x")
        plt.ylabel("y")
        plt.legend(["Training data", "Prediction", "Confidence Interval 99%"])
        plt.show()

    def test_gekpls(self):
        import numpy as np
        from mpl_toolkits.mplot3d import Axes3D
        import matplotlib.pyplot as plt

        from smt.surrogate_models import GEKPLS
        from smt.problems import Sphere
        from smt.sampling_methods import LHS

        # Construction of the DOE
        fun = Sphere(ndim=2)
        sampling = LHS(xlimits=fun.xlimits, criterion="m")
        xt = sampling(20)
        yt = fun(xt)
        # Compute the gradient
        for i in range(2):
            yd = fun(xt, kx=i)
            yt = np.concatenate((yt, yd), axis=1)

        # Build the GEKPLS model
        sm = GEKPLS(
            theta0=[1e-2], xlimits=fun.xlimits, extra_points=1, print_prediction=False
        )
        sm.set_training_values(xt, yt[:, 0])
        for i in range(2):
            sm.set_training_derivatives(xt, yt[:, 1 + i].reshape((yt.shape[0], 1)), i)
        sm.train()

        # Test the model
        X = np.arange(fun.xlimits[0, 0], fun.xlimits[0, 1], 0.25)
        Y = np.arange(fun.xlimits[1, 0], fun.xlimits[1, 1], 0.25)
        X, Y = np.meshgrid(X, Y)
        Z = np.zeros((X.shape[0], X.shape[1]))

        for i in range(X.shape[0]):
            for j in range(X.shape[1]):
                Z[i, j] = sm.predict_values(
                    np.hstack((X[i, j], Y[i, j])).reshape((1, 2))
                )

        fig = plt.figure()
        ax = fig.gca(projection="3d")
        surf = ax.plot_surface(X, Y, Z)

        plt.show()

    def test_genn(self):
        import numpy as np
        import matplotlib.pyplot as plt
        from smt.surrogate_models.genn import GENN, load_smt_data

        # Training data
        lower_bound = -np.pi
        upper_bound = np.pi
        number_of_training_points = 4
        xt = np.linspace(lower_bound, upper_bound, number_of_training_points)
        yt = xt * np.sin(xt)
        dyt_dxt = np.sin(xt) + xt * np.cos(xt)

        # Validation data
        number_of_validation_points = 30
        xv = np.linspace(lower_bound, upper_bound, number_of_validation_points)
        yv = xv * np.sin(xv)
        dyv_dxv = np.sin(xv) + xv * np.cos(xv)

        # Truth model
        x = np.arange(lower_bound, upper_bound, 0.01)
        y = x * np.sin(x)

        # GENN
        genn = GENN()
        genn.options["alpha"] = 0.1  # learning rate that controls optimizer step size
        genn.options["beta1"] = 0.9  # tuning parameter to control ADAM optimization
        genn.options["beta2"] = 0.99  # tuning parameter to control ADAM optimization
        genn.options[
            "lambd"
        ] = 0.1  # lambd = 0. = no regularization, lambd > 0 = regularization
        genn.options[
            "gamma"
        ] = 1.0  # gamma = 0. = no grad-enhancement, gamma > 0 = grad-enhancement
        genn.options["deep"] = 2  # number of hidden layers
        genn.options["wide"] = 6  # number of nodes per hidden layer
        genn.options[
            "mini_batch_size"
        ] = 64  # used to divide data into training batches (use for large data sets)
        genn.options["num_epochs"] = 20  # number of passes through data
        genn.options[
            "num_iterations"
        ] = 100  # number of optimizer iterations per mini-batch
        genn.options["is_print"] = True  # print output (or not)
        load_smt_data(
            genn, xt, yt, dyt_dxt
        )  # convenience function to read in data that is in SMT format
        genn.train()  # API function to train model
        genn.plot_training_history()  # non-API function to plot training history (to check convergence)
        genn.goodness_of_fit(
            xv, yv, dyv_dxv
        )  # non-API function to check accuracy of regression
        y_pred = genn.predict_values(
            x
        )  # API function to predict values at new (unseen) points

        # Plot
        fig, ax = plt.subplots()
        ax.plot(x, y_pred)
        ax.plot(x, y, "k--")
        ax.plot(xv, yv, "ro")
        ax.plot(xt, yt, "k+", mew=3, ms=10)
        ax.set(xlabel="x", ylabel="y", title="GENN")
        ax.legend(["Predicted", "True", "Test", "Train"])
        plt.show()

    def test_mgp(self):
        import numpy as np
        import matplotlib.pyplot as plt
        from smt.surrogate_models import MGP
        from smt.sampling_methods import LHS

        # Construction of the DOE
        dim = 3

        def fun(x):
            import numpy as np

            res = (
                np.sum(x, axis=1) ** 2
                - np.sum(x, axis=1)
                + 0.2 * (np.sum(x, axis=1) * 1.2) ** 3
            )
            return res

        sampling = LHS(xlimits=np.asarray([(-1, 1)] * dim), criterion="m")
        xt = sampling(8)
        yt = np.atleast_2d(fun(xt)).T

        # Build the MGP model
        sm = MGP(
            theta0=[1e-2],
            print_prediction=False,
            n_comp=1,
        )
        sm.set_training_values(xt, yt[:, 0])
        sm.train()

        # Get the transfert matrix A
        emb = sm.embedding["C"]

        # Compute the smallest box containing all points of A
        upper = np.sum(np.abs(emb), axis=0)
        lower = -upper

        # Test the model
        u_plot = np.atleast_2d(np.arange(lower, upper, 0.01)).T
        x_plot = sm.get_x_from_u(u_plot)  # Get corresponding points in Omega
        y_plot_true = fun(x_plot)
        y_plot_pred = sm.predict_values(u_plot)
        sigma_MGP, sigma_KRG = sm.predict_variances(u_plot, True)

        u_train = sm.get_u_from_x(xt)  # Get corresponding points in A

        # Plots
        fig, ax = plt.subplots()
        ax.plot(u_plot, y_plot_pred, label="Predicted")
        ax.plot(u_plot, y_plot_true, "k--", label="True")
        ax.plot(u_train, yt, "k+", mew=3, ms=10, label="Train")
        ax.fill_between(
            u_plot[:, 0],
            y_plot_pred - 3 * sigma_MGP,
            y_plot_pred + 3 * sigma_MGP,
            color="r",
            alpha=0.5,
            label="Variance with hyperparameters uncertainty",
        )
        ax.fill_between(
            u_plot[:, 0],
            y_plot_pred - 3 * sigma_KRG,
            y_plot_pred + 3 * sigma_KRG,
            color="b",
            alpha=0.5,
            label="Variance without hyperparameters uncertainty",
        )

        ax.set(xlabel="x", ylabel="y", title="MGP")
        fig.legend(loc="upper center", ncol=2)
        fig.tight_layout()
        fig.subplots_adjust(top=0.74)
        plt.show()

if __name__ == "__main__":
    unittest.main()


#
# Author:  Travis Oliphant  2002-2011 with contributions from
#          SciPy Developers 2004-2011
#
from __future__ import division, print_function, absolute_import

from scipy import special
from scipy.special import entr, gammaln as gamln
from scipy.misc import logsumexp

from numpy import floor, ceil, log, exp, sqrt, log1p, expm1, tanh, cosh, sinh

import numpy as np

from ._distn_infrastructure import (
        rv_discrete, _lazywhere, _ncx2_pdf, _ncx2_cdf, get_distribution_names)

class binom_gen(rv_discrete):
    """A binomial discrete random variable.

    %(before_notes)s

    Notes
    -----
    The probability mass function for `binom` is::

       binom.pmf(k) = choose(n, k) * p**k * (1-p)**(n-k)

    for ``k`` in ``{0, 1,..., n}``.

    `binom` takes ``n`` and ``p`` as shape parameters.

    %(after_notes)s

    %(example)s

    """
    def _rvs(self, n, p):
        return self._random_state.binomial(n, p, self._size)

    def _argcheck(self, n, p):
        self.b = n
        return (n >= 0) & (p >= 0) & (p <= 1)

    def _logpmf(self, x, n, p):
        k = floor(x)
        combiln = (gamln(n+1) - (gamln(k+1) + gamln(n-k+1)))
        return combiln + special.xlogy(k, p) + special.xlog1py(n-k, -p)

    def _pmf(self, x, n, p):
        return exp(self._logpmf(x, n, p))

    def _cdf(self, x, n, p):
        k = floor(x)
        vals = special.bdtr(k, n, p)
        return vals

    def _sf(self, x, n, p):
        k = floor(x)
        return special.bdtrc(k, n, p)

    def _ppf(self, q, n, p):
        vals = ceil(special.bdtrik(q, n, p))
        vals1 = np.maximum(vals - 1, 0)
        temp = special.bdtr(vals1, n, p)
        return np.where(temp >= q, vals1, vals)

    def _stats(self, n, p, moments='mv'):
        q = 1.0 - p
        mu = n * p
        var = n * p * q
        g1, g2 = None, None
        if 's' in moments:
            g1 = (q - p) / sqrt(var)
        if 'k' in moments:
            g2 = (1.0 - 6*p*q) / var
        return mu, var, g1, g2

    def _entropy(self, n, p):
        k = np.r_[0:n + 1]
        vals = self._pmf(k, n, p)
        return np.sum(entr(vals), axis=0)
binom = binom_gen(name='binom')

class bernoulli_gen(binom_gen):
    """A Bernoulli discrete random variable.

    %(before_notes)s

    Notes
    -----
    The probability mass function for `bernoulli` is::

       bernoulli.pmf(k) = 1-p  if k = 0
                        = p    if k = 1

    for ``k`` in ``{0, 1}``.

    `bernoulli` takes ``p`` as shape parameter.

    %(after_notes)s

    %(example)s

    """
    def _rvs(self, p):
        return binom_gen._rvs(self, 1, p)

    def _argcheck(self, p):
        return (p >= 0) & (p <= 1)

    def _logpmf(self, x, p):
        return binom._logpmf(x, 1, p)

    def _pmf(self, x, p):
        return binom._pmf(x, 1, p)

    def _cdf(self, x, p):
        return binom._cdf(x, 1, p)

    def _sf(self, x, p):
        return binom._sf(x, 1, p)

    def _ppf(self, q, p):
        return binom._ppf(q, 1, p)

    def _stats(self, p):
        return binom._stats(1, p)

    def _entropy(self, p):
        return entr(p) + entr(1-p)
bernoulli = bernoulli_gen(b=1, name='bernoulli')

class nbinom_gen(rv_discrete):
    """A negative binomial discrete random variable.

    %(before_notes)s

    Notes
    -----
    The probability mass function for `nbinom` is::

         nbinom.pmf(k) = choose(k+n-1, n-1) * p**n * (1-p)**k

    for ``k >= 0``.

    `nbinom` takes ``n`` and ``p`` as shape parameters.

    %(after_notes)s

    %(example)s

    """
    def _rvs(self, n, p):
        return self._random_state.negative_binomial(n, p, self._size)

    def _argcheck(self, n, p):
        return (n > 0) & (p >= 0) & (p <= 1)

    def _pmf(self, x, n, p):
        return exp(self._logpmf(x, n, p))

    def _logpmf(self, x, n, p):
        coeff = gamln(n+x) - gamln(x+1) - gamln(n)
        return coeff + n*log(p) + special.xlog1py(x, -p)

    def _cdf(self, x, n, p):
        k = floor(x)
        return special.betainc(n, k+1, p)

    def _sf_skip(self, x, n, p):
        # skip because special.nbdtrc doesn't work for 0<n<1
        k = floor(x)
        return special.nbdtrc(k, n, p)

    def _ppf(self, q, n, p):
        vals = ceil(special.nbdtrik(q, n, p))
        vals1 = (vals-1).clip(0.0, np.inf)
        temp = self._cdf(vals1, n, p)
        return np.where(temp >= q, vals1, vals)

    def _stats(self, n, p):
        Q = 1.0 / p
        P = Q - 1.0
        mu = n*P
        var = n*P*Q
        g1 = (Q+P)/sqrt(n*P*Q)
        g2 = (1.0 + 6*P*Q) / (n*P*Q)
        return mu, var, g1, g2
nbinom = nbinom_gen(name='nbinom')

class geom_gen(rv_discrete):
    """A geometric discrete random variable.

    %(before_notes)s

    Notes
    -----
    The probability mass function for `geom` is::

        geom.pmf(k) = (1-p)**(k-1)*p

    for ``k >= 1``.

    `geom` takes ``p`` as shape parameter.

    %(after_notes)s

    %(example)s

    """
    def _rvs(self, p):
        return self._random_state.geometric(p, size=self._size)

    def _argcheck(self, p):
        return (p <= 1) & (p >= 0)

    def _pmf(self, k, p):
        return np.power(1-p, k-1) * p

    def _logpmf(self, k, p):
        return special.xlog1py(k - 1, -p) + log(p)

    def _cdf(self, x, p):
        k = floor(x)
        return -expm1(log1p(-p)*k)

    def _sf(self, x, p):
        return np.exp(self._logsf(x, p))

    def _logsf(self, x, p):
        k = floor(x)
        return k*log1p(-p)

    def _ppf(self, q, p):
        vals = ceil(log(1.0-q)/log(1-p))
        temp = self._cdf(vals-1, p)
        return np.where((temp >= q) & (vals > 0), vals-1, vals)

    def _stats(self, p):
        mu = 1.0/p
        qr = 1.0-p
        var = qr / p / p
        g1 = (2.0-p) / sqrt(qr)
        g2 = np.polyval([1, -6, 6], p)/(1.0-p)
        return mu, var, g1, g2
geom = geom_gen(a=1, name='geom', longname="A geometric")

class hypergeom_gen(rv_discrete):
    """A hypergeometric discrete random variable.

    The hypergeometric distribution models drawing objects from a bin.
    M is the total number of objects, n is total number of Type I objects.
    The random variate represents the number of Type I objects in N drawn
    without replacement from the total population.

    %(before_notes)s

    Notes
    -----
    The probability mass function is defined as::

        pmf(k, M, n, N) = choose(n, k) * choose(M - n, N - k) / choose(M, N),
                                       for max(0, N - (M-n)) <= k <= min(n, N)

    %(after_notes)s

    Examples
    --------
    >>> from scipy.stats import hypergeom
    >>> import matplotlib.pyplot as plt

    Suppose we have a collection of 20 animals, of which 7 are dogs.  Then if
    we want to know the probability of finding a given number of dogs if we
    choose at random 12 of the 20 animals, we can initialize a frozen
    distribution and plot the probability mass function:

    >>> [M, n, N] = [20, 7, 12]
    >>> rv = hypergeom(M, n, N)
    >>> x = np.arange(0, n+1)
    >>> pmf_dogs = rv.pmf(x)

    >>> fig = plt.figure()
    >>> ax = fig.add_subplot(111)
    >>> ax.plot(x, pmf_dogs, 'bo')
    >>> ax.vlines(x, 0, pmf_dogs, lw=2)
    >>> ax.set_xlabel('# of dogs in our group of chosen animals')
    >>> ax.set_ylabel('hypergeom PMF')
    >>> plt.show()

    Instead of using a frozen distribution we can also use `hypergeom`
    methods directly.  To for example obtain the cumulative distribution
    function, use:

    >>> prb = hypergeom.cdf(x, M, n, N)

    And to generate random numbers:

    >>> R = hypergeom.rvs(M, n, N, size=10)

    """
    def _rvs(self, M, n, N):
        return self._random_state.hypergeometric(n, M-n, N, size=self._size)

    def _argcheck(self, M, n, N):
        cond = (M > 0) & (n >= 0) & (N >= 0)
        cond &= (n <= M) & (N <= M)
        self.a = max(N-(M-n), 0)
        self.b = min(n, N)
        return cond

    def _logpmf(self, k, M, n, N):
        tot, good = M, n
        bad = tot - good
        return gamln(good+1) - gamln(good-k+1) - gamln(k+1) + gamln(bad+1) \
            - gamln(bad-N+k+1) - gamln(N-k+1) - gamln(tot+1) + gamln(tot-N+1) \
            + gamln(N+1)

    def _pmf(self, k, M, n, N):
        # same as the following but numerically more precise
        # return comb(good, k) * comb(bad, N-k) / comb(tot, N)
        return exp(self._logpmf(k, M, n, N))

    def _stats(self, M, n, N):
        # tot, good, sample_size = M, n, N
        # "wikipedia".replace('N', 'M').replace('n', 'N').replace('K', 'n')
        M, n, N = 1.*M, 1.*n, 1.*N
        m = M - n
        p = n/M
        mu = N*p

        var = m*n*N*(M - N)*1.0/(M*M*(M-1))
        g1 = (m - n)*(M-2*N) / (M-2.0) * sqrt((M-1.0) / (m*n*N*(M-N)))

        g2 = M*(M+1) - 6.*N*(M-N) - 6.*n*m
        g2 *= (M-1)*M*M
        g2 += 6.*n*N*(M-N)*m*(5.*M-6)
        g2 /= n * N * (M-N) * m * (M-2.) * (M-3.)
        return mu, var, g1, g2

    def _entropy(self, M, n, N):
        k = np.r_[N - (M - n):min(n, N) + 1]
        vals = self.pmf(k, M, n, N)
        return np.sum(entr(vals), axis=0)

    def _sf(self, k, M, n, N):
        """More precise calculation, 1 - cdf doesn't cut it."""
        # This for loop is needed because `k` can be an array. If that's the
        # case, the sf() method makes M, n and N arrays of the same shape. We
        # therefore unpack all inputs args, so we can do the manual
        # integration.
        res = []
        for quant, tot, good, draw in zip(k, M, n, N):
            # Manual integration over probability mass function. More accurate
            # than integrate.quad.
            k2 = np.arange(quant + 1, draw + 1)
            res.append(np.sum(self._pmf(k2, tot, good, draw)))
        return np.asarray(res)

    def _logsf(self, k, M, n, N):
        """
        More precise calculation than log(sf)
        """
        res = []
        for quant, tot, good, draw in zip(k, M, n, N):
            # Integration over probability mass function using logsumexp
            k2 = np.arange(quant + 1, draw + 1)
            res.append(logsumexp(self._logpmf(k2, tot, good, draw)))
        return np.asarray(res)
hypergeom = hypergeom_gen(name='hypergeom')

# FIXME: Fails _cdfvec
class logser_gen(rv_discrete):
    """A Logarithmic (Log-Series, Series) discrete random variable.

    %(before_notes)s

    Notes
    -----
    The probability mass function for `logser` is::

        logser.pmf(k) = - p**k / (k*log(1-p))

    for ``k >= 1``.

    `logser` takes ``p`` as shape parameter.

    %(after_notes)s

    %(example)s

    """
    def _rvs(self, p):
        # looks wrong for p>0.5, too few k=1
        # trying to use generic is worse, no k=1 at all
        return self._random_state.logseries(p, size=self._size)

    def _argcheck(self, p):
        return (p > 0) & (p < 1)

    def _pmf(self, k, p):
        return -np.power(p, k) * 1.0 / k / log(1 - p)

    def _stats(self, p):
        r = log(1 - p)
        mu = p / (p - 1.0) / r
        mu2p = -p / r / (p - 1.0)**2
        var = mu2p - mu*mu
        mu3p = -p / r * (1.0+p) / (1.0 - p)**3
        mu3 = mu3p - 3*mu*mu2p + 2*mu**3
        g1 = mu3 / np.power(var, 1.5)

        mu4p = -p / r * (
            1.0 / (p-1)**2 - 6*p / (p - 1)**3 + 6*p*p / (p-1)**4)
        mu4 = mu4p - 4*mu3p*mu + 6*mu2p*mu*mu - 3*mu**4
        g2 = mu4 / var**2 - 3.0
        return mu, var, g1, g2
logser = logser_gen(a=1, name='logser', longname='A logarithmic')

class poisson_gen(rv_discrete):
    """A Poisson discrete random variable.

    %(before_notes)s

    Notes
    -----
    The probability mass function for `poisson` is::

        poisson.pmf(k) = exp(-mu) * mu**k / k!

    for ``k >= 0``.

    `poisson` takes ``mu`` as shape parameter.

    %(after_notes)s

    %(example)s

    """
    def _rvs(self, mu):
        return self._random_state.poisson(mu, self._size)

    def _logpmf(self, k, mu):
        Pk = k*log(mu)-gamln(k+1) - mu
        return Pk

    def _pmf(self, k, mu):
        return exp(self._logpmf(k, mu))

    def _cdf(self, x, mu):
        k = floor(x)
        return special.pdtr(k, mu)

    def _sf(self, x, mu):
        k = floor(x)
        return special.pdtrc(k, mu)

    def _ppf(self, q, mu):
        vals = ceil(special.pdtrik(q, mu))
        vals1 = np.maximum(vals - 1, 0)
        temp = special.pdtr(vals1, mu)
        return np.where(temp >= q, vals1, vals)

    def _stats(self, mu):
        var = mu
        tmp = np.asarray(mu)
        g1 = sqrt(1.0 / tmp)
        g2 = 1.0 / tmp
        return mu, var, g1, g2
poisson = poisson_gen(name="poisson", longname='A Poisson')

class planck_gen(rv_discrete):
    """A Planck discrete exponential random variable.

    %(before_notes)s

    Notes
    -----
    The probability mass function for `planck` is::

        planck.pmf(k) = (1-exp(-lambda_))*exp(-lambda_*k)

    for ``k*lambda_ >= 0``.

    `planck` takes ``lambda_`` as shape parameter.

    %(after_notes)s

    %(example)s

    """
    def _argcheck(self, lambda_):
        if (lambda_ > 0):
            self.a = 0
            self.b = np.inf
            return 1
        elif (lambda_ < 0):
            self.a = -np.inf
            self.b = 0
            return 1
        else:
            return 0

    def _pmf(self, k, lambda_):
        fact = (1-exp(-lambda_))
        return fact*exp(-lambda_*k)

    def _cdf(self, x, lambda_):
        k = floor(x)
        return 1-exp(-lambda_*(k+1))

    def _ppf(self, q, lambda_):
        vals = ceil(-1.0/lambda_ * log1p(-q)-1)
        vals1 = (vals-1).clip(self.a, np.inf)
        temp = self._cdf(vals1, lambda_)
        return np.where(temp >= q, vals1, vals)

    def _stats(self, lambda_):
        mu = 1/(exp(lambda_)-1)
        var = exp(-lambda_)/(expm1(-lambda_))**2
        g1 = 2*cosh(lambda_/2.0)
        g2 = 4+2*cosh(lambda_)
        return mu, var, g1, g2

    def _entropy(self, lambda_):
        l = lambda_
        C = (1-exp(-l))
        return l*exp(-l)/C - log(C)
planck = planck_gen(name='planck', longname='A discrete exponential ')

class boltzmann_gen(rv_discrete):
    """A Boltzmann (Truncated Discrete Exponential) random variable.

    %(before_notes)s

    Notes
    -----
    The probability mass function for `boltzmann` is::

        boltzmann.pmf(k) = (1-exp(-lambda_)*exp(-lambda_*k)/(1-exp(-lambda_*N))

    for ``k = 0,..., N-1``.

    `boltzmann` takes ``lambda_`` and ``N`` as shape parameters.

    %(after_notes)s

    %(example)s

    """
    def _pmf(self, k, lambda_, N):
        fact = (1-exp(-lambda_))/(1-exp(-lambda_*N))
        return fact*exp(-lambda_*k)

    def _cdf(self, x, lambda_, N):
        k = floor(x)
        return (1-exp(-lambda_*(k+1)))/(1-exp(-lambda_*N))

    def _ppf(self, q, lambda_, N):
        qnew = q*(1-exp(-lambda_*N))
        vals = ceil(-1.0/lambda_ * log(1-qnew)-1)
        vals1 = (vals-1).clip(0.0, np.inf)
        temp = self._cdf(vals1, lambda_, N)
        return np.where(temp >= q, vals1, vals)

    def _stats(self, lambda_, N):
        z = exp(-lambda_)
        zN = exp(-lambda_*N)
        mu = z/(1.0-z)-N*zN/(1-zN)
        var = z/(1.0-z)**2 - N*N*zN/(1-zN)**2
        trm = (1-zN)/(1-z)
        trm2 = (z*trm**2 - N*N*zN)
        g1 = z*(1+z)*trm**3 - N**3*zN*(1+zN)
        g1 = g1 / trm2**(1.5)
        g2 = z*(1+4*z+z*z)*trm**4 - N**4 * zN*(1+4*zN+zN*zN)
        g2 = g2 / trm2 / trm2
        return mu, var, g1, g2
boltzmann = boltzmann_gen(name='boltzmann',
        longname='A truncated discrete exponential ')

class randint_gen(rv_discrete):
    """A uniform discrete random variable.

    %(before_notes)s

    Notes
    -----
    The probability mass function for `randint` is::

        randint.pmf(k) = 1./(high - low)

    for ``k = low, ..., high - 1``.

    `randint` takes ``low`` and ``high`` as shape parameters.

    Note the difference to the numpy ``random_integers`` which
    returns integers on a *closed* interval ``[low, high]``.

    %(after_notes)s

    %(example)s

    """
    def _argcheck(self, low, high):
        self.a = low
        self.b = high - 1
        return (high > low)

    def _pmf(self, k, low, high):
        p = np.ones_like(k) / (high - low)
        return np.where((k >= low) & (k < high), p, 0.)

    def _cdf(self, x, low, high):
        k = floor(x)
        return (k - low + 1.) / (high - low)

    def _ppf(self, q, low, high):
        vals = ceil(q * (high - low) + low) - 1
        vals1 = (vals - 1).clip(low, high)
        temp = self._cdf(vals1, low, high)
        return np.where(temp >= q, vals1, vals)

    def _stats(self, low, high):
        m2, m1 = np.asarray(high), np.asarray(low)
        mu = (m2 + m1 - 1.0) / 2
        d = m2 - m1
        var = (d*d - 1) / 12.0
        g1 = 0.0
        g2 = -6.0/5.0 * (d*d + 1.0) / (d*d - 1.0)
        return mu, var, g1, g2

    def _rvs(self, low, high=None):
        """An array of *size* random integers >= ``low`` and < ``high``.

        If ``high`` is ``None``, then range is >=0  and < low
        """
        return self._random_state.randint(low, high, self._size)

    def _entropy(self, low, high):
        return log(high - low)
randint = randint_gen(name='randint', longname='A discrete uniform '
                      '(random integer)')

# FIXME: problems sampling.
class zipf_gen(rv_discrete):
    """A Zipf discrete random variable.

    %(before_notes)s

    Notes
    -----
    The probability mass function for `zipf` is::

        zipf.pmf(k, a) = 1/(zeta(a) * k**a)

    for ``k >= 1``.

    `zipf` takes ``a`` as shape parameter.

    %(after_notes)s

    %(example)s

    """
    def _rvs(self, a):
        return self._random_state.zipf(a, size=self._size)

    def _argcheck(self, a):
        return a > 1

    def _pmf(self, k, a):
        Pk = 1.0 / special.zeta(a, 1) / k**a
        return Pk

    def _munp(self, n, a):
        return _lazywhere(
            a > n + 1, (a, n),
            lambda a, n: special.zeta(a - n, 1) / special.zeta(a, 1),
            np.inf)
zipf = zipf_gen(a=1, name='zipf', longname='A Zipf')

class dlaplace_gen(rv_discrete):
    """A  Laplacian discrete random variable.

    %(before_notes)s

    Notes
    -----
    The probability mass function for `dlaplace` is::

        dlaplace.pmf(k) = tanh(a/2) * exp(-a*abs(k))

    for ``a > 0``.

    `dlaplace` takes ``a`` as shape parameter.

    %(after_notes)s

    %(example)s

    """
    def _pmf(self, k, a):
        return tanh(a/2.0) * exp(-a * abs(k))

    def _cdf(self, x, a):
        k = floor(x)
        f = lambda k, a: 1.0 - exp(-a * k) / (exp(a) + 1)
        f2 = lambda k, a: exp(a * (k+1)) / (exp(a) + 1)
        return _lazywhere(k >= 0, (k, a), f=f, f2=f2)

    def _ppf(self, q, a):
        const = 1 + exp(a)
        vals = ceil(np.where(q < 1.0 / (1 + exp(-a)), log(q*const) / a - 1,
                                                      -log((1-q) * const) / a))
        vals1 = vals - 1
        return np.where(self._cdf(vals1, a) >= q, vals1, vals)

    def _stats(self, a):
        ea = exp(a)
        mu2 = 2.*ea/(ea-1.)**2
        mu4 = 2.*ea*(ea**2+10.*ea+1.) / (ea-1.)**4
        return 0., mu2, 0., mu4/mu2**2 - 3.

    def _entropy(self, a):
        return a / sinh(a) - log(tanh(a/2.0))
dlaplace = dlaplace_gen(a=-np.inf,
                        name='dlaplace', longname='A discrete Laplacian')

class skellam_gen(rv_discrete):
    """A  Skellam discrete random variable.

    %(before_notes)s

    Notes
    -----
    Probability distribution of the difference of two correlated or
    uncorrelated Poisson random variables.

    Let k1 and k2 be two Poisson-distributed r.v. with expected values
    lam1 and lam2. Then, ``k1 - k2`` follows a Skellam distribution with
    parameters ``mu1 = lam1 - rho*sqrt(lam1*lam2)`` and
    ``mu2 = lam2 - rho*sqrt(lam1*lam2)``, where rho is the correlation
    coefficient between k1 and k2. If the two Poisson-distributed r.v.
    are independent then ``rho = 0``.

    Parameters mu1 and mu2 must be strictly positive.

    For details see: http://en.wikipedia.org/wiki/Skellam_distribution

    `skellam` takes ``mu1`` and ``mu2`` as shape parameters.

    %(after_notes)s

    %(example)s

    """
    def _rvs(self, mu1, mu2):
        n = self._size
        return (self._random_state.poisson(mu1, n) -
                self._random_state.poisson(mu2, n))

    def _pmf(self, x, mu1, mu2):
        px = np.where(x < 0,
                _ncx2_pdf(2*mu2, 2*(1-x), 2*mu1)*2,
                _ncx2_pdf(2*mu1, 2*(1+x), 2*mu2)*2)
        # ncx2.pdf() returns nan's for extremely low probabilities
        return px

    def _cdf(self, x, mu1, mu2):
        x = floor(x)
        px = np.where(x < 0,
                _ncx2_cdf(2*mu2, -2*x, 2*mu1),
                1-_ncx2_cdf(2*mu1, 2*(x+1), 2*mu2))
        return px

    def _stats(self, mu1, mu2):
        mean = mu1 - mu2
        var = mu1 + mu2
        g1 = mean / sqrt((var)**3)
        g2 = 1 / var
        return mean, var, g1, g2
skellam = skellam_gen(a=-np.inf, name="skellam", longname='A Skellam')

# Collect names of classes and objects in this module.
pairs = list(globals().items())
_distn_names, _distn_gen_names = get_distribution_names(pairs, rv_discrete)

__all__ = _distn_names + _distn_gen_names


# coding:utf-8

import math
import sys
import os
import csv
import random
from bs4 import BeautifulSoup
import pandas as pd
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from sklearn import datasets
from sklearn.decomposition import PCA
from sklearn.neighbors import NearestNeighbors
import matplotlib
import scipy.stats as st

matplotlib.use('Qt5Agg')
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
from matplotlib import ft2font
from matplotlib.font_manager import ttfFontProperty

import matplotlib.font_manager as font_manager
import matplotlib.image as mpimg

from pandas.plotting import radviz
from sklearn.neighbors import KNeighborsRegressor

def Del(prepath='/Volumes/Virtual/FastTmp/', path='raw', name='test.txt', head=3, end=-2):
    lines = open(path + '/' + name, 'r', encoding='windows-1252').readlines()
    open(prepath + 'new' + path + '/' + 'new' + name, 'w', encoding='utf-8').writelines(lines[head:end])

def OldJoin(prepath='/Volumes/Virtual/FastTmp/', path='Raw'):
    SourceList = os.listdir(path)
    for i in SourceList:
        if 'csv' in i and 'new' not in i and i[0] != '.':
            Del(prepath=prepath, path=path, name=i, head=3, end=-2)

    TargetList = []
    for i in SourceList:
        if 'csv' in i:
            df = pd.read_csv(prepath + 'new' + path + '/' + 'new' + i)

            TargetList.append(df)

    result = pd.concat(TargetList)

    result.reindex()

    result.to_csv(prepath + 'result.csv', sep=',', encoding='utf-8')

    return (result)

def Join(prepath='/Volumes/Virtual/FastTmp/', path='Excel', name='result'):
    SourceList = os.listdir(prepath + path)
    TargetList = []
    for i in SourceList:

        if 'csv' in i and '~' not in i and i[0] != '.':

            print(prepath + path + '/' + i)

            try:
                df = pd.read_csv(prepath + path + '/' + i)
            except():
                pass

        elif 'xls' in i and '~' not in i and i[0] != '.':
            try:
                df = pd.read_excel(prepath + path + '/' + i)
            except():
                pass

            TargetList.append(df)

    result = pd.concat(TargetList)

    result.reindex()

    result.to_excel(prepath + name + '.xlsx', encoding='utf-8')

    return (result)

def CsvToExcel(name='result'):
    if 'csv' in name and '~' not in name and name[0] != '.':
        df = pd.read_csv(name)
        df.to_excel('new' + name[0:-4] + '.xlsx', encoding='utf-8')
    pass

def ExcelToCsv(name='result'):
    if 'xls' in name and '~' not in name and name[0] != '.':
        df = pd.read_excel(name)
        df.to_csv('new' + name[0:-5] + '.csv', sep=',', encoding='utf-8')
    pass

prepath = '/Volumes/Virtual/FastTmp/'
path = 'Target'

df = pd.read_excel(prepath + 'XiaYing-SiO2-FeMg.xlsx')

# m = ['Width', 'Style', 'Alpha', 'Size', 'Color', 'Marker', 'Author']

# for i in m:
#    df = df.drop(i, 1)

df.set_index('Label', inplace=True)

newdf = pd.concat([df.SiO2, df.Ratio], axis=1)

numpyMatrix = df.as_matrix()

# X = numpyMatrix[:, :3]  # we only take the first two features.
# y = df.index

X = numpyMatrix

y = df.index

color = []

for i in range(len(y)):
    if i == 0:
        color.append(1)
    else:
        if y[i] == y[0]:
            color.append(1)
        else:
            color.append(2)

# x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5
# y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5

X_reduced = PCA(n_components=5).fit_transform(numpyMatrix)

df = pd.read_excel(prepath + 'XiaYing-SiO2-FeMg.xlsx')
df.set_index('Label', inplace=True)
x = df.SiO2
y = df.Ratio

xtouse = x.values
ytouse = y.values

XtoFit=[]
YtoFit=[]

for i in range(len(x.values)):
    if x.values[i] < 60:
        XtoFit.append(x.values[i])
        YtoFit.append(y.values[i])

z = np.polyfit(YtoFit, XtoFit, 3)

Yline = np.linspace(min(YtoFit), max(YtoFit), 30)
p = np.poly1d(z)
Xline = p(Yline)

newXline = []

#####################################

xmin,xmax = min(x),max(x)
ymin,ymax = min(y),max(y)

# Peform the kernel density estimate
xx, yy = np.mgrid[xmin:xmax:100j, ymin:ymax:100j]
positions = np.vstack([xx.ravel(), yy.ravel()])
values = np.vstack([x, y])
kernel = st.gaussian_kde(values)
f = np.reshape(kernel(positions).T, xx.shape)

fig = plt.figure()
ax = fig.gca()
# Contourf plot
cfset = ax.contourf(xx, yy, f, cmap='Blues',alpha=0.3)
## Or kernel density estimate plot instead of the contourf plot
#ax.imshow(np.rot90(f), cmap='Blues', extent=[xmin, xmax, ymin, ymax])
# Contour plot
cset = ax.contour(xx, yy, f, colors='k',alpha=0.3)
# Label plot
ax.clabel(cset, inline=1, fontsize=10)

#####################################

plt.plot(Xline, Yline, 'b-')

alphatouse = []

leveldistance=[]

for i in range(len(xtouse)):
    tmp = abs(p(ytouse[i]) - xtouse[i])
    leveldistance.append(tmp)
    alphatouse.append(tmp)

a = []

group= 100

step= abs(min(alphatouse)-max(alphatouse))/group

for i in alphatouse:
    if min(alphatouse)<=i<min(alphatouse)+step:
        a.append(0.8)
    elif min(alphatouse)+step<=i<min(alphatouse)+2*step:
        a.append(0.6)
    elif min(alphatouse)+2*step<=i<min(alphatouse)+3*step:
        a.append(0.4)
    else:
        a.append(0.2)

#plt.scatter(x, y, label='', s=3, color='red', alpha=a)

for i in range(len(xtouse)):
    plt.scatter(xtouse[i], ytouse[i], label='', s=3, color='red', alpha=a[i])
    pass

#fig = plt.figure(1, figsize=(8, 6))
# ax = Axes3D(fig, elev=-150, azim=110)

# plt.scatter(X_reduced[:, 1], X_reduced[:, 2], c=color, cmap=plt.cm.Set1, edgecolor='k', s=40)

# plt.scatter(x, y, label='', s=3, color='blue', alpha=0.3)

# z= np.polyfit(x, y, 2)

# ax.set_title("First three PCA directions")
# ax.set_xlabel("SiO2")
# ax.w_xaxis.set_ticklabels([])
# ax.set_ylabel("TFeO")
# ax.w_yaxis.set_ticklabels([])
# ax.set_zlabel("MgO")
# ax.w_zaxis.set_ticklabels([])

plt.show()

tm=Join(path='塔木兰沟组',name='新塔木兰沟')

'''
SourceList = os.listdir(prepath + path)
TargetList = []
for i in SourceList:
    ExcelToCsv(path='塔木兰沟组',name=i)

#df = pd.read_excel(prepath+"塔木兰沟组数据交集.xlsx",keep_default_na=False, na_values=[""])
#tm=Join(path='Target',name='满克头鄂博组数据交集')

#DataToPlot = pd.read_excel(prepath+'result.xlsx')
#DataToPlot.plot()
#DataToPlot.plot.area()
#plt.figure()
#radviz(DataToPlot , 'Ag109')
#plt.show()

# created by Huang Lu
# 27/08/2016 17:05:45
# Department of EE, Tsinghua Univ.

import cv2
import numpy as np

cap = cv2.VideoCapture(1)
while(1):
    # get a frame
    ret, frame = cap.read()
    # show a frame
    cv2.imshow("capture", frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

for i in alphatouse:
    #tmp = - np.power(np.e,i / max(alphatouse))
    #tmp = 1- np.power(i / max(alphatouse),2)

    tmp = np.power(np.e,i)
    a.append(tmp)

'''


"""
=============================================================
Receiver Operating Characteristic (ROC) with cross validation
=============================================================

Example of Receiver Operating Characteristic (ROC) metric to evaluate
classifier output quality using cross-validation.

ROC curves typically feature true positive rate on the Y axis, and false
positive rate on the X axis. This means that the top left corner of the plot is
the "ideal" point - a false positive rate of zero, and a true positive rate of
one. This is not very realistic, but it does mean that a larger area under the
curve (AUC) is usually better.

The "steepness" of ROC curves is also important, since it is ideal to maximize
the true positive rate while minimizing the false positive rate.

This example shows the ROC response of different datasets, created from K-fold
cross-validation. Taking all of these curves, it is possible to calculate the
mean area under curve, and see the variance of the curve when the
training set is split into different subsets. This roughly shows how the
classifier output is affected by changes in the training data, and how
different the splits generated by K-fold cross-validation are from one another.

.. note::

    See also :func:`sklearn.metrics.auc_score`,
             :func:`sklearn.cross_validation.cross_val_score`,
             :ref:`example_model_selection_plot_roc.py`,

"""
print(__doc__)

import numpy as np
from scipy import interp
import matplotlib.pyplot as plt

from sklearn import svm, datasets
from sklearn.metrics import roc_curve, auc
from sklearn.cross_validation import StratifiedKFold

###############################################################################
# Data IO and generation

# import some data to play with
iris = datasets.load_iris()
X = iris.data
y = iris.target
X, y = X[y != 2], y[y != 2]
n_samples, n_features = X.shape

# Add noisy features
random_state = np.random.RandomState(0)
X = np.c_[X, random_state.randn(n_samples, 200 * n_features)]

###############################################################################
# Classification and ROC analysis

# Run classifier with cross-validation and plot ROC curves
cv = StratifiedKFold(y, n_folds=6)
classifier = svm.SVC(kernel='linear', probability=True,
                     random_state=random_state)

mean_tpr = 0.0
mean_fpr = np.linspace(0, 1, 100)
all_tpr = []

for i, (train, test) in enumerate(cv):
    probas_ = classifier.fit(X[train], y[train]).predict_proba(X[test])
    # Compute ROC curve and area the curve
    fpr, tpr, thresholds = roc_curve(y[test], probas_[:, 1])
    mean_tpr += interp(mean_fpr, fpr, tpr)
    mean_tpr[0] = 0.0
    roc_auc = auc(fpr, tpr)
    plt.plot(fpr, tpr, lw=1, label='ROC fold %d (area = %0.2f)' % (i, roc_auc))

plt.plot([0, 1], [0, 1], '--', color=(0.6, 0.6, 0.6), label='Luck')

mean_tpr /= len(cv)
mean_tpr[-1] = 1.0
mean_auc = auc(mean_fpr, mean_tpr)
plt.plot(mean_fpr, mean_tpr, 'k--',
         label='Mean ROC (area = %0.2f)' % mean_auc, lw=2)

plt.xlim([-0.05, 1.05])
plt.ylim([-0.05, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic example')
plt.legend(loc="lower right")
plt.show()


import pytest

import pandas as pd
import numpy as np

import logging
from io import StringIO
from joblib import delayed, Parallel

@pytest.fixture
def input_data():
    pass

@pytest.fixture
def expected_result():
    pass

def merge_chip_and_input(windows, nb_cpu):
    """Merge lists of chromosome bin df chromosome-wise.

    Returns a list of dataframes, one per chromosome, with the collective count
    per bin for all files.

    Keyword Arguments:
    windows -- OrderedDict where the keys are files, the values are lists of
               dfs, one per chromosome.
    nb_cpu  -- cores to use
    """

    windows = iter(windows)
    merged = next(windows)

    for chromosome_dfs in windows:
        merged = merge_two_bin_dfs(merged, chromosome_dfs, nb_cpu)

    return merged

# @pytest.mark.unit
# def test_merge_two_bin_files(sample1_dfs, sample2_dfs):
#     """TODO: Need to test that the lists might not have the same/all chromosomes.

#     It might be possible that there are no sig islands on one chromosome in one
#     file, while there are in the others. Solve by taking in dict with chromos
#     instead of list with files?

#     You will probably be asked about a bug due to this some time.
#     """

#     print("Read run epic code. Begin there!\n" * 5)
#     result = merge_chip_and_input([sample2_dfs, sample2_dfs], 1)
#     print(result)
#     assert 1

def merge_two_bin_dfs(sample1_dfs, sample2_dfs, nb_cpu):
    merged_chromosome_dfs = Parallel(n_jobs=nb_cpu)(
        delayed(_merge_two_bin_dfs)(df1, df2)
        for df1, df2 in zip(sample1_dfs, sample2_dfs))

    return merged_chromosome_dfs

def _merge_two_bin_dfs(df1, df2):

    merged_df = df1.merge(df2, how="outer", on=["Chromosome", "Bin"])  #,
    # suffixes=("_x", "_y"))
    print(merged_df)
    raise
    merged_df = merged_df.fillna(0)

    merged_df["Count"] = merged_df["Count_x"] + merged_df["Count_y"]

    merged_df = merged_df.drop(["Count_x", "Count_y"], axis=1)

    return merged_df

@pytest.fixture
def sample1_dfs():
    return [pd.read_table(
        StringIO(u"""
Count Chromosome    Bin
1       chrM    400
1       chrM   2600
1       chrM   3600
1       chrM   3800
1       chrM  12800
1       chrM  14200"""),
        sep="\s+",
        header=0), pd.read_table(
            StringIO(u"""Count Chromosome        Bin
1       chrX    2820000
1       chrX    2854800
1       chrX    3001400
1       chrX    3354400
1       chrX    3489400
1       chrX    3560200
1       chrX    4011200
1       chrX    4644600
1       chrX    4653600
1       chrX    4793400
1       chrX    5136800
1       chrX    5572800
1       chrX    5589400
1       chrX    5792000
1       chrX    5961800
1       chrX    6951000
1       chrX    7125800
1       chrX    7199000
1       chrX    7443200
1       chrX    7606000
1       chrX    7627800
1       chrX    8035600
1       chrX    8073600
1       chrX    8367800
1       chrX    9021000
1       chrX    9472400
1       chrX    9620800
1       chrX    9652000
1       chrX    9801000
1       chrX    9953800"""),
            sep="\s+",
            header=0)]

@pytest.fixture
def sample2_dfs():
    return [pd.read_table(
        StringIO(u"""
Count Chromosome    Bin
1       chrM    400
1       chrM   2600
1       chrM   3600
1       chrM   3800
1       chrM  12800
1       chrM  14200"""),
        header=0,
        sep="\s+", ), pd.read_table(
            StringIO(u"""Count Chromosome        Bin
1       chrX    2820000
1       chrX    2854800
1       chrX    3001400
1       chrX    3354400
1       chrX    3489400
1       chrX    3560200
1       chrX    4011200
1       chrX    4644600
1       chrX    4653600
1       chrX    4793400
1       chrX    5136800
1       chrX    5572800
1       chrX    5589400
1       chrX    5792000
1       chrX    5961800
1       chrX    6951000
1       chrX    7125800
1       chrX    7199000
1       chrX    7443200
1       chrX    7606000
1       chrX    7627800
1       chrX    8035600
1       chrX    8073600
1       chrX    8367800
1       chrX    9021000
1       chrX    9472400
1       chrX    9620800
1       chrX    9652000
1       chrX    9801000
1       chrX    9953800"""),
            sep="\s+",
            header=0)]


"""
Representations which use local bases function (e.g. kernels) distributed
in the statespace according to some scheme (e.g. grid, random, on previous
samples)
"""
from __future__ import division
from __future__ import print_function
from __future__ import absolute_import
from __future__ import unicode_literals
from builtins import super
from future import standard_library
standard_library.install_aliases()
from builtins import range
from past.utils import old_div
from .Representation import Representation
import numpy as np
from rlpy.Tools.GeneralTools import addNewElementForAllActions
import matplotlib.pyplot as plt
try:
    from .kernels import batch
except ImportError:
    from .slow_kernels import batch
    print("C-Extensions for kernels not available, expect slow runtime")

__copyright__ = "Copyright 2013, RLPy http://acl.mit.edu/RLPy"
__credits__ = ["Alborz Geramifard", "Robert H. Klein", "Christoph Dann",
               "William Dabney", "Jonathan P. How"]
__license__ = "BSD 3-Clause"

class LocalBases(Representation):
    """
    abstract base class for representations that use local basis functions
    """
    #: centers of bases
    centers = None
    #: widths of bases
    widths = None

    def __init__(self, domain, kernel, normalization=False, seed=1, **kwargs):
        """
        :param domain: domain to learn on.
        :param kernel: function handle to use for kernel function evaluations.
        :param normalization: (Boolean) If true, normalize feature vector so
            that sum( phi(s) ) = 1.

        Associates a kernel function with each

        """
        self.kernel = batch[kernel.__name__]
        self.normalization = normalization
        self.centers = np.zeros((0, domain.statespace_limits.shape[0]))
        self.widths = np.zeros((0, domain.statespace_limits.shape[0]))
        super(LocalBases, self).__init__(domain, seed=seed)

    def phi_nonTerminal(self, s):
        v = self.kernel(s, self.centers, self.widths)
        if self.normalization and not v.sum() == 0.:
            # normalize such that each vector has a l1 norm of 1
            v /= v.sum()
        return v

    def plot_2d_feature_centers(self, d1=None, d2=None):
        """
        :param d1: 1 (of 2 possible) indices of dimensions to plot; ignore all
            others, purely visual.
        :param d2: 1 (of 2 possible) indices of dimensions to plot; ignore all
            others, purely visual.

        Phe centers of all features in dimension d1 and d2.
        If no dimensions are specified, the first two continuous dimensions
        are shown.

        """
        if d1 is None and d2 is None:
            # just take the first two dimensions
            d1, d2 = self.domain.continuous_dims[:2]
        plt.figure("Feature Dimensions {} and {}".format(d1, d2))
        for i in range(self.centers.shape[0]):
            plt.plot([self.centers[i, d1]],
                     [self.centers[i, d2]], "r", marker="x")
        plt.draw()

class NonparametricLocalBases(LocalBases):

    def __init__(self, domain, kernel,
                 max_similarity=0.9, resolution=5, **kwargs):
        """
        :param domain: domain to learn on.
        :param kernel: function handle to use for kernel function evaluations.
        :param max_similarity: threshold to allow feature to be added to
            representation.  Larger max_similarity makes it \"easier\" to add
            more features by permitting larger values of phi(s) before
            discarding.  (An existing feature function in phi() with large value
            at phi(s) implies that it is very representative of the true
            function at *s*.  i.e., the value of a feature in phi(s) is
            inversely related to the \"similarity\" of a potential new feature.
        :param resolution: to be used by the ``kernel()`` function, see parent.
            Determines *width* of basis functions, eg sigma in Gaussian basis.

        """
        self.max_similarity = max_similarity
        self.common_width = old_div((domain.statespace_limits[:, 1]
                             - domain.statespace_limits[:, 0]), resolution)
        self.features_num = 0
        super(
            NonparametricLocalBases,
            self).__init__(
            domain,
            kernel,
            **kwargs)

    def pre_discover(self, s, terminal, a, sn, terminaln):
        norm = self.normalization
        expanded = 0
        self.normalization = False
        if not terminal:
            phi_s = self.phi_nonTerminal(s)
            if np.all(phi_s < self.max_similarity):
                self._add_feature(s)
                expanded += 1
        if not terminaln:
            phi_s = self.phi_nonTerminal(sn)
            if np.all(phi_s < self.max_similarity):
                self._add_feature(sn)
                expanded += 1
        self.normalization = norm
        return expanded

    def _add_feature(self, center):
        self.features_num += 1
        self.centers = np.vstack((self.centers, center))
        self.widths = np.vstack((self.widths, self.common_width))
        # TODO if normalized, use Q estimate for center to fill weight_vec
        new = np.zeros((self.domain.actions_num, 1))
        self.weight_vec = addNewElementForAllActions(
            self.weight_vec,
            self.domain.actions_num,
            new)

class RandomLocalBases(LocalBases):

    def __init__(self, domain, kernel, num=100, resolution_min=5,
                 resolution_max=None, seed=1, **kwargs):
        """
        :param domain: domain to learn on.
        :param kernel: function handle to use for kernel function evaluations.
        :param num: Fixed number of feature (kernel) functions to use in
            EACH dimension. (for a total of features_num=numDims * num)
        :param resolution_min: resolution selected uniform random, lower bound.
        :param resolution_max: resolution selected uniform random, upper bound.
        :param seed: the random seed to use when scattering basis functions.

        Randomly scatter ``num`` feature functions throughout the domain, with
        sigma / noise parameter selected uniform random between
        ``resolution_min`` and ``resolution_max``.  NOTE these are
        sensitive to the choice of coordinate (scale with coordinate units).

        """
        self.features_num = num
        self.dim_widths = (domain.statespace_limits[:, 1]
                      - domain.statespace_limits[:, 0])
        self.resolution_max = resolution_max
        self.resolution_min = resolution_min

        super(
            RandomLocalBases,
            self).__init__(
            domain,
            kernel,
            seed=seed,
            **kwargs)
        self.centers = np.zeros((num, len(self.dim_widths)))
        self.widths = np.zeros((num, len(self.dim_widths)))
        self.init_randomization()

    def init_randomization(self):
        for i in range(self.features_num):
            for d in range(len(self.dim_widths)):
                self.centers[i, d] = self.random_state.uniform(
                    self.domain.statespace_limits[d, 0],
                    self.domain.statespace_limits[d, 1])
                self.widths[i, d] = self.random_state.uniform(
                    old_div(self.dim_widths[d], self.resolution_max),
                    old_div(self.dim_widths[d], self.resolution_min))