#!/usr/bin/env python
from File import File
from LSA import LSA
from Set import Set
from NaiveBayesClassifier import NaiveBayesClassifier
from nltk.corpus import stopwords
import numpy
import datetime
import matplotlib.pyplot as plt
from matplotlib.pyplot import figure

###############################################################################
#  Initializing
###############################################################################

f = File()

print("Data imported.")

MIN_FREQ = 3
MAX_GRAM = 5
P_EIG = 0.95
y = []
yerrormin = []
yerrormax = []

aux = stopwords.words("portuguese")
stop_words = [aux]
aux.append('é')
stop_words.append(aux)
stop_words.append(["e", "de", "da", "do", "dos", "das", "em", "o", "a", "os", "as", "que", "um", "uma", "para", "com", "no", "na", "nos", "nas",
                          "por", "por", "mais", "se", "como", "mais", "à", "às", "ao", "aos", "ou", "quando", "muito", "pela", "pelas", "pelos",
                          "pelo", "isso", "esse", "essa", "esses", "essas", "num", "numa", "nuns", "numas", "este", "esta", "estes", "estas", "isto",
                          "aquilo", "aquele", "aquela", "aqueles", "aquelas", "sem", "entre", "nem", "quem", "qual", "depois", "só", "mesmo"])
stop_words.append([])

for s in stop_words:
    l = LSA(MAX_GRAM, MIN_FREQ, P_EIG, f.x, s)
    test_score = []
    print("LSA created.")

    ###########################
    # LSA
    human_keywords = l.manage_keywords(f.keywords)
    lsa_results = l.train_phrases([])
    print("LSA Results computed.")
    for time in range(50):
        sets = Set(lsa_results, f.y, f.x)
        for i in range(len(sets.x_train)):
            ###########################

            ###########################
            # NAIVE BAYES
            naive = NaiveBayesClassifier(alpha=0.01)
            naive.train(numpy.array(sets.x_train[i]), sets.y_train[i])
            test_score.append(naive.test_score(numpy.array(sets.x_test[i]), numpy.array(sets.y_test[i])))
    avg = numpy.round(numpy.average(numpy.array(test_score)), 2)
    y.append(avg)
    min_ = numpy.round(numpy.array(test_score).min(), 2)
    yerrormin.append(numpy.round(avg - min_, 2))
    max_ = numpy.round(numpy.array(test_score).max(), 2)
    yerrormax.append(numpy.round(max_ - avg, 2))
    print("Avg test performance: ", avg)
    print(min_)
    print(max_)
    print('\n'*3)

print("y = ", y)
print("yerrormin = ", yerrormin)
print("yerrormax = ", yerrormax)

Software Trials/trial_lsa_all_phrases_and_no_trucantedSVD/LSA stop words/script_stop_words.py


"""
Some simple models with multinomial observations and Gaussian priors.
"""
from __future__ import print_function
import abc
import numpy as np

from scipy.misc import logsumexp
from scipy.special import gammaln

from pybasicbayes.abstractions import Distribution
from pylds.states import LDSStates
from pylds.lds_messages_interface import filter_and_sample_diagonal, kalman_filter
from pylds.models import NonstationaryLDS

import pypolyagamma as ppg

from pyglm.utils.utils import logistic, sample_gaussian

class _PGObservationsBase(object):
    """
    Base class for Polya-gamma observations
    """
    __metaclass__ = abc.ABCMeta

    def __init__(self, X=None, psi=None):
        """
        :param X: TxN matrix of observations
        """
        assert X is not None or psi is not None
        if psi is not None and X is None:
            X = self.rvs(psi)

        assert X.ndim == 2
        self.X = X
        self.T, self.N = X.shape

        # Initialize Polya-gamma samplers
        num_threads = ppg.get_omp_num_threads()
        seeds = np.random.randint(2**16, size=num_threads)
        self.ppgs = [ppg.PyPolyaGamma(seed) for seed in seeds]

        # Initialize auxiliary variables, omega
        self.omega = np.ones((self.T, self.N))

    @abc.abstractproperty
    def a(self):
        # Distribution specific exponent a(x)
        raise NotImplementedError()

    @abc.abstractproperty
    def b(self):
        # Distribution specific exponent a(x)
        raise NotImplementedError()

    @abc.abstractmethod
    def log_likelihood_given_activation(self, psi):
        raise NotImplementedError()

    @abc.abstractmethod
    def rvs(self, psi):
        raise NotImplementedError

    @property
    def kappa(self):
        # TODO: Cache this?
        return self.a - self.b / 2.0

    def resample(self, psi):
        ppg.pgdrawvpar(self.ppgs, self.b.ravel(), psi.ravel(),
                       self.omega.ravel())

    def conditional_mean(self):
        """
        Compute the conditional mean \psi given \omega
        :param augmented_data:
        :return:
        """
        return self.kappa / self.omega

    def conditional_prec(self, flat=False):
        """
        Compute the conditional mean \psi given \omega
        """
        O, T, N = self.omega, self.T, self.N

        if flat:
            prec = O
        else:
            prec = np.zeros((T, N, N))
            for t in xrange(T):
                prec[t,:,:] = np.diag(O[t,:])

        return prec

    def conditional_cov(self, flat=False):
        O, T, N = self.omega, self.T, self.N

        if flat:
            cov = 1./O
        else:
            cov = np.zeros((T, N, N))
            for t in xrange(T):
                cov[t,:,:] = np.diag(1./O[t,:])

        return cov

class BernoulliObservations(_PGObservationsBase):
    @property
    def a(self):
        return self.X

    @property
    def b(self):
        return np.ones_like(self.X)

    def log_likelihood_given_activation(self, psi):
        p   = logistic(psi)
        p   = np.clip(p, 1e-16, 1-1e-16)

        ll = (self.X * np.log(p) + (1-self.X) * np.log(1-p))
        return ll

    def rvs(self, psi):
        p = logistic(psi)
        return (np.random.rand(*p.shape) < p).astype(np.float)

class NegativeBinomialObservations(_PGObservationsBase):
    def __init__(self, xi=10., **kwargs):
        assert xi > 0
        self.xi = xi

        super(NegativeBinomialObservations, self).__init__(**kwargs)

    @property
    def a(self):
        return self.X

    @property
    def b(self):
        return self.X + self.xi

    def rvs(self, psi):
        p = logistic(psi)
        p = np.clip(p, 1e-32, 1-1e-32)
        return np.random.negative_binomial(self.xi, 1-p).astype(np.float)

    def log_likelihood_given_activation(self, psi):
        p   = logistic(psi)
        p   = np.clip(p, 1e-32, 1-1e-32)

        return self.log_normalizer(self.X, self.xi) \
               + self.X * np.log(p) \
               + self.xi * np.log(1-p)

    @staticmethod
    def log_normalizer(S, xi):
        return gammaln(S+xi) - gammaln(xi) - gammaln(S+1)

class PGEmissions(Distribution):
    """
    A base class for the emission matrix, C.
    """
    def __init__(self, D_out, D_in, C=None, sigmasq_C=1., b=None, sigmasq_b=1.):
        """
        :param D_out: Observation dimension
        :param D_in: Latent dimension
        :param C: Initial NxD emission matrix
        :param sigmasq_C: prior variance on C
        :param b: Initial Nx1 emission matrix
        :param sigmasq_b: prior variance on b
        """
        self.D_out, self.D_in, self.sigmasq_C, self.sigmasq_b = D_out, D_in, sigmasq_C, sigmasq_b

        if C is not None:
            assert C.shape == (self.D_out, self.D_in)
            self.C = C
        else:
            self.C = np.sqrt(sigmasq_C) * np.random.rand(self.D_out, self.D_in)

        if b is not None:
            assert b.shape == (self.D_out, 1)
            self.b = b
        else:
            self.b = np.sqrt(sigmasq_b) * np.random.rand(self.D_out, 1)

    def resample(self, states_list):
        for n in xrange(self.D_out):
            # Resample C_{n,:} given z, omega[:,n], and kappa[:,n]
            prior_h = np.zeros(self.D_in)
            prior_J = 1./self.sigmasq_C * np.eye(self.D_in)

            lkhd_h = np.zeros(self.D_in)
            lkhd_J = np.zeros((self.D_in, self.D_in))

            for states in states_list:
                z = states.stateseq
                kappa = states.data.kappa
                omega = states.data.omega

                # J += z.T.dot(diag(omega_n)).dot(z)
                lkhd_J += (z * omega[:,n][:,None]).T.dot(z)
                lkhd_h += kappa[:,n].T.dot(z)

            post_h = prior_h + lkhd_h
            post_J = prior_J + lkhd_J

            self.C[n,:] = sample_gaussian(J=post_J, h=post_h)

        for n in xrange(self.D_out):
            # Resample b_{n} given z, omega[:,n], and kappa[:,n]
            prior_h = np.zeros(1)
            prior_J = 1./self.sigmasq_b * np.eye(1)

            lkhd_h = np.zeros(1)
            lkhd_J = np.zeros((1, 1))

            for states in states_list:
                z = states.stateseq
                kappa = states.data.kappa
                omega = states.data.omega

                # A bias is equivalent to an element of z fixed at 1,
                # so just sum things
                lkhd_J += np.sum(omega[:,n][:,None].T)
                lkhd_h += np.sum(kappa[:,n].T)

            post_h = prior_h + lkhd_h
            post_J = prior_J + lkhd_J

            self.b[n] = sample_gaussian(J=post_J, h=post_h)

    def log_likelihood(self, C, b):
        # TODO: Normalize
        C_ll = -0.5 * (C**2 / self.sigmasq_C).sum()
        b_ll = -0.5 * (b ** 2  / self.sigmasq_b).sum()
        return C_ll + b_ll

    def rvs(self,size=[],x=None):
        assert x.ndim==2 and x.shape[1] == self.D_in
        psi = x.dot(self.C.T)

        for n in xrange(self.D_out):
            psi[n, :] += self.b[n]

        return psi

class PGLDSStates(LDSStates):
    def __init__(self, model, data):
        assert isinstance(model, _PGLDSBase)
        assert isinstance(data, _PGObservationsBase)
        T = data.X.shape[0]
        super(PGLDSStates, self).__init__(model, data=data, T=T)

    def resample(self):
        self.resample_states()
        self.resample_auxiliary_variables()

    def resample_states(self):

        # Have the observation object compute the conditional mean and covariance
        conditional_mean = self.data.conditional_mean()
        conditional_cov = self.data.conditional_cov(flat=True)

        ll, self.stateseq = filter_and_sample_diagonal(
            self.mu_init, self.sigma_init,
            self.A, self.sigma_states,
            self.C, conditional_cov, conditional_mean)

        assert np.all(np.isfinite(self.stateseq))

    def resample_auxiliary_variables(self):
        psi = self.stateseq.dot(self.C.T)
        self.data.resample(psi)

    def log_likelihood(self):
        psi = self.stateseq.dot(self.C.T)
        return self.data.log_likelihood_given_activation(psi).sum()

    def heldout_log_likelihood(self, M=100):
        """
        Compute conditional log likelihood by Monte Carlo sampling omega
        """
        # TODO: We can derive better ways of estimating the log likelihood
        lls = np.zeros(M)
        for m in xrange(M):
            # Sample latent states from the prior
            z = self.generate_states()
            psi = z.dot(self.C.T)
            lls[m] = self.data.log_likelihood_given_activation(psi).sum()

        # Compute the average
        hll = logsumexp(lls) - np.log(M)

        # Use bootstrap to compute error bars
        samples = np.random.choice(lls, size=(100, M), replace=True)
        hll_samples = logsumexp(samples, axis=1) - np.log(M)
        std_hll = hll_samples.std()

        return hll, std_hll

