"""
Script to start server to drive your car.
"""

import model

import keras

# Load a trained keras model and use it in the KerasAngle pilot
# model_file = ''

model_file = '/home/'
model = keras.models.load_model(model_file)
pilot = model.pilots.KerasAngle(model=model, throttle=20)

# Specify where sessions data should be saved
sh = model.sessions.SessionHandler(sessions_path='~/data/sessions')
session = sh.new()

# Start server
w = model.remotes.RemoteServer(session, pilot, port=8886)
w.start()

# in a browser go to localhost:8887 to drive your car


import os
import csv
import numpy as np
from .mfcc import mfcc_kaldi, mfcc_librosa
from .custom import acf, histogram, rms_energy, rms_energy_infra
from .utils import root_folder, concat_samples

CACHE_SIZE = 20

def get_available_features() -> tuple:
	feats = (mfcc_kaldi, mfcc_librosa, acf, histogram, rms_energy, rms_energy_infra)
	return tuple(f.__name__ for f in feats), feats

def read_dataset(name: str, partition: str, label: str=None) -> tuple:
	if partition.lower() not in ("train", "test"):
		raise ValueError("Partition must be 'train' or 'test'")
	files_root = os.path.join(root_folder(), "datasets", name, partition)
	if not os.path.exists(files_root):
		raise ValueError(f"Dataset does not exist: {name} ({partition})")

	with open(os.path.join(files_root, "labels.csv"), newline='') as f:
		reader = csv.reader(f)
		classes = next(reader)[1:]
		filenames, labels = zip(*((line[0], line[1:]) for line in reader))

	filenames = np.array([os.path.join(files_root, fn) for fn in filenames])
	classes = np.array(classes)
	labels = np.array(labels) != '0'

	if label is None:
		return filenames, classes, labels
	else:
		try:
			mask = labels[:, np.nonzero(classes == label)]
			return filenames[mask], classes, labels[mask]
		except ValueError as e:
			raise ValueError(f"Label {label} not found in dataset {name}") from e

def _filename(filenames: list, feature: str, feature_args: dict, vad: dict):
	from pickle import dumps
	from hashlib import sha256
	obj = (tuple(filenames), feature, tuple(sorted(feature_args.items())), tuple() if vad is None else tuple(sorted(vad.items())))
	_hash = sha256(dumps(obj)).hexdigest()
	return os.path.join(root_folder(), "features", "cache", str(_hash) + ".features")

def extract_features(filenames: list, feature: str, feature_args: dict, vad: dict=None,
		concatenate: bool=False, cache: bool=True):

	if cache:
		# Lookup features in cache and return them if found
		cache_filename = _filename(filenames, feature, feature_args, vad)

		if os.path.exists(cache_filename):
			from pickle import load
			with open(cache_filename, "rb") as f:
				cached_tuple, feature_vals, index = load(f)
			if (np.array(cached_tuple[0]) == filenames).all() and cached_tuple[1:] == (feature, feature_args, vad):
				return feature_vals, index
			else:
				del cached_tuple, feature_vals, index

	# Get feature function
	available_features = get_available_features()
	if feature not in available_features[0]:
		raise ValueError(f"Unrecognized feature {feature}")
	feature_func = available_features[1][available_features[0].index(feature)]

	if vad is None or len(vad) == 0:
		# Compute features on original files
		index = np.arange(len(filenames))
		feature_vals = feature_func(filenames, **feature_args)
	else:
		# Split files according to VAD output and perform feature extraction on each part
		from .vad import analyze_gen, smooth, splitaudio, write_tempfiles, clean_tempdir
		if "frame_length" not in vad or "aggressiveness" not in vad:
			raise ValueError("Argument 'vad' must contain 'frame_length' and 'aggressiveness'")

		gen = analyze_gen(filenames, vad["frame_length"], vad["aggressiveness"])
		if "smooth_n" in vad:
			gen = (
				(audio, smooth(activity, n=vad["smooth_n"], threshold=vad.get("smooth_treshold")))
					for audio, activity in gen)

		# TODO: this essentially copies the entire dataset to disk, which is ugly
		tempfiles = []
		tempdir = None
		for audio, activity in gen:
			segments = splitaudio(audio, vad["frame_length"], activity, vad.get("inverse", False), vad.get("min_length", 0))
			_tf, tempdir = write_tempfiles(segments, tempdir)
			tempfiles.append(_tf)

		index = np.array([i for i in range(len(tempfiles)) for j in range(len(tempfiles[i]))])

		tempfiles = [t for l in tempfiles for t in l]
		feature_vals = feature_func(tempfiles, **feature_args)
		clean_tempdir(tempdir)

	empty = sum(np.prod(v.shape) == 0 for v in feature_vals if isinstance(v, np.ndarray))
	if empty > 0:
		raise ValueError(f"{empty} feature value{'' if empty == 1 else 's'} of dimension 0")

	if cache:
		# Remove least recently used cache entries if needed
		cache_files = next(os.walk(os.path.join(root_folder(), "features", "cache")))
		cache_files = [os.path.join(cache_files[0], fn) for fn in cache_files[2] if fn.endswith(".features")]
		cache_files = sorted(cache_files, key=lambda fn: os.stat(fn).st_atime, reverse=True)
		if len(cache_files) > CACHE_SIZE - 1:
			for fn in cache_files[CACHE_SIZE-1:]:
				try:
					os.remove(fn)
				except OSError:
					pass

		from pickle import dump
		with open(cache_filename, "wb") as f:
			dump(((filenames, feature, feature_args, vad), feature_vals, index), f)

	if concatenate:
		feature_vals = concat_samples(feature_vals)

	return feature_vals, index

# For compability with older classifiers
def extract_dataset_features(name: str, partition: str, features: list, feature_args: list,
		concatenate: bool=False, cache: bool=True) -> dict:

	filenames, classes, labels = read_dataset(name, partition, None)
	feature_vals, _ = [extract_features(filenames, f, f_a, concatenate=False, cache=cache) for f, f_a in zip(features, feature_args)]
	res = dict()
	for label in classes:
		mask = labels[:, classes.index(label)]
		f_vals = []
		for i in range(len(feature_vals)):
			f_vals.append([sequence for sequence, bit in zip(feature_vals[i], mask) if bit])
		res[label] = f_vals

	del filenames, feature_vals, classes, labels

	if concatenate:
		for label in res:
			for i in range(len(res[label])):
				res[label][i] = concat_samples(res[label][i])

	return res


from typing import List

from drf_yasg import openapi

from winter.core import ComponentMethodArgument
from winter.web.routing import Route
from .route_parameters_inspector import RouteParametersInspector
from .type_inspection import InspectorNotFound
from .type_inspection import TypeInfo
from .type_inspection import inspect_type

class PathParametersInspector(RouteParametersInspector):

    def inspect_parameters(self, route: 'Route') -> List[openapi.Parameter]:
        parameters = []

        for argument in self._path_arguments(route):
            openapi_parameter = self._convert_argument_to_openapi_parameter(argument)
            parameters.append(openapi_parameter)

        return parameters

    def _convert_argument_to_openapi_parameter(self, argument: ComponentMethodArgument) -> openapi.Parameter:
        try:
            type_info = inspect_type(argument.type_)
            description = argument.description
        except InspectorNotFound:
            type_info = TypeInfo(openapi.TYPE_STRING)
            description = 'winter_openapi has failed to inspect the parameter'
        return openapi.Parameter(
            name=argument.name,
            description=description,
            required=True,
            in_=openapi.IN_PATH,
            default=argument.get_default(None),
            **type_info.as_dict(output=False),
        )

    def _path_arguments(self, route: 'Route') -> List[ComponentMethodArgument]:
        path_arguments = []
        for path_variable in route.get_path_variables():
            argument = route.method.get_argument(path_variable)
            if argument is not None:
                path_arguments.append(argument)
        return path_arguments


from argparse import ArgumentParser
from args import LightningBaseArgParser
from pytorch_lightning import Trainer, seed_everything
from pytorch_lightning import loggers as pl_loggers
from pytorch_lightning.callbacks import EarlyStopping, ModelCheckpoint, LearningRateLogger

from lightning.example_lightning import ExampleModel

seed_everything(6)

def main(args):
    logger = pl_loggers.WandbLogger(experiment="example", save_dir=None)
    early_stop = EarlyStopping(
        monitor="val_loss"
    )
    checkpoint_callback = ModelCheckpoint(dirpath="ckpts/", monitor="val_loss")
    model = ExampleModel(args)
    lr_logger = LearningRateLogger()
    trainer = Trainer.from_argparse_args(
        args,
        logger=logger,
        callbacks =  [early_stop, lr_logger],
        checkpoint_callback=checkpoint_callback
    )
    trainer.fit(model)

if __name__ == "__main__":
    parser = LightningBaseArgParser().get_parser()
    parser = ExampleModel.add_model_specific_args(parser)
    parser = Trainer.add_argparse_args(parser)
    args = parser.parse_args()
    main(args)


'''
Created on Feb 27, 2015

@author: Carlos Lallana
'''
import os

import jinja2
import webapp2

class Main(webapp2.RequestHandler):

    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        self.response.out.write('Hello, Jenkins 2!')

JINJA_ENVIRONMENT = jinja2.Environment(
	loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
	extensions=['jinja2.ext.autoescape'],
	autoescape=True)

app = webapp2.WSGIApplication(
	[
		('/', Main)
	], debug=True)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Jul 18 09:40:22 2019

