import pygame
from collections import namedtuple, defaultdict
from progress.pathfind import MinHeap, Graph, is_edge, maze_to_graph

BLACK = (0,0,0)
WHITE = (255, 255, 255)
RED = (255,0,0)
BLUE = (5,21,104)

pygame.font.init()
myfont = pygame.font.SysFont('Comic Sans MS', 50)
WINDOW_WIDTH = 500
WINDOW_HEIGHT = 600
GAME_WIDTH = 500
GAME_HEIGHT = 500
top_offset = (WINDOW_HEIGHT - GAME_HEIGHT) / 2
gameDisplay = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption('pacman')

Coord = namedtuple('Coord', 'x, y')
Move = namedtuple('Move', 'dest, cost')

# Maze
maze_arr = []
with open('mazes/maze_01.txt', 'r') as maze:
    m = maze.readlines()
    for i in m:
        line = list(i.rstrip())
        maze_arr.append(line)

target_score = sum(row.count('@') for row in maze_arr)
# print(target_score)

maze_height = len(maze_arr)
maze_width = len(maze_arr[0])
pixel_height = GAME_HEIGHT / maze_height
pixel_width = GAME_WIDTH / maze_width

# Pacman
obj_width = 18
obj_height = 18
pacman_orig = pygame.image.load('img/pacman.png')
pacman_orig = pygame.transform.scale(pacman_orig, (obj_width, obj_height))
pacman_right = pygame.transform.rotate(pacman_orig, 0)
pacman_left = pygame.transform.rotate(pacman_orig, 180)
pacman_up = pygame.transform.rotate(pacman_orig, 90)
pacman_down = pygame.transform.rotate(pacman_orig, 270)
obj_x = 1
obj_y = 1
score = 0

# Pacman movement
MOVE_UP = 1
MOVE_DOWN = 2
MOVE_RIGHT = 3
MOVE_LEFT = 4
next_move = 0
change_x = 0
change_y = 0

# Ghost
ghost_width = 16
ghost_height = 16
ghost = pygame.image.load('img/red.png')
ghost = pygame.transform.scale(ghost, (ghost_width, ghost_height))
ghost_x = 23
ghost_y = 23
ghost_change_x = 0
ghost_change_y = 0

node_list = maze_to_graph(maze_arr).return_node_list()

ghost_recalculate_counter = 0
graph = maze_to_graph(maze_arr)
start = Coord(ghost_x,ghost_y)
end = Coord(obj_x,obj_y)
path = graph.dijkstra(start, end)
target_index = 0
def ghost_recalculate():
    global start
    global end
    global path
    global graph
    global node_list
    start = Coord(ghost_x,ghost_y)
    end = Coord(obj_x,obj_y)
    if start not in node_list:
        dist = 1 #UP
        while(True):
            if maze_arr[start.y-dist][start.x] == '#':
                break
            if is_edge(maze_arr, start.y-dist, start.x):
                dest = Coord(start.x, start.y-dist)
                graph.add_edge(start, dest, dist) #src, dest, cost
                break
            dist += 1
        dist = 1    #DOWN
        while(True):
            if maze_arr[start.y+dist][start.x] == '#':
                break
            if is_edge(maze_arr, start.y+dist, start.x):
                dest = Coord(start.x, start.y+dist)
                graph.add_edge(start, dest, dist) #src, dest, cost
                break
            dist += 1
        dist = 1    #LEFT
        while(True):
            if maze_arr[start.y][start.x-dist] == '#':
                break
            if is_edge(maze_arr, start.y, start.x-dist):
                dest = Coord(start.x-dist, start.y)
                graph.add_edge(start, dest, dist) #src, dest, cost
                break
            dist += 1
        dist = 1    #RIGHT
        while(True):
            if maze_arr[start.y][start.x+dist] == '#':
                break
            if is_edge(maze_arr, start.y, start.x+dist):
                dest = Coord(start.x+dist, start.y)
                graph.add_edge(start, dest, dist) #src, dest, cost
                break
            dist += 1

    if end not in node_list:
        dist = 1 #UP
        while(True):
            if maze_arr[end.y-dist][end.x] == '#':
                break
            if is_edge(maze_arr, end.y-dist, end.x):
                dest = Coord(end.x, end.y-dist)
                graph.add_edge(end, dest, dist) #src, dest, cost
                break
            dist += 1
        dist = 1    #DOWN
        while(True):
            if maze_arr[end.y+dist][end.x] == '#':
                break
            if is_edge(maze_arr, end.y+dist, end.x):
                dest = Coord(end.x, end.y+dist)
                graph.add_edge(end, dest, dist) #src, dest, cost
                break
            dist += 1
        dist = 1    #LEFT
        while(True):
            if maze_arr[end.y][end.x-dist] == '#':
                break
            if is_edge(maze_arr, end.y, end.x-dist):
                dest = Coord(end.x-dist, end.y)
                graph.add_edge(end, dest, dist) #src, dest, cost
                break
            dist += 1
        dist = 1    #RIGHT
        while(True):
            if maze_arr[end.y][end.x+dist] == '#':
                break
            if is_edge(maze_arr, end.y, end.x+dist):
                dest = Coord(end.x+dist, end.y)
                graph.add_edge(end, dest, dist) #src, dest, cost
                break
            dist += 1

    path = graph.dijkstra(start, end)
    if start not in node_list:
        graph.remove_edge(start)
    if end not in node_list:
        graph.remove_edge(end)

keepGoing = True
pause = False
clock = pygame.time.Clock()
pacman = pacman_orig

while keepGoing:
    for event in pygame.event.get():    #event handler
        if event.type == pygame.QUIT:
            keepGoing = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP:
                if maze_arr[obj_y-1][obj_x] != '#':
                    change_x = 0
                    change_y = -1
                    next_move = 0
                else:
                    next_move = MOVE_UP
            elif event.key == pygame.K_DOWN:
                if maze_arr[obj_y+1][obj_x] != '#':
                    change_x = 0
                    change_y = 1
                    next_move = 0
                else:
                    next_move = MOVE_DOWN
            elif event.key == pygame.K_LEFT:
                if maze_arr[obj_y][obj_x-1] != '#':
                    change_x = -1
                    change_y = 0
                    next_move = 0
                else:
                    next_move = MOVE_LEFT
            elif event.key == pygame.K_RIGHT:
                if maze_arr[obj_y][obj_x+1] != '#':
                    change_x = 1
                    change_y = 0
                    next_move = 0
                else:
                    next_move = MOVE_RIGHT

    if ghost_x == obj_x and ghost_y == obj_y:
        print('CAUGHT!')
        gameDisplay.fill(BLACK)
        final_font = pygame.font.SysFont('Comic Sans MS', 50)
        stop_text = final_font.render('GAME OVER...', True, WHITE)
        gameDisplay.blit(stop_text,(0,0))
        pygame.display.update()
        pygame.time.delay(1000)
        keepGoing = False
        continue

    if next_move > 0:
        if next_move == MOVE_UP and maze_arr[obj_y-1][obj_x] != '#':
            change_x = 0
            change_y = -1
        elif next_move == MOVE_DOWN and maze_arr[obj_y+1][obj_x] != '#':
            change_x = 0
            change_y = 1
        elif next_move == MOVE_LEFT and maze_arr[obj_y][obj_x-1] != '#':
            change_x = -1
            change_y = 0
        elif next_move == MOVE_RIGHT and maze_arr[obj_y][obj_x+1] != '#':
            change_x = 1
            change_y = 0
    if maze_arr[obj_y+change_y][obj_x+change_x] == '#':
        change_x = 0
        change_y = 0
    elif maze_arr[obj_y+change_y][obj_x+change_x] == '@':
        maze_arr[obj_y+change_y][obj_x+change_x] = ' '
        score += 1
        if score == target_score:
            keepGoing = False

    if change_x == 1: #right
        pacman = pacman_right
    elif change_x == -1: #left
        pacman = pacman_left
    elif change_y == -1: #up
        pacman = pacman_up
    elif change_y == 1: #down
        pacman = pacman_down

    obj_x += change_x
    obj_y += change_y

    #GHOST MOVEMENT
    target_x = path[target_index].x
    target_y = path[target_index].y
    if target_x > ghost_x:
        ghost_change_x = 1
        ghost_change_y = 0
    elif target_x < ghost_x:
        ghost_change_x = -1
        ghost_change_y = 0
    elif target_y > ghost_y:
        ghost_change_y = 1
        ghost_change_x = 0
    elif target_y < ghost_y:
        ghost_change_y = -1
        ghost_change_x = 0

    ghost_x += ghost_change_x
    ghost_y += ghost_change_y

    ghost_recalculate_counter += 1
    if target_x == ghost_x and target_y == ghost_y:
        target_index += 1
    if target_index == len(path) or ghost_recalculate_counter == 5:
        ghost_recalculate_counter = 0
        ghost_recalculate()
        target_index = 0
    # print('path_length:', len(path))
    # print('start:', start)
    # print('end:', end)
    # print('path:', path)
    # print('target_index:', target_index, '\n')

    #Draw maze
    gameDisplay.fill(BLACK)
    lead_x = 0
    lead_y = 0
    for row in maze_arr:
        for col in row:
            if col == '#':
                pygame.draw.rect(gameDisplay, BLUE, (lead_x, top_offset+lead_y, pixel_width, pixel_height))
            elif col == '@':
                pygame.draw.circle(gameDisplay, WHITE, (int(lead_x + pixel_width/2), int(top_offset + lead_y + pixel_height/2)), 3, 0)
            lead_x += pixel_width
        lead_y += pixel_height
        lead_x = 0

    gameDisplay.blit(pacman, (obj_x*pixel_width+1,top_offset+obj_y*pixel_height+1))
    gameDisplay.blit(ghost, (ghost_x*pixel_width+2,top_offset+ghost_y*pixel_height+2))
    #pygame.draw.rect(gameDisplay, RED, (ghost_x*pixel_width+5, top_offset+ghost_y*pixel_height+5, 10, 10))
    score_text = myfont.render('score: '+ str(score), True, WHITE)
    gameDisplay.blit(score_text,(WINDOW_WIDTH/30, top_offset/5))
    pygame.display.update()
    clock.tick(5)

pygame.quit()
quit()


import sys
import os

try:
    import pytest
except ImportError:
    fname = os.__file__
    if fname.endswith('.pyc'):
        fname = fname[:-1]

    if not os.path.islink(fname):
        raise

    real_prefix = os.path.dirname(os.path.realpath(fname))
    site_packages = os.path.join(real_prefix, 'site-packages')
    old_path = sys.path
    sys.path = old_path + [site_packages]
    try:
        import pytest
    finally:
        sys.path = old_path

class Collector(object):
    def __init__(self, send):
        self.send = send

    def extract_trace(self, excinfo):
        """:type excinfo: py._code.code.ReprExceptionInfo"""

        result = []
        for entry in excinfo.reprtraceback.reprentries:
            result.append((entry.reprfileloc.path, entry.reprfileloc.lineno))

        return result

    def extract_output(self, report):
        result = str(report.longrepr)
        for s, d in report.sections:
            result += '\n\n===================== ' + s + '=======================\n' + d

        return result

    def pytest_runtest_logreport(self, report):
        """:type report: _pytest.runner.TestReport()"""

        if report.when != 'call':
            return

        if report.passed:
            self.send(('PASS', report.nodeid))
        elif report.failed:
            if report.when != "call":
                self.send(('ERROR', report.nodeid, self.extract_output(report),
                    self.extract_trace(report.longrepr)))
            else:
                self.send(('FAIL', report.nodeid, self.extract_output(report),
                    self.extract_trace(report.longrepr)))
        elif report.skipped:
            self.send(('SKIP', report.nodeid))

    def pytest_runtest_call(self, item):
        self.send(('ITEM_CALL', item.nodeid))

    def pytest_collectreport(self, report):
        """:type report: _pytest.runner.CollectReport()"""
        if report.failed:
            self.send(('FAILED_COLLECT', report.nodeid, self.extract_output(report),
                self.extract_trace(report.longrepr)))

    def pytest_internalerror(self, excrepr):
        self.send(('INTERNAL_ERROR', excrepr))

    def pytest_sessionstart(self, session):
        self.send(('START', str(session.fspath)))

    def pytest_sessionfinish(self, session, exitstatus):
        self.send(('END', ))

    def pytest_collection_finish(self, session):
        self.send(('COLLECTED_TESTS', [t.nodeid for t in session.items]))