class _PGLDSBase(NonstationaryLDS):
    _observation_class = _PGObservationsBase
    _observation_kwargs = {}

    def __init__(self, init_dynamics_distn, dynamics_distn, emission_distn, observation_kwargs={}):
        assert isinstance(emission_distn, PGEmissions)
        super(_PGLDSBase, self).__init__(init_dynamics_distn=init_dynamics_distn,
                                         dynamics_distn=dynamics_distn,
                                         emission_distn=emission_distn)
        self._observation_kwargs.update(observation_kwargs)

    @property
    def C(self):
        return self.emission_distn.C

    def add_data(self, data, **kwargs):
        assert isinstance(data, np.ndarray) and data.ndim == 2 and data.shape[1] == self.p
        obs = self._observation_class(X=data, **self._observation_kwargs)
        self.states_list.append(PGLDSStates(model=self, data=obs))

    def _generate_obs(self, s):
        if s.data is None:
            psi = self.emission_distn.rvs(x=s.stateseq)
            data = self._observation_class(psi=psi, **self._observation_kwargs)
            s.data = data
        else:
            # filling in missing data
            raise NotImplementedError

        return s.data

    def resample_parameters(self):
        self.resample_dynamics_distn()
        self.resample_emission_distn()

    def resample_emission_distn(self):
        self.emission_distn.resample(self.states_list)

class BernoulliLDS(_PGLDSBase):
    _observation_class = BernoulliObservations
    _observation_kwargs = {}

class NegativeBinomialLDS(_PGLDSBase):
    _observation_class = NegativeBinomialObservations
    _observation_args = {"xi": 1.}


from urllib.request import urlopen
from urllib.error import HTTPError
from bs4 import BeautifulSoup

url = 'http://www.pythonscraping.com/pages/warandpeace.html'

def gettitle(url_info):
    try:
        html = urlopen(url_info)
    except HTTPError as e:
        return None
    else:
        try:
            bsobj = BeautifulSoup(html.read())
            title = bsobj.find_all('span', {'class':{'red', 'green'}})
        except AttributeError as e:
            return None
        else:
            return title

# 获取span标签下属性为green或red的内容
title_list = gettitle(url)
for title_info in title_list:
    if title_info == None:
        print('Title could not be found')
    else:
        print(title_info)


import json, requests
import coordinates, cadnums
url_point = 'http://212.26.144.110/kadastrova-karta/find-Parcel'
url_data = 'http://212.26.144.110/kadastrova-karta/get-parcel-Info'

#cadnum='0524587000:01:003:0358'
cadnum = input('Вставьте кадастровый номер: ')

params_point = dict(
    cadnum=cadnum,
)

resp = (json.loads(requests.get(url=url_point, params=params_point).text)['data'])[0]
params_data = dict(
    koatuu=cadnum.split(':')[0],
    zone=cadnum.split(':')[1],
    quartal=cadnum.split(':')[2],
    parcel=cadnum.split(':')[3],
)
resp.update((json.loads(requests.get(url=url_data, params=params_data).text)['data'])[0])
coordinates.addCoordinates(resp)

if __name__ == '__main__':
    try:
        print(resp)
    except:
        print("Нет данных по {}".format(cadnum))


from .googlesuggest import g_suggest
import json
import re
#import requests
import collections as cl

def main(phrase):
    vol = 1000
    ret = g_suggest (phrase)
    #ret = [['データサイエンティスト 資格', 'データサイエンティスト 資格 難易度', 'データサイエンティスト 資格 emc', 'データサイエンティスト 資格 費用', 'データサイエンティスト 資格 価格', 'データサイエンティスト 転職 資格'], ['データサイエンティスト 転職', 'データサイエンティスト 転職 エージェント', 'データサイエンティスト 転職 資格'], ['データサイエンティスト 勉強'], ['データサイエンティスト とは'], ['データサイエンティスト アナリスト', 'データサイエンティスト アナリスト 違い'], ['データサイエンティスト アメリカ', 'データサイエンティスト 大学院 アメリカ', 'アメリカ データサイエンティスト 年収']]
    idnum = 0
    d_nodes = {}
    nodeslist = []
    linkslist = []
    data = {}
    idnum2=0
    blank_d = re.compile('  ')
    blank_d2 = re.compile(' ')
    name_list = ["nodes"]
    colors = ['#F3C759','#C0D860','#5EC84E','#3DB680','#40BFB0','#42AAC7','#44A5CB','#6A8CC7','#8B90BE','#CE579B','#C35B9D','#F9DB57','#FFEE55','#E4EC5B','#45A1CF','#E6855E','#D45D87','#9499C5','#7F96CA','#6C9CCF','#6C9CCF','#6C9CCF','#6C9CCF']

    data["size"] = 150
    data["color"] = '#DA6272'
    data["keyword"] = phrase
    nodeslist.append(data)

    for j,ret_list in enumerate(ret[1:20]):
        dict_sg = {}
        color = colors[j]
        for i,suggest in enumerate(ret_list):
            data = {}
            links = {}
            if i == 0:
                suggest = secondword = suggest[len(phrase):]
                secondword = blank_d.sub('', secondword)
                secondword = blank_d2.sub('', secondword)
                size =60
                links["source"] = 0
                links["target"] = idnum+1
            else:
                pattern = re.compile(phrase)
                pattern2 = re.compile(secondword)
                suggest = pattern.sub('',suggest)
                suggest = pattern2.sub('',suggest)
                size =10
                links["source"] = 1+idnum2
                links["target"] = idnum+1

            if suggest != '':
                idnum += 1
                dict_sg[suggest] = idnum
                data["size"] = size
                data["color"] = color
                data["keyword"] = suggest
                data["number"] = idnum
                nodeslist.append(data)
                linkslist.append(links)
        idnum2 = idnum

    d_nodes["graph"] = []
    d_nodes["links"] = linkslist
    d_nodes["nodes"] = nodeslist
    d_nodes["directed"] = "false"
    d_nodes["multigraph"] = "false"

    fw = open('static/jsonfiles/s_graph.json','w')
    json.dump(d_nodes,fw,ensure_ascii=False,indent=4)
    return


#!/usr/bin/python

from PIL import Image
import Modules
import optparse
import pyscreenshot

def main():
    # Parse arguments
    parser = optparse.OptionParser()
    parser.add_option('-i', '--image',
                      action="store", dest="imageFile",
                      help="Path to an image file", default="")
    parser.add_option('-d', '--database',
                      action="store", dest="database",
                      help="Path to the database", default="")
    options, args = parser.parse_args()

    # Calculate and write values to db
    if options.imageFile != "":
        # No database given -> return
        if options.database == "":
            print("Error: No database file given!")
            return
        # Load image
        sprites = Image.open(options.imageFile)
        # Open database
        f = open(options.database, 'a')
        spriteHeight = int(sprites.height / 2)
        # Seek to the second byte of the file
        f.seek(2)
        # Write name to database
        string = options.imageFile.split("/")[-1].split(".")[0]
        f.write(string + ":")
        i = 0
        j = 1
        # Calculate all images and write values to database
        while i < sprites.width:
            # Crop image to current sprite
            image = image.crop(box=(i, spriteHeight,
                                    Modules.image.spriteWidth + i, image.height))
            # Do image processing
            values = image_processing(image)
            # Write to file
            for d in values:
                # <number>=<hu moment>,
                f.write(str(j) + "=" + str(d) + ",")
                j += 1
            i += Modules.image.spriteWidth
            j = 1
        # Write newline and close file
        f.write("\n")
        f.close()
    # Game loop
    else:
        # Do game loop
        gameLoop()

def gameLoop():
    # Get all adjacent cells
    cells = Modules.image.getNearCells()
    # Calculate cells
    for c in cells:
        image = c.im
        image.show()

def imageProcessing(image):
    # Calculate image values
    return Modules.image_processing.imageValues(image)

if __name__ == "__main__":
    main()


#
# Reluzy : A Lazy NN-with-Relu Solver
#
# Author : Ahmed Irfan
#          <irfan@cs.stanford.edu>
#

import logging

from nnet2smt import Nnet2Smt

from pysmt.shortcuts import Solver, And, Real, Max, Equals, GE, LE, Implies

class Reluzy:

    def __init__(self, filename, violationfile, logger):
        self.logger = logger
        self.nnet2smt = Nnet2Smt(filename, violationfile)
        self.nnet2smt.convert(True)
        self.input_vars = self.nnet2smt.input_vars
        self.output_vars = self.nnet2smt.output_vars
        self.formulae = self.nnet2smt.formulae
        self.relus = self.nnet2smt.relus
        self.relus_level = self.nnet2smt.relus_level
        self.solver = Solver(name='yices')
        self.sat_checker = Solver(name='yices')
        self.init()

    def init(self):
        self.solver.add_assertion(And(self.formulae))
        self.sat_checker.add_assertion(And(self.formulae))
        for r1, r2 in self.relus:
            self.sat_checker.add_assertion(Equals(r1, Max(r2, Real(0))))
        #lemmas = self.refine_zero_lb(False)
        #self.solver.add_assertion(And(lemmas))
        #lemmas = self.refine_slope_lb(False)
        #self.solver.add_assertion(And(lemmas))

    def solve(self):
        while True:
            self.logger.info('Solving')
            res = self.solver.solve()
            if not res:
                print('unsat')
                break
            else:
                lemmas = self.refine()
                if not lemmas:
                    print('sat')
                    break
                else:
                    self.solver.add_assertion(And(lemmas))

    def check_sat(self):
        self.logger.info('Checking for Sat')
        self.sat_checker.push()
        for v in self.input_vars:
            self.sat_checker.add_assertion(Equals(v, self.solver.get_value(v)))
        res = self.sat_checker.solve()
        if res:
            for x in self.input_vars:
                print(v, self.sat_checker.get_value(x))
            return True
        else:
            self.sat_checker.pop()
            return False

    def refine(self):
        self.logger.info('Refining')
        lemmas = self.refine_zero_lb()
        if not lemmas:
            lemmas = self.refine_slope_lb()

        if not lemmas:
            lemmas = self.refine_zero_ub()

        if not lemmas:
            lemmas = self.refine_slope_ub()

        if not lemmas:
            for v in self.input_vars:
                print(v, self.solver.get_value(v))
        #elif self.check_sat():
        #    return []

        return lemmas

    def refine_zero_lb(self, check=True):
        lemmas = []
        zero = Real(0)
        for r1, _ in self.relus:
            l = GE(r1, zero)
            if check:
                tval = self.solver.get_value(l)
                if tval.is_false():
                    lemmas.append(l)
                    self.logger.debug('Adding %s' % l )
            else:
                lemmas.append(l)
        return lemmas

    def refine_zero_ub(self):
        lemmas = []
        zero = Real(0)
        for s in self.relus_level:
            for r1, r2 in s:
                l = Implies(LE(r2, zero), LE(r1, zero))
                tval = self.solver.get_value(l)
                if tval.is_false():
                    lemmas.append(l)
                    self.logger.debug('Adding %s' % l )
            if lemmas:
                break
        return lemmas

    def refine_slope_lb(self, check=True):
        lemmas = []
        for r1, r2 in self.relus:
            l = GE(r1, r2)
            if check:
                tval = self.solver.get_value(l)
                if tval.is_false():
                    lemmas.append(l)
                    self.logger.debug('Adding %s' % l )
            else:
                lemmas.append(l)
        return lemmas

    def refine_slope_ub(self):
        lemmas = []
        zero = Real(0)
        for s in self.relus_level:
            for r1, r2 in s:
                l = Implies(GE(r2, zero), LE(r1, r2))
                tval = self.solver.get_value(l)
                if tval.is_false():
                    lemmas.append(l)
                    self.logger.debug('Adding %s' % l )
            if lemmas:
                break
        return lemmas