@author: gabin
"""

import pickle
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import time
from scipy.signal import savgol_filter

#dico=pickle.load(open('Shots','rb'))

def shot_type(row):
    if row['Time_to_shoot']>-2:
        return('catch-and-shoot')
    else :
        return('pull-up')

def shooting_efficiency_inferior(data):

    ### getting the data ###
    D_CLOSEST_PLAYER=data['D_CLOSEST_DEF']
    T_CLOSEST_PLAYER=data['T_CLOSEST_DEF']
    TIME=data['TIME_ABSCISSE']
    TIME_TO_SHOOT=data['TIME_TO_SHOOT']

    ### differentiating catch-and-shoot, pull-up shots and success and fails ###
    D_CLOSEST_PLAYER1=[]
    D_CLOSEST_PLAYER2=[]
    T_CLOSEST_PLAYER1=[]
    T_CLOSEST_PLAYER2=[]
    TIME1=[]
    TIME2=[]

    for k in range(len(D_CLOSEST_PLAYER)):
        ## success ##
        if D_CLOSEST_PLAYER[k][0]==1:

            # all shots #
            D_CLOSEST_PLAYER1.append(D_CLOSEST_PLAYER[k][1])
            T_CLOSEST_PLAYER1.append(T_CLOSEST_PLAYER[k][1])
            TIME1.append(np.array(TIME[k][1]))

        ## fails ##
        else :

            # all shots #
            D_CLOSEST_PLAYER2.append(D_CLOSEST_PLAYER[k][1])
            T_CLOSEST_PLAYER2.append(T_CLOSEST_PLAYER[k][1])
            TIME2.append(np.array(TIME[k][1]))

    print(len(D_CLOSEST_PLAYER1)/(len(D_CLOSEST_PLAYER2)+len(D_CLOSEST_PLAYER1)))
    closest1=[]
    pos1=[]
    closest2=[]
    pos2=[]
    for i in range(len(D_CLOSEST_PLAYER1)):
        min1=0
        min2=0
        for j in range(len(D_CLOSEST_PLAYER1[i])):
            if -0.04<TIME1[i][j]<0.04:
                if T_CLOSEST_PLAYER1[i][j]>min1:
                    min1=T_CLOSEST_PLAYER1[i][j]
                if D_CLOSEST_PLAYER1[i][j]>min2:
                    min2=D_CLOSEST_PLAYER1[i][j]
        closest1.append(min1)
        pos1.append(min2)

    for i in range(len(D_CLOSEST_PLAYER2)):
        min1=np.inf
        min2=np.inf
        for j in range(len(D_CLOSEST_PLAYER2[i])):
            if -0.04<TIME2[i][j]<0.04:
                if T_CLOSEST_PLAYER2[i][j]<min1:
                    min1=T_CLOSEST_PLAYER2[i][j]
                if D_CLOSEST_PLAYER2[i][j]<min2:
                    min2=D_CLOSEST_PLAYER2[i][j]
        closest2.append(min1)
        pos2.append(min2)

    inferior_values=[]
    time_abs=[0.02*i+0.2 for i in range(60)]
    S1=[]
    T1=[]
    for i in range(60):
        success=0
        fails=0
        for j in range(len(closest1)):
            if not np.isinf(closest1[j]):
                if closest1[j]<time_abs[i]:
                    success+=1
        for j in range(len(closest2)):
            if not np.isinf(closest2[j]):
                if closest2[j]<time_abs[i]:
                    fails+=1
        S1.append(success/len(closest1))
        T1.append(fails/len(closest2))

        #print('inf to :', i)
        #print(success,fails)

        inferior_values.append(success/(fails+success)*100)

    fig,ax1=plt.subplots()
    plt.plot(time_abs,inferior_values)
    plt.xlabel(r'$\delta_{t}^*(0)$ inferior to [s]')
    plt.ylabel('Three point shooting percentage')
    plt.vlines(time_abs[15], inferior_values[0], inferior_values[15], linestyle="dashed",lw=0.5)
    plt.hlines(inferior_values[15], time_abs[0], time_abs[15], linestyle="dashed",lw=0.5)
    plt.xlim(time_abs[0],time_abs[-1])
    plt.ylim(inferior_values[0],inferior_values[-1]+1)
    ax1.tick_params(direction='in')
    plt.show()
#    plt.plot(time_abs2,inferior_values2)
    #plt.figure(2)
    #plt.plot(time_abs,S1)
    #plt.plot(time_abs,T1)

    d_abs=[0.1*i+3 for i in range(140)]
    inferior_values=[]
    S=[]
    T=[]
    for i in range(140):
        success=0
        fails=0
        for j in range(len(pos1)):
            if not np.isinf(pos1[j]):
                if pos1[j]<d_abs[i]:
                    success+=1
        for j in range(len(pos2)):
            if not np.isinf(pos2[j]):
                if pos2[j]<d_abs[i]:
                    fails+=1
        S.append(success/len(pos1))
        T.append(fails/len(pos2))

        #print('inf to :', i*0.2)
        #print(success,fails)
        #print(round(success/len(pos1),2),round(fails/len(pos2),2),round(success/(fails+success),2)*100)

        inferior_values.append(success/(fails+success)*100)

    print(inferior_values[10],inferior_values[50])

#    d_abs2=[0.2*i+1 for i in range(120)]
#    inferior_values2=[]
#    for i in range(120):
#        success=0
#        fails=0
#        for j in range(len(pos3)):
#            if not np.isinf(pos3[j]):
#                if pos3[j]<d_abs2[i]:
#                    success+=1
#        for j in range(len(pos4)):
#            if not np.isinf(pos4[j]):
#                if pos4[j]<d_abs2[i]:
#                    fails+=1
#        #print('inf to :', i*0.2)
#        #print(success,fails)
#        #print(round(success/len(pos1),2),round(fails/len(pos2),2),round(success/(fails+success),2)*100)
#
#        inferior_values2.append(success/(fails+success)*100)

    fig,ax2=plt.subplots()
    plt.plot(d_abs,inferior_values)
    plt.xlabel(r'$\delta_{d}^*(0)$ inferior to [feet]')
    plt.ylabel('Three point shooting percentage')
    ax2.tick_params(direction='in')
    plt.xlim(d_abs[0],d_abs[-1])
    plt.ylim(min(inferior_values),inferior_values[-1]+1)
    plt.vlines(d_abs[10], inferior_values[0], inferior_values[10], linestyle="dashed",lw=0.5)
    plt.hlines(inferior_values[10], d_abs[0], d_abs[10], linestyle="dashed",lw=0.5)
    plt.vlines(d_abs[50], inferior_values[0], inferior_values[50], linestyle="dashed",lw=0.5)
    plt.hlines(inferior_values[50], d_abs[0], d_abs[50], linestyle="dashed",lw=0.5)
    plt.show()
#    plt.plot(d_abs2,inferior_values2)
    #fig = plt.figure(4)
    #sns.kdeplot(np.array(pos1),bw=0.2)
    #sns.kdeplot(np.array(pos2),bw=0.2)
   # plt.show()
    #plt.plot(S, label='success')
    #plt.plot(T, label='fails')
    #plt.legend()

def restructure_data(data):

    ### getting the data ###
    D_CLOSEST_PLAYER=data['D_CLOSEST_DEF']
    T_CLOSEST_PLAYER=data['T_CLOSEST_DEF']
    TIME=data['TIME_ABSCISSE']
    TIME_TO_SHOOT=data['TIME_TO_SHOOT']

    ### only the second column because the first one contains if it is a succes or a miss ###
    D_CLOSEST_PLAYER_bis=[]
    T_CLOSEST_PLAYER_bis=[]
    TIME_bis=[]
    TIME_TO_SHOOT_bis=[]
    SUCCESS=[]
    nb_catch_and_shoot=0
    nb_pull_up=0
    nb_success=0
    nb_missed=0
    nb_cns_success=0
    nb_cns_missed=0
    nb_pull_up_success=0
    nb_pull_up_missed=0
    for k in range(len(D_CLOSEST_PLAYER)):
        unique,count=np.unique(np.array(TIME[k][1]).round(2), return_counts=True)
        if list(count)==[1]*len(count): # we don't take shots where values of time are repeated, because in the data, sometimes the values of time doesn't change so stay on the same second but we count the evolution on this second
            if D_CLOSEST_PLAYER[k][0]==0:
                nb_missed+=1
                if TIME_TO_SHOOT[k][1]>-2:
                    nb_catch_and_shoot+=1
                    nb_cns_missed+=1
                else :
                    nb_pull_up+=1
                    nb_pull_up_missed+=1
            else :
                nb_success+=1
                if TIME_TO_SHOOT[k][1]>-2:
                    nb_catch_and_shoot+=1
                    nb_cns_success+=1
                else :
                    nb_pull_up+=1
                    nb_pull_up_success+=1
            D_CLOSEST_PLAYER_bis.append(D_CLOSEST_PLAYER[k][1])
            T_CLOSEST_PLAYER_bis.append(T_CLOSEST_PLAYER[k][1])
            TIME_bis.append(np.array(TIME[k][1]).round(2)) # round to 0.01 second
            TIME_TO_SHOOT_bis.append([TIME_TO_SHOOT[k][1]]*len(TIME[k][1]))
            SUCCESS.append([TIME_TO_SHOOT[k][0]]*len(TIME[k][1]))

    print('number of valid shot:',len(D_CLOSEST_PLAYER_bis))
    print('number of success :',nb_success)
    print('number of miss :',nb_missed)
    print('percentage of success:',nb_success/(nb_success+nb_missed)*100)
    print('percentage of catch-and-shoot shots :',nb_catch_and_shoot/(nb_pull_up+nb_catch_and_shoot)*100)
    print('percentage of catch-and-shoot success:',nb_cns_success/(nb_cns_missed+nb_cns_success)*100)
    print('percentage of pull-up success:',nb_pull_up_success/(nb_pull_up_missed+nb_pull_up_success)*100)

    ### we concatenate all the data
    TIME_bis=np.concatenate(np.array(TIME_bis))
    D_CLOSEST_PLAYER_bis=np.concatenate(np.array(D_CLOSEST_PLAYER_bis))
    T_CLOSEST_PLAYER_bis=np.concatenate(np.array(T_CLOSEST_PLAYER_bis))
    TIME_TO_SHOOT_bis=np.concatenate(np.array(TIME_TO_SHOOT_bis))
    SUCCESS=np.concatenate(np.array(SUCCESS))

    ### put the data into a dataframe ###
    df=pd.DataFrame({'D':D_CLOSEST_PLAYER_bis,'T':T_CLOSEST_PLAYER_bis,'Time':TIME_bis,'Time_to_shoot':TIME_TO_SHOOT_bis,'Shot result':SUCCESS})

    ## only evolution between 3.2 seconds before shot and 0.8 second after. (It is because there are some errors in the data) ##
    df=df.query('Time>-3.2 and Time<0.8').copy()

    return(df)


import ipdb
import numpy as np
import theano
import theano.tensor as T

from cle.cle.data import Iterator
from cle.cle.cost import Gaussian
from cle.cle.models import Model
from cle.cle.layers import InitCell
from cle.cle.layers.feedforward import FullyConnectedLayer
from cle.cle.layers.layer import PriorLayer
from cle.cle.layers.recurrent import LSTM
from cle.cle.train import Training
from cle.cle.train.ext import (
    EpochCount,
    GradientClipping,
    Monitoring,
    Picklize,
    EarlyStopping,
    WeightNorm
)
from cle.cle.train.opt import Adam
from cle.cle.utils import flatten, sharedX
from cle.cle.utils.compat import OrderedDict
from sk.datasets.blizzard_h5 import Blizzard_h5_tbptt

data_path = '/raid/chungjun/data/blizzard_unseg/'
save_path = '/raid/chungjun/repos/sk/cle/models/nips2015/blizzard/pkl/'
#data_path = '/home/junyoung/data/blizzard_unseg/'
#save_path = '/home/junyoung/repos/sk/cle/models/nips2015/blizzard/pkl/'

reset_freq = 4
batch_size = 128
mn_batch_size = 1280
frame_size = 200
latent_size = 200
encoder_dim = 3100
decoder_dim = 3100
target_size = frame_size
lr = 3e-4
debug = 0

file_name = 'blizzard_unseg_tbptt'
normal_params = np.load(data_path + file_name + '_normal.npz')
X_mean = normal_params['X_mean']
X_std = normal_params['X_std']

model = Model()
train_data = Blizzard_h5_tbptt(name='train',
                               path=data_path,
                               frame_size=frame_size,
                               file_name=file_name,
                               X_mean=X_mean,
                               X_std=X_std)

valid_data = Blizzard_h5_tbptt(name='valid',
                               path=data_path,
                               frame_size=frame_size,
                               file_name=file_name,
                               X_mean=X_mean,
                               X_std=X_std)

init_W = InitCell('rand')
init_U = InitCell('ortho')
init_b = InitCell('zeros')
init_b_sig = InitCell('const', mean=0.6)

x = train_data.theano_vars()
mn_x = valid_data.theano_vars()
if debug:
    x.tag.test_value = np.zeros((15, batch_size, frame_size), dtype=theano.config.floatX)
    mn_x.tag.test_value = np.zeros((15, mn_batch_size, frame_size), dtype=theano.config.floatX)
x_tm1 = T.concatenate([T.zeros((1, x.shape[1], x.shape[2])), x[:-1]], axis=0)
x_tm1.name = 'x_tm1'
mn_x_tm1 = T.concatenate([T.zeros((1, mn_x.shape[1], mn_x.shape[2])), mn_x[:-1]], axis=0)
mn_x_tm1.name = 'mn_x_tm1'

encoder = LSTM(name='encoder',
               parent=['x_t'],
               parent_dim=[frame_size],
               batch_size=batch_size,
               nout=encoder_dim,
               unit='tanh',
               init_W=init_W,
               init_U=init_U,
               init_b=init_b)

decoder = LSTM(name='decoder',
               parent=['x_tm1', 'z_t'],
               parent_dim=[frame_size, latent_size],
               batch_size=batch_size,
               nout=decoder_dim,
               unit='tanh',
               init_W=init_W,
               init_U=init_U,
               init_b=init_b)

phi_mu = FullyConnectedLayer(name='phi_mu',
                             parent=['enc_t'],
                             parent_dim=[encoder_dim],
                             nout=latent_size,
                             unit='linear',
                             init_W=init_W,
                             init_b=init_b)

phi_sig = FullyConnectedLayer(name='phi_sig',
                              parent=['enc_t'],
                              parent_dim=[encoder_dim],
                              nout=latent_size,
                              unit='softplus',
                              cons=1e-4,
                              init_W=init_W,
                              init_b=init_b_sig)

prior = PriorLayer(name='prior',
                   parent=['phi_mu', 'phi_sig'],
                   parent_dim=[latent_size, latent_size],
                   use_sample=1,
                   num_sample=1,
                   nout=latent_size)

kl = PriorLayer(name='kl',
                parent=['phi_mu', 'phi_sig'],
                parent_dim=[latent_size, latent_size],
                use_sample=0,
                nout=latent_size)

theta_mu = FullyConnectedLayer(name='theta_mu',
                               parent=['dec_t'],
                               parent_dim=[decoder_dim],
                               nout=target_size,
                               unit='linear',
                               init_W=init_W,
                               init_b=init_b)

theta_sig = FullyConnectedLayer(name='theta_sig',
                                parent=['dec_t'],
                                parent_dim=[decoder_dim],
                                nout=target_size,
                                unit='softplus',
                                cons=1e-4,
                                init_W=init_W,
                                init_b=init_b_sig)

nodes = [encoder, decoder, prior, kl,
         phi_mu, phi_sig, theta_mu, theta_sig]

for node in nodes:
    node.initialize()

params = flatten([node.get_params().values() for node in nodes])

step_count = sharedX(0, name='step_count')
last_encoder = np.zeros((batch_size, encoder_dim*2), dtype=theano.config.floatX)
last_decoder = np.zeros((batch_size, decoder_dim*2), dtype=theano.config.floatX)
encoder_tm1 = sharedX(last_encoder, name='encoder_tm1')
decoder_tm1 = sharedX(last_decoder, name='decoder_tm1')
update_list = [step_count, encoder_tm1, decoder_tm1]

step_count = T.switch(T.le(step_count, reset_freq), step_count + 1, 0)
enc_0 = T.switch(T.or_(T.cast(T.eq(step_count, 0), 'int32'),
                       T.cast(T.eq(T.sum(encoder_tm1), 0.), 'int32')),
                 encoder.get_init_state(batch_size), encoder_tm1)
dec_0 = T.switch(T.or_(T.cast(T.eq(step_count, 0), 'int32'),
                       T.cast(T.eq(T.sum(decoder_tm1), 0.), 'int32')),
                 decoder.get_init_state(batch_size), decoder_tm1)

x_shape = x.shape
x_in = x.reshape((x_shape[0]*x_shape[1], -1))

def inner_fn(x_t, x_tm1, enc_tm1, dec_tm1):

    enc_t = encoder.fprop([[x_t], [enc_tm1]])

    phi_mu_t = phi_mu.fprop([enc_t])
    phi_sig_t = phi_sig.fprop([enc_t])

    z_t = prior.fprop([phi_mu_t, phi_sig_t])

    dec_t = decoder.fprop([[x_tm1, z_t], [dec_tm1]])

    return enc_t, dec_t, phi_mu_t, phi_sig_t

((enc_t, dec_t, phi_mu_t, phi_sig_t), updates) =\
    theano.scan(fn=inner_fn,
                sequences=[x, x_tm1],
                outputs_info=[enc_0, dec_0, None, None])

for k, v in updates.iteritems():
    k.default_update = v

encoder_tm1 = enc_t[-1]
decoder_tm1 = dec_t[-1]

dec_shape = dec_t.shape
dec_in = dec_t.reshape((dec_shape[0]*dec_shape[1], -1))
theta_mu_in = theta_mu.fprop([dec_in])
theta_sig_in = theta_sig.fprop([dec_in])

z_shape = phi_mu_t.shape
phi_mu_in = phi_mu_t.reshape((z_shape[0]*z_shape[1], -1))
phi_sig_in = phi_sig_t.reshape((z_shape[0]*z_shape[1], -1))
kl_in = kl.fprop([phi_mu_in, phi_sig_in])
kl_t = kl_in.reshape((z_shape[0], z_shape[1]))

recon = Gaussian(x_in, theta_mu_in, theta_sig_in)
recon = recon.reshape((x_shape[0], x_shape[1]))
recon_term = recon.mean()
kl_term = kl_t.mean()
nll_lower_bound = recon_term + kl_term
nll_lower_bound.name = 'nll_lower_bound'

mn_x_shape = mn_x.shape
mn_x_in = mn_x.reshape((mn_x_shape[0]*mn_x_shape[1], -1))

mn_enc_0 = encoder.get_init_state(mn_batch_size)
mn_dec_0 = decoder.get_init_state(mn_batch_size)

((mn_enc_t, mn_dec_t, mn_phi_mu_t, mn_phi_sig_t), mn_updates) =\
    theano.scan(fn=inner_fn,
                sequences=[mn_x, mn_x_tm1],
                outputs_info=[mn_enc_0, mn_dec_0, None, None])

for k, v in mn_updates.iteritems():
    k.default_update = v

mn_dec_shape = mn_dec_t.shape
mn_dec_in = mn_dec_t.reshape((mn_dec_shape[0]*mn_dec_shape[1], -1))
mn_theta_mu_in = theta_mu.fprop([mn_dec_in])
mn_theta_sig_in = theta_sig.fprop([mn_dec_in])

mn_z_shape = mn_phi_mu_t.shape
mn_phi_mu_in = mn_phi_mu_t.reshape((mn_z_shape[0]*mn_z_shape[1], -1))
mn_phi_sig_in = mn_phi_sig_t.reshape((mn_z_shape[0]*mn_z_shape[1], -1))
mn_kl_in = kl.fprop([mn_phi_mu_in, mn_phi_sig_in])
mn_kl_t = mn_kl_in.reshape((mn_z_shape[0], mn_z_shape[1]))

mn_recon = Gaussian(mn_x_in, mn_theta_mu_in, mn_theta_sig_in)
mn_recon = mn_recon.reshape((mn_x_shape[0], mn_x_shape[1]))
mn_recon_term = mn_recon.mean()
mn_kl_term = mn_kl_t.mean()
mn_nll_lower_bound = mn_recon_term + mn_kl_term
mn_nll_lower_bound.name = 'nll_lower_bound'
mn_recon_term.name = 'recon_term'
mn_kl_term.name = 'kl_term'

mn_kl_ratio = mn_kl_term / T.abs_(mn_recon_term)
mn_kl_ratio.name = 'kl_term proportion'

max_x = mn_x.max()
mean_x = mn_x.mean()
min_x = mn_x.min()
max_x.name = 'max_x'
mean_x.name = 'mean_x'
min_x.name = 'min_x'

max_theta_mu = mn_theta_mu_in.max()
mean_theta_mu = mn_theta_mu_in.mean()
min_theta_mu = mn_theta_mu_in.min()
max_theta_mu.name = 'max_theta_mu'
mean_theta_mu.name = 'mean_theta_mu'
min_theta_mu.name = 'min_theta_mu'

max_theta_sig = mn_theta_sig_in.max()
mean_theta_sig = mn_theta_sig_in.mean()
min_theta_sig = mn_theta_sig_in.min()
max_theta_sig.name = 'max_theta_sig'
mean_theta_sig.name = 'mean_theta_sig'
min_theta_sig.name = 'min_theta_sig'

max_phi_sig = mn_phi_sig_t.max()
mean_phi_sig = mn_phi_sig_t.mean()
min_phi_sig = mn_phi_sig_t.min()
max_phi_sig.name = 'max_phi_sig'
mean_phi_sig.name = 'mean_phi_sig'
min_phi_sig.name = 'min_phi_sig'

model.inputs = [x]
model._params = params
model.nodes = nodes
model.set_updates(update_list)

optimizer = Adam(
    lr=lr
)

mn_fn = theano.function(inputs=[mn_x],
                        outputs=[mn_nll_lower_bound, mn_recon_term, mn_kl_term, mn_kl_ratio,
                                 max_phi_sig, mean_phi_sig, min_phi_sig,
                                 max_theta_sig, mean_theta_sig, min_theta_sig,
                                 max_x, mean_x, min_x,
                                 max_theta_mu, mean_theta_mu, min_theta_mu],
                        on_unused_input='ignore')

extension = [
    GradientClipping(batch_size=batch_size),
    EpochCount(4),
    Monitoring(freq=1000,
               monitor_fn=mn_fn,
               ddout=[mn_nll_lower_bound, mn_recon_term, mn_kl_term, mn_kl_ratio,
                      max_phi_sig, mean_phi_sig, min_phi_sig,
                      max_theta_sig, mean_theta_sig, min_theta_sig,
                      max_x, mean_x, min_x,
                      max_theta_mu, mean_theta_mu, min_theta_mu],
               data=[Iterator(valid_data, mn_batch_size, start=2040064, end=2152704)]), #112640 is 5%
    Picklize(freq=1000, force_save_freq=10000, path=save_path),
    EarlyStopping(freq=1000, force_save_freq=10000, path=save_path),
    WeightNorm()
]

mainloop = Training(
    name='storn0_1',
    data=Iterator(train_data, batch_size, start=0, end=2040064),
    model=model,
    optimizer=optimizer,
    cost=nll_lower_bound,
    outputs=[nll_lower_bound],
    extension=extension
)
mainloop.run()


# Copyright 2021, Mycroft AI Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Representations and conversions of the data returned by the weather API."""
from datetime import timedelta
from pathlib import Path
from typing import List