#class Collector(object):
#    def __init__(self, *args, **kwargs):
#        self.f = open('/tmp/result.txt', 'w')
#
#    def __getattr__(self, name):
#        if not name.startswith('pytest_'):
#            raise AttributeError(name)
#
#        from _pytest import hookspec
#        import inspect
#
#        space = {'f':self.f}
#        exec 'def {0}{1}:\n    print >>f, "{0}{1}", locals()'.format(
#            name, inspect.formatargspec(*inspect.getargspec(getattr(hookspec, name)))) in space
#
#        return space[name]

if __name__ == '__main__':
    from multiprocessing.connection import Listener
    listener = Listener(sys.argv[1])
    conn = listener.accept()

    if sys.version_info[0] == 3:
        from pickle import dumps
        def sender(data):
            return conn.send_bytes(dumps(data, 2))
    else:
        sender = conn.send

    pytest.main(sys.argv[2:], plugins=[Collector(sender)])


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon Apr 12 11:24:01 2021

@author: aidan
"""
import numpy as np
import matplotlib
from matplotlib import pyplot as plt

import Ofpp
from os.path import basename, realpath, exists
from scipy import interpolate

REarth=6371000
G=6.673e-11
MEarth=5.972e24

def findInd(Param, LatArr,LatGoal):
    targInd=0
    for i in range(len(LatArr)):
        if(np.abs(LatArr[targInd]-LatGoal)>=np.abs(LatArr[i]-LatGoal)):
            targInd=i
    return targInd

class OrbitParam(object):
    """
    Takes orbital parameters as input and outputs atmospheric parameters
    currently designed for Phi,Theta, Ecc=0, and varying RE
    RE: height above surface in metres (input in km)
    Ecc:eccentricity
    Phi:angle away from being in plane with daynight boundary (check word for this)
    Theta:Angle in plane
    (need to check real words for these, but theta is the angle specifying progress through orbit, phi is the angle of the orbit all orbits pass over poles)

    """

    def __init__(self,RE=0,Theta=0,Ecc=0,Phi=0):
        if RE==0:
            RE=input('please specify the height above the surface of earth in m:')
        else:
            self.RE=RE*1000
        self.Theta=Theta
        self.Ecc=Ecc
        self.Phi=Phi
        # CalcVel()

    def CalcVel(self, Height=None):
        """
        calculates velocity relative to the earth (currently perpendicular velocity)
        currently uses basic orbital velocity formula
        """
        if Height==None:
            Rtot=self.RE+REarth
        else:
            Rtot=(Height*1000)+REarth
        VelPerp=np.sqrt(G*MEarth)*1/np.sqrt(Rtot)
        self.VelPerp=VelPerp
        # print('perpendicular velocity: '+str(VelPerp)+' (m/s)')
        return VelPerp

    def CalcVeLat(self, Lat):
        """
        calculates velocity relative to the earths atmosphere for SSO
        """
        Rtot=self.RE+REarth
        VelPerp=(np.sqrt(G*MEarth)*1/np.sqrt(Rtot))
        VeLat=(2*np.pi*Rtot/86400*np.cos(np.radians(Lat)))
        # print(VelPerp)
        # print(VeLat)
        VeRel=(np.sqrt(VelPerp**2+VeLat**2))
        self.VelPerp=VelPerp
        # print('perpendicular velocity: '+str(VelPerp)+' (m/s)')
        return VeRel

    def LoadDataMSIS(self,filename):
        self.__dict__['MSISFname']=filename
        Dat=readMSISFile(filename)
        dataNames=['height','RhoO',"RhoN2","RhoO2","RhoMass","Tn","RhoHe","RhoAr","RhoH","RhoN"]
        for i in range(len(Dat)):
            rawName=dataNames[i]
            self.__dict__[rawName]=Dat[i]

    def getParam(self, param=None,TargHeight=None):#interpolates parameter from array at given height
        if param==None:
            param=input('enter param to be output:')
        height=self.__dict__['height']

        targ=self.__dict__[param]
        tck = interpolate.splrep(height, targ, s=1)
        if TargHeight==None:
            PH=interpolate.splev((self.RE/1000),tck,der=0)
        else:
            PH=interpolate.splev((TargHeight),tck,der=0)

        print('interpolated '+param+' succesfully')
        return PH

    def CalcRhoTot(self):#returns total number density of particles
        RhoNames=['RhoO',"RhoN2","RhoO2","RhoHe","RhoAr","RhoH","RhoN"]
        RhoTot=[]
        for i in range(len(self.__dict__['RhoO'])):
            RhoTot.append(0)
            for nam in RhoNames:
                RhoTot[i]=RhoTot[i]+self.__dict__[nam][i]*1e6
        self.__dict__['RhoTot']=RhoTot
        return RhoTot

    def OutputParams(self):
        Vel=self.CalcVel()
        RhO=self.getParam('RhoO')*1e6
        RhN2=self.getParam('RhoN2')*1e6
        RhO2=self.getParam('RhoO2')*1e6
        RhM=self.getParam('RhoMass')*1e3
        Tn=self.getParam('Tn')
        RhHe=self.getParam('RhoHe')*1e6
        RhAr=self.getParam('RhoAr')*1e6
        RhH=self.getParam('RhoH')*1e6
        RhN=self.getParam('RhoN')*1e6
        print(" ")
        print('   __________________Ionosphere Parameters_____________________')
        print('At a height of '+str(self.__dict__['RE']/1000)+' km, parameters as extracted from MSIS file '+self.__dict__['MSISFname']+" ")
        print("Mass density: "+str(RhM)+' '+'{:.4e}'.format(RhM)+" (kg/m^3) with number density: "+'{:.3e}'.format(np.sum([RhO,RhN2,RhO2,RhM,RhHe,RhAr,RhH,RhN]))+" (1/m^3)")
        print('Perpendicular velocity: '+'{:.3e}'.format(Vel)+' (m/s) (calculated for spherical orbit only)')
        print('Neutral Temperature: '+'{:.3e}'.format(Tn))
        print('_________ Density of Ions ________')
        print('O:'+'{:.3e}'.format(RhO)+'      N2:'+'{:.3e}'.format(RhN2)+'       O2:'+'{:.3e}'.format(RhO2))
        print('He: '+'{:.3e}'.format(RhHe)+'  Ar:'+'{:.3e}'.format(RhAr)+'  H:'+'{:.3e}'.format(RhH)+'   N:'+'{:.3e}'.format(RhN))
        print('Ion densities in 1/m^3')
        print('mass interpolation currently broken, as is ion number density below 90km for H,N,O ')

    def WriteFile(self,fname, Harray): #prints file of rows of variables for bash script to run
        writeSwag=open(fname, "w+")
        VariablesArray=['RhoO', 'RhoN2', 'RhoO2',  'Tn', 'RhoHe', 'RhoAr', 'RhoH', 'RhoN']
        VarString='Heights: '
        for Hval in Harray:
            VarString=VarString+str(Hval)+' '
        writeSwag.write(VarString+' \n')
        print(VarString)

        for VarKey in VariablesArray:
            VarString=VarKey+' '
            for Hval in Harray:
                print(VarKey)
                print(Hval)
                VarString=VarString+' '+'{:.3e}'.format(self.getParam(VarKey,Hval)*1e6)
            print(VarString)
            writeSwag.write(VarString+' \n')
        VarString=' RhoNum: '
        for Hval in Harray:
            VarString=VarString+' '+'{:.2e}'.format(self.FindN(Hval,5e3))
        writeSwag.write(VarString+' \n')

    def WriteFileLat(self,fname, LArray): #prints file of rows of variables for bash script to run
        writeSwag=open(fname, "w+")
        VariablesArray=['RhoO', 'RhoN2', 'RhoO2',   'RhoHe', 'RhoAr', 'RhoH', 'RhoN']
        VarString='latitudes: '
        for Hval in LArray:
            VarString=VarString+str((Hval))+' '
        writeSwag.write(VarString+' \n')
        print(VarString)
        VarString='Tn: '
        for Hval in LArray:
            VarString=VarString+' '+'{:.3e}'.format(self.getParam('Tn',Hval))
        writeSwag.write(VarString+' \n')

        for VarKey in VariablesArray:
            VarString=VarKey+' '
            for Hval in LArray:
                print(VarKey)
                print(Hval)
                VarString=VarString+' '+'{:.3e}'.format(self.getParam(VarKey,Hval)*1e6)
            print(VarString)
            writeSwag.write(VarString+' \n')
        VarString=' NEquivs: '
        for Hval in LArray:
            VarString=VarString+' '+'{:.2e}'.format(self.FindN(Hval,5e3))
        writeSwag.write(VarString+' \n')
        VarString='RelSpeeds: '
        for LVal in LArray:
            VarString=VarString+' '+'{:.2e}'.format(self.CalcVeLat(LVal))
        writeSwag.write(VarString+' \n')

    def FindN(self,Height, NGoal=None):#calculates total number density per cubic metre from component ions, adjusts nequiv to suit
        if NGoal==None:
            NGoal=5e3
        RhO=self.getParam('RhoO',Height)*1e6
        RhN2=self.getParam('RhoN2',Height)*1e6
        RhO2=self.getParam('RhoO2',Height)*1e6
        RhHe=self.getParam('RhoHe',Height)*1e6
        RhAr=self.getParam('RhoAr',Height)*1e6
        RhH=self.getParam('RhoH',Height)*1e6
        RhN=self.getParam('RhoN',Height)*1e6
        totN=np.sum([RhO,RhN2,RhO2,RhHe,RhAr,RhH,RhN])

        NEquiv=NGoal*totN/1e11
        return NEquiv

def readMSISFile(filename=None):#reads a height dependent MSIS file
    """
    Reads from MSIS files from https://ccmc.gsfc.nasa.gov/cgi-bin/modelweb/models/vitmo_model.cgi

    Parameters
    ----------
    filename : string, optional

    Returns
    -------
    DatArray : TYPE
        contains list of height(or other independent variable), density of O,N2,O2,Mass, temperature, density of He,Ar,H,N.
    density in units of number per cm^3, except mass density (g/cm^3), height in km, and T in K

    """
    if filename==None:
        filename=input('input file to read data from: ')
    try:
        logfile=str(filename)
        infile = open(logfile, 'r')
    except:
        print('no MSIS file in '+filename)
    if True:
        indVar=[]
        RhoO=[]
        RhoN2=[]
        RhoO2=[]
        RhoMass=[]
        Tn=[]
        RhoHe=[]
        RhoAr=[]
        RhoH=[]
        RhoN=[]
    DatArray=[indVar,RhoO,RhoN2,RhoO2,RhoMass,Tn,RhoHe,RhoAr,RhoH,RhoN]

    for line in infile:
        SL1=line.strip().split('  ')#getting around weirdness of the file printing
        #fudging a missing space in the line
        splitline=[SL1[0],SL1[1],SL1[2],SL1[3].split(' ')[0],SL1[3].split(' ')[1],SL1[4],SL1[5],SL1[6],SL1[7],SL1[8]]

        for i in range(len(DatArray)):
            DatArray[i].append(float(splitline[i]))

    return DatArray

def HInterp(Height=None, TargDat=None,heightFac=None,S=0,d=0):#takes height and target data as input, returns array of new height and interpolated data
   #HeightFac is the fineness factor, how many new points are included between each data point, S is the smoothing (usually 0)
    if(Height==None):
        print("No height data given to HInterp")
    if TargDat==None:
        print("no data to interpolate")

    tck = interpolate.splrep(Height, TargDat, s=S)#interpolation

    Hnew=np.linspace(Height[0],Height[len(Height)-1],len(Height)*heightFac)#new array to extrapolate to
    ynew = interpolate.splev(Hnew, tck, der=d)

    return [Hnew,ynew]

def CombineLatFiles(File1,File2, FileFinalName):
    """
    Parameters
    ----------
    File1 : Lat dep MSISE file, starting from South pole at -90 degrees.
    File2 : Lat dep MSISE file, be ending at north pole at 360 degrees.
    FileFinalName : File to be written to.
    Returns
    -------
    prints a File to FileFinalName, containing the latitude dependent data from files 1 and 2
    Takes two files running from -90 to 90, and returns one, starting at 0 (north pole), with the data from File1, and continuing around to 360 degrees
    """
    try:
        # print(File1)
        logfile=str(File1)
        infile = open(logfile, 'r')
    except:
        print('no MSIS file in '+File1)
    LatArr=[]
    DatArr=[]
    L2Arr=[]
    DatArr2=[]
    for line in infile:
        SL1=line.strip().split('  ')
        LatArr.append(SL1[0])
        # print(SL1)
        splitline=[SL1[1],SL1[2],SL1[3].split(' ')[0],SL1[3].split(' ')[1],SL1[4],SL1[5],SL1[6],SL1[7],SL1[8]]
        DatArr.append(splitline)
    infile.close()

    try:
        logfile=str(File2)
        infile = open(logfile, 'r')
    except:
        print('no MSIS file in '+File2)
    for line in infile:
        SL1=line.strip().split('  ')
        L2Arr.append(SL1[0])
        splitline=[SL1[1],SL1[2],SL1[3].split(' ')[0],SL1[3].split(' ')[1],SL1[4],SL1[5],SL1[6],SL1[7],SL1[8]]
        DatArr2.append(splitline)
    infile.close()

    writeSwag=open(FileFinalName, "w+")
    LatFake=np.linspace(0,180,181)
    for i in range(len(LatFake)):
        splitline=DatArr[len(LatFake)-i-1]
        for j in [0,1,3,4,5,6,7,8]:
            splitline[j]=splitline[j]+' '#FUDGEFUDGEFUDGE #adding the right amount of spaces to mimic the MSISE files
        NewString='  '+str(LatFake[i])+"  "
        for dat in splitline:
            NewString=NewString+dat+' '
        NewString=NewString+'\n'
        writeSwag.write(NewString)

    LatFake2=np.linspace(181,360,(len(DatArr2)-1))
    for i in range(len(LatFake2)):

        splitline=DatArr2[i+1]
        for j in [0,1,3,4,5,6,7,8]:
            splitline[j]=splitline[j]+' '#FUDGEFUDGEFUDGE #adding the right amount of spaces to mimic the MSISE files
        NewString='  '+str(LatFake2[i])+"  "
        for dat in splitline:
            NewString=NewString+dat+' '
        NewString=NewString+'\n'
        writeSwag.write(NewString)
    writeSwag.close()

def test1():
    fname='/home/aidan/Documents/IonSpeciesFiles/IonSpeciesFileFine'
    swaggy=OrbitParam(300,0,0,0)
    swaggy.CalcVel()
    print(swaggy.__dict__)
    FDat1=readMSISFile(fname)
    densIndex=[1,2,3,6,7,8,9]#index of the density files
    dataNames=['height (km)','r/$ \rho $ O',"RhoN2","RhoO2","RhoMass","Tn","RhoHe","RhoAr","RhoH","RhoN"]
    datType=['-','--','-','-','-','-','-','-','--','--']

    fig1=plt.figure()
    for ind in densIndex:
        plt.plot(FDat1[0],FDat1[ind],datType[ind],linewidth=0.8,label=dataNames[ind])
    plt.yscale('log')
    plt.ylabel('Density (1/cm^3)')
    plt.title("Species density")
    plt.xlabel('Height (km)')
    plt.legend()
    plt.show()

    fig2=plt.figure()
    plt.plot(FDat1[0],FDat1[5])
    plt.yscale('log')
    plt.ylabel('T(K)')
    plt.xlabel('Height (km)')
    plt.show()

    fig3=plt.figure()
    plt.plot(FDat1[0],FDat1[4])
    plt.yscale('log')
    plt.ylabel('Mass density(g/cm^3)')
    plt.xlabel('Height (km)')
    plt.show()

def test2():#testing interpolation for various values of interpolation parameters
    fname='/home/aidan/Documents/IonSpeciesFiles/IonSpeciesFile'
    swaggy=OrbitParam(300,0,0,0)
    swaggy.CalcVel()
    print(swaggy.__dict__)
    swaggy.LoadDataMSIS(fname)
    print(swaggy.__dict__.keys())
    height=swaggy.__dict__['height']
    TargName='Tn'
    Targ=swaggy.__dict__[TargName]

    fig4=plt.figure()
    # HInterp(height,Tn,HFac,0)
    plt.plot(height,Targ,label='Raw Data')
    for Sc in [1,40]:
        for S in [0,1,2,10]:
            intDat=HInterp(height,Targ,Sc,S,0)
            plt.plot(intDat[0], intDat[1],label='Sc,S:'+str(Sc)+','+str(S),linewidth=0.4)
        # for S in [0,1]
    plt.xlim([20,60])
    plt.ylim([150,300])
    plt.xlabel('height')
    plt.ylabel(TargName)
    # plt.yscale('log')
    plt.legend()
    plt.title('Interpolation test')

def test3():#plot of longitude in degrees
    fname='/home/aidan/Documents/IonSpeciesFiles/IonSpeciesFileFine'
    swaggy=OrbitParam(300,0,0,0)
    swaggy.CalcVel()
    print(swaggy.__dict__)
    FDat1=readMSISFile(fname)
    densIndex=[1,2,3,6,7,8,9]#index of the density files

    IndVarName='height (m)'

    dataNames=[IndVarName,'RhoO',"RhoN2","RhoO2","RhoMass","Tn","RhoHe","RhoAr","RhoH","RhoN"]
    latt=[(a) for a in FDat1[0]]
    IndVar=latt
    fig1=plt.figure()
    for ind in densIndex:
        plt.plot(IndVar,FDat1[ind],linewidth=0.8,label=dataNames[ind])
    plt.yscale('log')
    plt.ylabel('Density (1/cm^3)')
    plt.xlabel(IndVarName)
    plt.title('Ion species by '+IndVarName)
    plt.legend()
    plt.show()

    intT=HInterp(IndVar,FDat1[5],1)
    fig2=plt.figure()
    plt.plot(IndVar,FDat1[5])
    plt.plot(intT[0],intT[1])
    plt.yscale('log')
    plt.ylabel('T(K)')
    plt.xlabel(IndVarName)
    plt.title("Temperature by "+IndVarName)
    plt.show()

    intM=HInterp(IndVar,FDat1[5],1)

    fig3=plt.figure()
    plt.plot(IndVar,FDat1[4])
    plt.plot(intM[0],intM[1])
    plt.yscale('log')
    plt.ylabel('Mass density(g/cm^3)')
    plt.title('Mass density by '+IndVarName)
    plt.xlabel(IndVarName)
    plt.show()

def test4():#combines two opposing latitude files along same axis
    fname='/home/aidan/Documents/IonSpeciesFiles/IonSpeciesLatDep1'
    fname2='/home/aidan/Documents/IonSpeciesFiles/IonSpeciesLatDep2'

    swaggy=OrbitParam(300,0,0,0)
    swaggy.CalcVel()
    print(swaggy.__dict__)
    FDat2=readMSISFile(fname)
    FDat3=readMSISFile(fname2)
    FDat1=[]

    for i in range(len(FDat2)):
        CombEntry=[]
        for j in range(len(FDat2[i])):
            CombEntry.append(FDat2[i][j])
        for j in range(len(FDat3[i])):
            CombEntry.append(FDat3[i][len(FDat3[i])-j-1])
        FDat1.append(CombEntry)

    densIndex=[1,2,3,6,7,8,9]#index of the density files

    IndVarName='latitude(deg)'

    dataNames=[IndVarName,'RhoO',"RhoN2","RhoO2","RhoMass","Tn","RhoHe","RhoAr","RhoH","RhoN"]
    latt=[(a+90) for a in FDat1[0]]
    IndVar=latt
    fig1=plt.figure()
    for ind in densIndex:
        plt.plot(IndVar,FDat1[ind],linewidth=0.8,label=dataNames[ind])
    plt.yscale('log')
    plt.ylabel('Density (1/cm^3)')
    plt.xlabel(IndVarName)
    plt.title('Ion species by '+IndVarName)
    plt.legend()
    plt.show()

    fig2=plt.figure()
    plt.plot(IndVar,FDat1[5])
    # plt.yscale('log')
    plt.ylabel('T(K)')
    plt.xlabel(IndVarName)
    plt.title("Temperature by "+IndVarName)
    plt.show()

    fig3=plt.figure()
    plt.plot(IndVar,FDat1[4])
    # plt.yscale('log')
    plt.ylabel('Mass density(g/cm^3)')
    plt.title('Mass density by '+IndVarName)
    plt.xlabel(IndVarName)
    plt.show()

def HTest(height):#tests output of parameters
    fname='/home/aidan/Documents/IonSpeciesFiles/IonSpeciesFileFine'
    swaggy=OrbitParam(height,0,0,0)
    swaggy.LoadDataMSIS(fname)
    print(swaggy.__dict__.keys())
    swaggy.CalcVel()
    swaggy.OutputParams()

def HTest2(heights):#outputs velocity for array of input heights
    fname='/home/aidan/Documents/IonSpeciesFiles/IonSpeciesFileFine'
    swaggy=OrbitParam(400,0,0,0)
    swaggy.LoadDataMSIS(fname)
    print(swaggy.__dict__.keys())
    for h in heights:
        print('height: '+str(h)+' V:'+str(swaggy.CalcVel(h)))
    swaggy.CalcVel()
    swaggy.OutputParams()

def test6():#checking interpolations of values for low numbers

    fname='/home/aidan/Documents/IonSpeciesFiles/IonSpeciesLatDepCombi_Long270H500'
    swaggy=OrbitParam(300,0,0,0)
    swaggy.CalcVel()
    print(swaggy.__dict__)
    FDat1=readMSISFile(fname)
    densIndex=[1,2,3,6,7,8,9]#index of the density files

    IndVarName='height (m)'

    dataNames=[IndVarName,'RhoO',"RhoN2","RhoO2","RhoMass","Tn","RhoHe","RhoAr","RhoH","RhoN"]
    latt=[(a) for a in FDat1[0]]
    IndVar=latt
    fig1=plt.figure()
    for ind in densIndex:
        intIon=HInterp(IndVar,FDat1[ind],2)
        plt.plot(intIon[0],intIon[1],'--')
        plt.plot(IndVar,FDat1[ind],linewidth=0.8,label=dataNames[ind])
    plt.yscale('log')
    plt.ylabel('Density (1/cm^3)')
    plt.xlabel(IndVarName)
    plt.title('Ion species by '+IndVarName)
    plt.legend()
    plt.show()

    intT=HInterp(IndVar,FDat1[5],2)
    fig2=plt.figure()
    plt.plot(IndVar,FDat1[5])
    plt.plot(intT[0],intT[1])
    plt.yscale('log')
    plt.ylabel('T(K)')
    plt.xlabel(IndVarName)
    plt.title("Temperature by "+IndVarName)
    plt.show()

    intM=HInterp(IndVar,FDat1[5],1)
    fig3=plt.figure()
    plt.plot(IndVar,FDat1[4])
    plt.plot(intM[0],intM[1])
    plt.yscale('log')
    plt.ylabel('Mass density(g/cm^3)')
    plt.title('Mass density by '+IndVarName)
    plt.xlabel(IndVarName)
    plt.show()

def FilePrint(HArr,fileIn=None,fileOut=None):#tests output of parameters
    if fileIn==None:

        fname='/home/aidan/Documents/IonSpeciesFiles/IonSpeciesFileFine'
    else:
        fname=fileIn
    swaggy=OrbitParam(HArr[0],0,0,0)
    swaggy.LoadDataMSIS(fname)
    print(swaggy.__dict__.keys())
    swaggy.CalcVel()
    swaggy.OutputParams()
    if fileOut==None:
        swaggy.WriteFile('/home/aidan/Documents/IonSpeciesFiles/FileWriteTest', HArr)
    else:
        swaggy.WriteFile(fileOut, HArr)

def SSOOrbitTest(fname,Height,Lats):#takes input of file, height, and latitudes, and writes to a file the appropriate parameters
    swaggy=OrbitParam(Height,0,0,0)
    swaggy.LoadDataMSIS(fname)
    swaggy.CalcRhoTot()
    # plt.plot(swaggy.height,swaggy.RhoTot)
    # plt.title("Number Density SSO")
    # plt.xlabel('')
    swaggy.WriteFileLat('/home/aidan/Documents/IonSpeciesFiles/ParamFileLatDepSSO2',Lats)
    # for L in Lats:
    #     print("Latitude: "+str(L)+"  Tn:"+str(swaggy.getParam("Tn",L)))

def LatCombiTest(FLat1,FLat2,FLat3,RName=' ',Bool=False):#combines two lat dependent files.

       CombineLatFiles(FLat1,FLat2,FLat3)
       # readMSISFile(FLat3)

       fname=FLat3
       swaggy=OrbitParam(500,0,0,0)
       swaggy.CalcVel()
       print(swaggy.__dict__)
       FDat1=readMSISFile(fname)
       densIndex=[1,2,3,6,7,8,9]#index of the density files

       IndVarName='Latitude (degrees)'

       dataNames=[IndVarName,'RhoO',"RhoN2","RhoO2","RhoMass","Tn","RhoHe","RhoAr","RhoH","RhoN"]

       if Bool:
           FDat=[]
           l1=np.linspace(0,180,181)
           l2=np.linspace(180,1,180)

           for i in range(len(l1)):
               FDat.append(l1[i])
           for i in range(len(l2)):
               FDat.append(l2[i])

           latt=[(a) for a in FDat]
       else:
           latt=[(a) for a in FDat1[0]]

       IndVar=latt
       fig1=plt.figure()
       for ind in densIndex:
           plt.plot(IndVar,FDat1[ind],linewidth=0.8,label=dataNames[ind])

       plt.yscale('log')
       plt.ylabel('Density (1/cm^3)')
       plt.xlabel(IndVarName)
       plt.title('Ion species by '+IndVarName+' '+RName)
       plt.legend()
       plt.show()

       intT=HInterp(IndVar,FDat1[5],1)
       fig2=plt.figure()
       plt.plot(IndVar,FDat1[5])
       plt.plot(intT[0],intT[1])
       plt.yscale('log')
       plt.ylabel('T(K)')
       plt.xlabel(IndVarName)
       plt.title("Temperature by "+IndVarName+' '+RName)
       plt.show()

       intM=HInterp(IndVar,FDat1[5],1)

       fig3=plt.figure()
       plt.plot(IndVar,FDat1[4])
       # plt.plot(intM[0],intM[1])
       plt.yscale('log')
       plt.ylabel('Mass density(g/cm^3)')
       plt.title('Mass density by '+IndVarName+' '+RName)
       plt.xlabel(IndVarName)
       plt.show()

def LatCompare(FLat1,FLat2,RName=' ', Bool=False):#takes two lat dependent files, circling an area, and plots the difference.
    FDat2=readMSISFile(FLat1)
    FDat3=readMSISFile(FLat2)
    if Bool:
        FDat=[]
        l1=np.linspace(0,180,181)
        l2=np.linspace(180,1,180)

        for i in range(len(l1)):
            FDat.append(l1[i])
        for i in range(len(l2)):
            FDat.append(l2[i])

        latt=[(a) for a in FDat]
    else:
        latt=[(a) for a in FDat2[0]]
    FDat1=[]
    for i in range(len(FDat2)):
        tempF=[]
        for j in range(len(FDat2[i])):
            tempF.append(FDat2[i][j]-FDat3[i][j])
        FDat1.append(tempF)

    densIndex=[1,2,3,6,7,8,9]#index of the density files

    IndVarName='Latitude (degrees)'
    dataNames=[IndVarName,'RhoO',"RhoN2","RhoO2","RhoMass","Tn","RhoHe","RhoAr","RhoH","RhoN"]

    IndVar=latt
    fig1=plt.figure()
    for ind in densIndex:
        plt.plot(IndVar,FDat1[ind],linewidth=0.8,label=dataNames[ind])

    # plt.yscale('log')
    plt.ylabel('Density (1/cm^3)')
    plt.xlabel(IndVarName)
    plt.title('Ion species Difference by '+IndVarName+' '+RName)
    plt.legend()
    plt.show()

    intT=HInterp(IndVar,FDat1[5],1)
    fig2=plt.figure()
    plt.plot(IndVar,FDat1[5])
    plt.plot(intT[0],intT[1])
    # plt.yscale('log')
    plt.ylabel('T(K)')
    plt.xlabel(IndVarName)
    plt.title("Temperature Difference by "+IndVarName+' '+RName)
    plt.show()

    intM=HInterp(IndVar,FDat1[5],1)

    fig3=plt.figure()
    plt.plot(IndVar,FDat1[4])
       # plt.plot(intM[0],intM[1])
    # plt.yscale('log')
    plt.ylabel('Mass density(g/cm^3)')
    plt.title('Mass density Difference by '+IndVarName+' '+RName)
    plt.xlabel(IndVarName)
    plt.show()

def test7(fname,Height,Lats): #tests output of mass density file
    swaggy=OrbitParam(Height,0,0,0)
    swaggy.LoadDataMSIS(fname)
    swaggy.CalcRhoTot()
    MassInd=[]
    for lat in Lats:
        MassInd.append(swaggy.__dict__['RhoMass'][findInd(swaggy.__dict__['RhoMass'],swaggy.height,lat)])
    print(MassInd)
    plt.plot(swaggy.height,swaggy.RhoMass)

def LatPlot(FLat1,Indices=[0]):#plots parameters by latitude from file
    FDat1=readMSISFile(FLat1)
    latt=[(a) for a in FDat1[0]]
    densIndex=[1,2,3,6,7,8,9]#index of the density files

    IndVarName='Angle(degrees)'#'Latitude (degrees)'
    dataNames=[IndVarName,'RhoO',"RhoN2","RhoO2","RhoMass","Tn","RhoHe","RhoAr","RhoH","RhoN"]
    IonRatio=[]
    for i in range(len(FDat1[1])):
        IonRatio.append((FDat1[1][i]+FDat1[6][i]+FDat1[7][i]+FDat1[8][i]+FDat1[9][i])/(FDat1[2][i]+FDat1[3][i]))
    IndVar=latt
    # fig1=plt.figure()
    fig1, axs1=plt.subplots()
    axs1.set_xticks([0, 30,60,90,120,150,180,210,240,270,300,330,360], minor=False)
    axs1.xaxis.grid(True, which='major',linestyle='--',alpha=0.5)
    for ind in densIndex:
        plt.plot(IndVar,FDat1[ind],linewidth=0.8,label=dataNames[ind])

    plt.yscale('log')
    plt.ylabel('Density (1/cm^3)')
    plt.xlabel(IndVarName)
    plt.title('Ion species by Latitude')
    plt.legend()
    plt.show()

    fig4,axs=plt.subplots()
    plt.plot(IndVar,IonRatio)
    # plt.yscale('log')
    axs.set_xticks([0, 30,60,90,120,150,180,210,240,270,300,330,360], minor=False)
    axs.xaxis.grid(True, which='major',linestyle='--',alpha=0.5)
    plt.ylabel('Ni/Nn')
    plt.xlabel(IndVarName)
    plt.title("Relative Ion Density by Latitude")
    plt.show()

    intT=HInterp(IndVar,FDat1[5],1)
    # fig2=plt.figure()
    fig2,axs=plt.subplots()
    plt.plot(IndVar,FDat1[5])
    plt.plot(intT[0],intT[1])
    # plt.yscale('log')
    axs.set_xticks([0, 30,60,90,120,150,180,210,240,270,300,330,360], minor=False)
    axs.xaxis.grid(True, which='major',linestyle='--',alpha=0.5)
    plt.ylabel('T(K)')
    plt.xlabel(IndVarName)
    plt.title("Temperature by Latitude")
    plt.show()

    intM=HInterp(IndVar,FDat1[5],1)

    # fig3=plt.figure()
    fig3,ax=plt.subplots()
    plt.plot(IndVar,FDat1[4])
    ax.set_xticks([0, 30,60,90,120,150,180,210,240,270,300,330,360], minor=False)
    ax.xaxis.grid(True, which='major',linestyle='--',alpha=0.5)
    plt.ylabel('Mass density(g/cm^3)')
    plt.title('Mass density Through SSO')
    plt.xlabel(IndVarName)
    plt.show()

# test1()
# test2()
# test3()
# test4()

# HTest(400)
# test6()
# FilePrint([300,320,340,360,380,400])
fname1='/home/aidan/Documents/IonSpeciesFiles/IonSpeciesLatDep_Long270_H500'
FLat1='/home/aidan/Documents/IonSpeciesFiles/IonSpeciesLatDep_Long90_H500'
FLat2='/home/aidan/Documents/IonSpeciesFiles/IonSpeciesLatDep_Long270_H500'
FLat3='/home/aidan/Documents/IonSpeciesFiles/IonSpeciesLatDepCombi_Long270H500'

FLat4='/home/aidan/Documents/IonSpeciesFiles/ISLatDep_L0H500'
FLat5='/home/aidan/Documents/IonSpeciesFiles/ISLatDep_L180H500'
FLat6='/home/aidan/Documents/IonSpeciesFiles/ISLatDep_Combi_L0H500'
FH1='/home/aidan/Documents/IonSpeciesFiles/IonSpeciesFileFine'

# HTest2([100,500])
# SSOOrbitTest(FLat3,500,[270,240,210,180,120,150])
# LatCombiTest(FLat1,FLat2,FLat3, 'SSO')
# LatCombiTest(FLat4,FLat5,FLat6, "0-180")
# LatCompare(FLat3,FLat6)
# test6()
# test7(FLat3,500,[0,30,60,90,120,150,180,210,240,270,300,330])
# SSOOrbitTest(FLat3,500,[0,30,60,90,120,150,180,210,240,270,300,330])
LatPlot(FLat3,'Angle')

# test1()


#! /bin/env python
#

from argparse import ArgumentParser, FileType
from collections import defaultdict

HEADERS = ("operation", "key")

class LazyOpener(dict):

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        for stream in self.values():
            stream.close()
        self.clear()

    def __missing__(self, key):
        self[key] = open(key ,'w')
        # print(','.join(HEADERS), file=self[key])
        return self[key]

def partname(filename, index):
    try:
        filename, suffix = filename.rsplit('.', 1)
    except ValueError:
        return "%s-%i" % (filename, index)
    return "%s-%i.%s" % (filename, index, suffix)

def _main(source, count):
    files = {partname(source.name, i): 0 for i in range(count)}
    key2file = defaultdict(lambda : min(files, key=lambda x: files[x]))
    with LazyOpener() as streams:
        for line in source:
            operation, key, _ = line.split(',')
            _file = key2file[key]
            print(','.join((operation, key)), file=streams[_file])
            files[_file] += 1

def main(args):
    for stream in args.path:
        stream.readline()
        _main(stream, args.count)

def parser():
    _parser = ArgumentParser()
    _parser.add_argument("path", nargs='+', type=FileType('r'))
    _parser.add_argument("count", type=int)
    return _parser

if __name__ == "__main__":
    main(parser().parse_args())


import TranslationAndCleaning
import pandas as pd
import statsmodels.api as sm
import matplotlib.pyplot as plt
from statsmodels.formula.api import ols

data = TranslationAndCleaning.data.reset_index()

# ------------------------
# Define used column names
# ------------------------
cluster_vars = ['person', 'household_id', 'home_id', 'conglomerado', 'city']

indep_vars = ['sex', 'age', 'income_pc', 'poverty', 'has_received_free_school_uniform']
dep_vars = ['level_of_education']

# Is this a numerical proxy for level of education? Perhaps better to use the level directly.

# ---------------------------------------
# Study Completeness for Different Models
# ---------------------------------------

# Count per-variable completeness.
#  Note: level_of_education is 92% complete, years of schooling only 47.6%.
#  Note: has_received_free_school_uniform is 11.48% complete.
#  Note: All other variables are >99% complete.
#  Note: Missingness in income_pc seems to correspond precisely with missingness in poverty.
total_entries = data.shape[0]
for var in dep_vars + indep_vars + ['level_of_education']:
    complete_entries = data[var].dropna().shape[0]
    print("missing values for " + var, ":", total_entries - complete_entries, "/", total_entries, "|| Completeness",
          100 * complete_entries / total_entries, "%")

# Count completeness by complete series using these data
model_1_vars = dep_vars + indep_vars
print("Completeness for " + ", ".join(model_1_vars) + ":",
      1 - data[model_1_vars].notnull().all(axis=1).value_counts()[False] / total_entries)
# 0% complete.

model_2_vars = ['level_of_education'] + indep_vars
print("Completeness for " + ", ".join(model_2_vars) + ":",
      1 - data[model_2_vars].notnull().all(axis=1).value_counts()[False] / total_entries)
# Exchange years of schooling for level of education: 11% complete.

model_3_vars = ['level_of_education'] + indep_vars
model_3_vars.remove('has_received_free_school_uniform')
print("Completeness for " + ", ".join(model_3_vars) + ":",
      1 - data[model_3_vars].notnull().all(axis=1).value_counts()[False] / total_entries)
# Exchange years of schooling for level of education & remove has_received_free_school_uniform: 91% complete.
# Completeness is 99% without level of education\.

model_4_vars = ['level_of_education'] + indep_vars
model_4_vars.remove('has_received_free_school_uniform')
model_4_assumptions = data['age'] > 4
print("Completeness for " + ", ".join(model_4_vars) + ":",
      1 - data.loc[model_4_assumptions, model_4_vars].notnull().all(axis=1).value_counts()[False] / total_entries)
print("Assumption: age > 4")

total_entries_filt = data.loc[model_4_assumptions, :].shape[0]
for var in model_4_vars:
    complete_entries = data.loc[model_4_assumptions, var].dropna().shape[0]
    print("missing values for " + var, ":", total_entries_filt - complete_entries, "/", total_entries_filt,
          "|| Completeness", 100 * complete_entries / total_entries_filt, "%")
# 0% is missing in level of education, sex, and age.
# 1.11% is missing in income_pc, poverty

# -----------------------------------------
# Study Completeness for Level of Education
# -----------------------------------------
data['missing_level_of_education'] = [1 if pd.isnull(x) else 0 for x in data['level_of_education']]

X = pd.get_dummies(data=data[['sex', 'age', 'income_pc', 'poverty']], drop_first=True).dropna()
y = data.iloc[X.index]['missing_level_of_education']

for i in range(0, X.shape[1]):
    plt.scatter(X.iloc[:, i], y)
    plt.xlabel(X.columns[i])
    plt.show()
# Age almost fully separates the data, with no missing values existing for ages above 8 years old or so.
# Note: this way of plotting does not work for sex and poverty. Need a value count. See below.

print(data[data['missing_level_of_education'] == 1]['age'].value_counts())
age_for_non_missing_data = data[data['missing_level_of_education'] == 0]['age']
print(min(age_for_non_missing_data), max(age_for_non_missing_data))
# Level of education is missing only for ages 0-4, and exists for above 5.

data[data['age'] > 4].missing_level_of_education.value_counts()
# Conclusion: When filtering for ages above 4 all missing data points are removed.

# -----------------------------------------------------
# Study Amount of Missingness for poverty and income_pc
# -----------------------------------------------------
total_measurements_per_year = data.iloc[data.index[data['person'].notnull()]]['year'].value_counts().reset_index()

data['has_received_human_dev_bond'].notnull().value_counts()
data['poverty'].notnull().value_counts()

missing_pov_idx = data.index[data['poverty'].isnull()]
missing_inc_idx = data.index[data['income_pc'].isnull()]
present_inc_idx = data.index[data['income_pc'].notnull()]

missing_pov_idx.equals(missing_inc_idx)
# Returns True: Precisely the same values are missing here. Strange.
# TODO: What does it mean for our model results that missingness in poverty and income_pc is perfectly correlated?

pov_count_per_year = data[data['poverty'] == 'pobre']['year'].value_counts().reset_index()
missing_per_year = data[data['poverty'].isnull()]['year'].value_counts().reset_index()
missing_per_year = (missing_per_year.merge(total_measurements_per_year, on='index')
                    .merge(pov_count_per_year, on='index')
                    .rename({'year': 'count_pov', 'index': 'year', 'year_x': 'count_missing', 'year_y': 'count_full'},
                            axis=1)
                    .sort_values(by='year'))
missing_per_year['percentage_miss'] = missing_per_year['count_missing'] / missing_per_year['count_full']
missing_per_year['percentage_pov'] = missing_per_year['count_pov'] / missing_per_year['count_full']
missing_per_year['factor'] = missing_per_year['percentage_miss'] / missing_per_year['percentage_pov']
# Summary of created tables:
# Missingness fluctuates from 1.9% to 0.05% per year for this variable. If removing the data does not induce significant
# bias, it is probably safe to remove it: In no single year is the percentage of values missing more than 5% of the
# amount of people self-reporting poverty. It is unlikely we are removing important dynamics.

# ------------------------------------------------------------------------------------------
# Study Type of Missingness for poverty and income_pc (e.g. at random, completely at random)
# ------------------------------------------------------------------------------------------

data['poverty_num'] = pd.factorize(data['poverty'])[0]
data[['poverty_num', 'income_pc']].corr(method='spearman')
# Poverty and income_pc are very strongly correlated; -0.8.

data['missing_poverty'] = [1 if pd.isnull(x) else 0 for x in data['poverty']]

X = pd.get_dummies(data=data[['sex', 'age']], drop_first=True)
y = data['missing_poverty']

for i in range(0, X.shape[1]):
    plt.scatter(X.iloc[:, i], y)
    plt.xlabel(X.columns[i])
    plt.show()
# On first sight it appears evenly distributed.

missingness_by_level_of_ed = data.loc[data['missing_poverty'] == 1, 'level_of_education'].value_counts()
missingness_pct_by_level_of_ed = (data.loc[data['missing_poverty'] == 1, 'level_of_education']
                                  .value_counts().div(data['level_of_education'].value_counts()))
missingness_by_level_of_ed.plot(kind='bar')
plt.show()
missingness_pct_by_level_of_ed.plot(kind='bar')
plt.show()
# More values are missing in the bracket for higher educated people, i.e. post-grado and universitario.

X = pd.get_dummies(data.loc[model_4_assumptions, 'level_of_education'], drop_first=True)
y = data.loc[model_4_assumptions, 'missing_poverty']
model = sm.OLS(y, sm.add_constant(X)).fit()
print(model.summary())
# ANOVA shows that coefficients for post-grado, secundaria, and superior universitario are all statistically significant.
# Hence data missingness is related to our dependent variable. As such, it may even be related to income levels.

model_for_anova = ols(formula='missing_poverty ~ level_of_education', data=data[model_4_assumptions]).fit()
sm.stats.anova_lm(model_for_anova)
# Corroborated by statistical test: F-test says we can reject the null hypothesis that all means are the same.
# --> Data is definitely not MCAR, and unlikely to be MAR, since level of education is weakly correlated to income.

data.loc[model_4_assumptions, ['income_pc', 'level_of_education_num']].corr(method='spearman')
# corr is .23

# Conclusion: To prevent any bias data should be imputed with some model.
# TODO: Create data imputation model.

# ------------------------------------------------
# Study Possible Proxies for poverty and income_pc
# ------------------------------------------------
missing_pov_idx = data.index[data['poverty'].isnull()]

income_cols = ['income_self_employed', 'income_wage_and_domestic', 'income_capital', 'income_capital_transactions',
               'income_retirement_pension', 'income_gift_donation', 'income_from_abroad', 'income_labour']
hh_income_cols = ['hh_income_total', 'hh_size', 'hh_income_pc']  # can impute based on hh wealth?
pov_proxy_1 = ['number_of_jobs']  # perhaps strongly related to poverty? where more jobs = less money per job = poorer?
pov_proxy_2 = ['hours_worked1', 'place_of_work']  # use in nn imputation?

def count_missing_values_for_selection(idx, df, mask, cols):
    for col in cols:
        print(df.iloc[idx].loc[mask, col].isnull().value_counts())

count_missing_values_for_selection(missing_pov_idx, data, model_4_assumptions, income_cols)
# wage and domestic covers all but 634 missing values!
# capital and capital transactions cover all but one missing value!

count_missing_values_for_selection(missing_pov_idx, data, model_4_assumptions, pov_proxy_1)
# covers all but 446 values.

count_missing_values_for_selection(missing_pov_idx, data, model_4_assumptions, pov_proxy_2)
# cover a bit more than half of missing values; 5499

count_missing_values_for_selection(missing_pov_idx, data, model_4_assumptions, hh_income_cols)
# hh_inc_total and hh_income_pc
# present for all values! Size missing, though.

data['income_tot'] = data[income_cols].sum(axis=1)
data['income_pct_change'] = (data['income_pc'] - data['income_tot']) / data['income_pc']
(data.loc[(-3 < data['income_pct_change']) & (data['income_pct_change'] < 101), 'income_pct_change']
 .value_counts(bins=50)
 .sort_index(ascending=True))
(data.loc[(-101 < data['income_pct_change']) & (data['income_pct_change'] < 101), 'income_pct_change']
 .value_counts()
 .sum())
# For 615k entries the change is almost 100%; i.e. income_tot is near 0 for these entries. Changes are around 0% for only 22k
# entries: Very big discrepancies exist.

# TODO: Contact statistical office to ask why this discrepancy exists.
# TODO: Further decide on what proxy to use.

# Impute income data with total data. NOTE: This is far from perfect, but produces a complete dataset for now, until
# I can get some information from the producer of the dataset.
# So: Right now income_pc is leading, and imputed with the sum of incomes where necessary.
data['income_imp'] = data.loc[:, 'income_pc']
data.loc[missing_inc_idx, 'income_imp'] = data.loc[:, 'income_tot']

# Assert that no values are missing.
data['income_imp'].isnull().value_counts()[False] == len(data)

# Assert values have been imputed
data.loc[present_inc_idx, 'income_imp'].equals(data.loc[present_inc_idx, 'income_pc'])
data.loc[missing_inc_idx, 'income_imp'].equals(data.loc[missing_inc_idx, 'income_tot'])


from Bio.Blast import NCBIXML
import re
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D

def scientific_name_filter(bestandnaam):
    """Opent een XML bestand. Deze wordt geparset met behulp van de
    NCBIXML parser. Hier worden de value discriptie uitgefilterd.
    Hieruit wordt de scientific_name gefilterd. De scientific_name wordt
    in een lijst gezet.
    :param bestandnaam: XML File
    :return: l_scientific_name
    """
    try:
        l_scientific_name = []
        # Opent een bestand
        with open(bestandnaam) as out_handle:
            blast_records = NCBIXML.parse(out_handle)
            try:
                # Loopt door iedere read heen
                for blast_record in blast_records:
                    try:
                        # Loopt door iedere hit heen
                        for alignment in blast_record.alignments:
                            try:
                                for hsp in alignment.hsps:
                                    description = alignment.title
                                    scientific_name = re.search(
                                        "\[[^\]]*\]", description)
                                    scientific_name = scientific_name.\
                                        group()
                                    scientific_name = scientific_name.\
                                        strip("[]")
                                    l_scientific_name.append(
                                        scientific_name)
                            except IndexError:
                                print("Er is een invalide index "
                                      "gevonden in de functie "
                                      "scientific_name_filter in de"
                                      "hsp loop")
                            except NameError:
                                print("Functienaam of variabelenaam "
                                      "bestaat niet in de functie "
                                      "scientific_name_filter in de"
                                      "hsp loop")
                    except IndexError:
                        print("Er is een invalide index gevonden in de "
                              "functie scientific_name_filter in de"
                              "alignment loop")
                    except NameError:
                        print("Functienaam of variabelenaam bestaat "
                              "niet in de functie "
                              "scientific_name_filter in de "
                              "alignment loop")
            except IndexError:
                print("Er is een invalide index gevonden in de functie "
                      "scientific_name_filter in de blast_record loop")
            except NameError:
                print("Functienaam of variabelenaam bestaat niet in de "
                      "functie scientific_name_filter in de"
                      "blast_record loop")
        return l_scientific_name
    except FileNotFoundError:
        print("Het bestand is niet gevonden in de functie "
              "scientific_name_filter")
    except IOError:
        print("Het bestand is niet leesbaar in de functie "
              "scientific_name_filter")
    except NameError:
        print("Functienaam of variabelenaam bestaat niet in de functie"
              "scientific_name_filter")

def scientific_name_frequency(l_scientific_name):
    """
    Maakt van een lijst van organismen een lijst en een dictionary die
    aangeven hoevaak die organismen voorkomen. 1 lijst met absoluten
    waarden en 1 lijst met relatieve waarden.
    :param l_scientific_name: Lijst met organismen namen
    :return: 1 lijst en 1 dictionary die per organisme een waarde bevat
    hoevaak die
    voorkomt. 1 dictionary met absolute waarden (freq) en 1 lijst
    relatieve waarden (frequency)
    """
    try:
        freq = {}
        counter = 1
        frequency = []
        # Maakt een dictionary met als opbouw;
        # (organisme, hoevaak komt het organisme voor in absolute
        # waarde)
        for sn in l_scientific_name:
            freq[sn] = freq.get(sn, 0) + 1
            counter += 1
        # Maakt een lijst met als opbouw;
        # (organisme, hoevaak komt het organisme voor in relatieve
        # waarde)
        for key, value in freq.items():
            f = (key, value / counter * 100)
            frequency.append(f)
        return frequency, freq
    except IndexError:
        print("Er is een invalide index gevonden in de functie "
              "scientific_name_frequency")
    except KeyError:
        print("Er is een invalide key gevonden in de functie "
              "scientific_name_frequency")
    except NameError:
        print("Functienaam of variabelenaam bestaat niet in de functie"
              "scientific_name_frequency")

def sorting_one(frequency):
    """ Zet de lijst frequency om in 2 lijsten waarin 1 de top 10
    voorkomende organismen zitten en 1 waarin de bijbehorende relatieve
    frequenties zitten. Bij beide lijsten wordt ook de naam other en de
    bijbehorende waarde toegevoegd
    :param frequency: Lijst die per organisme een relatieve waarde bevat
     over hoevaak die voorkomt
    :return: 2 lijsten waarin 1 de top 10 voorkomende organismen zitten
    (organism) en 1 waarin de bijbehorende relatieve frequentie zit
    (frequency)
    """
    try:
        # Zet per tuple die in elk lijst item zit in de frequency lijst,
        # de eerste waarde in org en de tweede waarde in frq
        org = []
        frq = []
        for item in frequency:
            org.append(item[0])
            frq.append(item[1])
        # Sorteert de frequenties van hoog naar laag waarbij de
        # bijbehorende organismen meegenomen wordt. Daarbij wordt
        # alleen de top 10 opgeslagen
        mx = sorted(zip(frq, org), reverse=True)[:10]
        # Zet per tuple die in elk lijst item zit in de mx lijst,
        # de eerste waarde in frequency en de tweede waarde in organism
        organism = []
        frequency = []
        for item in mx:
            organism.append(item[1])
            frequency.append(item[0])
        # Berekent het percentage van de niet top 10 voorkomende
        # organismen
        other = 100
        for f in frequency:
            other -= f
        # Voegt de naam "Other" toe aan lijst organism en het
        # bijbehorende percentage bij frequency
        organism.append("Other")
        frequency.append(other)
        return frequency, organism
    except IndexError:
        print("Er is een invalide index gevonden in de functie "
              "sorting_one")
    except NameError:
        print("Functienaam of variabelenaam bestaat niet in de functie"
              "sorting_one")

def sorting_two(freq):
    """ Zet de dictionary freq om in 2 lijsten waarin 1 de top 10
    voorkomende organismen zitten en 1 waarin de bijbehorende absolute
    frequenties zitten
    :param freq: Dictionary die per organisme een absolute waarde bevat
    over hoevaak die voorkomt
    :return: 2 lijsten waarin 1 de top 10 voorkomende organismen zitten
    (orga) en 1 waarin de bijbehorende absolute frequentie zit (freq)
    """
    try:
        # Zet per dictionary item die in de freq dictionary zit,
        # de key organism in org om en de value in frq
        org = []
        frq = []
        for organism, frequency in freq.items():
            org.append(organism)
            frq.append(frequency)
        # Sorteert de frequenties van hoog naar laag waarbij de
        # bijbehorende organismen meegenomen wordt. Daarbij wordt
        # alleen de top 10 opgeslagen
        mx = sorted(zip(frq, org), reverse=True)[:10]
        # Zet per tuple die in elk lijst item zit in de mx lijst,
        # de eerste waarde in frequency en de tweede waarde in organism
        orga = []
        freq = []
        for item in mx:
            orga.append(item[1])
            freq.append(item[0])
        return freq, orga
    except KeyError:
        print("Er is een invalide key gevonden in de functie "
              "sorting_two")
    except IndexError:
        print("Er is een invalide index gevonden in de functie "
              "sorting_two")
    except NameError:
        print("Functienaam of variabelenaam bestaat niet in de functie"
              "sorting_two")

def top_ten_one(frequency, organism):
    """ Maakt een taartdiagram over de top 10 meest voorkomende
    organismen tegenover de rest
    :param frequency: Lijst met de relatieve waardes over de top 10
    voorkomende organismen + de waarde van other
    :param organism: Lijst met de namen van de top 10 organismen
    + "other"
    :return: Een taartdiagram
    """
    try:
        plt.pie(frequency, labels=organism, startangle=90,
                shadow=True, textprops={"fontsize": 6.9},
                colors=["Red", "Orange", "Yellow", "Lime", "Green",
                        "Teal", "Dodgerblue", "Blue", "Blueviolet",
                        "Magenta", "Grey"],
                autopct='%.2f%%', pctdistance=0.85)
        plt.title("Top 10 organism appearances in percentages")
        plt.show()
    except IndexError:
        print("Er is een invalide index gevonden in de functie "
              "top_ten_one")
    except NameError:
        print("Functienaam of variabelenaam bestaat niet in de functie"
              "top_ten_one")

def addlabels(orga, freq):
    """Zorgt voor de aanmaak van waarde labels bij de barplot
    :param orga: Lijst met de namen van de top 10 organismen
    :param freq: Lijst met de absolute waardes over de top 10
    voorkomende organismen
    :return: n.v.t.
    """
    try:
        for i in range(len(orga)):
            plt.text(i, freq[i]//2, freq[i], ha="center")
    except NameError:
        print("Functienaam of variabelenaam bestaat niet in de functie"
              "addlabels")
    except IndexError:
        print("Er is een invalide index gevonden in de functie "
              "addlabels")

def top_ten_two(freq, orga):
    """ Maakt een barplot over de top 10 meest voorkomende organismen
    :param orga: Lijst met de namen van de top 10 organismen
    :param freq: Lijst met de absolute waardes over de top 10
    :return: Een barplot
    """
    try:
        # Labels x-as
        label_org = ["Gam. b.", "Pro. b.", "Fir. b.", "Xan. b.",
                     "Del. b.", "Gem. b.", "Chi. b.", "Chl. b.",
                     "Aci. b.", "Sin. a."]
        # Kleuren van de bars
        colors = ["Red", "Orange", "Yellow", "Lime", "Green", "Teal",
                  "Dodgerblue", "Blue", "Blueviolet", "Magenta",
                  "Black"]
        plt.bar(orga, freq, color=colors)
        plt.xlabel("Species")
        plt.ylabel("Number of appearences in absolute values")
        # Aanpassingen x-labels
        plt.xticks(orga, label_org, rotation='vertical')
        # Maakt witte horizontale rasterlijnen aan
        plt.grid(True, color="w", axis="y")
        # Maakt een custom legenda aan
        legend = [Line2D([0], [0], color=colors[0], label=orga[0]),
                  Line2D([0], [0], color=colors[1], label=orga[1]),
                  Line2D([0], [0], color=colors[2], label=orga[2]),
                  Line2D([0], [0], color=colors[3], label=orga[3]),
                  Line2D([0], [0], color=colors[4], label=orga[4]),
                  Line2D([0], [0], color=colors[5], label=orga[5]),
                  Line2D([0], [0], color=colors[6], label=orga[6]),
                  Line2D([0], [0], color=colors[7], label=orga[7]),
                  Line2D([0], [0], color=colors[8], label=orga[8]),
                  Line2D([0], [0], color=colors[9], label=orga[9])]
        plt.legend(handles=legend, loc="upper right")
        # Voegt waarde labels toe
        addlabels(orga, freq)
        plt.title("Top 10 organism appearances in absolute values")
        plt.show()
    except IndexError:
        print("Er is een invalide index gevonden in de functie "
              "top_ten_two")
    except NameError:
        print("Functienaam of variabelenaam bestaat niet in de functie"
              "top_ten_two")

def main():
    l_scientific_name = scientific_name_filter("De_definitieve_blast."
                                               "xml")
    frequency, freq = scientific_name_frequency(l_scientific_name)
    frequency, organism = sorting_one(frequency)
    freq, orga = sorting_two(freq)
    top_ten_one(frequency, organism)
    top_ten_two(freq, orga)

main()


import os, sys, glob, numpy as np, matplotlib.pyplot as mpl

m = 51
n = 1
T = 50
Hc = 100

tofile = 1
x0 = 0.1
x1 = 0.2
y0 = 0.1
y1 = 0.2
result_path = 'blasdf'
filename = 'asfd'
dt = 0.001

os.system('./main_walk %d %f %f %f %f %d %d %d %s %s %f %g'%(tofile,x0,x1,y0,y1,m,n,T,result_path,filename,Hc,dt))
# exit()
mpl.ion()
for step in sorted(glob.glob('spine_n*.txt')):
	tmp = np.loadtxt(step)
	if len(np.shape(tmp))==1:
		break
	for i in xrange(len(tmp)):
		mpl.plot(tmp[i,0],tmp[i,1],'r-x')
	mpl.draw()
a = raw_input('press return>')


import logging

logger = logging.getLogger(__name__)

def validate_item(item: dict):
    """Validate Item data and return dict of data.

    Args:
        item (dict): Feed Item dict

    Returns:
        dict: masked item dict
    """
    try:
        required_item_keys = ['title', 'author',
                              'summary', 'link', 'published']
        if not item.keys() in required_item_keys:
            logger.warning('Invalid item keys')
            return False, 'Invalid item keys'

        cleaned_data = {
            'title': item['title'],
            'author': item['author'],
            'summary': item['summary'],
            'link': item['link'],
            'rights': item['rights'],
            'publication_date': item['published']
        }
        return True, cleaned_data
    except Exception:
        logger.exception('Invalid item data')
        return False, 'Invalid item data'


import random
import PySimpleGUI as sg

class SimuladorDeDado:
    def __init__(self):
        self.valor_minimo = 1
        self.valor_maximo = 6
        self.layout = [
        [sg.Text("JOGAR O DADO? ")],
        [sg.Button("SIM"),sg.Button("NÃO")]
        ]

    def Iniciar(self):

        self.janela = sg.Window("SIMULADOR DE DADO",layout = self.layout)
        self.eventos, self.valores = self.janela.Read()

        try:
            if self.eventos == 'SIM':
                self.GerarValorDoDado()
            elif self.eventos == 'NÃO':
                print("AGRADECEMOS SUA PARTICIPAÇÃO")
            else:
                print("FAVOR DIGITAR APENAS SIM OU NÃO!!")
        except:
            print("OCORREU UM ERRO AO RECEBER SUA RESPOSTA")

    def GerarValorDoDado(self):
        print(random.randint(self.valor_minimo,self.valor_maximo))

simulador = SimuladorDeDado()
simulador.Iniciar()


#!/bin/python
# -*- coding:utf-8 -*-

import bluetooth
import os
import sys
from PyOBEX.client import Client

# Scan addresses of the nearby devices and find their servers
def Bluetooth_Scan():
    print("Scan devices nearby")
    devices = bluetooth.discover_devices(lookup_names=True)
    if len(devices):
        print("Found devices")
        return devices
    else:
        print("Found none devices")

        return

# Send file to the phone
def RFCOMM_Sendfile(address, fname="test.txt", fdata=b'Hello world\n'):

    print("Searching for OBEX service on %s" % address)

    # Use the server named "OBEX Object Push" to send file
    service_matches = bluetooth.find_service(name="OBEX Object Push", address=address)
    if len(service_matches) == 0:
        print("Couldn't find the service")
        sys.exit(0)

    match = service_matches[0]
    name = match["name"]
    host = match["host"]
    port = match["port"]

    print("Service Name: %s" % match["name"])
    print("    Host:        %s" % match["host"])
    print("    Description: %s" % match["description"])
    print("    Provided By: %s" % match["provider"])
    print("    Protocol:    %s" % match["protocol"])
    print("    channel/PSM: %s" % match["port"])
    print("    svc classes: %s " % match["service-classes"])
    print("    profiles:    %s " % match["profiles"])
    print("    service id:  %s " % match["service-id"])

    print("Connecting to \"%s\" on %s" % (name, host))
    client = Client(host, port)
    client.connect()

    # The parameter [file_data] must be bytes type like [b'****'],otherwise there will be some error occur in Python3
    client.put(name=fname, file_data=fdata)
    client.disconnect()

    return

def Test(devicename):

    specdevfound = False
    devices = Bluetooth_Scan()
    if not len(devices):
        return
    for addr, name in devices:
        print("%s - %s" % (name, addr))
        if devicename == name:
            print("Lucky! Found device to send file")
            RFCOMM_Sendfile(address=addr, fdata=b'Hello Bluetooth\n')
            specdevfound = True
    if not specdevfound:
        print("Not found device wanna")

    return

if __name__ == "__main__":
    print("Your Bluetooth name is [%s]" % sys.argv[1])
    Test(devicename=sys.argv[1])


from selenium import webdriver
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager
import io
from PIL import Image
from datetime import datetime

start=datetime.now()
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.set_window_size(1920,1080)
print(datetime.now()-start)

start=datetime.now()
# driver = webdriver.Chrome(executable_path = './chromedriver.exe')
url = "http://127.0.0.1:8080/"
driver.get(url)
# driver.save_screenshot('screenie.png')
img = driver.find_element(By.ID, "container").screenshot_as_png
imageStream = io.BytesIO(img)
im = Image.open(imageStream)
im.save("aaaaa.png")
print(datetime.now()-start)

start=datetime.now()
url = "http://127.0.0.1:8080/"
driver.get(url)
# driver.save_screenshot('screenie.png')
img = driver.find_element(By.ID, "container").screenshot_as_png
imageStream = io.BytesIO(img)
im = Image.open(imageStream)
im.save("aaaaa2.png")
print(datetime.now()-start)

start=datetime.now()
url = "http://127.0.0.1:8080/"
driver.get(url)
# driver.save_screenshot('screenie.png')
img = driver.find_element(By.ID, "container").screenshot_as_png
imageStream = io.BytesIO(img)
im = Image.open(imageStream)
im.save("aaaaa3.png")
print(datetime.now()-start)
# screenshot = Image.open('screenie.png')
# w, h = screenshot.size
# print(w)
# print(h)
# im1 = screenshot.crop((10, 0, w-15, 300))
# im1.save('screenie.png')


from django.urls import path
from . import views

urlpatterns = [

    path('shows/', views.home_shows, name='home-shows'),

    path('show/<str:pk>/', views.shows, name='show'),
    path('post-show/', views.post_show, name="post-show"),
    path('update-show/<str:pk>/', views.update_show, name="update-show"),
    path('delete-show/<str:pk>/', views.delete_show, name="delete-show"),

    path('profile/<str:pk>/', views.user_profile, name='user-profile'),

]


from __future__ import print_function, division

import torch
import torch.nn as nn
import torch.optim as optim
from torch.optim import lr_scheduler
import torch.backends.cudnn as cudnn
import numpy as np
import torchvision
from torchvision import datasets, models, transforms
from torch.utils.tensorboard import SummaryWriter
import matplotlib.pyplot as plt
import time
import os
import copy

from PIL import Image
import re

cudnn.benchmark = True
plt.ion()   # interactive mode

class PlantAssessmentDataset(torch.utils.data.Dataset):
    def __init__(self, root, transforms):
        self.root = root
        self.transforms = transforms
        # load all image files, sorting them to
        # ensure that they are aligned
        self.imgs = list(sorted(os.listdir(root)))
        with open('challenge_anno.txt') as f:
            self.score_labels_txt = f.readlines()

    def __getitem__(self, idx):
        # load images and masks
        img_path = os.path.join(self.root, self.imgs[idx])
        img = Image.open(img_path).convert("RGB")

        # get the plant health label
        health_score = [re.search('\t(.*)\n', x).group(1) for x in self.score_labels_txt if self.imgs[idx] in x]
        #health_score = torch.tensor(int(health_score[0]), dtype=torch.int64)
        health_score = torch.tensor(int(health_score[0]), dtype=torch.float32)

        if self.transforms is not None:
            img = self.transforms(img)

        return img, health_score

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

# Data augmentation and normalization for training
# Just normalization for validation
data_transforms = {
    'train': transforms.Compose([
        transforms.Resize(344),
        transforms.RandomRotation(degrees=180, fill=255),
        transforms.RandomResizedCrop(344, scale=(0.80, 1)),
        transforms.CenterCrop(224),
        transforms.RandomHorizontalFlip(),
        transforms.RandomVerticalFlip(),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ]),
    'val': transforms.Compose([
        transforms.Resize(344),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ]),
    'test': transforms.Compose([
            transforms.Resize(344),
            transforms.CenterCrop(224),
            transforms.ToTensor(),
            transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
        ]),
}

if __name__ == "__main__":

    folds = ['fold1', 'fold2', 'fold3', 'fold4', 'fold5']
    for fold in folds:
        print('\nFOLD: %s\n' % fold)

        for num_trial in range(1, 6):

            # log metrics to tensorboard
            with SummaryWriter() as writer:
                writer = SummaryWriter('runs_resnet18/' + fold + '/trial' + str(num_trial))

                data_dir = os.path.join('data_folds', fold)
                image_datasets = {x: PlantAssessmentDataset(os.path.join(data_dir, x),
                                                          data_transforms[x])
                                  for x in ['train', 'val', 'test']}
                dataloaders = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=8,
                                                             shuffle=True, num_workers=0)
                              for x in ['train', 'val', 'test']}
                dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val', 'test']}

                device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

                ######################################################################
                # Visualize a few images
                # ^^^^^^^^^^^^^^^^^^^^^^
                # Let's visualize a few training images so as to understand the data
                # augmentations.

                def imshow(inp, title=None):
                    """Display image for Tensor."""
                    inp = inp.numpy().transpose((1, 2, 0))
                    mean = np.array([0.485, 0.456, 0.406])
                    std = np.array([0.229, 0.224, 0.225])
                    inp = std * inp + mean
                    inp = np.clip(inp, 0, 1)
                    plt.imshow(inp)
                    if title is not None:
                        plt.title(title)
                    plt.pause(0.001)  # pause a bit so that plots are updated

                # Get a batch of training data
                #inputs, health_scores = next(iter(dataloaders['train']))

                # Make a grid from batch
                #out = torchvision.utils.make_grid(inputs)

                #imshow(out, title=[x.item() for x in health_scores])

                def train_model(model, criterion, optimizer, scheduler, num_epochs=25):
                    since = time.time()

                    best_model_wts = copy.deepcopy(model.state_dict())
                    best_min_loss = 10000000

                    for epoch in range(num_epochs):
                        print(f'Epoch {epoch}/{num_epochs - 1}')
                        print('-' * 10)

                        # Each epoch has a training and validation phase
                        for phase in ['train', 'val']:
                            if phase == 'train':
                                model.train()  # Set model to training mode
                            else:
                                model.eval()   # Set model to evaluate mode

                            running_loss = 0.0
                            #running_corrects = 0

                            # Iterate over data.
                            for inputs, health_scores in dataloaders[phase]:
                                inputs = inputs.to(device)
                                #health_scores = health_scores.to(device)
                                health_scores = torch.unsqueeze(health_scores, dim=1).to(device)

                                # zero the parameter gradients
                                optimizer.zero_grad()

                                # forward
                                # track history if only in train
                                with torch.set_grad_enabled(phase == 'train'):
                                    outputs = model(inputs)
                                    loss = criterion(outputs, health_scores)
                                    # log loss to tensorboard
                                    writer.add_scalar(phase + "_loss", loss, epoch)

                                    # backward + optimize only if in training phase
                                    if phase == 'train':
                                        loss.backward()
                                        optimizer.step()

                                # statistics
                                running_loss += loss.item() * inputs.size(0)
                                #running_corrects += torch.sum(preds == labels.data)
                            if phase == 'train':
                                scheduler.step()

                            epoch_loss = running_loss / dataset_sizes[phase]
                            #epoch_acc = running_corrects.double() / dataset_sizes[phase]

                            print(f'{phase} Loss: {epoch_loss:.4f}')

                            # deep copy the model
                            if phase == 'val' and epoch_loss < best_min_loss:
                                best_min_loss = epoch_loss
                                best_model_wts = copy.deepcopy(model.state_dict())

                        print()

                    # test phase
                    model.eval()  # Set model to evaluate mode
                    test_running_loss = 0
                    for inputs, health_scores in dataloaders['test']:
                        inputs = inputs.to(device)
                        #health_scores = health_scores.to(device)
                        health_scores = torch.unsqueeze(health_scores, dim=1).to(device)

                        # zero the parameter gradients
                        optimizer.zero_grad()

                        with torch.set_grad_enabled(phase == 'train'):
                            outputs = model(inputs)
                            loss = criterion(outputs, health_scores)

                        # statistics
                        test_running_loss += loss.item() * inputs.size(0)
                    test_loss = test_running_loss / dataset_sizes['test']

                    time_elapsed = time.time() - since
                    print(f'Training complete in {time_elapsed // 60:.0f}m {time_elapsed % 60:.0f}s')
                    print(f'Best val Loss: {best_min_loss:4f}')
                    print(f'TEST Loss: {test_loss:.4f}')
                    writer.add_text('TEST Loss', str(test_loss), num_epochs)

                    writer.add_hparams({'optimizer': 'SGD', 'epochs': num_epochs, 'lr': optimizer.defaults['lr'], 'momentum': optimizer.defaults['momentum'],
                                        'step_size': scheduler.step_size, 'gamma': scheduler.gamma, 'bs': 8, 'loss_function': 'L1Loss'},
                                      {'best_val_loss': best_min_loss, 'best_test_loss': test_loss})

                    writer.flush()

                    # load best model weights
                    model.load_state_dict(best_model_wts)
                    return model

            ######################################################################
            # Visualizing the model predictions
            # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            #
            # Generic function to display predictions for a few images
            #

            def visualize_model(model, split_name, num_images=12):
                was_training = model.training
                model.eval()
                images_so_far = 0
                fig = plt.figure()

                with torch.no_grad():
                    for i, (inputs, labels) in enumerate(dataloaders[split_name]):
                        inputs = inputs.to(device)
                        labels = labels.to(device)

                        outputs = model(inputs)
                        outputs = torch.squeeze(outputs)
                        #_, preds = torch.max(outputs, 1)

                        for j in range(inputs.size()[0]):
                            images_so_far += 1
                            ax = plt.subplot(num_images//2, 2, images_so_far)
                            ax.axis('off')
                            ax.set_title(f'HR: {int(labels[j])} Predicted: {outputs[j]}')
                            imshow(inputs.cpu().data[j])

                            if images_so_far == num_images:
                                model.train(mode=was_training)
                                return
                    model.train(mode=was_training)

            ######################################################################
            # Finetuning the ConvNet
            # ----------------------
            #
            # Load a pretrained model and reset final fully connected layer.
            #

            model_ft = models.resnet18(weights='IMAGENET1K_V1')
            num_ftrs = model_ft.fc.in_features
            # Here the size of each output sample is set to 1.
            #model_ft.fc = nn.Linear(num_ftrs, 100)
            #model_ft.classifier[1] = nn.Linear(num_ftrs, 1,  bias=True)
            """model_ft.fc = nn.Sequential(
                                    nn.Dropout(p=0.4, inplace=True),
                                    nn.Linear(num_ftrs, 1024,  bias=True),
                                    nn.Dropout(p=0.4, inplace=True),
                                    nn.Linear(1024, 512,  bias=True),
                                    nn.Dropout(p=0.4, inplace=True),
                                    nn.Linear(512, 256,  bias=True),
                                    nn.Dropout(p=0.4, inplace=True),
                                    nn.Linear(256, 128,  bias=True),
                                    nn.Dropout(p=0.4, inplace=True),
                                    nn.Linear(128, 64,  bias=True),
                                    nn.Dropout(p=0.4, inplace=True),
                                    nn.Linear(64, 32,  bias=True),
                                    nn.Dropout(p=0.4, inplace=True),
                                    nn.Linear(32, 1,  bias=True),
            )"""
            model_ft.fc = nn.Sequential(
                                    nn.Dropout(p=0.4, inplace=True),
                                    nn.Linear(num_ftrs, 256,  bias=True),
                                    nn.Dropout(p=0.4, inplace=True),
                                    nn.Linear(256, 128,  bias=True),
                                    nn.Dropout(p=0.4, inplace=True),
                                    nn.Linear(128, 64,  bias=True),
                                    nn.Dropout(p=0.4, inplace=True),
                                    nn.Linear(64, 32,  bias=True),
                                    nn.Dropout(p=0.4, inplace=True),
                                    nn.Linear(32, 1,  bias=True),
            )

            model_ft = model_ft.to(device)

            #criterion = nn.MSELoss()
            criterion = nn.L1Loss()

            # Observe that all parameters are being optimized
            optimizer_ft = optim.SGD(model_ft.parameters(), lr=0.0005, momentum=0.9)

            # Decay LR by a factor of 0.5 every 4 epochs
            exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=4, gamma=0.5)

            model_ft = train_model(model_ft, criterion, optimizer_ft, exp_lr_scheduler,
                                   num_epochs=25)

            # store best model for each fold
            torch.save(model_ft.state_dict(), os.path.join('runs_resnet18/', fold + '/trial' + str(num_trial), 'model_resnet18_bestvalloss.pth'))

            writer.flush()
            writer.close()

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

            #visualize_model(model_ft, 'val')
            #visualize_model(model_ft, 'test')

            plt.ioff()
            plt.show()


import os
import sys
from pathlib import Path

import click
from tabulate import tabulate

from knext import rest
from knext.core.reasoner import Reasoner

@click.option("--file", help="Path of DSL file.")
@click.option("--dsl", help="DSL string enclosed in double quotes.")
def run_dsl(file, dsl):
    """
    Query dsl by providing a string or file.
    """
    client = Reasoner()
    dsl_content = ""
    if file and not dsl:
        with open(file, "r") as f:
            dsl_content = f.read()
    elif not file and dsl:
        dsl_content = dsl
    else:
        click.secho("ERROR: Please choose either --file or --dsl.", fg="bright_red")

    result = client.run_dsl(dsl_content)
    table = tabulate(result.cells, result.columns, tablefmt="github")
    click.echo(table)

@click.option("--file", help="Path of DSL file.")
@click.option("--dsl", help="DSL string enclosed in double quotes.")
def submit_reasoner_job(file, dsl):
    """
    Submit asynchronous reasoner jobs to server by providing DSL file or string.
    """
    client = Reasoner()
    if file and not dsl:
        with open(file, "r") as f:
            dsl_content = f.read()
    elif not file and dsl:
        dsl_content = dsl
    else:
        click.secho("ERROR: Please choose either --file or --dsl.", fg="bright_red")
        sys.exit()
    inst = client.submit(dsl_content)

    click.secho(
        f"ReasonerJob [\n{dsl_content}] has been successfully submitted."
        f" Use ` knext reasoner get --id {inst.reasoner_job_inst_id} ` to check job status.",
        fg="bright_green",
    )

@click.option("--id", help="Unique id of submitted reasoner job.")
def query_reasoner_job(id):
    """
    Query submitted reasoner job status.
    """
    try:
        job_inst_id = int(id)
    except:
        click.secho("ERROR: Option [--id] must be a integer.", fg="bright_red")
        sys.exit()

    client = Reasoner()
    res = client.query(job_inst_id=job_inst_id)
    if res and len(res) > 0:
        data = {k: [v if v else "-"] for k, v in res[0].to_dict().items()}
        table = tabulate(data, headers="keys", tablefmt="github")
        click.echo(table)
    else:
        click.secho(
            f"ERROR: Cannot find ReasonerJob instance. "
            f"Please check if the [--id {id}] is correct.",
            fg="bright_red",
        )
        sys.exit()

    if (
        res[0].status in ["SUCCESS", "FAILURE"]
        and res[0].result
        and res[0].result.table_name
    ):
        confirm = click.style(
            f"ReasonerJob instance with id [{res[0].job_inst_id}] execution completed. "
            f"Do you need to download result_file?",
            fg="bright_green",
        )
        if click.confirm(confirm):
            client = rest.TableStoreApi()
            table_name = res[0].result.table_name
            content = client.table_store_download_get(file_name=table_name)

            file_path = os.path.join(
                os.environ["KNEXT_ROOT_PATH"],
                os.environ["KNEXT_REASONER_RESULT_DIR"],
                table_name.split("/")[-1],
            )
            if not Path(file_path).parent.exists():
                os.mkdir(Path(file_path).parent.resolve())
            with open(file_path, "w") as file:
                file.write(content)
            click.secho(
                f"Download successful. The file path is [{file_path}].",
                fg="bright_green",
            )
        else:
            sys.exit()


import requests
from requests.structures import CaseInsensitiveDict

from http.server import BaseHTTPRequestHandler, HTTPServer
import json

class MyRequestHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        content_length = int(self.headers['Content-Length'])
        post_data = self.rfile.read(content_length)

        # decodificar el mensaje HTTP POST
        post_data = post_data.decode('utf-8')

        # analizar el contenido JSON del mensaje HTTP POST
        post_json = json.loads(post_data)

        # imprimir el contenido del mensaje HTTP POST
        print(f"Mensaje HTTP POST recibido: {post_json}")

        ######################
        # Envia el mensaje al whatsapp

        url = "https://graph.facebook.com/v15.0/101042539575372/messages"

        headers = CaseInsensitiveDict()
        headers["Authorization"] = "Bearer EAAJd7y5KaZA8BAN0t0ZC8VVVAhNzmtmpaESVrJlLEDwLwAqVCMg9z5ImZCWX1LLGCVOhDrbXM03VoE9oS2vrSWWbav5oRrw6djnVs1nPoWKZAT6IJSxPKsWuy697jPkfeLtq7PtQIj8VyjZCHZBoGUrjchZB3EmSosLdZAsfL5LelNV92DcVz653oN6RrRETjGQX3RMXCURxggZDZD"
        headers["Content-Type"] = "application/json"

        data = '{ "messaging_product": "whatsapp", "to": "50256327243", "type": "template", "template": { "name": "hello_world", "language": { "code": "en_US" } } }'

        resp = requests.post(url, headers=headers, data=data)

        print(resp.status_code)

        # enviar una respuesta al cliente
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        response = "Mensaje HTTP POST recibido"
        self.wfile.write(response.encode('utf-8'))

def run_server():
    print("Ip: ")
    Ip_k = str(input())
    print("Puerto: ")
    Puerto_k = int(input())
    server_address = (Ip_k, Puerto_k)
    httpd = HTTPServer(server_address, MyRequestHandler)
    print(f'Servidor en ejecución: http://{server_address[0]}:{server_address[1]}')
    httpd.serve_forever()

if __name__ == '__main__':
    run_server()


import boto3
from botocore.exceptions import ClientError
import json
import os
import time
from datetime import datetime, timezone
from dateutil import tz

from antiope.aws_account import *
from common import *

import logging
logger = logging.getLogger()
logger.setLevel(getattr(logging, os.getenv('LOG_LEVEL', default='INFO')))
logging.getLogger('botocore').setLevel(logging.WARNING)
logging.getLogger('boto3').setLevel(logging.WARNING)
logging.getLogger('urllib3').setLevel(logging.WARNING)

RESOURCE_PATH = "accessanalyzer/analyzer"
RESOURCE_TYPE = "AWS::AccessAnalyzer::Analyzer"

def lambda_handler(event, context):
    logger.debug("Received event: " + json.dumps(event, sort_keys=True))
    message = json.loads(event['Records'][0]['Sns']['Message'])
    logger.info("Received message: " + json.dumps(message, sort_keys=True))

    try:

        account_id = message['account_id']
        target_account = AWSAccount(message['account_id'])

        regions = target_account.get_regions()
        if 'region' in message:
            regions = [message['region']]

        # describe ec2 instances
        for r in regions:
            client = target_account.get_client('accessanalyzer', region=r)
            analyzer = get_analyzer(target_account, client, r)

    except AntiopeAssumeRoleError as e:
        logger.error("Unable to assume role into account {}({})".format(target_account.account_name, target_account.account_id))
        return()
    except AntiopeAssumeRoleError as e:
        logger.error("Unable to assume role into account {}({})".format(target_account.account_name, target_account.account_id))
        return()
    except ClientError as e:
        if e.response['Error']['Code'] == 'AccessDeniedException' or e.response['Error']['Code'] == 'UnauthorizedOperation':
            logger.error(f"AccessDeniedException/UnauthorizedOperation for access-analyzer in {target_account.account_name}({target_account.account_id}): {e}")
            return()
        else:
            logger.critical("AWS Error getting info for {}: {}".format(account_id, e))
            capture_error(message, context, e, "ClientError for {}: {}".format(account_id, e))
            raise
    except Exception as e:
        logger.critical("{}\nMessage: {}\nContext: {}".format(e, message, vars(context)))
        capture_error(message, context, e, "General Exception for {}: {}".format(account_id, e))
        raise

def get_analyzer(target_account, client, region):
    analyzers = []
    response = client.list_analyzers()
    while 'nextToken' in response:
        analyzers += response['analyzers']
        response = client.list_analyzers(nextToken=response['nextToken'])
    analyzers += response['analyzers']

    # There may be no analyzers in this region, so we return none
    if len(analyzers) == 0:
        return(None)

    for a in analyzers:
        resource_item = {}
        resource_item['awsAccountId']                   = target_account.account_id
        resource_item['awsAccountName']                 = target_account.account_name
        resource_item['resourceType']                   = RESOURCE_TYPE
        resource_item['source']                         = "Antiope"
        resource_item['configurationItemCaptureTime']   = str(datetime.datetime.now())
        resource_item['awsRegion']                      = region
        resource_item['configuration']                  = a
        resource_item['supplementaryConfiguration']     = {}
        resource_item['resourceId']                     = f"{target_account.account_id}-{region}-{a['name']}"
        resource_item['ARN']                            = a['arn']
        resource_item['errors']                         = {}
        save_resource_to_s3(RESOURCE_PATH, resource_item['resourceId'], resource_item)

    # There can currently only be one analyzer. When that changes this part needs to be fixed
    return(analyzers[0]['arn'])  # Arn is needed for getting findings


from collections import Counter
import matplotlib.pyplot as plt
from matplotlib import style
import numpy as np
import pandas as pd
import random
import warnings

style.use('fivethirtyeight')

def k_nearest_neighbours(data, predict, k=3):
    """
    :param data: Dictionary of labels and set of features for each label
    :param predict: The feature for we need to classify
    :param k: The number of neighbours
    :return: The classified label
    """
    if len(data) >= k:  # If number of labels is >= number of neighbours to test
        warnings.warn('K is set to a value less than total voting groups!')  # We haven't tested for all possible labels
    distances = []
    for label in data:
        for featureList in data[label]:
            # The below line gives most intuitive way for what we are calculating with data and test point (predict)
            # euclidean_distance = sqrt( (feature[0]-predict[0])**2 + (feature[1]-predict[1])**2 )
            euclidean_distance = np.linalg.norm(np.array(featureList) - np.array(predict))  # Built-in fast version of above
            distances.append((euclidean_distance, label))

    # Sort all distances and choose top k elements, get those labels (tup[1])
    votes = [tup[1] for tup in sorted(distances)[:k]]
    vote_result = Counter(votes).most_common(1)[0][0]
    '''
    Counter.most_common: Given a list of values, the Counter class analyses it to produce a list of tuples.
    Each tuple consists of (value, count) from the list.
    most_common() takes an argument n and returns the list of top n tuples. If n < length of analysed data, returns
    available data.
    '''
    return vote_result

'''Trial dataset to test K nearest neighbuours with custom data'''
dataset = {    # The keys represent the labels of classification and sub-list represnets list of features for that label
    'k': [[1, 2], [2, 3], [3, 1]],
    'r': [[6, 5], [7, 7], [8, 6]]
    }
# for label in dataset:   # To show dataset
#     for feature in dataset[label]:
#         plt.scatter(feature[0], feature[1], s=30, color=label)      # s argument is size of points
# plt.show()

# new_feature = [5, 7]    # The new feature we want to classify and attach a label from existing label in dataset
# result = k_nearest_neighbours(dataset, new_feature, k=3)
# print("Classification of feature: label ", result)

'''Testing our K nearest neighbours algorithm with the breast cancer data to compare with sci-kit learn'''
df = pd.read_csv('breast-cancer-wisconsin.txt')
df.replace('?', -99999, inplace=True)
df.drop(['id'], 1, inplace=True)
# Convert all data to float, full_data is list of lists (each is a row of data from input file, labels and features)
full_data = df.astype(float).values.tolist()
random.shuffle(full_data)   # Shuffles order of lists and stores in same variable

test_size = 0.2
train_set = {2: [], 4: []}
test_set = {2: [], 4: []}
train_data = full_data[:-int(test_size * len(full_data))]    # Split the data, first 80% train
test_data = full_data[-int(test_size * len(full_data)):]     # Split the data, last 20% train

# Populate the train_set and test_set from train_data and set_data
for dataRow in train_data:
    label = dataRow[-1]  # Get label attached to each row of data and use this as key in training dictionary
    train_set[label].append(dataRow[:-1])   # Append row of data without label to training dictionary

# Do same as above for train_set
[test_set[dataRow[-1]].append(dataRow[:-1]) for dataRow in test_data]

correct = 0
total = 0
for label in test_set:
    for featureList in test_set[label]:
        # The train_set is the bunch of features with attached labels and for each time we want to classify new features
        # we simply pass this as an argument. Training is just having labelled data points to compare test point to!
        vote = k_nearest_neighbours(train_set, featureList, k=5)
        if label == vote:
            correct += 1
        total += 1
print("Accuracy: ", correct / total)