import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.examples.tutorials.mnist.input_data import read_data_sets

# fully connected hidden layer
def fully_conn(x, n_hid, name):
    n_batch, n_dim = x.shape
    W = tf.get_variable(name + '_W', dtype=tf.float32, initializer=tf.random_normal([int(n_dim), n_hid], stddev=0.1))
    b = tf.get_variable(name + '_b', dtype=tf.float32, initializer=tf.zeros([n_hid]))

    return tf.matmul(x, W) + b

# ordinary Variational Autoencoder
class M1:
    def __init__(self, n_in, n_z):
        self.n_in = n_in
        self.n_z = n_z

    def _build_encoder(self, x):
        with tf.variable_scope('M1_encoder', reuse=tf.AUTO_REUSE):
            h1 = tf.nn.softplus(fully_conn(x, int(self.n_in / 2), 'M1_encoder1'))
            mu = fully_conn(h1, self.n_z, 'M1_mu')
            sig = tf.nn.softplus(fully_conn(h1, self.n_z, 'M1_sig'))

        return mu, sig

    def _build_decoder(self, z):
        with tf.variable_scope('M1_decoder', reuse=tf.AUTO_REUSE):
            h1 = tf.nn.softplus(fully_conn(z, int(self.n_in / 2), 'M1_decoder1'))
            y = fully_conn(h1, self.n_in, 'M1_output')

        return y

    def ELBO(self, mu, sig, y):
        loss_recon = tf.reduce_mean(tf.reduce_sum(tf.nn.sigmoid_cross_entropy_with_logits(labels=self.x, logits=y), 1))
        loss_kld = tf.reduce_mean(tf.reduce_sum(tf.distributions.kl_divergence(self._get_dist(mu, sig),
                                                                               self._get_dist(tf.zeros([self.n_z]),
                                                                                tf.ones([self.n_z]))), 1))
        return loss_recon + 0.5 * loss_kld

    def build(self):
        self.x = tf.placeholder(tf.float32, [None, self.n_in])
        self.lr = tf.placeholder(tf.float32, [])

        mu, sig = self._build_encoder(self.x)
        e = tf.random_normal(tf.shape(mu))
        # modify original code
        # z = mu + tf.multiply(e, sig)
        self.z = mu + tf.multiply(e, sig)

        # modify original code
        # y = self._build_decoder(self.z)
        self.y = self._build_decoder(self.z)

        self.loss = self.ELBO(mu, sig, self.y)
        self.opt = tf.train.AdamOptimizer(self.lr).minimize(self.loss)

    def _get_dist(self, mu, sig):
        dist = tf.distributions.Normal(loc=mu, scale=sig)
        return dist

class M2:
    def __init__(self, n_in, n_z, n_cls):
        self.n_in = n_in
        self.n_z = n_z
        self.n_cls = n_cls

    def _build_classifier(self, x):
        with tf.variable_scope('M2_classifier', reuse=tf.AUTO_REUSE):
            h1 = tf.nn.softplus(fully_conn(x, int(self.n_in / 2), 'M2_classifier1'))
            pred = fully_conn(h1, self.n_cls, 'M2_classifier2')
        return pred

    def _build_encoder(self, x):
        with tf.variable_scope('M2_encoder', reuse=tf.AUTO_REUSE):
            h1 = tf.nn.softplus(fully_conn(x, int(self.n_in / 2), 'M2_encoder1'))
            mu = fully_conn(h1, self.n_z, 'M2_mu')
            sig = tf.nn.softplus(fully_conn(h1, self.n_z, 'M2_sig'))
        return mu, sig

    def _build_decoder(self, z):
        with tf.variable_scope('M2_decoder', reuse=tf.AUTO_REUSE):
            h1 = tf.nn.softplus(fully_conn(z, int(self.n_in / 2), 'M2_decode1'))
            y = fully_conn(h1, self.n_in, 'M2_output')
        return y

    def _pathway(self, x_l, label):
        x_with_label = tf.concat([x_l, label], 1)
        mu, sig = self._build_encoder(x_with_label)

        e = tf.random_normal(tf.shape(mu))
        z = mu = tf.multiply(e, sig)
        y = self._build_decoder(z)

        return mu, sig, z, y

    def _loss_labelled(self, x, y, mu, sig, label):
        loss_recon = tf.reduce_mean(tf.reduce_sum(tf.nn.sigmoid_cross_entropy_with_logits(labels=x, logits=y), 1))
        loss_kld = tf.reduce_mean(tf.reduce_sum(tf.distributions.kl_divergence(self._get_dist(mu, sig), self._get_dist(tf.zeros([self.n_z]), tf.ones([self.n_z]))), 1))
        prior_y = (1. / self.n_cls) * tf.ones_like(label)
        loss_logpy = tf.reduce_mean(tf.reduce_sum(tf.nn.sigmoid_cross_entropy_with_logits(labels = prior_y, logits = label), 1))
        loss_labbeld = loss_recon + loss_kld + loss_logpy

        return loss_labbeld

    def total_loss(self, mu_l, sig_l, z_l, y_l, mu_u, sig_u, z_u, y_u):
        # TODO: write the codes that calcuate the loss
        # loss = Loss_labelled + Loss_unlabelled + alpha * cross_entropy

        # Loss_labelled
        loss_l = tf.reduce_mean(self._loss_labelled(self.x_l, y_l, mu_l, sig_l, self.label))
        # Loss_unlabelled
        loss_u = None
        for i in range(self.n_cls):
            _loss_u = self._loss_labelled(self.x_u, y_u[i], mu_u[i], sig_u[i], self.label_u[i])
            if i==0:
                _loss_u = tf.reshape(_loss_u, [1, 1])
                # loss_u = tf.expand_dims(_loss_u, 1)
                loss_u = _loss_u
            else:
                # _loss_u = tf.expand_dims(_loss_u, 1)
                _loss_u = tf.reshape(_loss_u, [1, 1])
                # loss_u = tf.concat([loss_u, tf.reshape(_loss_u, [1,1])], 1)
                loss_u = tf.concat([loss_u, _loss_u], 1)

        self.prob_u = tf.nn.softmax(self.pred_u, dim=-1)
        loss_u = tf.multiply(self.prob_u, tf.subtract(loss_u, -tf.log(self.prob_u)))
        loss_u = tf.reduce_mean(tf.reduce_sum(loss_u, 1))
        # Loss classification
        loss_clf = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels = self.label, logits = self.pred_l))
        # alpha
        alpha = 0.1*100

        self.loss_l = loss_l
        self.loss_u = loss_u
        self.loss_clf = loss_clf

        loss = loss_l + loss_u + alpha * loss_clf

        return loss

    def build(self):
        self.x_l = tf.placeholder(tf.float32, [None, self.n_in])        # labelled data
        self.x_u = tf.placeholder(tf.float32, [None, self.n_in])        # unlabelled data
        self.label = tf.placeholder(tf.float32, [None, self.n_cls])     # label corresponding to labelled data
        self.lr = tf.placeholder(tf.float32, [])                         # learning rata

        self.pred_l = self._build_classifier(self.x_l)
        self.pred_u = self._build_classifier(self.x_u)
        mu_l, sig_l, z_l, y_l = self._pathway(self.x_l, self.label)     # forward path for labelled data

        # Modify original source code
        # mu_u, sig_u, z_u, y_u = self._pathway(self.x_u, self.pred_u)      # forward path for unlabelled data
        mu_u = [0] * self.n_cls
        sig_u = [0] * self.n_cls
        z_u = [0] * self.n_cls
        y_u = [0] * self.n_cls
        # self.label_u = tf.one_hot(list(range(self.n_cls)), self.n_cls)
        self.label_u = [0] * self.n_cls
        # print(self.label_u[0])
        for i in range(self.n_cls):
            _y = i * tf.ones([tf.shape(self.x_u)[0]], tf.int32)
            self.label_u[i] = tf.one_hot(_y, self.n_cls)
            mu_u[i], sig_u[i], z_u[i], y_u[i] = self._pathway(self.x_u, self.label_u[i])      # forward path for unlabelled data

        self.loss = self.total_loss(mu_l, sig_l, z_l, y_l, mu_u, sig_u, z_u, y_u)           # caclcuating loss(need to implement)
        self.opt = tf.train.AdamOptimizer(self.lr).minimize(self.loss)  # optimizing the model

    def _get_dist(self, mu, sig):
        dist = tf.distributions.Normal(loc=mu, scale=sig)
        return dist

def main():
    # hyper parameters
    # it is fine to change the value if you want to
    n_in = 784
    n_z1 = 128
    n_z2 = 32
    n_cls = 10
    # modify original code
    # lr = 1e-2
    lr_1 = 1e-2
    lr_2 = 1e-5
    mnist = read_data_sets('./MNIST-data/', one_hot=True)

    with tf.Session() as sess:
        m1 = M1(n_in, n_z1)
        m1.build()
        m2 = M2(n_z1, n_z2, n_cls)
        m2.build()
        sess.run(tf.global_variables_initializer())

        # TODO: train M1
        # need to implement
        fig, ax = plt.subplots(1, 3)
        xs1 = list()
        losses1 = list()
        # for i in range(10000):
        for i in range(10000):
            tr_x, _ = mnist.train.next_batch(100)
            loss, y, _ = sess.run([m1.loss, m1.y, m1.opt], feed_dict={m1.x:tr_x, m1.lr:lr_1})

            if i % 100 == 0:
                print(i, loss)
                xs1.append(i)
                losses1.append(loss)

                ax[0].cla()
                ax[0].imshow(y[0].reshape(28, 28), cmap='gray')
                ax[1].set_title('recon img')
                ax[1].cla()
                ax[1].plot(xs1, losses1, c='r')
                ax[1].set_title('m1 loss')

                fig.canvas.draw()
                plt.pause(0.1)

        # TODO: train M2
        # z1 = m1.z
        # m2.x = z1
        # need to implement
        xs2 = list()
        losses2 = list()
        for i in range(10000):
            tr_l_x, tr_l_y = mnist.train.next_batch(50)
            tr_u_x, _ = mnist.train.next_batch(50)

            z1_l = sess.run(m1.z, feed_dict={m1.x:tr_l_x, m1.lr:lr_1})
            z1_u = sess.run(m1.z, feed_dict={m1.x:tr_u_x, m1.lr:lr_1})

            loss, loss_l, loss_u, loss_clf, _ = sess.run([m2.loss, m2.loss_l, m2.loss_u, m2.loss_clf, m2.opt], feed_dict={m2.x_l:z1_l, m2.x_u:z1_u, m2.label:tr_l_y, m2.lr:lr_2})

            if i % 100 == 0:
                print(i, loss, loss_l, loss_u, loss_clf)
                xs2.append(i)
                losses2.append(loss)

                ax[2].cla()
                ax[2].plot(xs2, losses2, c='r')
                ax[2].set_title('m2 loss')

                fig.canvas.draw()
                plt.pause(0.1)
        plt.show()