from .config import MILES_PER_HOUR
from .util import convert_to_local_datetime

# Forecast timeframes
CURRENT = "current"
DAILY = "daily"
HOURLY = "hourly"

# Days of week
SATURDAY = 5
SUNDAY = 6

# Condition Icons (see https://openweathermap.org/weather-conditions)
#   Map each of the possible weather condition icon codes from OpenWeatherMap to an
#   image/animation file used by the GUI.  The icon codes contain a number and a letter.
#   A "n" after the number indicates night and a "d" indicates day.
#
#   The icon/image map is used by the Mark II, which does not use animations for
#   performance reasons.  The icon/animation map is used by the scalable QML.  The
#   icon/code map is for the Mark I, which accepts a code to determine what
#   is displayed.
ICON_IMAGE_MAP = (
    (("01d",), "sun.svg"),
    (("01n",), "moon.svg"),
    (("04d", "04n"), "clouds.svg"),
    (("50d",), "fog.svg"),
    (("02d", "03d"), "partial_clouds_day.svg"),
    (("02n", "03n"), "partial_clouds_night.svg"),
    (("09d", "10d"), "rain.svg"),
    (("13d",), "snow.svg"),
    (("11d",), "storm.svg"),
)
ICON_ANIMATION_MAP = (
    (("01d", "01n"), "sun.json"),
    (("04d", "04n"), "clouds.json"),
    (("50d",), "fog.json"),
    (("02d", "03d", "02n", "03n"), "partial_clouds.json"),
    (("09d", "10d"), "rain.json"),
    (("13d",), "snow.json"),
    (("11d",), "storm.json"),
)
ICON_CODE_MAP = (
    (("01d", "01n"), 0),
    (("04d", "04n"), 2),
    (("50d",), 7),
    (("02d", "03d", "02n", "03n"), 1),
    (("09d", "10d"), 3),
    (("13d",), 6),
    (("11d",), 5),
)

THIRTY_PERCENT = 30
WIND_DIRECTION_CONVERSION = (
    (22.5, "north"),
    (67.5, "northeast"),
    (112.5, "east"),
    (157.5, "southeast"),
    (202.5, "south"),
    (247.5, "southwest"),
    (292.5, "west"),
    (337.5, "northwest"),
)

class WeatherCondition:
    """Data representation of a weather conditions JSON object from the API"""

    def __init__(self, conditions: dict):
        self.id = conditions["id"]
        self.category = conditions["main"]
        self.description = conditions["description"]
        self.icon = conditions["icon"]

    @property
    def image(self) -> str:
        """Use the icon to image mapping to determine which image to display."""
        image_path = Path("images")
        for icons, image_file_name in ICON_IMAGE_MAP:
            if self.icon in icons:
                image_path = image_path.joinpath(image_file_name)

        return str(image_path)

    @property
    def animation(self) -> str:
        """Use the icon to animation mapping to determine which animation to display."""
        image_path = Path("animations")
        for icons, animation_file_name in ICON_ANIMATION_MAP:
            if self.icon in icons:
                image_path = image_path.joinpath(animation_file_name)

        return str(image_path)

    @property
    def code(self) -> str:
        """Use the icon to animation mapping to determine which animation to display."""
        condition_code = None
        for icons, code in ICON_CODE_MAP:
            if self.icon in icons:
                condition_code = code

        return condition_code

class Weather:
    """Abstract data representation of commonalities in forecast types."""

    def __init__(self, weather: dict, timezone: str):
        self.date_time = convert_to_local_datetime(weather["dt"], timezone)
        self.feels_like = weather["feelsLike"]
        self.pressure = weather["pressure"]
        self.humidity = weather["humidity"]
        self.dew_point = weather["dewPoint"]
        self.clouds = weather["clouds"]
        self.wind_speed = int(weather["windSpeed"])
        self.wind_direction = self._determine_wind_direction(weather["windDeg"])
        self.condition = WeatherCondition(weather["weather"][0])

    @staticmethod
    def _determine_wind_direction(degree_direction: int):
        """Convert wind direction from compass degrees to compass direction.

        Args:
            degree_direction: Degrees on a compass indicating wind direction.

        Returns:
            the wind direction in one of eight compass directions
        """
        for min_degree, compass_direction in WIND_DIRECTION_CONVERSION:
            if degree_direction < min_degree:
                wind_direction = compass_direction
                break
        else:
            wind_direction = "north"

        return wind_direction

    def determine_wind_strength(self, speed_unit: str):
        """Convert a wind speed to a wind strength.

        Args:
            speed_unit: unit of measure for speed depending on device configuration

        Returns:
            a string representation of the wind strength
        """
        if speed_unit == MILES_PER_HOUR:
            limits = dict(strong=20, moderate=11)
        else:
            limits = dict(strong=9, moderate=5)
        if self.wind_speed >= limits["strong"]:
            wind_strength = "strong"
        elif self.wind_speed >= limits["moderate"]:
            wind_strength = "moderate"
        else:
            wind_strength = "light"

        return wind_strength

class CurrentWeather(Weather):
    """Data representation of the current weather returned by the API"""

    def __init__(self, weather: dict, timezone: str):
        super().__init__(weather, timezone)
        self.sunrise = convert_to_local_datetime(weather["sunrise"], timezone)
        self.sunset = convert_to_local_datetime(weather["sunset"], timezone)
        self.temperature = round(weather["temp"])
        self.visibility = weather["visibility"]
        self.low_temperature = None
        self.high_temperature = None

class DailyFeelsLike:
    """Data representation of a "feels like" JSON object from the API"""

    def __init__(self, temperatures: dict):
        self.day = round(temperatures["day"])
        self.night = round(temperatures["night"])
        self.evening = round(temperatures["eve"])
        self.morning = round(temperatures["morn"])

class DailyTemperature(DailyFeelsLike):
    """Data representation of a temperatures JSON object from the API"""

    def __init__(self, temperatures: dict):
        super().__init__(temperatures)
        self.low = round(temperatures["min"])
        self.high = round(temperatures["max"])

class DailyWeather(Weather):
    """Data representation of a daily forecast JSON object from the API"""

    def __init__(self, weather: dict, timezone: str):
        super().__init__(weather, timezone)
        self.sunrise = convert_to_local_datetime(weather["sunrise"], timezone)
        self.sunset = convert_to_local_datetime(weather["sunset"], timezone)
        self.temperature = DailyTemperature(weather["temp"])
        self.feels_like = DailyFeelsLike(weather["feelsLike"])
        self.chance_of_precipitation = int(weather["pop"] * 100)

class HourlyWeather(Weather):
    """Data representation of a hourly forecast JSON object from the API"""

    def __init__(self, weather: dict, timezone: str):
        super().__init__(weather, timezone)
        self.temperature = round(weather["temp"])
        self.chance_of_precipitation = int(weather["pop"] * 100)

class WeatherAlert:
    """Data representation of a weather conditions JSON object from the API"""

    def __init__(self, alert: dict, timezone: str):
        self.sender = alert.get("sender_name")
        self.event = alert["event"]
        self.start = convert_to_local_datetime(alert["start"], timezone)
        self.end = convert_to_local_datetime(alert["end"], timezone)
        self.description = alert["description"]

class WeatherReport:
    """Full representation of the data returned by the Open Weather Maps One Call API"""

    def __init__(self, report):
        timezone = report["timezone"]
        self.current = CurrentWeather(report["current"], timezone)
        self.hourly = [HourlyWeather(hour, timezone) for hour in report["hourly"]]
        self.daily = [DailyWeather(day, timezone) for day in report["daily"]]
        today = self.daily[0]
        self.current.high_temperature = today.temperature.high
        self.current.low_temperature = today.temperature.low
        if "alerts" in report:
            self.alerts = [WeatherAlert(alert, timezone) for alert in report["alerts"]]
        else:
            self.alerts = None

    def get_weather_for_intent(self, intent_data):
        """Use the intent to determine which forecast satisfies the request.

        Args:
            intent_data: Parsed intent data
        """
        if intent_data.timeframe == "hourly":
            weather = self.get_forecast_for_hour(intent_data)
        elif intent_data.timeframe == "daily":
            weather = self.get_forecast_for_date(intent_data)
        else:
            weather = self.current

        return weather

    def get_forecast_for_date(self, intent_data):
        """Use the intent to determine which daily forecast(s) satisfies the request.

        Args:
            intent_data: Parsed intent data
        """
        if intent_data.intent_datetime.date() == intent_data.location_datetime.date():
            forecast = self.daily[0]
        else:
            delta = intent_data.intent_datetime - intent_data.location_datetime
            day_delta = int(delta / timedelta(days=1))
            day_index = day_delta + 1
            forecast = self.daily[day_index]

        return forecast

    def get_forecast_for_multiple_days(self, days: int) -> List[DailyWeather]:
        """Use the intent to determine which daily forecast(s) satisfies the request.

        Args:
            days: number of forecast days to return

        Returns:
            list of daily forecasts for the specified number of days

        Raises:
            IndexError when number of days is more than what is returned by the API
        """
        if days > 7:
            raise IndexError("Only seven days of forecasted weather available.")

        forecast = self.daily[1 : days + 1]

        return forecast

    def get_forecast_for_hour(self, intent_data):
        """Use the intent to determine which hourly forecast(s) satisfies the request.

        Args:
            intent_data: Parsed intent data

        Returns:
            A single hour of forecast data based on the intent data
        """
        delta = intent_data.intent_datetime - intent_data.location_datetime
        hour_delta = int(delta / timedelta(hours=1))
        hour_index = hour_delta + 1
        report = self.hourly[hour_index]

        return report

    def get_weekend_forecast(self):
        """Use the intent to determine which daily forecast(s) satisfies the request.

        Returns:
            The Saturday and Sunday forecast from the list of daily forecasts
        """
        forecast = list()
        for forecast_day in self.daily:
            report_date = forecast_day.date_time.date()
            if report_date.weekday() in (SATURDAY, SUNDAY):
                forecast.append(forecast_day)

        return forecast

    def get_next_precipitation(self, intent_data):
        """Determine when the next chance of precipitation is in the forecast.

        Args:
            intent_data: Parsed intent data

        Returns:
            The weather report containing the next chance of rain and the timeframe of
            the selected report.
        """
        report = None
        current_precipitation = True
        timeframe = HOURLY
        for hourly in self.hourly:
            if hourly.date_time.date() > intent_data.location_datetime.date():
                break
            if hourly.chance_of_precipitation > THIRTY_PERCENT:
                if not current_precipitation:
                    report = hourly
                    break
            else:
                current_precipitation = False

        if report is None:
            timeframe = DAILY
            for daily in self.daily:
                if daily.date_time.date() == intent_data.location_datetime.date():
                    continue
                if daily.chance_of_precipitation > THIRTY_PERCENT:
                    report = daily
                    break

        return report, timeframe


from __future__ import absolute_import
import wx
from utils.date_time import wxDefaultDateTime
from wx.lib import masked