if __name__  == '__main__':
    main()


from datetime import timedelta
from uuid import UUID

import pytest
from colour import Color
from pytest import raises
from sqlalchemy.util import OrderedSet

from ereuse_devicehub.client import UserClient
from ereuse_devicehub.db import db
from ereuse_devicehub.devicehub import Devicehub
from ereuse_devicehub.resources.device.exceptions import NeedsId
from ereuse_devicehub.resources.device.models import Component, Computer, Desktop, Device, \
    GraphicCard, Laptop, Microtower, Motherboard, NetworkAdapter
from ereuse_devicehub.resources.device.schemas import Device as DeviceS
from ereuse_devicehub.resources.device.sync import MismatchBetweenTags, MismatchBetweenTagsAndHid, \
    Sync
from ereuse_devicehub.resources.event.models import Remove, Test
from ereuse_devicehub.resources.tag.model import Tag
from ereuse_devicehub.resources.user import User
from ereuse_utils.naming import Naming
from teal.db import ResourceNotFound
from tests.conftest import file

@pytest.mark.usefixtures('app_context')
def test_device_model():
    """
    Tests that the correctness of the device model and its relationships.
    """
    pc = Desktop(model='p1mo', manufacturer='p1ma', serial_number='p1s')
    net = NetworkAdapter(model='c1mo', manufacturer='c1ma', serial_number='c1s')
    graphic = GraphicCard(model='c2mo', manufacturer='c2ma', memory=1500)
    pc.components.add(net)
    pc.components.add(graphic)
    db.session.add(pc)
    db.session.commit()
    pc = Desktop.query.one()
    assert pc.serial_number == 'p1s'
    assert pc.components == OrderedSet([net, graphic])
    network_adapter = NetworkAdapter.query.one()
    assert network_adapter.parent == pc

    # Removing a component from pc doesn't delete the component
    pc.components.remove(net)
    db.session.commit()
    pc = Device.query.first()  # this is the same as querying for Desktop directly
    assert pc.components == {graphic}
    network_adapter = NetworkAdapter.query.one()
    assert network_adapter not in pc.components
    assert network_adapter.parent is None

    # Deleting the pc deletes everything
    gcard = GraphicCard.query.one()
    db.session.delete(pc)
    db.session.flush()
    assert pc.id == 1
    assert Desktop.query.first() is None
    db.session.commit()
    assert Desktop.query.first() is None
    assert network_adapter.id == 2
    assert NetworkAdapter.query.first() is not None, 'We removed the network adaptor'
    assert gcard.id == 3, 'We should still hold a reference to a zombie graphic card'
    assert GraphicCard.query.first() is None, 'We should have deleted it –it was inside the pc'

@pytest.mark.usefixtures('app_context')
def test_device_schema():
    """Ensures the user does not upload non-writable or extra fields."""
    device_s = DeviceS()
    device_s.load({'serialNumber': 'foo1', 'model': 'foo', 'manufacturer': 'bar2'})
    device_s.dump(Device(id=1))

@pytest.mark.usefixtures('app_context')
def test_physical_properties():
    c = Motherboard(slots=2,
                    usb=3,
                    serial_number='sn',
                    model='ml',
                    manufacturer='mr',
                    width=2.0,
                    color=Color())
    pc = Computer()
    pc.components.add(c)
    db.session.add(pc)
    db.session.commit()
    assert c.physical_properties == {
        'usb': 3,
        'serial_number': 'sn',
        'pcmcia': None,
        'model': 'ml',
        'slots': 2,
        'serial': None,
        'firewire': None,
        'manufacturer': 'mr',
        'weight': None,
        'height': None,
        'width': 2.0,
        'color': Color(),
        'depth': None
    }

@pytest.mark.usefixtures('app_context')
def test_component_similar_one():
    snapshot = file('pc-components.db')
    d = snapshot['device']
    snapshot['components'][0]['serial_number'] = snapshot['components'][1]['serial_number'] = None
    pc = Computer(**d, components=OrderedSet(Component(**c) for c in snapshot['components']))
    component1, component2 = pc.components  # type: Component
    db.session.add(pc)
    db.session.flush()
    # Let's create a new component named 'A' similar to 1
    componentA = Component(model=component1.model, manufacturer=component1.manufacturer)
    similar_to_a = componentA.similar_one(pc, set())
    assert similar_to_a == component1
    # Component B does not have the same model
    componentB = Component(model='nope', manufacturer=component1.manufacturer)
    with pytest.raises(ResourceNotFound):
        assert componentB.similar_one(pc, set())
    # If we blacklist component A we won't get anything
    with pytest.raises(ResourceNotFound):
        assert componentA.similar_one(pc, blacklist={componentA.id})

@pytest.mark.usefixtures('auth_app_context')
def test_add_remove():
    # Original state:
    # pc has c1 and c2
    # pc2 has c3
    # c4 is not with any pc
    values = file('pc-components.db')
    pc = values['device']
    c1, c2 = (Component(**c) for c in values['components'])
    pc = Computer(**pc, components=OrderedSet([c1, c2]))
    db.session.add(pc)
    c3 = Component(serial_number='nc1')
    pc2 = Computer(serial_number='s2', components=OrderedSet([c3]))
    c4 = Component(serial_number='c4s')
    db.session.add(pc2)
    db.session.add(c4)
    db.session.commit()

    # Test:
    # pc has only c3
    events = Sync.add_remove(device=pc, components={c3, c4})
    db.session.add_all(events)
    db.session.commit()  # We enforce the appliance of order_by
    assert len(events) == 1
    assert isinstance(events[0], Remove)
    assert events[0].device == pc2
    assert events[0].components == OrderedSet([c3])

@pytest.mark.usefixtures('app_context')
def test_sync_run_components_empty():
    """
    Syncs a device that has an empty components list. The system should
    remove all the components from the device.
    """
    s = file('pc-components.db')
    pc = Computer(**s['device'], components=OrderedSet(Component(**c) for c in s['components']))
    db.session.add(pc)
    db.session.commit()

    # Create a new transient non-db synced object
    pc = Computer(**s['device'])
    db_pc, _ = Sync().run(pc, components=OrderedSet())
    assert not db_pc.components
    assert not pc.components

@pytest.mark.usefixtures('app_context')
def test_sync_run_components_none():
    """
    Syncs a device that has a None components. The system should
    keep all the components from the device.
    """
    s = file('pc-components.db')
    pc = Computer(**s['device'], components=OrderedSet(Component(**c) for c in s['components']))
    db.session.add(pc)
    db.session.commit()

    # Create a new transient non-db synced object
    transient_pc = Computer(**s['device'])
    db_pc, _ = Sync().run(transient_pc, components=None)
    assert db_pc.components
    assert db_pc.components == pc.components

@pytest.mark.usefixtures('app_context')
def test_sync_execute_register_computer_new_computer_no_tag():
    """
    Syncs a new computer with HID and without a tag, creating it.
    :return:
    """
    # Case 1: device does not exist on DB
    pc = Computer(**file('pc-components.db')['device'])
    db_pc = Sync().execute_register(pc)
    assert pc.physical_properties == db_pc.physical_properties

@pytest.mark.usefixtures('app_context')
def test_sync_execute_register_computer_existing_no_tag():
    """
    Syncs an existing computer with HID and without a tag.
    """
    pc = Computer(**file('pc-components.db')['device'])
    db.session.add(pc)
    db.session.commit()

    pc = Computer(**file('pc-components.db')['device'])  # Create a new transient non-db object
    # 1: device exists on DB
    db_pc = Sync().execute_register(pc)
    assert pc.physical_properties == db_pc.physical_properties

@pytest.mark.usefixtures('app_context')
def test_sync_execute_register_computer_no_hid_no_tag():
    """
    Syncs a computer without HID and no tag.

    This should fail as we don't have a way to identify it.
    """
    pc = Computer(**file('pc-components.db')['device'])
    # 1: device has no HID
    pc.hid = pc.model = None
    with pytest.raises(NeedsId):
        Sync().execute_register(pc)

@pytest.mark.usefixtures('app_context')
def test_sync_execute_register_computer_tag_not_linked():
    """
    Syncs a new computer with HID and a non-linked tag.

    It is OK if the tag was not linked, it will be linked in this process.
    """
    tag = Tag(id='FOO')
    db.session.add(tag)
    db.session.commit()

    # Create a new transient non-db object
    pc = Computer(**file('pc-components.db')['device'], tags=OrderedSet([Tag(id='FOO')]))
    returned_pc = Sync().execute_register(pc)
    assert returned_pc == pc
    assert tag.device == pc, 'Tag has to be linked'
    assert Computer.query.one() == pc, 'Computer had to be set to db'

@pytest.mark.usefixtures('app_context')
def test_sync_execute_register_no_hid_tag_not_linked(tag_id: str):
    """
    Validates registering a computer without HID and a non-linked tag.

    In this case it is ok still, as the non-linked tag proves that
    the computer was not existing before (otherwise the tag would
    be linked), and thus it creates a new computer.
    """
    tag = Tag(id=tag_id)
    pc = Computer(**file('pc-components.db')['device'], tags=OrderedSet([tag]))
    returned_pc = Sync().execute_register(pc)
    db.session.commit()
    assert returned_pc == pc
    db_tag = next(iter(returned_pc.tags))
    # they are not the same tags though
    # tag is a transient obj and db_tag the one from the db
    # they have the same pk though
    assert tag != db_tag, 'They are not the same tags though'
    assert db_tag.id == tag.id
    assert Computer.query.one() == pc, 'Computer had to be set to db'

@pytest.mark.usefixtures('app_context')
def test_sync_execute_register_tag_does_not_exist():
    """
    Ensures not being able to register if the tag does not exist,
    even if the device has HID or it existed before.

    Tags have to be created before trying to link them through a Snapshot.
    """
    pc = Computer(**file('pc-components.db')['device'], tags=OrderedSet([Tag()]))
    with raises(ResourceNotFound):
        Sync().execute_register(pc)

@pytest.mark.usefixtures('app_context')
def test_sync_execute_register_tag_linked_same_device():
    """
    If the tag is linked to the device, regardless if it has HID,
    the system should match the device through the tag.
    (If it has HID it validates both HID and tag point at the same
    device, this his checked in ).
    """
    orig_pc = Computer(**file('pc-components.db')['device'])
    db.session.add(Tag(id='foo', device=orig_pc))
    db.session.commit()

    pc = Computer(**file('pc-components.db')['device'])  # Create a new transient non-db object
    pc.tags.add(Tag(id='foo'))
    db_pc = Sync().execute_register(pc)
    assert db_pc.id == orig_pc.id
    assert len(db_pc.tags) == 1
    assert next(iter(db_pc.tags)).id == 'foo'

@pytest.mark.usefixtures('app_context')
def test_sync_execute_register_tag_linked_other_device_mismatch_between_tags():
    """
    Checks that sync raises an error if finds that at least two passed-in
    tags are not linked to the same device.
    """
    pc1 = Computer(**file('pc-components.db')['device'])
    db.session.add(Tag(id='foo-1', device=pc1))
    pc2 = Computer(**file('pc-components.db')['device'])
    pc2.serial_number = 'pc2-serial'
    pc2.hid = Naming.hid(pc2.manufacturer, pc2.serial_number, pc2.model)
    db.session.add(Tag(id='foo-2', device=pc2))
    db.session.commit()

    pc1 = Computer(**file('pc-components.db')['device'])  # Create a new transient non-db object
    pc1.tags.add(Tag(id='foo-1'))
    pc1.tags.add(Tag(id='foo-2'))
    with raises(MismatchBetweenTags):
        Sync().execute_register(pc1)