class CorrectionPanelUI(wx.Panel):

    def __init__(self, parent):
        wx.Panel.__init__(self, parent, id=wx.ID_ANY,
                          pos=wx.DefaultPosition,
                          size=wx.Size(760, 280), style=wx.TAB_TRAVERSAL)

        bSizer1 = wx.BoxSizer(wx.HORIZONTAL)

        self.m_splitter1 = wx.SplitterWindow(self, wx.ID_ANY,
                                             wx.DefaultPosition,
                                             wx.DefaultSize, wx.SP_3D)
        #self.m_splitter1.Bind(wx.EVT_IDLE, self.m_splitter1OnIdle)

        self.rightPanel = wx.Panel(self.m_splitter1, wx.ID_ANY,
                                   wx.DefaultPosition, wx.DefaultSize,
                                   wx.TAB_TRAVERSAL)
        bSizer2 = wx.BoxSizer(wx.VERTICAL)

        self.lc_correctionList = wx.ListCtrl(self.rightPanel, wx.ID_ANY,
                                             wx.DefaultPosition,
                                             wx.DefaultSize, wx.LC_REPORT)
        self.lc_correctionList.InsertColumn(0, "Correction Id", width=20)
        self.lc_correctionList.InsertColumn(1, "Episode Id", width=50)
        self.lc_correctionList.InsertColumn(2, "User Id", width=50)
        self.lc_correctionList.InsertColumn(3, "Complain Date", width=60)
        self.lc_correctionList.InsertColumn(4, "Timecode", width=50)
        self.lc_correctionList.InsertColumn(5, "Error Description", width=80)
        self.lc_correctionList.InsertColumn(6, "Editor Id", width=40)
        self.lc_correctionList.InsertColumn(7, "Correction Date", width=40)
        self.lc_correctionList.InsertColumn(8, "Correction Status", width=40)
        bSizer2.Add(self.lc_correctionList, 1, wx.ALL | wx.EXPAND, 5)

        self.rightPanel.SetSizer(bSizer2)
        self.rightPanel.Layout()
        bSizer2.Fit(self.rightPanel)
        self.m_splitter1.Initialize(self.rightPanel)
        bSizer1.Add(self.m_splitter1, 1, wx.EXPAND, 5)

        self.m_splitter2 = wx.SplitterWindow(self, wx.ID_ANY,
                                             wx.DefaultPosition,
                                             wx.DefaultSize, wx.SP_3D)
        #self.m_splitter2.Bind(wx.EVT_IDLE, self.m_splitter2OnIdle)

        self.leftPanel = wx.ScrolledWindow(self.m_splitter2, wx.ID_ANY,
                                           wx.DefaultPosition,
                                           wx.DefaultSize,
                                           wx.HSCROLL | wx.VSCROLL)
        self.leftPanel.SetScrollRate(5, 5)
        fgSizer1 = wx.FlexGridSizer(0, 2, 0, 0)
        fgSizer1.AddGrowableCol(1)
        fgSizer1.AddGrowableRow(4)
        fgSizer1.SetFlexibleDirection(wx.BOTH)
        fgSizer1.SetNonFlexibleGrowMode(wx.FLEX_GROWMODE_SPECIFIED)

        self.st_userID = wx.StaticText(self.leftPanel, wx.ID_ANY,
                                       u"User Name", wx.DefaultPosition,
                                       wx.DefaultSize, 0)
        self.st_userID.Wrap(-1)
        fgSizer1.Add(self.st_userID, 0, wx.ALL, 5)

        self.tc_userID = wx.TextCtrl(self.leftPanel, wx.ID_ANY,
                                     wx.EmptyString, wx.DefaultPosition,
                                     wx.DefaultSize, 0)
        self.tc_userID.Enable(False)

        fgSizer1.Add(self.tc_userID, 1, wx.ALL | wx.EXPAND, 5)

        self.st_complain_date = wx.StaticText(self.leftPanel, wx.ID_ANY,
                                              u"Complaint Date",
                                              wx.DefaultPosition,
                                              wx.DefaultSize, 0)
        self.st_complain_date.Wrap(-1)
        fgSizer1.Add(self.st_complain_date, 0, wx.ALL, 5)

        self.dp_complain_date = wx.DatePickerCtrl(self.leftPanel, wx.ID_ANY,
                                                  wxDefaultDateTime(),
                                                  wx.DefaultPosition,
                                                  wx.DefaultSize, wx.DP_DEFAULT)
        fgSizer1.Add(self.dp_complain_date, 0, wx.ALL, 5)

        self.st_complain_Time = wx.StaticText(self.leftPanel, wx.ID_ANY,
                                              u"Complaint Time",
                                              wx.DefaultPosition,
                                              wx.DefaultSize, 0)
        self.st_complain_Time.Wrap(-1)
        fgSizer1.Add(self.st_complain_Time, 0, wx.ALL, 5)

        complaintSizer = wx.BoxSizer(wx.HORIZONTAL)

        self.tc_compTime = masked.TimeCtrl(self.leftPanel, wx.ID_ANY,
                                           wx.EmptyString, wx.DefaultPosition,
                                           wx.DefaultSize,
                                           display_seconds=False,
                                           oob_color="White")
        complaintSizer.Add(self.tc_compTime, 1, wx.ALL | wx.EXPAND, 5)
        self.spin_compTime = wx.SpinButton(self.leftPanel, wx.ID_ANY,
                                           wx.DefaultPosition,
                                           wx.DefaultSize, 0)
        self.tc_compTime.BindSpinButton(self.spin_compTime)
        complaintSizer.Add(self.spin_compTime, 0, wx.ALL, 5)

        fgSizer1.Add(complaintSizer, 1, wx.EXPAND, 5)

        self.st_timecode = wx.StaticText(self.leftPanel, wx.ID_ANY,
                                         u"Time Code", wx.DefaultPosition,
                                         wx.DefaultSize, 0)
        self.st_timecode.Wrap(-1)
        fgSizer1.Add(self.st_timecode, 0, wx.ALL, 5)

        self.tc_timecode = masked.TextCtrl(self.leftPanel, wx.ID_ANY,
                                           wx.EmptyString, wx.DefaultPosition,
                                           wx.DefaultSize,
                                           mask='##:##:##:##',
                                           defaultValue='00:00:00:00')
        fgSizer1.Add(self.tc_timecode, 0, wx.ALL | wx.EXPAND, 5)

        self.st_desc = wx.StaticText(self.leftPanel, wx.ID_ANY,
                                     u"Description", wx.DefaultPosition,
                                     wx.DefaultSize, 0)
        self.st_desc.Wrap(-1)
        fgSizer1.Add(self.st_desc, 0, wx.ALL, 5)

        self.tc_desc = wx.TextCtrl(self.leftPanel, wx.ID_ANY,
                                   wx.EmptyString, wx.DefaultPosition,
                                   wx.DefaultSize, wx.TE_MULTILINE)
        self.tc_desc.SetMaxLength(255)
        self.tc_desc.SetMinSize(wx.Size(-1, 70))

        fgSizer1.Add(self.tc_desc, 1, wx.ALL | wx.EXPAND, 5)

        self.st_editorName = wx.StaticText(self.leftPanel, wx.ID_ANY,
                                           u"Editor Name", wx.DefaultPosition,
                                           wx.DefaultSize, 0)
        self.st_editorName.Wrap(-1)
        fgSizer1.Add(self.st_editorName, 0, wx.ALL, 5)

        self.tc_editorName = wx.TextCtrl(self.leftPanel, wx.ID_ANY,
                                         wx.EmptyString, wx.DefaultPosition,
                                         wx.DefaultSize, 0)
        self.tc_editorName.Enable(False)

        fgSizer1.Add(self.tc_editorName, 0, wx.ALL | wx.EXPAND, 5)

        self.st_correctionDate = wx.StaticText(self.leftPanel, wx.ID_ANY,
                                               u"Correction Date",
                                               wx.DefaultPosition,
                                               wx.DefaultSize, 0)
        self.st_correctionDate.Wrap(-1)
        fgSizer1.Add(self.st_correctionDate, 0, wx.ALL, 5)

        self.dp_correctionDate = wx.DatePickerCtrl(self.leftPanel, wx.ID_ANY,
                                                   wxDefaultDateTime(),
                                                   wx.DefaultPosition,
                                                   wx.DefaultSize,
                                                   wx.DP_DEFAULT)
        fgSizer1.Add(self.dp_correctionDate, 0, wx.ALL, 5)

        self.st_correction_Time = wx.StaticText(self.leftPanel, wx.ID_ANY,
                                                u"Correction Time",
                                                wx.DefaultPosition,
                                                wx.DefaultSize, 0)
        self.st_correction_Time.Wrap(-1)
        fgSizer1.Add(self.st_correction_Time, 0, wx.ALL, 5)

        correctionSizer = wx.BoxSizer(wx.HORIZONTAL)

        self.tc_corrTime = masked.TimeCtrl(self.leftPanel, wx.ID_ANY,
                                           wx.EmptyString, wx.DefaultPosition,
                                           wx.DefaultSize,
                                           display_seconds=False,
                                           oob_color="White")
        correctionSizer.Add(self.tc_corrTime, 1, wx.ALL | wx.EXPAND, 5)

        self.spin_corrTime = wx.SpinButton(self.leftPanel, wx.ID_ANY,
                                           wx.DefaultPosition,
                                           wx.DefaultSize, 0)
        self.tc_corrTime.BindSpinButton(self.spin_corrTime)
        correctionSizer.Add(self.spin_corrTime, 0, wx.ALL, 5)

        fgSizer1.Add(correctionSizer, 1, wx.EXPAND, 5)

        self.st_correctionStatus = wx.StaticText(self.leftPanel, wx.ID_ANY,
                                                 u"Correction Status",
                                                 wx.DefaultPosition,
                                                 wx.DefaultSize, 0)
        self.st_correctionStatus.Wrap(-1)
        fgSizer1.Add(self.st_correctionStatus, 0, wx.ALL, 5)

        self.cb_correction = wx.CheckBox(self.leftPanel, wx.ID_ANY,
                                         u"Completed!", wx.DefaultPosition,
                                         wx.DefaultSize, 0)
        fgSizer1.Add(self.cb_correction, 0, wx.ALL, 5)

        self.btn_NewCorrection = wx.Button(self.leftPanel, wx.ID_ANY,
                                           u"Add New Correction",
                                           wx.DefaultPosition,
                                           wx.DefaultSize, 0)
        fgSizer1.Add(self.btn_NewCorrection, 0, wx.ALL, 5)

        self.btn_UpdateCorrection = wx.Button(self.leftPanel, wx.ID_ANY,
                                              u"Update Correction",
                                              wx.DefaultPosition,
                                              wx.DefaultSize, 0)
        fgSizer1.Add(self.btn_UpdateCorrection, 0, wx.ALL, 5)

        self.btn_GetCorrections = wx.Button(self.leftPanel, wx.ID_ANY,
                                            u"Get Correction List",
                                            wx.DefaultPosition,
                                            wx.DefaultSize, 0)
        fgSizer1.Add(self.btn_GetCorrections, 0, wx.ALL, 5)

        self.btn_DeleteCorrection = wx.Button(self.leftPanel, wx.ID_ANY,
                                              u"Delete Correction",
                                              wx.DefaultPosition,
                                              wx.DefaultSize, 0)
        self.btn_DeleteCorrection.Enable(False)

        fgSizer1.Add(self.btn_DeleteCorrection, 0, wx.ALL, 5)

        self.btn_Now = wx.Button(self.leftPanel, wx.ID_ANY, u"Now",
                                 wx.DefaultPosition, wx.DefaultSize, 0)
        fgSizer1.Add(self.btn_Now, 0, wx.ALL, 5)

        self.leftPanel.SetSizer(fgSizer1)
        self.leftPanel.Layout()
        fgSizer1.Fit(self.leftPanel)
        self.m_splitter2.Initialize(self.leftPanel)
        bSizer1.Add(self.m_splitter2, 1, wx.EXPAND, 5)

        self.SetSizer(bSizer1)
        self.Layout()

        # Connect Events
        self.lc_correctionList.Bind(wx.EVT_LIST_ITEM_ACTIVATED,
                                    self.CorrectionSelected)
        self.dp_complain_date.Bind(wx.EVT_DATE_CHANGED,
                                   self.ComplainDate_Entered)
        self.tc_compTime.Bind(wx.EVT_TEXT, self.ComplaintTime_Entered)
        self.tc_timecode.Bind(wx.EVT_TEXT, self.TimeCode_Entered)
        self.tc_desc.Bind(wx.EVT_TEXT, self.Description_Entered)
        self.dp_correctionDate.Bind(wx.EVT_DATE_CHANGED,
                                    self.CorrectionDate_Entered)
        self.tc_corrTime.Bind(wx.EVT_TEXT, self.correctionTime_Entered)
        self.cb_correction.Bind(wx.EVT_CHECKBOX, self.CorrectionStatus_Entered)
        self.btn_NewCorrection.Bind(wx.EVT_BUTTON, self.AddCorrection)
        self.btn_UpdateCorrection.Bind(wx.EVT_BUTTON, self.UpdateCorrection)
        self.btn_GetCorrections.Bind(wx.EVT_BUTTON, self.GetCorrection)
        self.btn_DeleteCorrection.Bind(wx.EVT_BUTTON, self.DeleteCorrection)
        self.btn_Now.Bind(wx.EVT_BUTTON, self.Now)
        # --
        self.dp_complain_date.Bind(wx.EVT_DATE_CHANGED,
                                   self.ComplainDateChanged)
        self.tc_compTime.Bind(wx.lib.masked.EVT_TIMEUPDATE,
                              self.ComplainDateChanged)
        self.complain_date = None
        self.dp_correctionDate.Bind(wx.EVT_DATE_CHANGED,
                                    self.CorrectionDateChanged)
        self.tc_corrTime.Bind(wx.lib.masked.EVT_TIMEUPDATE,
                              self.CorrectionDateChanged)
        self.correction_date = None
        self.complain_timecode = '00:00:00:00'
        self.correction_id = None

    def __del__(self):
        pass

    # Virtual event handlers, overide them in your derived class
    def ComplaintTime_Entered(self, event):
        event.Skip()

    def correctionTime_Entered(self, event):
        event.Skip()

    def ComplainDateChanged(self, event):
        event.Skip()

    def CorrectionDateChanged(self, event):
        event.Skip()

    def Now(self, event):
        event.Skip()

    def CorrectionSelected(self, event):
        event.Skip()

    def ComplainDate_Entered(self, event):
        event.Skip()

    def TimeCode_Entered(self, event):
        event.Skip()

    def Description_Entered(self, event):
        event.Skip()

    def CorrectionDate_Entered(self, event):
        event.Skip()

    def CorrectionStatus_Entered(self, event):
        event.Skip()

    def AddCorrection(self, event):
        event.Skip()

    def UpdateCorrection(self, event):
        event.Skip()

    def GetCorrection(self, event):
        event.Skip()

    def DeleteCorrection(self, event):
        event.Skip()


# -*- coding:utf-8 -*-
import re
from django.contrib.auth import authenticate
from django.contrib.auth.signals import user_login_failed

def my_clean_credentials(credentials):
    SENSITIVE_CREDENTIALS = re.compile('api|token|key|secret|password|signature', re.I)
    CLEANSED_SUBSTITUTE = '********************'
    for key in credentials:
        if SENSITIVE_CREDENTIALS.search(key):
            credentials[key] = CLEANSED_SUBSTITUTE
    return credentials

def my_authenticate(**credentials):
    if 'the_backend' in credentials:
        the_backend = credentials['the_backend']
        try:
            user = the_backend.authenticate(**credentials)
        except TypeError:
            # This backend doesn't accept these credentials as arguments. Try the next one.
            user = None
        if user is  not None:
        # Annotate the user object with the path of the backend.
            user.backend = "%s.%s" % (the_backend.__module__, the_backend.__class__.__name__)
            return user
    else:
        return authenticate(**credentials)

    # The credentials supplied are invalid to all backends, fire signal
    user_login_failed.send(sender=__name__, credentials=my_clean_credentials(credentials))


from torch.utils.data import Dataset, DataLoader
import torch.nn as nn
from torchvision import transforms
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import pims
import pathlib
import torch.optim as optim
from torch.autograd import Variable
import torch
torch.cuda.empty_cache()
import skimage as skm
import glob
import sys

#classes/functions

class DefectDataset(Dataset):
    """custom dataset for star locator"""

    def __init__(self, label_dir, root_dir):
        """
        Args:
            csvfile (pathlib): folder containing labels
            root_dir (pathlib): root directory with all the images
        """
        self.root_dir = root_dir
        self.label_dir = label_dir
        self.labels = self.process_labels()
        self.frames = pims.ImageSequence(str(root_dir / '*.tiff'))
        self.shape = self.frames[1].shape
        ar = np.array(self.frames).reshape(-1,4)
        self.meand = ar.mean(axis=0)
        self.stdd = ar.std(axis=0)
        ar = None
        self.n = self.shape[0]
        #self.to_tensor = transforms.Compose([transforms.ToTensor(), transforms.Normalize(tuple(self.meand[0:3]),tuple(self.stdd[0:3]))])
        self.to_tensor = transforms.ToTensor()

    def process_labels(self):
        '''
        we need a function that will read in all the annotations and create a master dataframe [img_name][total_defect]
        '''
        files = glob.glob(str(self.label_dir / '*.dat'))
        df = pd.DataFrame([[f,np.count_nonzero(np.genfromtxt(f))] for f in files], columns = ['names', 'numbers'])
        df['frame'] = df['names'].str.extract('label-t_(\d*)\.dat').astype('int')
        df = df.sort_values('frame').reset_index(drop='True')
        #df.set_index('frame', inplace=True)
        return(df)

    def __len__(self):
        return len(self.frames)

    def __getitem__(self, idx):
        if torch.is_tensor(idx):
            idx.tolist()

        sample = [self.to_tensor(self.frames[idx][:,:,0:3]/255).float(), torch.tensor(self.labels.iloc[idx]['numbers']).float()/256**2]
        return sample

class Net(nn.Module):
    def __init__(self):
        super().__init__()
        cLayers1 = 16
        cLayers2 = 8

        self.conv1 = nn.Conv2d(3, 32, kernel_size = 3, padding = 1)
        self.conv2 = nn.Conv2d(32, 64, kernel_size = 3, padding = 1)
        self.conv3 = nn.Conv2d(64, 1, kernel_size = 3, padding = 1)
        self.fc1 = nn.Linear(1 * 4*4, 1)

        self.fc3 = nn.Linear(1, 1, bias = True)

        self.pool = nn.MaxPool2d(4)
        self.act1 = nn.LeakyReLU()
        self.act1 = nn.ReLU()
        self.prob = nn.Sigmoid()
    def forward(self, x):
        out = self.pool( self.act1( self.conv1(x)))
        out = self.pool(self.act1(self.conv2(out)))
        out = self.pool(self.act1(self.conv3(out)))
        out = out.view(-1, 1*4*4)
        out = self.act1(self.fc1(out))
        out = self.act1(self.fc3(out))

        return out
        #the output of this will be a 125*125 matrix.

#first, read in data into dataloader, and split into test and validation set
data_folder = pathlib.Path('.') /'..' / 'data' /'img'
csv_name = pathlib.Path('.')/'..'/'data' / 'labels'

print(data_folder)
defectD = DefectDataset(csv_name, data_folder)
train_size = int(0.8*len(defectD))
test_size = len(defectD) - train_size