@pytest.mark.usefixtures('app_context')
def test_sync_execute_register_mismatch_between_tags_and_hid():
    """
    Checks that sync raises an error if it finds that the HID does
    not point at the same device as the tag does.

    In this case we set HID -> pc1 but tag -> pc2
    """
    pc1 = Computer(**file('pc-components.db')['device'])
    db.session.add(Tag(id='foo-1', device=pc1))
    pc2 = Computer(**file('pc-components.db')['device'])
    pc2.serial_number = 'pc2-serial'
    pc2.hid = Naming.hid(pc2.manufacturer, pc2.serial_number, pc2.model)
    db.session.add(Tag(id='foo-2', device=pc2))
    db.session.commit()

    pc1 = Computer(**file('pc-components.db')['device'])  # Create a new transient non-db object
    pc1.tags.add(Tag(id='foo-2'))
    with raises(MismatchBetweenTagsAndHid):
        Sync().execute_register(pc1)

def test_get_device(app: Devicehub, user: UserClient):
    """Checks GETting a Desktop with its components."""
    with app.app_context():
        pc = Desktop(model='p1mo', manufacturer='p1ma', serial_number='p1s')
        pc.components = OrderedSet([
            NetworkAdapter(model='c1mo', manufacturer='c1ma', serial_number='c1s'),
            GraphicCard(model='c2mo', manufacturer='c2ma', memory=1500)
        ])
        db.session.add(pc)
        db.session.add(Test(device=pc,
                            elapsed=timedelta(seconds=4),
                            error=False,
                            author=User(email='bar@bar.com')))
        db.session.commit()
    pc, _ = user.get(res=Device, item=1)
    assert len(pc['events']) == 1
    assert pc['events'][0]['type'] == 'Test'
    assert pc['events'][0]['device'] == 1
    assert pc['events'][0]['elapsed'] == 4
    assert not pc['events'][0]['error']
    assert UUID(pc['events'][0]['author'])
    assert 'events_components' not in pc, 'events_components are internal use only'
    assert 'events_one' not in pc, 'they are internal use only'
    assert 'author' not in pc
    assert tuple(c['id'] for c in pc['components']) == (2, 3)
    assert pc['hid'] == 'p1ma-p1s-p1mo'
    assert pc['model'] == 'p1mo'
    assert pc['manufacturer'] == 'p1ma'
    assert pc['serialNumber'] == 'p1s'
    assert pc['type'] == 'Desktop'

def test_get_devices(app: Devicehub, user: UserClient):
    """Checks GETting multiple devices."""
    with app.app_context():
        pc = Desktop(model='p1mo', manufacturer='p1ma', serial_number='p1s')
        pc.components = OrderedSet([
            NetworkAdapter(model='c1mo', manufacturer='c1ma', serial_number='c1s'),
            GraphicCard(model='c2mo', manufacturer='c2ma', memory=1500)
        ])
        pc1 = Microtower(model='p2mo', manufacturer='p2ma', serial_number='p2s')
        pc2 = Laptop(model='p3mo', manufacturer='p3ma', serial_number='p3s')
        db.session.add_all((pc, pc1, pc2))
        db.session.commit()
    devices, _ = user.get(res=Device)
    assert tuple(d['id'] for d in devices) == (1, 2, 3, 4, 5)
    assert tuple(d['type'] for d in devices) == ('Desktop', 'Microtower',
                                                 'Laptop', 'NetworkAdapter', 'GraphicCard')


"""adding date imgaed

Revision ID: d1e5eef0bd70
Revises: f2d46bc0e813
Create Date: 2020-01-02 12:11:26.489005

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = 'd1e5eef0bd70'
down_revision = 'f2d46bc0e813'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('precise_filters', sa.Column('_date_img', sa.Date(), nullable=True))
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_column('precise_filters', '_date_img')
    # ### end Alembic commands ###


# -*- coding: utf-8 -*-
"""
Dubalu Framework
~~~~~~~~~~~~~~~~

:author: Dubalu Framework Team. See AUTHORS.
:copyright: Copyright (c) 2013-2014, deipi.com LLC. All Rights Reserved.
:license: See LICENSE for license details.