import datetime  # <1>
device = (torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu'))
print(f"Training on device {device}.")

def loss_funct(output, target):
    #loss = torch.sum((torch.mm((torch.exp( (output-target)**2)-1).t(),target))[:,0])
    #rel_error = torch.sum((output.T[0]-target)**2/(target+1)**2)
    error = torch.mean((output.sum(dim=1)-target)**2)
    return error #+.5*rel_error

def training_loop(n_epochs, optimizer, model, loss_fn, train_loader):
    for epoch in range(1, n_epochs + 1):  # <2>
        loss_train = 0.0
        for imgs, labels in train_loader:  # <3>
            imgs = imgs.to(device=device)
            labels = labels.to(device=device)
            outputs = model(imgs)  # <4>

            loss = loss_fn(outputs, labels)  # <5>
            optimizer.zero_grad()  # <6>

            loss.backward()  # <7>

            optimizer.step()  # <8>

            loss_train += loss.item()  # <9>

        if epoch == 1 or epoch % 10 == 0:
            print('{} Epoch {}, Training loss {}, std{} , teststd {} '.format(
                datetime.datetime.now(), epoch, loss_train/len(train_loader), outputs.std(), labels.float().std()))

def validate(model, train_loader, val_loader):
    for name, loader in [('train', train_loader), ('val', val_loader)]:
        correct = 0
        total = 0

        with torch.no_grad():
            for imgs, labels in loader:
                imgs = imgs.to(device)
                labels = labels.to(device)
                outputs = model(imgs)
                total += labels.shape[0]
                cor = ((outputs - labels)*256**2).int()
                correct += int((cor == 0).sum())
        print("Accuracy {}: {:.2f}".format(name , correct / total))

def val2(model, train_loader, val_loader):
    for name, loader in [('train', train_loader), ('val', val_loader)]:
        ave_dist= 0
        total = 0
        right_counts = 0

        with torch.no_grad():
            for imgs, labels in loader:
                imgs = imgs.to(device)
                labels = labels.to(device)
                outputs = model(imgs)
                total += labels.shape[0]
                num= outputs.argmax(dim=1)
                cor =  (num-labels)
                right_counts += int((cor == 0).sum())
                ave_dist = torch.sqrt( ((num-labels)**2).float().sum())
        print("Right percent {}, dist to truth {}".format(right_counts/total , ave_dist))

train_dataset, test_dataset = torch.utils.data.random_split(defectD, [train_size, test_size])
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size =32 , shuffle = True)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size =32, shuffle = False)
model = Net().to(device = device)
lr = 1e-4
optimizer = optim.SGD(model.parameters(), lr=lr, weight_decay = .0005, momentum = .9)
loss_fn = loss_funct
loss_fn = nn.CrossEntropyLoss()
loss_fn = nn.MSELoss()
weight_file = pathlib.Path('./m1.pt')
if weight_file.is_file():
    loaded_model = Net().to(device)
    loaded_model.load_state_dict(torch.load(str(weight_file), map_location=torch.device(device)))
    val2(loaded_model, train_loader, test_loader)
else:
    run_more = lr
    while(run_more != 'n'):
        try:
            optimizer = optim.SGD(model.parameters(), lr=float(lr))
            training_loop(  # <5>
                n_epochs = 1000,
                optimizer = optimizer,
                model = model,
                loss_fn = loss_fn,
                train_loader = train_loader,
            )
        except KeyboardInterrupt:
            run_more = 'n'

    weight_file = pathlib.Path('./m1.pt')
    torch.save(model.state_dict(), str(weight_file))

    val2(model, train_loader, test_loader)

def plt_frame(frame):
   f=test_dataset.__getitem__(frame)
   fig,ax = plt.subplots()
   ax.imshow(f[0].permute(1,2,0))
   outputs = model(f[0].unsqueeze(0).to(device))
   prob = torch.exp(outputs)/torch.exp(outputs).sum()
   thresh = .0015
   pred = torch.where(prob > thresh)
   ax.scatter(20,20, color = 'blue', s = 10)
   for i in pred:
       x = (i//31)*8
       y = (i % 31)*8
       print(x,y)
       ax.scatter(x.cpu(),y.cpu(),color = 'red', s = 10)

#plt_frame(10)
plt.show()


# -*- coding: utf-8 -*-
"""
This module provides a class for real-time plotting of results in a pop-up
graph window using PyQt.

Call a graph in main GUI class like this:

x = np.arange(-50, 50, 1)
y = x**3 + (np.random.random(len(x))+1)*100000
data = np.column_stack((x, y))

# if plot does not exist, then create it
if not self.p1:
    self.p1 = rtplot.MakeGraph(title='Title',
                               xlabel='X-vals',
                               ylabel='Y-vals')
self.p1.add_data(data)
self.p1.show()

Created on Wed Nov  6 14:37:55 2019
@author: a6q

"""

from PyQt5.QtCore import Qt
from PyQt5.QtGui import QColor, QPen
import pyqtgraph as pg
import numpy as np

class MakeGraph(pg.GraphicsLayoutWidget):
    """Class for creating real-time plots using PyQt."""
    def __init__(self, parent=None, title=None,
                 line_color=QColor(Qt.lightGray),
                 xmax=500, xlabel='X', ylabel='Y'):
        # color of plot line
        pen = QPen(line_color)
        # width of plot line
        pen.setWidth(0)
        # inherit properties from GraphicsLayoutWidget
        super().__init__(parent)
        # set title of plot window and add axis labels
        self.setWindowTitle(title)
        self.plot = self.addPlot(title=title,
                                 labels={'left': ylabel, 'bottom': xlabel})
        # self.plot.showAxis("bottom", False)
        self.curve = self.plot.plot(pen=pen)
        self.xs = []
        self.ys = []
        self.xmax = xmax

    def trim(self):
        self.curve.setData(self.xs[-self.xmax:], self.ys[-self.xmax:])

    def append_data(self, data):
        # append single point to graph and trim off points past xmax
        self.xs.append(data[0])
        self.ys.append(data[1])
        self.trim()

    def add_data(self, data):
        """Add data to graph in form [[x1,y1],[x2,y2],...]."""
        self.xs = []
        self.ys = []
        if len(np.shape(data)) == 0:
            pass
        if len(np.shape(data)) == 1:
            self.xs.append(data[0])
            self.ys.append(data[1])
        if len(np.shape(data)) == 2:
            for d in data:
                self.xs.append(d[0])
                self.ys.append(d[1])
        self.trim()


# # Sentiment analysis with TFLearn

import pandas as pd
import numpy as np
import tensorflow as tf
import tflearn
from tflearn.data_utils import to_categorical
from collections import Counter

# Preparing the data

reviews = pd.read_csv('reviews.txt', header=None)
labels = pd.read_csv('labels.txt', header=None)

stop_words = ['a', 'about', 'above', 'according', 'across', 'after', 'afterwards', 'again', 'against', 'albeit',
              'all', 'almost', 'alone', 'along', 'already', 'also', 'although', 'always', 'am', 'among',
              'amongst', 'an', 'and', 'another', 'any', 'anybody', 'anyhow', 'anyone', 'anything', 'anyway',
              'anywhere', 'apart', 'are', 'around', 'as', 'at', 'av', 'be', 'became', 'because', 'become',
              'becomes', 'becoming', 'been', 'before', 'beforehand', 'behind', 'being', 'below', 'beside',
              'besides', 'between', 'beyond', 'both', 'but', 'by', 'can', 'cannot', 'canst', 'certain', 'cf',
              'choose', 'contrariwise', 'cos', 'could', 'cu', 'day', 'do', 'does', "doesn't", 'doing', 'dost',
              'doth', 'double', 'down', 'dual', 'during', 'each', 'either', 'else', 'elsewhere', 'enough', 'et',
              'etc', 'even', 'ever', 'every', 'everybody', 'everyone', 'everything', 'everywhere', 'except',
              'excepted', 'excepting', 'exception', 'exclude', 'excluding', 'exclusive', 'far', 'farther',
              'farthest', 'few', 'ff', 'first', 'for', 'formerly', 'forth', 'forward', 'from', 'front',
              'further', 'furthermore', 'furthest', 'get', 'go', 'had', 'halves', 'hardly', 'has', 'hast',
              'hath', 'have', 'he', 'hence', 'henceforth', 'her', 'here', 'hereabouts', 'hereafter', 'hereby',
              'herein', 'hereto', 'hereupon', 'hers', 'herself', 'him', 'himself', 'hindmost', 'his', 'hither',
              'hitherto', 'how', 'however', 'howsoever', 'i', 'ie', 'if', 'in', 'inasmuch', 'inc', 'include',
              'included', 'including', 'indeed', 'indoors', 'inside', 'insomuch', 'instead', 'into', 'inward',
              'inwards', 'is', 'it', 'its', 'itself', 'just', 'kind', 'kg', 'km', 'last', 'latter', 'latterly',
              'less', 'lest', 'let', 'like', 'little', 'ltd', 'many', 'may', 'maybe', 'me', 'meantime',
              'meanwhile', 'might', 'moreover', 'most', 'mostly', 'more', 'mr', 'mrs', 'ms', 'much', 'must',
              'my', 'myself', 'namely', 'need', 'neither', 'never', 'nevertheless', 'next', 'no', 'nobody',
              'none', 'nonetheless', 'noone', 'nope', 'nor', 'not', 'nothing', 'notwithstanding', 'now',
              'nowadays', 'nowhere', 'of', 'off', 'often', 'ok', 'on', 'once', 'one', 'only', 'onto', 'or',
              'other', 'others', 'otherwise', 'ought', 'our', 'ours', 'ourselves', 'out', 'outside', 'over',
              'own', 'per', 'perhaps', 'plenty', 'provide', 'quite', 'rather', 'really', 'round', 'said', 'sake',
              'same', 'sang', 'save', 'saw', 'see', 'seeing', 'seem', 'seemed', 'seeming', 'seems', 'seen',
              'seldom', 'selves', 'sent', 'several', 'shalt', 'she', 'should', 'shown', 'sideways', 'since',
              'slept', 'slew', 'slung', 'slunk', 'smote', 'so', 'some', 'somebody', 'somehow', 'someone',
              'something', 'sometime', 'sometimes', 'somewhat', 'somewhere', 'spake', 'spat', 'spoke', 'spoken',
              'sprang', 'sprung', 'stave', 'staves', 'still', 'such', 'supposing', 'than', 'that', 'the', 'thee',
              'their', 'them', 'themselves', 'then', 'thence', 'thenceforth', 'there', 'thereabout',
              'thereabouts', 'thereafter', 'thereby', 'therefore', 'therein', 'thereof', 'thereon', 'thereto',
              'thereupon', 'these', 'they', 'this', 'those', 'thou', 'though', 'thrice', 'through', 'throughout',
              'thru', 'thus', 'thy', 'thyself', 'till', 'to', 'together', 'too', 'toward', 'towards', 'ugh',
              'unable', 'under', 'underneath', 'unless', 'unlike', 'until', 'up', 'upon', 'upward', 'upwards',
              'us', 'use', 'used', 'using', 'very', 'via', 'vs', 'want', 'was', 'we', 'week', 'well', 'were',
              'what', 'whatever', 'whatsoever', 'when', 'whence', 'whenever', 'whensoever', 'where',
              'whereabouts', 'whereafter', 'whereas', 'whereat', 'whereby', 'wherefore', 'wherefrom', 'wherein',
              'whereinto', 'whereof', 'whereon', 'wheresoever', 'whereto', 'whereunto', 'whereupon', 'wherever',
              'wherewith', 'whether', 'whew', 'which', 'whichever', 'whichsoever', 'while', 'whilst', 'whither',
              'who', 'whoa', 'whoever', 'whole', 'whom', 'whomever', 'whomsoever', 'whose', 'whosoever', 'why',
              'will', 'wilt', 'with', 'within', 'without', 'worse', 'worst', 'would', 'wow', 'ye', 'yet', 'year',
              'yippee', 'you', 'your', 'yours', 'yourself', 'yourselves', '']

# Counting word frequency

total_counts = Counter()
for review in reviews[0]:
	words = review.split(" ")
	for word in words:
		total_counts[word] += 1

print("Total words in data set: ", len(total_counts))

for word in stop_words:
	if word in total_counts:
		del total_counts[word]

print("Total words in data set after removing stop words: ", len(total_counts))

vocab = sorted(total_counts, key=total_counts.get, reverse=True)[:10000]

word2idx = {}

for i in range(len(vocab)):
	word2idx[vocab[i]] = i

# Text to vector function

def text_to_vector(text):
	w_vec = np.zeros(len(vocab))
	words = text.lower().split(' ')

	for word in words:
		if word in word2idx:
			w_to_i = word2idx[word]
			w_vec[w_to_i] += 1
	return w_vec

word_vectors = np.zeros((len(reviews), len(vocab)), dtype=np.int_)
for ii, (_, text) in enumerate(reviews.iterrows()):
	word_vectors[ii] = text_to_vector(text[0])

# Train, Validation, Test sets

Y = (labels == 'positive').astype(np.int_)
records = len(labels)

shuffle = np.arange(records)
np.random.shuffle(shuffle)
test_fraction = 0.9

train_split, test_split = shuffle[:int(records * test_fraction)], shuffle[int(records * test_fraction):]
trainX, trainY = word_vectors[train_split, :], to_categorical(Y.values[train_split], 2)
testX, testY = word_vectors[test_split, :], to_categorical(Y.values[test_split], 2)

# Network building
def build_model():
	net = tflearn.input_data([None, len(vocab)])
	net = tflearn.fully_connected(net, 100, activation='ReLU')
	net = tflearn.fully_connected(net, 25, activation='ReLU')
	net = tflearn.fully_connected(net, 2, activation='softmax')

	net = tflearn.regression(net, optimizer='sgd', learning_rate=0.1, loss='categorical_crossentropy')

	model = tflearn.DNN(net)
	return model

# Intializing the model

model = build_model()

# Training
model.fit(trainX, trainY, validation_set=0.1, show_metric=True, batch_size=128, n_epoch=20)

# Testing
predictions = (np.array(model.predict(testX))[:, 0] >= 0.5).astype(np.int_)
test_accuracy = np.mean(predictions == testY[:, 0], axis=0)
print("Test accuracy: ", test_accuracy)

# Try out your own text!
text = "This movie is so bad. It was awful and the worst"
positive_prob = model.predict([text_to_vector(text.lower())])[0][1]
print('P(positive) = {:.3f} :'.format(positive_prob), 'Positive' if positive_prob > 0.5 else 'Negative')


import numpy as np
from scipy import sparse, linalg
import osqp
import pdb

#from compatibility_lib.cleaned_LMPC.local_linearization import PredictiveModel
import copy
from matplotlib import pyplot as plt

class MPCUtil():
    '''
    General purpose MPC utility. Can be used for MPC, LMPC, ATV_MPC, etc...

    '''

    def __init__(self, N, dim_x, dim_u, num_ss = 50):
        #support for non-LMPC is not yet implemented
        self.N = N
        self.dim_x = dim_x
        self.dim_u = dim_u
        self.num_ss = num_ss
        self.num_lambda = self.num_ss
        self.num_eps = self.N
        self.num_mu = self.dim_x

        self.last_output = np.zeros((self.dim_u,1))

        #TODO: These are currently placeholders and may not work if changed
        self.use_ss = True
        self.use_terminal_slack = True
        self.use_lane_slack = True
        self.use_affine = True
        self.use_time_varying = False
        return

    def set_model_matrices(self, A ,B ,C = None):
        assert A.shape[1] == A.shape[0]
        assert A.shape[1] == self.dim_x
        assert B.shape[0] == self.dim_x
        assert B.shape[1] == self.dim_u

        if C is None: C = np.zeors((self.dim_x, 1))
        assert C.shape[0] == self.dim_x
        assert C.shape[1] == 1

        self.A = A
        self.B = B
        self.C = C
        return

    def set_state_costs(self, Q, P, R, dR):
        assert Q.shape[0] == Q.shape[1]
        assert Q.shape[0] == self.dim_x
        assert P.shape[0] == P.shape[1]
        assert P.shape[0] == self.dim_x
        assert R.shape[0] == R.shape[1]
        assert R.shape[0] == self.dim_u
        assert dR.shape[0] == dR.shape[1]
        assert dR.shape[0] == self.dim_u

        self.Q = Q   # intermediate state cost
        self.P = P   # terminal state cost
        self.R = R   # output state cost
        self.dR = dR # output rate cost
        return

    def set_slack_costs(self, Q_mu, Q_eps, b_eps):
        assert Q_mu.shape[0] == Q_mu.shape[1]
        assert Q_mu.shape[0] == self.num_mu
        assert Q_eps.shape[0] == Q_eps.shape[1]
        assert Q_eps.shape[0] == self.num_eps
        assert b_eps.shape[0] == self.num_eps
        assert b_eps.shape[1] == 1

        self.Q_mu = Q_mu
        self.Q_eps = Q_eps
        self.b_eps = b_eps
        return

    def set_state_constraints(self,Fx, bx_u, bx_l, Fu, bu_u, bu_l, E, max_lane_slack = 1):
        assert Fx.shape[1] == self.dim_x
        assert Fx.shape[0] == bx_u.shape[0]
        assert Fx.shape[0] == bx_l.shape[0]
        assert bx_u.shape[1] == 1
        assert bx_l.shape[1] == 1
        assert Fu.shape[1] == self.dim_u
        assert Fu.shape[0] == bu_u.shape[0]
        assert Fu.shape[0] == bu_l.shape[0]
        assert bu_u.shape[1] == 1
        assert bu_l.shape[1] == 1
        assert E.shape[0] == Fx.shape[0]
        assert E.shape[1] == 1

        self.Fx = Fx
        self.bx_u = bx_u
        self.bx_l = bx_l
        self.Fu = Fu
        self.bu_u = bu_u
        self.bu_l = bu_l
        self.E = E
        self.max_lane_slack = max_lane_slack
        return

    def set_ss(self,ss_vecs, ss_q):
        assert ss_vecs.shape[0] == self.dim_x
        assert ss_vecs.shape[1] == self.num_ss
        assert ss_q.shape[0] == self.num_ss
        assert ss_q.shape[1] == 1

        self.ss_terminal_q = ss_q
        self.ss_terminal_vecs = ss_vecs
        return

    def set_x0(self,x0, xf = None):
        if xf is None:
            xf = np.zeros(x0.shape)
        assert x0.shape[0] == self.dim_x
        assert x0.shape[1] == 1
        assert xf.shape[0] == self.dim_x
        assert xf.shape[1] == 1
        self.x0 = x0
        self.xf = xf

        return

    def build_cost_matrix(self):

        Mx = sparse.block_diag((*([self.Q]*self.N), self.P))
        Mu = sparse.kron(sparse.eye(self.N, k = -1), -self.dR)  +\
             sparse.kron(sparse.eye(self.N, k =  1), -self.dR)  +\
             sparse.kron(sparse.eye(self.N), self.R+2*self.dR)
        M = 2*sparse.block_diag([Mx, Mu])

        #q = np.zeros((self.num_x,1))
        if self.use_ss:
            q = np.vstack([np.kron(np.ones((self.N,1)), -self.Q @ self.ss_terminal_vecs[:,-1:]), self.P @ self.ss_terminal_vecs[:,-1:]])
        else:
            q = np.vstack([np.kron(np.ones((self.N,1)), -self.Q @ self.xf), self.P @ self.xf])

        #q = np.vstack([q, np.zeros((self.num_u,1))])
        for i in range(self.N):                             #TODO: prior output cost should go here
            q = np.vstack([q, np.array([[0],[0],[-14]])])

        #q = np.vstack([q, -2 * self.dR @ self.last_output])         # untested (thomasfork)
        #q = np.vstack([q, np.zeros((self.dim_u * (self.N-1),1))])

        if self.use_ss:
            M = sparse.block_diag([M, sparse.csc_matrix((self.num_lambda, self.num_lambda))])
            q = np.vstack([q, self.ss_terminal_q])

        if self.use_terminal_slack:
            M = sparse.block_diag([M, 2*self.Q_mu])
            q = np.vstack([q, np.zeros((self.dim_x,1))])

        if self.use_lane_slack:
            M = sparse.block_diag([M, 2*self.Q_eps])
            q = np.vstack([q, self.b_eps])

        self.osqp_P = sparse.csc_matrix(M)
        self.osqp_q = q

        return

    def build_constraint_matrix(self):
        #more info on the constraints for OSQP can be found at https://osqp.org
        # in particular, https://osqp.org/docs/examples/mpc.html provides a great MPC example

        #more info on the constraints for the berkeley car can be found at a location coming soon.

        #Equality constraints:
        # state constraints - x_k+1 = A*x_k + B*u_k
        # except x_0 = self.x0
        Ax = sparse.kron(sparse.eye(self.N+1),sparse.eye(self.dim_x)) + \
             sparse.kron(sparse.eye(self.N+1, k=-1), -self.A)                #TODO: Time varying case would be implemented here
        Au = sparse.kron(sparse.vstack([sparse.csc_matrix((1, self.N)), sparse.eye(self.N)]), -self.B)
        Aeq = sparse.hstack([Ax, Au])
        leq = np.vstack([self.x0, np.tile(self.C.T,self.N).T])

        # safe set constraints:
        #  terminal point must be a weighted sum of safe set points and slack:
        #  weights must also sum to zero
        if self.use_ss:
            temp_Aeq_height = Aeq.shape[0]
            if self.use_terminal_slack:

                A_lambda = np.vstack((np.hstack((self.ss_terminal_vecs, -np.eye(self.dim_x))), np.hstack((np.ones((1,self.num_ss)), np.zeros((1,self.dim_x))))))
            else:
                A_lambda = sparse.vstack([self.ss_terminal_vecs, np.ones((1,self.num_ss))])

            Aeq = sparse.block_diag((Aeq,A_lambda))
            Aeq = sparse.lil_matrix(Aeq)
        #  finish terminal point constraint - sum of weights and slack variables must equal x_N
            Aeq[temp_Aeq_height: temp_Aeq_height + self.dim_x, self.dim_x * self.N: self.dim_x * (self.N+1)] = -sparse.eye(self.dim_x)

        #  update leq, ueq with terminal constraints
            leq = np.vstack([leq, np.zeros((self.dim_x, 1)), 1])

        # otherwise add terminal constraint
        else:
            tmp = np.zeros((1,self.N + 1))
            tmp[0,self.N] = 1
            A_terminal = sparse.kron(tmp, sparse.eye(self.dim_x))
            A_terminal = sparse.hstack([A_terminal, sparse.csc_matrix((self.dim_x, self.num_u))])
            Aeq = sparse.vstack([Aeq, A_terminal])

            leq = np.vstack([leq, self.xf])
        # upper and lower constraints are identical for equality constraints
        ueq = copy.copy(leq)

        # no equality constraints for lane slack but need to add columns of zeros
        if self.use_lane_slack:
            Aeq = sparse.hstack((Aeq, sparse.csc_matrix((Aeq.shape[0],  self.num_eps))))

        assert Aeq.shape[0] == ueq.shape[0]

        #Inequality constraints:
        # state constraints
        '''if self.use_ss:
            #  no state constraint for x_N since it is handleded by safe set constraint
            Aineq = sparse.block_diag(([self.Fx]*self.N))  #, sparse.csc_matrix((self.dim_x,self.dim_x))))
            Aineq = sparse.hstack([Aineq, sparse.csc_matrix((Aineq.shape[0],self.dim_x))])

        else:'''

        Aineq = sparse.block_diag(([self.Fx]*(self.N+1)))
        lineq = np.kron(np.ones((self.N+1,1)), self.bx_l)
        uineq = np.kron(np.ones((self.N+1,1)), self.bx_u)

        # generate upper and lower bounds
        '''if self.use_ss:
            lineq = np.kron(np.ones((self.N,1)), self.bx_l)
            uineq = np.kron(np.ones((self.N,1)), self.bx_u)
        else:'''

        assert Aineq.shape[0] == lineq.shape[0]

        # add output constraints
        Aineq = sparse.block_diag((Aineq,*([self.Fu]*self.N)))
        lineq = np.vstack((lineq, *([self.bu_l]*self.N)))
        uineq = np.vstack((uineq, *([self.bu_u]*self.N)))

        # force safe set weighting terms (lamda) to be positive
        #   note: upper bound is 1 not inf since their sum must be 1
        if self.use_ss:
            Aineq = sparse.block_diag((Aineq,sparse.eye(self.num_ss)))
            lineq = np.vstack([lineq,  np.zeros((self.num_ss,1))])
            uineq = np.vstack([uineq,  np.ones((self.num_ss,1))])

        assert Aineq.shape[0] == lineq.shape[0]

        # zero pad if terminal slack is used (no constriants on terminal slack)
        if self.use_terminal_slack:
            Aineq = sparse.hstack([Aineq,sparse.csc_matrix((Aineq.shape[0], self.dim_x))])

        # add effect on state constraints if lane slack is added.
        #    note: does not effect terminal state
        if self.use_lane_slack:
            slack_matrix = sparse.block_diag(([self.E]*self.N))
            Aineq = sparse.block_diag([Aineq, sparse.eye(self.num_eps)])
            Aineq = sparse.lil_matrix(Aineq)
            Aineq [0:slack_matrix.shape[0],-slack_matrix.shape[1]:] = slack_matrix

            #force lane slack to less than max_lane_slack (+/- since slack can act on either side of the lane)

            lineq = np.vstack([lineq, -np.ones((self.E.shape[1]*self.N,1))*self.max_lane_slack])
            uineq = np.vstack([uineq, np.ones((self.E.shape[1]*self.N,1))*self.max_lane_slack])

        assert Aineq.shape[0] == lineq.shape[0]

        # - OSQP constraints
        A = sparse.vstack([Aeq, Aineq], format='csc')
        l = np.vstack([leq, lineq])
        u = np.vstack([ueq, uineq])

        self.osqp_A = sparse.csc_matrix(A)
        self.osqp_l = l
        self.osqp_u = u

        return

    def setup(self):
        self.num_x =         (self.N + 1) * self.dim_x
        self.num_u =         self.N * self.dim_u

        self.index_x =       0
        self.index_u =       self.index_x + self.num_x
        self.index_lambda =  self.index_u + self.num_u
        self.index_mu =      self.index_lambda + self.num_lambda
        self.index_eps =     self.index_mu + self.num_mu

        self.use_ss = True
        self.use_terminal_slack = False
        self.use_lane_slack = False

        self.build_cost_matrix()
        self.build_constraint_matrix()

        self.solver = osqp.OSQP()
        self.solver.setup(P=self.osqp_P, q=self.osqp_q, A=self.osqp_A, l=self.osqp_l, u=self.osqp_u, verbose=True, polish=True)
        return

    def setup_MPC(self):
        self.num_x =         (self.N + 1) * self.dim_x
        self.num_u =         self.N * self.dim_u
        self.index_x =       0
        self.index_u =       self.index_x + self.num_x

        self.use_ss = False
        self.use_terminal_slack = False
        self.use_lane_slack = False

        self.build_cost_matrix()
        self.build_constraint_matrix()

        self.solver = osqp.OSQP()
        self.solver.setup(P=self.osqp_P, q=self.osqp_q, A=self.osqp_A, l=self.osqp_l, u=self.osqp_u, verbose=True, polish=True)
        return

    def update(self):
        self.update_ss()
        self.update_x0()
        self.update_model_matrices()
        self.solver.update(q = self.osqp_q, Ax = self.osqp_A.data, l = self.osqp_l ,u = self.osqp_u)
        return

    def update_ss(self):
        if not self.use_ss:
            return
        num_x = self.dim_x * (self.N + 1)
        num_u = self.dim_u * self.N
        self.osqp_q[num_x + num_u: num_x + num_u + self.num_ss] = self.ss_terminal_q
        self.osqp_A = sparse.lil_matrix(self.osqp_A)
        self.osqp_A[num_x + num_u :num_x+num_u + self.dim_x, num_x+num_u : num_x+num_u + self.num_ss] = self.ss_terminal_vecs
        self.osqp_A = sparse.csc_matrix(self.osqp_A)
        return

    def update_x0(self):
        self.osqp_l[0:self.dim_x] = self.x0
        self.osqp_u[0:self.dim_x] = self.x0
        return

    def update_model_matrices(self):
        Ax = sparse.kron(sparse.eye(self.N+1),sparse.eye(self.dim_x)) + \
             sparse.kron(sparse.eye(self.N+1, k=-1), -self.A)                #TODO: Implement time varying case
        Au = sparse.kron(sparse.vstack([sparse.csc_matrix((1, self.N)), sparse.eye(self.N)]), -self.B)
        Aeq = sparse.hstack([Ax, Au])

        self.osqp_A[0:Aeq.shape[0], 0:Aeq.shape[1]] = Aeq
        return

    def solve(self, init_vals = None):
        if init_vals is not None:
            self.solver.warm_start(x=init_vals)

        z0 = np.vstack([self.x0, self.ss_terminal_vecs[:,0:self.N].reshape(-1,1)])
        z0 = np.vstack([z0, np.zeros((self.osqp_P.shape[0] - z0.shape[0],1))])
        self.solver.warm_start(x = z0)

        res = self.solver.solve()
        self.osqp_feasible = res.info.status_val == 1

        if self.osqp_feasible:
            self.unpack_results(res)
        else:
            print('Ineasible OSQP')
        return

    def unpack_results(self,res):
        num_x = self.dim_x * (self.N + 1)
        num_u = self.dim_u * self.N
        self.predicted_x = np.reshape(res.x[self.index_x:self.index_x + self.num_x], (self.N+1, self.dim_x))
        self.predicted_u = np.reshape(res.x[self.index_u:self.index_u + self.num_u], (self.N, self.dim_u))

        if self.use_ss:
            self.predicted_lambda = res.x[self.index_lambda:self.index_lambda + self.num_lambda]
        else:
            self.predicted_lambda = np.nan
        if self.use_terminal_slack:
            self.predicted_mu = res.x[self.index_mu:self.index_mu + self.num_mu]
        else:
            self.predicted_mu = np.nan
        if self.use_lane_slack:
            self.predicted_eps = res.x[self.index_eps:self.index_eps + self.num_eps]
        else:
            self.predicted_eps = np.nan

        return

def main():
    N = 5
    dim_x = 2
    dim_u = 1
    dim_mu = dim_x
    dim_eps = N
    dim_ss = 4

    A = np.array([[1,0.1],[0,.9]])
    B = np.array([[0],[1]])
    C = np.array([[0.0],[0]])

    x0 = np.ones((dim_x,1)) * 4

    Q = sparse.eye(dim_x) * 10
    P = sparse.eye(dim_x) * 100
    R = sparse.eye(dim_u) * 10
    dR = sparse.eye(dim_u) * 0
    Q_mu = sparse.eye(dim_mu) * 10000
    Q_eps = sparse.eye(dim_eps) * 100
    b_eps = np.ones((dim_eps,1)) * 0

    ss_vecs = np.ones((dim_x,dim_ss))
    ss_vecs[1,:] = 0
    ss_q    = np.zeros((dim_ss,1))

    #Fx = np.array([[0,0,0,0,0,1]])
    #bx_u = np.array([[0.8]])
    #bx_l =  np.array([[-0.8]])

    #Fu = np.eye(2)
    #bu_u = np.array([[10],[0.5]])
    #bu_l = np.array([[-10],[-0.5]])

    Fx = np.eye(2)
    bx_u = np.array([[10],[10]])
    bx_l = np.array([[-10],[-10]])

    Fu = np.eye(1)
    bu_u = np.array([[1]])
    bu_l = np.array([[-1]])

    E = np.array([[1],[1]])

    m = MPCUtil(N, dim_x, dim_u, num_ss = dim_ss)
    m.set_model_matrices(A,B,C)
    m.set_x0(x0)
    m.set_state_costs(Q, P, R, dR)
    m.set_slack_costs(Q_mu, Q_eps, b_eps)
    m.set_ss(ss_vecs, ss_q)
    m.set_state_constraints(Fx, bx_u, bx_l, Fu, bu_u, bu_l, E)

    m.setup()

    assert m.osqp_P.shape[0] == dim_x  *(N+1) + N*dim_u + dim_eps + dim_mu + dim_ss
    assert m.osqp_P.shape[0] == m.osqp_P.shape[1]

    assert m.osqp_A.shape[1] == m.osqp_A.shape[1]
    assert m.osqp_A.shape[0] == m.osqp_l.shape[0]
    assert m.osqp_A.shape[0] == m.osqp_u.shape[0]
    assert m.osqp_l.shape[1] == 1
    assert m.osqp_u.shape[1] == 1
    m.solve()

    print('LMPC u: %s'%str(m.predicted_u[0]))
    print('avg. terminal point: %f'%np.sum(m.predicted_lambda * np.arange(m.num_ss)))
    print('terminal slack: %f'%np.linalg.norm(m.predicted_mu))
    print('lane slack: %f'%np.linalg.norm(m.predicted_eps))

    plt.figure()

    x = x0.copy()
    xlist = [x]
    ulist = []
    for j in range(150):
        m.set_x0(x)
        m.update() #setup()
        m.solve()
        u = m.predicted_u[0:1]
        print(u)
        x = A @ x + B @ u + C
        for i in range(dim_x):
            plt.subplot(2,2,i*2+1)
            plt.plot(range(j,j+N+1), m.predicted_x[:,i],'--')
        for i in range(dim_u):
            plt.subplot(2,2,i*2+2)
            plt.plot(range(j,j+N), m.predicted_u[:,i],'--')
        xlist.append(x)
        ulist.append(u)
    xlist = np.array(xlist)
    ulist = np.array(ulist)
    for i in range(dim_x):
        plt.subplot(2,2,i*2+1)
        plt.plot(xlist[:,i,0],'-')
    for i in range(dim_u):
        plt.subplot(2,2,i*2+2)
        plt.plot(ulist[:,i,0],'-')

    plt.show()

    #pdb.set_trace()

    return

if __name__ == '__main__':
    main()


import requests_mock
import requests.exceptions
import pytest

from .. import weather

def test_simple_result():
    """Check that the weather info can be parsed."""

    sample_good_output = '{"coord":{"lon":0.08,"lat":52.24},"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04d"}],"base":"stations","main":{"temp":282.57,"pressure":1034,"humidity":76,"temp_min":282.15,"temp_max":283.15},"visibility":10000,"wind":{"speed":3.6,"deg":260},"clouds":{"all":90},"dt":1546262760,"sys":{"type":1,"id":1482,"message":0.0031,"country":"GB","sunrise":1546243745,"sunset":1546271815},"id":2648627,"name":"Girton","cod":200}'

    with requests_mock.Mocker() as m:
        m.get(weather.WEATHER_API_ENDPOINT, text=sample_good_output)
        responses = [
                weather.get_weather('apikey', 'Girton,GB'),
                weather.Weather('apikey', 'Girton,GB').get_weather()
                ]
        for resp in responses:
            assert 'temperature' in resp
            assert resp['temperature'] == 282.57
            assert all(x in resp for x in
                    ['temperature', 'humidity', 'sunset', 'sunrise'])

class TestErrorCases(object):
    sample_error_output = '{"cod":"500","message":"Internal error: 500001"}'

    def test_error_response(self):
        """Check that appropriate exception is raised on error."""
        with requests_mock.Mocker() as m:
            m.get(weather.WEATHER_API_ENDPOINT, text=self.sample_error_output,
                    status_code=500)
            with pytest.raises(weather.WeatherServiceError):
                weather.get_weather('apikey', 'Girton,GB')
            with pytest.raises(weather.WeatherServiceError):
                weather.Weather('apikey', 'Girton,GB').get_weather()


"""
# Definition for a Node.
class Node(object):
    def __init__(self, val, children):
        self.val = val
        self.children = children
"""
from collections import deque

class Solution(object):
    def levelOrder(self, root):
        """
        :type root: Node
        :rtype: List[List[int]]
        """
        if not root:
            return []
        res = []
        queue = deque([root])
        while len(queue) > 0:
            level_len = len(queue)
            temp = []
            while level_len > 0:
                node = queue.popleft()
                temp.append(node.val)
                while node.children:
                    queue.append(node.children.pop(0))
                level_len -= 1
            res.append(temp)
        return res


from collections import defaultdict
import csv
import matplotlib as mpl

mpl.use('agg')

import matplotlib.pyplot as plt

contentID_to_listAttempts = defaultdict(list)

with open("UCRCS10Spring2016_16CAs.csv", 'r', newline = '', encoding = "utf8") as input_csv:
    reader = csv.reader(input_csv)
    for row in reader:
        zyBook_code, user_id, resource_id, part0, part1, total = row
        if total.isdigit():
            contentID_to_listAttempts[resource_id].append(int(total))

#making one graph with all of the boxplots
data_to_plot = []
content_ids = []
x_tick_labels = []

for content_id, list_attempts in contentID_to_listAttempts.items():
    data_to_plot.append(list_attempts)
    content_ids.append(content_id)

x_tick_labels = list(range(1, len(content_ids) + 1))

fig = plt.figure(1, figsize=(25, 10))
ax = fig.add_subplot(111)
ax.tick_params(axis=u'x', which=u'both', length=0)
ax.set_xlabel('Programming homeworks')
ax.set_ylabel('Number of attempts')
ax.set_xticklabels(x_tick_labels)

bp = ax.boxplot(data_to_plot, patch_artist=True)

for box in bp['boxes']:
    box.set( color='#7570b3', linewidth=2)
    box.set( facecolor = '#1b9e77' )

for whisker in bp['whiskers']:
    whisker.set(color='#7570b3', linewidth=2)

for cap in bp['caps']:
    cap.set(color='#7570b3', linewidth=2)

for median in bp['medians']:
    median.set(color='#b2df8a', linewidth=2)

for flier in bp['fliers']:
    flier.set(marker='o', color='#e7298a', alpha=0.5)

plt.axes().set_ylim(ymin=0)

fig.savefig('UCRCS10Spring2016_16CAs_boxplots.png', bbox_inches='tight')

print(content_ids)

#making a graph per activity
for content_id, list_attempts in contentID_to_listAttempts.items():
    fig = plt.figure()

    plt.ylabel("Number of attempts")
    plt.xlabel("Programming homework")
    bp = plt.boxplot(list_attempts, patch_artist=True)
    plt.axes().get_xaxis().set_ticks([])

    for box in bp['boxes']:
        box.set( color='#7570b3', linewidth=2)
        box.set( facecolor = '#1b9e77' )

    for whisker in bp['whiskers']:
        whisker.set(color='#7570b3', linewidth=2)

    for cap in bp['caps']:
        cap.set(color='#7570b3', linewidth=2)

    for median in bp['medians']:
        median.set(color='#b2df8a', linewidth=3)

    for flier in bp['fliers']:
        flier.set(marker='o', color='#e7298a', alpha=0.5)

    plt.axes().set_ylim(ymin=0)

    fig.savefig('UCRCS10Spring2016_16CAs_boxplots/{}_boxplot.png'.format(content_id), bbox_inches='tight')