"""
from __future__ import absolute_import, unicode_literals, print_function

import os
import datetime

# For django to work, we need to populate apps and models as soon as possible
# If the apps have not yet been populated by now (as is the case when using uwsgi),
# populate.
from django.db.models.loading import cache
cache._populate()

from django.conf import settings
from django.conf.urls import patterns, include, url
from django.conf.urls.static import static
from django.utils.functional import memoize

from django.views.decorators.http import last_modified
from django.views.decorators.cache import cache_page
from django.views.i18n import javascript_catalog

# from dfw.sections.urls_base import get_urlresolver as get_sections_urlresolver

# Admin:
# from django.contrib import admin
# admin.autodiscover()

handler400 = settings.HANDLER400
handler403 = settings.HANDLER403
handler404 = settings.HANDLER404
handler500 = settings.HANDLER500

JSI18N_DATE_FILE = getattr(settings, 'JSI18N_DATE_FILE', '/tmp/jsi18n')
try:
    JSI18N_DATE = os.path.getmtime(JSI18N_DATE_FILE)
except OSError:
    JSI18N_DATE = float(datetime.datetime.now().strftime('%s'))
    open(JSI18N_DATE_FILE, 'a').close()
jsi18n_date = datetime.datetime.fromtimestamp(JSI18N_DATE)

# The value of JSI18N_DATE must change when translations change.
@last_modified(lambda req, **kw: jsi18n_date)
@cache_page(86400, key_prefix='js18n-%s' % JSI18N_DATE)
def cached_javascript_catalog(request, domain='djangojs', packages=None):
    if packages is None:
        packages = tuple(settings.INSTALLED_APPS) + ('django.conf',)
    return javascript_catalog(request, domain, packages)

# Default base urlpatterns:
urlpatterns = patterns('')

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    urlpatterns += static(settings.STATIC_URL, view='django.contrib.staticfiles.views.serve')

urlpatterns += patterns('',
    # url(r'^autocomplete/', include('dfw.autocomplete.urls')),
    # url(r'^impersonate/', include('dfw.impersonation.urls')),

    url(r'^i18n/', include('django.conf.urls.i18n')),
    url(r'^i18n/js/$', cached_javascript_catalog, name='javascript_catalog'),

    # url(r'^morsels/(?P<__params__>[^/]+)/', include('dfw.morsels.urls_base', app_name='morsel')),
)

# urlconf_module = include('dfw.notification.urls')[0]
# urlpatterns += getattr(urlconf_module, 'urlpatterns', urlconf_module)

# urlconf_module = include('dfw.pluggables.urls_base')[0]
# urlpatterns += getattr(urlconf_module, 'urlpatterns', urlconf_module)

if settings.PROJECT_NAME:
    urlconf_module = include('%s.urls' % settings.PROJECT_NAME)[0]
    urlpatterns += getattr(urlconf_module, 'urlpatterns', urlconf_module)

urlconf_module = include('dfw.contrib.pages.urls')[0]
urlpatterns += getattr(urlconf_module, 'urlpatterns', urlconf_module)

def get_urls(project_name, project_suffix):
    return type(b'ProjectUrls', (object,), dict(
        handler400=handler400,
        handler403=handler403,
        handler404=handler404,
        handler500=handler500,
        urlpatterns=urlpatterns,
    ))()
get_urls._cache = {}
get_urls = memoize(get_urls, get_urls._cache, 2)


from flask import Flask, flash, request, redirect, render_template, jsonify
import model_final,db

app = Flask(__name__)

@app.route('/old')
def upload_form():
    return render_template('TV.html')

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/predict', methods=['POST'])
def predict():
    data = request.json
    print("data", data)

    brand = data["brand"]
    hd = data["hd"]
    rating = int(data["rating"])
    speaker = int(data["speaker"])
    size = int(data["size"])
    hdmi = int(data["hdmi"])
    usb = int(data["usb"])
    result = model_final.output(brand, rating, speaker, size, hd, hdmi, usb)
    tv1,tv2,tv3 = db.output(speaker, size, hd, hdmi, usb)
    return jsonify({"price": result}) #tv1,tv2,tv3

@app.route('/result', methods=['POST'])
def result():
    if request.method == 'POST':
        brand = (request.form.get('brand'))
        hd = (request.form.get('hd'))
        rating = int(request.form.get('rating'))
        usb = int(request.form.get('usb'))
        size = float(request.form.get('size'))
        hdmi = int(request.form.get('hdmi'))
        speaker = int(request.form.get('speaker'))

        result = model_final.output(brand, rating, speaker, size, hd, hdmi, usb)
        return render_template("result.html", prediction=result)

if __name__ == "__main__":
    app.run(host="127.0.0.1", port=5000)


import numpy as np
import tensorflow as tf
from sklearn import datasets
from tensorflow.examples.tutorials.mnist import input_data

def convert_to_1_hot(in_data, max_val):
    a = np.array(in_data)
    out_data = np.zeros((len(in_data),max_val))
    out_data[np.arange(len(in_data)), a] = 1
    return out_data

def get_diabetes(train_test_ratio):
    diabetes = datasets.load_diabetes()
    x = diabetes.data
    y = diabetes.target

    y = np.reshape(y,(y.shape[0],1))
    cutoff = int(x.shape[0] * train_test_ratio)

    x = x.astype(np.float32)
    y = y.astype(np.float32)

    x_train = x[0:cutoff, :]
    x_test = x[cutoff:, :]
    y_train = y[:cutoff]
    y_test = y[cutoff:]
    return x_train, y_train, x_test, y_test

def get_boston(train_test_ratio):
    boston = datasets.load_boston()
    x = boston.data
    y = boston.target

    y = np.reshape(y,(y.shape[0],1))
    cutoff = int(x.shape[0] * train_test_ratio)

    x = x.astype(np.float32)
    y = y.astype(np.float32)

    x_train = x[0:cutoff, :]
    x_test = x[cutoff:, :]
    y_train = y[:cutoff]
    y_test = y[cutoff:]
    return x_train, y_train, x_test, y_test

def get_covertype(train_test_ratio):
    covertype = datasets.fetch_covtype()
    x = covertype.data

    y = convert_to_1_hot(covertype.target - 1, 7)
    cutoff = int(x.shape[0] * train_test_ratio)

    x = x.astype(np.float32)
    y = y.astype(np.float32)

    x_train = x[0:cutoff, :]
    x_test = x[cutoff:, :]
    y_train = y[0:cutoff]
    y_test = y[cutoff:]
    return x_train, y_train, x_test, y_test

def get_iris(train_test_ratio):
    iris = datasets.load_iris()
    x = iris.data
    y = convert_to_1_hot(iris.target, 3)

    cutoff = int(x.shape[0] * train_test_ratio)

    x = x.astype(np.float32)
    y = y.astype(np.float32)

    x_train = x[0:cutoff, :]
    x_test = x[cutoff:, :]
    y_train = y[:cutoff]
    y_test = y[cutoff:]
    return x_train, y_train, x_test, y_test

def get_mnist(train_test_ratio):
    # mnist = tf.examples.tutorials.mnist.input_data.read_data_sets("MNIST_data/", one_hot=True)
    digits = datasets.load_digits()
    x = digits.data

    y = convert_to_1_hot(digits.target, 10)
    cutoff = int(x.shape[0] * train_test_ratio)

    x = x.astype(np.float32)
    y = y.astype(np.float32)

    x_train = x[0:cutoff, :] / 16.
    x_test = x[cutoff:, :] / 16.
    y_train = y[0:cutoff]
    y_test = y[cutoff:]
    return x_train, y_train, x_test, y_test

def generate_noisy_polinomial_data(mu, sigma, n_samples, f0, f1, f2, low=-100., high=100. ):
    if mu == 0. and sigma == 0.:
        noise = np.zeros(n_samples)
    else:
        noise = np.random.normal(mu, sigma, n_samples)

    x = (high - low) * np.random.random_sample(n_samples) + low

    y = f0 * x**2 + f1 * x**1 + f2 + noise
    x = np.expand_dims(x, 1)
    y = np.expand_dims(y, 1)

    return x, y

def generate_noisy_linear_data(mu,sigma,n_samples, w, b, low=-100.,high=100.):
    if mu == 0. and sigma == 0.:
        noise = np.zeros(n_samples)
    else:
        noise = np.random.normal(mu, sigma, n_samples)
    x = (high - low) * np.random.random_sample(n_samples) + low

    y = x * w + b + noise

    x = np.expand_dims(x,1)
    y = np.expand_dims(y,1)

    return x, y

if __name__ == '__main__':
    mnist = get_mnist()


# coding=utf-8
# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md).
# Licensed under the Apache License, Version 2.0 (see LICENSE).

from __future__ import (absolute_import, division, generators, nested_scopes, print_function,
                        unicode_literals, with_statement)

import os

from pants.util.contextutil import temporary_dir
from pants.util.process_handler import subprocess
from pants_test.pants_run_integration_test import PantsRunIntegrationTest

class CleanAllTest(PantsRunIntegrationTest):
  def test_clean_all_on_wrong_dir(self):
    with temporary_dir() as workdir:
      self.assert_failure(self.run_pants_with_workdir(["clean-all"], workdir))
      self.assert_failure(self.run_pants_with_workdir(["clean-all", "--async"], workdir))

  # Ensure async clean-all exits normally.

  def test_clean_all_async(self):
    self.assert_success(self.run_pants(["clean-all", "--async"]))

  # The tests below check for the existence of trash directories.
  def test_empty_trash(self):
    with self.temporary_workdir() as work_dir:
      trash_dir = os.path.join(work_dir, "trash")
      subprocess.call(["touch", trash_dir + "foo.txt"])
      self.assert_success(self.run_pants_with_workdir(["clean-all"], work_dir))
      self.assertFalse(os._exists(trash_dir))

  def test_empty_trash_async(self):
    with self.temporary_workdir() as work_dir:
      trash_dir = os.path.join(work_dir, "trash")
      subprocess.call(["touch", trash_dir + "foo.txt"])
      self.assert_success(self.run_pants_with_workdir(["clean-all", "--async"], work_dir))
      self.assertFalse(os._exists(trash_dir))


import os
import time
import sys
import pandas as pd
import numpy as np
import sklearn.pipeline
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error
import matplotlib.pyplot as plt

# We can play with the constants below to see how far we can accurately forecast the growth rate of counties by state
# CONSTANTS
# ____________________________________________________________

PREDICTOR_INTERVAL = 14  # 2 weeks
FORECASTING_INTERVAL = 7  # 1 week
REGRESSION_INTERVAL = PREDICTOR_INTERVAL + FORECASTING_INTERVAL

# ______________________________________________________________

def retrieve_data(timeseries_cases_path, timeseries_deaths_path):
    if time.time() - os.path.getmtime(timeseries_cases_path) > 86400:
        print('Downloading raw data...')

        # Import Johns Hopkins time series data
        os.system('curl https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/'
                  'csse_covid_19_time_series/time_series_covid19_confirmed_US.csv'
                  ' > ' + '"' + timeseries_cases_path + '"')
        os.system('curl https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/'
                  'csse_covid_19_time_series/time_series_covid19_deaths_US.csv'
                  ' > ' + '"' + timeseries_deaths_path + '"')

        print('Finished downloading raw data.')

# TODO:
# Convert date into days since first case
# We will use RMSE to measure accuracy of the model
# (https://medium.com/making-sense-of-data/time-series-next-value-prediction-using-regression-over-a-rolling-window-228f0acae363
# The idea is that we can build regression models based on different features, or attributes, recorded for each county
# in each state or province.

def build_regression_models(timeseries_dataset):
    datasets_bystate_index = []  # Used to index data frames stored in datasets_bystate
    datasets_bystate = []
    regression_model_bystate = []  # Used to keep track random forest models for each state

    # Transforming and cleaning data. Check to see if the prediction and target intervals are available for the
    # county being examined by the for-loop. The interval of time needed to make an accurate prediction is
    # REGRESSION_INTERVAL = PREDICTOR_INTERVAL + FORECASTING_INTERVAL. If the county examined has not had cases
    # for the requisite amount of time specified by REGRESSION_INTERVAL, then it will be dropped from the model.

    for state in timeseries_dataset.Province_State.unique():
        print("Building model for state: " + state)

        # Set index and labels
        state_dataset = timeseries_dataset.loc[timeseries_dataset['Province_State'] == state].copy()
        state_dataset.index = pd.RangeIndex(len(state_dataset.index))  # Reset index for proper func. of iloc

        # Drop unneeded attributes
        state_dataset.drop(columns=['UID', 'iso2', 'iso3', 'code3', 'FIPS',
                                    'Admin2', 'Province_State', 'Country_Region', 'Lat',
                                    'Long_', 'Combined_Key'], inplace=True)
        column_names = []  # Store new column names
        for col in range(1, state_dataset.shape[1] + 1):
            column_names.append("Day " + str(col))
        state_dataset.columns = column_names

        if state_dataset.shape[0] < 6:
            print("Unable to build model for state:" + state + " due to an insufficient number counties.")

        else:
            county = 0
            while county < state_dataset.shape[0]:
                has_dropped = False  # Control variable

                # Here, we are counting zeros and adding them to lag_count to shift lag_count columns so that
                # the data is in the format of (day 1, day 2, day 3) where each day is a day that the county
                # is infected with the virus.

                lag_count = 0  # Num. of days the county has NOT been infected.
                for date in range(state_dataset.shape[1]):
                    if state_dataset.iloc[county, date] == 0:
                        lag_count += 1
                    elif state_dataset.shape[1] - lag_count < REGRESSION_INTERVAL:
                        state_dataset.drop(state_dataset.index[county], inplace=True)
                        state_dataset.index = pd.RangeIndex(len(state_dataset.index))
                        has_dropped = True
                        break
                    elif state_dataset.iloc[county, 0] == 0:
                        # Shift the day the cases began in the county to the first column of the data frame
                        for val in range(lag_count, state_dataset.shape[1]):
                            state_dataset.iloc[county, val - lag_count] = state_dataset.iloc[county, val]
                            state_dataset.iloc[county, val] = 0  # To replace shifted values with 0
                        break
                    # Check to see if we have a county full of no cases... for some reason these are in here!
                    if date == state_dataset.shape[1] - 1 and state_dataset.iloc[county].sum() == 0:
                        state_dataset.drop(state_dataset.index[county], inplace=True)
                        state_dataset.index = pd.RangeIndex(len(state_dataset.index))
                        has_dropped = True

                if not has_dropped:
                    county += 1

                if state_dataset.shape[0] < 6:
                    break

        if state_dataset.shape[0] >= 6:
            state_dataset.drop(state_dataset.iloc[:, -(state_dataset.shape[1] - REGRESSION_INTERVAL):], axis='columns',
                               inplace=True)
            datasets_bystate.append(state_dataset)
            datasets_bystate_index.append(state)

    # Building regression model via multistep recursive forecasting with RandomForestRegressor. We analyze the
    # performance of each model with RMSE.
    for state_dataset in datasets_bystate:
        train, test = train_test_split(state_dataset, test_size=.2)

    return datasets_bystate_index, datasets_bystate

def main():
    pd.set_option('display.max_rows', None)
    pd.set_option('display.max_columns', None)

    # Dataset paths
    timeseries_cases_path = os.path.join('Covid-19 Data', 'time_series_covid19_confirmed_US.csv')
    timeseries_deaths_path = os.path.join('Covid-19 Data', 'time_series_covid19_deaths_US.csv')

    # Retrieve data from GitHub of Johns Hopkins
    retrieve_data(timeseries_cases_path, timeseries_deaths_path)

    # Making data frames from csv's
    timeseries_cases_dataset = pd.read_csv(timeseries_cases_path)

    # print(timeseries_cases_dataset.groupby('Province_State').nunique())

    datasets_bystate_index, datasets_bystate = build_regression_models(timeseries_cases_dataset)

    current_removed_state_index = 0
    for i in range(0, len(datasets_bystate)):
        print(datasets_bystate_index[i])
        print(datasets_bystate[i])

main()


import stan

schools_code = """
data {
  int<lower=0> J;         // number of schools
  real y[J];              // estimated treatment effects
  real<lower=0> sigma[J]; // standard error of effect estimates
}
parameters {
  real mu;                // population treatment effect
  real<lower=0> tau;      // standard deviation in treatment effects
  vector[J] eta;          // unscaled deviation from mu by school
}
transformed parameters {
  vector[J] theta = mu + tau * eta;        // school treatment effects
}
model {
  target += normal_lpdf(eta | 0, 1);       // prior log-density
  target += normal_lpdf(y | theta, sigma); // log-likelihood
}
"""

def model_1():
    print("RUNNING MODEL 1")
    schools_data = {
        "J": 8,
        "y": [28, 8, -3, 7, -1, 1, 18, 12],
        "sigma": [15, 10, 16, 11, 9, 11, 10, 18],
    }

    posterior = stan.build(schools_code, data=schools_data)
    fit = posterior.sample(num_chains=4, num_samples=1000)
    print(fit)

def model_2():
    print("RUNNING MODEL 2")
    schools_data = {
        "J": 8 * 10,
        "y": [28, 8, -3, 7, -1, 1, 18, 12] * 10,
        "sigma": [15, 10, 16, 11, 9, 11, 10, 18] * 10,
    }

    posterior = stan.build(schools_code, data=schools_data)
    fit = posterior.sample(num_chains=4, num_samples=1000)
    print(fit)

def model_3():
    print("RUNNING MODEL 3")
    schools_data = {
        "J": 8 * 11,
        "y": [28, 8, -3, 7, -1, 1, 18, 12] * 11,
        "sigma": [15, 10, 16, 11, 9, 11, 10, 18] * 11,
    }

    posterior = stan.build(schools_code, data=schools_data)
    fit = posterior.sample(num_chains=4, num_samples=1000)
    print(fit)

if __name__ == "__main__":
    skip = False
    try:
        model_1()
    except:
        skip = True
        print("FAILURE 1")
    if not skip:
        try:
            model_2()
        except:
            skip = True
            print("FAILURE 2")
    if not skip:
        try:
            model_3()
        except:
            print("FAILURE 3")


"""
Simple but highly configurable plotting functions for spiketrains in neo format.
While building on the matplotlib libary the functions lay an emphasis on clear,
pleasant-to-look-at visualizations.
"""

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from elephant.statistics import mean_firing_rate
from math import log10, floor

def _round_to_1(x):
    rounded = round(x, -int(floor(log10(abs(x)))))
    return rounded, rounded > x

def _get_attributes(spiketrains, key_list):
    """
    This function returns attribute_array which is of an array of shape
    (len(spiketrains), len(key_list)) and consists of numerical ids for each
    value of each key for each spike train.

    Passed spike trains must be already sorted according to key_list and
    key_list must not be empty.
    """

    key_count = len(key_list)
    attribute_array = np.zeros((len(spiketrains), len(key_list)))
    # count all group sizes for all keys in key_list:
    while key_count > 0:
        key_count -= 1
        group_key = key_list[key_count]
        i = 0
        if group_key in spiketrains[i].annotations:
            current_value = spiketrains[i].annotations[group_key]
        else:
            # use placeholder value when key is not in annotations
            # of the current spike train
            current_value = '####BLANK####'
        ref_value = current_value
        values = np.array([])
        # count all group sizes for values of current key:
        while i < spiketrains.__len__():
            if not len(values) or current_value not in values:
                values = np.append(values, current_value)
            # count group size for a value of the current key:
            while i < len(spiketrains) and current_value == ref_value:
                attribute_array[i][key_count] = \
                np.where(values == current_value)[0][0]
                i += 1
                if i < len(spiketrains):
                    if group_key in spiketrains[i].annotations:
                        current_value = spiketrains[i].annotations[
                            group_key]
                    else:
                        current_value = '####BLANK####'
            ref_value = current_value
    return attribute_array

def rasterplot(spiketrain_list,
               key_list=[],
               groupingdepth=0,
               spacing=[8, 3],
               colorkey=0,
               pophist_mode='color',
               pophistbins=100,
               right_histogram=mean_firing_rate,
               righthist_barwidth=1.01,
               filter_function=None,
               histscale=.1,
               labelkey=None,
               markerargs={'markersize':4,'marker':'.'},
               separatorargs=[{'linewidth':2, 'linestyle':'--', 'color':'0.8'},
                              {'linewidth':1, 'linestyle':'--', 'color':'0.8'}],
               legend=False,
               legendargs={'loc':(.98,1.), 'markerscale':1.5, 'handletextpad':0},
               ax=None,
               rasterized=False,
               style='ticks',
               palette=None,
               context=None,  # paper, poster, talk
               ):

    """
    This function plots the dot display of spike trains alongside its
    population histogram and the mean firing rate (or a custom function).

    Optional visual aids are offered such as sorting, grouping and color coding
    on the basis of the arrangement in list of spike trains and spike train
    annotations.
    Changes to optics of the dot marker, the separators and the legend can be
    applied by providing a dict with the respective parameters. Changes and
    additions to the dot display itself or the two histograms are best realized
    by using the returned axis handles.

    :param spiketrain_list: list
        List can either contain Neo SpikeTrains object or lists of Neo
        SpikeTrains objects.
    :param key_list: str | list of str
        Annotation key(s) for which the spike trains should be ordered.
        When list of keys is given the spike trains are ordered successively
        for the keys.
        By default the ordering by the given lists of spike trains have
        priority. This can be bypassed by using an empty string '' as list-key
        at any position in the key_list.
    :param groupingdepth: 0 | 1 | 2
        * 0: No grouping (default)
        * 1: grouping by first key in key_list.
             Note that when list of lists of spike trains are given the first
             key is by the list identification key ''. If this is unwanted
             the empty string '' can be placed at a different position in
             key_list.
        * 2: additional grouping by second key respectively
        The groups are separated by whitespace specified in the spacing
        parameter and optionally by a line specified by the the separatorargs.
    :param spacing: int | [int] | [int, int]
        Size of whitespace separating the groups in units of spike trains.
        When groupingdepth == 2 a list of two values can specify the distance
        between the groups in level 1 and level 2. When only one value is given
        level 2 spacing is set to half the spacing of level 1.
        Default: [5, 3]
    :param colorkey: str | int  (default 0)
        Contrasts values of a key by color. The key can be defined by its
        namestring or its position in key_list. Note that position 0 points to
        the list identification key ('') when list of lists of spike trains are
        given, if not otherwise specified in key_list!
    :param pophist_mode: 'color' (default) | 'total'
         * total: One population histogram for all drawn spike trains
         * color: Additionally to the total population histogram,
                  a histogram for each colored subset is drawn (see colorkey).
    :param pophistbins: int (default 100)
        Number of bins used for the population histogram.
    :param right_histogram: function
        The function gets ONE neo.SpikeTrain object as argument and has to
        return a scalar.
        For example the functions in the elephant.statistics module can
        be used. (default: mean_firing_rate)
        When a function is applied is is recommended to set the axis label
        accordingly by using the axis handle returned by the function:
        axhisty.set_xlabel('Label Name')
    :param filter_function: function
        The function gets ONE neo.SpikeTrain object as argument and if the
        return is True the spike train is included; if False it is exluded.
    :param histscale: float (default .1)
        Portion of the figure used for the histograms on the right and upper
        side.
    :param labelkey: 0 | 1 | '0+1' (default) | 'annotation key' | None
        * 0, 1: Set label according to first or second key in key_list.
                Note that the first key is by default the list identification
                key ('') when list of lists of spike trains are given.
        * '0+1': Two level labeling of 0 and 1
        * annotation-key: Labeling each spike train with its value for given key
        * None: No labeling
        Note that only groups (-> see groupingdepth) can be labeled as bulks.
        Alternatively you can color for an annotation key and show a legend.
    :param markerargs: dict
        Arguments dictionary is passed on to matplotlib.pyplot.plot()
    :param separatorargs: dict | [dict, dict] | None
        If only one dict is given and groupingdepth == 2 the arguments are
        applied to the separator of both level. Otherwise the arguments are
        of separatorargs[0] are applied to the level 1 and [1] to level 2.
        Arguments dictionary is passed on to matplotlib.pyplot.plot()
        To turn of separators set it to None.
    :param legend: boolean
        Show legend?
    :param legendargs: dict
        Arguments dictionary is passed on to matplotlib.pyplot.legend()
    :param ax: matplotlib axis | None (default)
        The axis onto which to plot. If None a new figure is created.
        When an axis is given, the function can't handle the figure settings.
        Therefore it is recommended to call seaborn.set() with your preferred
        settings before creating your matplotlib figure in order to control
        your plotting layout.
    :param rasterized: bool (default: False)
        Passed as 'rasterized' keyword to the matplotlib plot function for the dot display.
    :param style: str
        seaborn style setting. Default: 'ticks'
    :param palette: string | sequence
        Define the color palette either by its name or use a custom palette in
        a sequence of the form ([r,g,b],[r,g,b],...).
    :param context: 'paper'(default) | 'talk' | 'poster'
        seaborn context setting which controls the scaling of labels. For the
        three options the parameters are scaled by .8, 1.3, and 1.6
        respectively.
    :return: ax, axhistx, axhisty   <matplotlib axis handle>
        * ax is handle of the dot display plot
        * axhistx is handle of the histogram plot above the the dot display
        * axhisty is handle of the histogram plot on the right hand side

    *Basic Example:*
        >>> from elephant.spike_train_generation import homogeneous_poisson_process as HPP
        >>> from quantities import Hz
        >>> import matplotlib.pyplot as plt
        >>>
        >>> st_list = [HPP(rate=10*Hz) for _ in range(100)]
        >>> rasterplot(st_list)
        >>> plt.show()

    *Grouping Example:*
        >>> from elephant.spike_train_generation import homogeneous_poisson_process as HPP
        >>> from elephant.spike_train_generation import homogeneous_gamma_process as HGP
        >>> from quantities import Hz
        >>> import matplotlib.pyplot as plt
        >>>
        >>> st_list1 = [HPP(rate=10*Hz) for _ in range(100)]
        >>> st_list2 = [HGP(a=3, b=10*Hz) for _ in range(100)]
        >>>
        >>> # plot visually separates the two lists
        >>> rasterplot([st_list1, st_list2])
        >>>
        >>> # add annotations to spike trains
        >>> for i, (st1, st2) in enumerate(zip(st_list1, st_list2)):
        >>>     if i.__mod__(2):
        >>>         st1.annotations['parity'] = 'odd'
        >>>         st2.annotations['parity'] = 'odd'
        >>>     else:
        >>>         st1.annotations['parity'] = 'even'
        >>>         st2.annotations['parity'] = 'even'
        >>>
        >>> # plot separates the lists and the annotation values within each list
        >>> rasterplot([st_list1, st_list2], key_list=['parity'],
        >>>            groupingdepth=2, labelkey='0+1')
        >>>
        >>> # '' key can change the priority of the list grouping
        >>> rasterplot([st_list1, st_list2], key_list=['parity', ''],
        >>>            groupingdepth=2, labelkey='0+1')
        >>>
        >>> # groups can also be emphasized by an explicit color code
        >>> rasterplot([st_list1, st_list2], key_list=['', 'parity'],
        >>>            groupingdepth=1, labelkey=0, colorkey='parity',
        >>>            legend=True)
        >>>
        >>> plt.show()

    """

    # Initialize plotting canvas
    sns.set_style(style)

    if context is not None:
        sns.set_context(context)

    if palette is not None:
        sns.set_palette(palette)
    else:
        palette = sns.color_palette()

    if ax is None:
        fig, ax = plt.subplots()
        # axis must be created after sns.set() command for style to apply!

    margin = 1 - histscale
    left, bottom, width, height = ax.get_position().bounds
    ax.set_position([    left,                  bottom,
                         margin * width,        margin * height])
    axhistx = plt.axes([left,                   bottom + margin * height,
                        margin * width,         histscale * height])
    axhisty = plt.axes([left + margin * width,  bottom,
                        histscale * width,      margin * height])

    sns.despine(ax=axhistx)
    sns.despine(ax=axhisty)

    # Whitespace margin around dot display = 2%
    ws_margin = 0.02

    # Control of user entries
    if groupingdepth > 2:
        raise ValueError("Grouping is limited to two layers.")
    groupingdepth = int(groupingdepth)

    list_key = "%$\@[#*&/!"  # unique key to be added to annotations to store
                             # list ordering information.

    if type(key_list) == 'str':
        key_list = [key_list]

    if '' not in key_list:
        key_list = [list_key] + key_list
    else:
        key_list = [list_key if not key else key for key in key_list]

    if type(spacing) == list:
        if len(spacing) == 1:
            spacing = [spacing[0], spacing[0]/2.]
    else:
        spacing = [spacing, spacing/2.]
    if spacing[0] < spacing[1]:
        raise DeprecationWarning("For reasonable visual aid, spacing between" \
                               + " top level group (spacing[0]) must be larger" \
                               + " than for subgroups (spacing[1]).")

    if type(colorkey) == int and len(key_list):
        if colorkey >= len(key_list):
            raise IndexError("An integer colorkey must refer to a position in" \
                           + " key_list.")
        colorkey = key_list[colorkey]
    else:
        if not colorkey:
            colorkey = list_key
        elif colorkey not in key_list:
            raise AttributeError("colorkey must be in key_list.")

    if legend and not key_list:
        raise AttributeError("Legend requires a non empty key_list.")

    if labelkey == '':
        labelkey = list_key

    if type(separatorargs) == list:
        if len(separatorargs) == 1:
            separatorargs += separatorargs
        for args in separatorargs:
            if type(args) != dict:
                raise TypeError("The parameters must be given as dict.")
    else:
        separatorargs = [separatorargs, separatorargs]

    for i, args in enumerate(separatorargs):
        if 'c' in args:
            separatorargs[i]['color'] = args['c']
        elif 'color' not in args:
            separatorargs[i]['color'] = '0.8'

    markerargs['linestyle'] = ''

    # Flatten list of lists while keeping the grouping info in annotations
    if isinstance(spiketrain_list[0], list):
        for list_nbr, st_list in enumerate(spiketrain_list):
            for st in st_list:
                st.annotations[list_key] = "set {}".format(list_nbr)
        spiketrain_list = [st for sublist in spiketrain_list for st in sublist]
    else:
        for st in spiketrain_list:
            st.annotations[list_key] = "set {}".format(0)
        key_list.remove(list_key)
        key_list.append(list_key)

    # Input checks on flattened lists
    if len(key_list) < groupingdepth:
        raise ValueError("Can't group more as keys in key_list.")

    # Filter spike trains according to given filter function
    if filter_function is not None:
        filter_index = []
        for st_count, spiketrain in enumerate(spiketrain_list):
            if filter_function(spiketrain):
                filter_index += [st_count]
        spiketrain_list = [spiketrain_list[i] for i in filter_index]

    # Initialize plotting parameters
    t_lims = [(st.t_start, st.t_stop) for st in spiketrain_list]
    tmin = min(t_lims, key=lambda f: f[0])[0]
    tmax = max(t_lims, key=lambda f: f[1])[1]
    period = tmax - tmin
    ax.set_xlim(tmin - ws_margin*period, tmax + ws_margin*period)
    yticks = np.zeros(len(spiketrain_list))

    # Sort spike trains according to keylist
    def sort_func(x):
        return ['' if key not in x.annotations
                else x.annotations[key] for key in key_list]

    spiketrain_list = sorted(spiketrain_list, key=lambda x: sort_func(x))
    if len(key_list) > 1:
        attribute_array = _get_attributes(spiketrain_list, key_list)
    elif len(key_list) == 1:
        attribute_array = np.zeros((len(spiketrain_list), 2))
        attribute_array[:,0] = _get_attributes(spiketrain_list, key_list)[:,0]
    else:
        attribute_array = np.zeros((len(spiketrain_list), 1))

    # Define colormap
    if not len(key_list):
        nbr_of_colors = 1
        colorkey = None
    else:
        colorkey = np.where(colorkey == np.array(key_list))[0][0]
        nbr_of_colors = int(max(attribute_array[:, colorkey]) + 1)

    colormap = sns.color_palette(palette, nbr_of_colors)

    # Draw population histogram (upper side)
    colorkeyvalues = np.unique(attribute_array[:, colorkey])

    if pophist_mode == 'color' and len(colorkeyvalues)-1:
        if len(sns.color_palette()) < len(colorkeyvalues):
            print("\033[31mWarning: There are more subsets than can be " +
                  "separated by colors in the color palette which might lead " +
                  "to confusion!\033[0m")
        max_y = 0
        for value in colorkeyvalues:
            idx = np.where(attribute_array[:, colorkey] == value)[0]
            histout = axhistx.hist([stime for strain in
                                      [spiketrain_list[i] for i in idx]
                                      for stime in strain],
                                     pophistbins, histtype='step', linewidth=1,
                                     color=colormap[int(value)])
            max_y = np.max([max_y, np.max(histout[0])])

    else: # pophist_mode == 'total':
        if len(colorkeyvalues)-1:
            sum_color = separatorargs[0]['color']
        else:
            sum_color = sns.color_palette()[0]

        histout = axhistx.hist([stime for strain in spiketrain_list
                                      for stime in strain],
                               pophistbins, histtype='step', linewidth=1,
                               color=sum_color)
        max_y = np.max(histout[0])

    # Set ticks and labels for population histogram
    axhistx_ydim, up = _round_to_1(max_y)
    if max_y > axhistx.get_ylim()[-1]:
        axhistx.set_ylim(0, max_y)
    if up and axhistx_ydim > max_y:
        axhistx.set_ylim(0, axhistx_ydim)
    axhistx.set_yticks([axhistx_ydim])
    axhistx.set_yticklabels(['{:.0f}'.format(axhistx_ydim)])
    axhistx.set_ylabel('count')

    # Legend for colorkey
    if legend:
        __, index = np.unique(attribute_array[:, colorkey], return_index=True)
        legend_labels = [spiketrain_list[i].annotations[key_list[colorkey]]
                         for i in index]
        legend_handles = [0] * len(index)

    # Reshape list into sublists according to groupingdepth
    if groupingdepth > 0:
        value1, index1, counts1 = np.unique(attribute_array[:, 0],
                                            return_index=True,
                                            return_counts=True)
        for v1, i1, c1 in zip(value1, index1, counts1):
            v1 = int(v1)
            spiketrain_list[v1:v1 + c1] = [spiketrain_list[v1:v1 + c1]]
            if groupingdepth > 1:
                __, counts2 = np.unique(attribute_array[i1:i1 + c1, 1],
                                        return_counts=True)
                for v2, c2 in enumerate(counts2):
                    v2 = int(v2)
                    spiketrain_list[v1][v2:v2+c2] = [spiketrain_list[v1][v2:v2+c2]]
            else:
                spiketrain_list[v1] = [spiketrain_list[v1]]
    else:
        spiketrain_list = [[spiketrain_list]]

    # HIERARCHIE:
    # [ [ []..[] ] .... [ []..[] ] ] spiketrain_list
    # [ []..[] ] LIST
    # [] list
    # spike train

    # Loop through lists of lists of spike trains
    for COUNT, SLIST in enumerate(spiketrain_list):

        # Separator depth 1
        if COUNT and separatorargs is not None:
            linepos = ypos + len(spiketrain_list[COUNT-1][-1]) \
                      + spacing[0]/2. - 0.5
            ax.plot(ax.get_xlim(), [linepos] * 2, **separatorargs[0])

        # Loop through lists of spike trains
        for count, slist in enumerate(SLIST):
            nbr_of_drawn_sts = int(sum([len(sl) for SL in
                                        spiketrain_list[:COUNT] for sl in SL])\
                                 + sum([len(sl) for sl in SLIST[:count]]))

            # Calculate postition of next spike train to draw
            prev_spaces = np.sum([len(SLIST_it) - 1
                                  for SLIST_it in spiketrain_list[:COUNT]])
            ypos = nbr_of_drawn_sts \
                 + int(bool(groupingdepth)) * COUNT * spacing[0] \
                 + groupingdepth/2 * count * spacing[1] \
                 + groupingdepth/2 * prev_spaces * spacing[1]

            # Separator depth 2
            if count and separatorargs is not None:
                linepos = ypos - (spacing[1] + 1) / 2.
                ax.plot(ax.get_xlim(), [linepos] * 2, **separatorargs[1])

            # Loop through spike trains
            for st_count, st in enumerate(slist):
                current_st = nbr_of_drawn_sts + st_count
                annotation_value = int(attribute_array[current_st, colorkey])
                color = colormap[annotation_value]

                # Dot display
                handle = ax.plot(st.times.magnitude,
                                 [st_count + ypos] * st.__len__(),
                                 color=color, **markerargs, rasterized=rasterized)
                if legend:
                    legend_handles[annotation_value] = handle[0]

                # Right side histogram bar
                barvalue = right_histogram(st)
                barwidth = righthist_barwidth
                axhisty.barh(y=st_count + ypos, # - barwidth/2.,
                             width=barvalue,
                             height=barwidth,
                             color=color,
                             edgecolor=color)

            # Append positions of spike trains to tick list
            ycoords = np.arange(len(slist)) + ypos
            yticks[nbr_of_drawn_sts:nbr_of_drawn_sts+len(slist)] = ycoords

    # Plotting axis
    yrange = yticks[-1] - yticks[0]
    ax.set_ylim(yticks[0] - ws_margin*yrange,
                yticks[-1] + ws_margin*yrange)
    axhistx.set_xlim(ax.get_xlim())
    axhisty.set_ylim(ax.get_ylim())
    ax.set_xlabel('t [{}]'.format(spiketrain_list[0][0][0].units.dimensionality))
    axhistx.get_xaxis().set_visible(False)
    axhisty.get_yaxis().set_visible(False)

    # Set ticks and labels for right side histogram
    axhisty_xdim, up = _round_to_1(axhisty.get_xlim()[-1])
    if up:
        axhistx.set_ylim(0, axhistx_ydim)
    axhisty.set_xticks([axhisty_xdim])
    axhisty.set_xticklabels(['{}'.format(axhisty_xdim)])

    # Y labeling
    if key_list and labelkey in key_list + [0, 1, '0+1']:
        if labelkey == key_list[0]:
            if groupingdepth > 0:
                labelkey = 0
        elif len(key_list) > 1 and labelkey == key_list[1]:
            if groupingdepth > 1:
                labelkey = 1

        if type(labelkey) == int or labelkey == '0+1':
            labelpos = [[] for label_level in range(2)]
            labelname = [[] for label_level in range(2)]

            # Labeling depth 1 + 2
            if groupingdepth:
                values1, index1, counts1 = np.unique(attribute_array[:, 0],
                                                     return_index=True,
                                                     return_counts=True)

                for v1, i1, c1 in zip(values1, index1, counts1):
                    st = spiketrain_list[int(v1)][0][0]
                    if key_list[0] in st.annotations:
                        labelname[0] += [st.annotations[key_list[0]]]
                        if labelkey == '0+1':
                            labelname[0][-1] += ' ' * 5
                    else:
                        labelname[0] += ['']

                    labelpos[0] += [(yticks[i1] + yticks[i1+c1-1])/2.]

                    # Labeling depth 2
                    if groupingdepth / 2 and labelkey and len(key_list) - 1:
                        __, index2, counts2 = np.unique(attribute_array[i1:i1+c1, 1],
                                                        return_index=True,
                                                        return_counts=True)

                        for v2, (i2, c2) in enumerate(zip(index2, counts2)):
                            st = spiketrain_list[int(v1)][int(v2)][0]
                            if key_list[1] in st.annotations:
                                labelname[1] += [st.annotations[key_list[1]]]
                            else:
                                labelname[1] += ['']

                            labelpos[1] += [(yticks[i1+i2] + yticks[i1+i2+c2-1])/2.]

            # Set labels according to labelkey
            if type(labelkey) == int:
                ax.set_yticks(labelpos[1] if labelkey else labelpos[0])
                ax.set_yticklabels(labelname[1] if labelkey else labelname[0])

            elif labelkey == "0+1":
                ax.set_yticks(labelpos[0] + labelpos[1])
                ax.set_yticklabels(labelname[0] + labelname[1])

        else:
            # Annotatation key as labelkey
            labelname = []
            for COUNT, SLIST in enumerate(spiketrain_list):
                for count, slist in enumerate(SLIST):
                    for st_count, st in enumerate(slist):
                        if labelkey in st.annotations:
                            labelname += [st.annotations[labelkey]]
                        else:
                            labelname += ['']
            ax.set_yticks(yticks)
            ax.set_yticklabels(labelname)

    else:
        ax.set_yticks([])
        ax.set_yticklabels([''])

    # Draw legend
    if legend:
        ax.legend(legend_handles, legend_labels, **legendargs)

    # Remove list_key from annotations
    for SLIST in spiketrain_list:
        for slist in SLIST:
            for st in slist:
                st.annotations.pop(list_key, None)

    return ax, axhistx, axhisty