#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Oct 17 22:52:51 2020

@author: maysa
"""

lista_frutas = ['maça', 'banana', 'manga']
f=0
while f < len(lista_frutas):
	print(lista_frutas[f] , 'foi adicionada 	à lista.\n\n')
	f = f+1

#----------------------

lista_recheio =[]
limite_numero_recheios = 3

print("Você pode escolher ", limite_numero_recheios, "recheios.")

i=0
while  i < limite_numero_recheios :

    input_recheio = input('Entre com o '+str(i+1)+'o.    	 recheio: ')
    lista_recheio.append(input_recheio)
    i=i+1

print("Você escolheu esses recheios:",lista_recheio[:])

#-____________________________________________________________________________--------

lista_recheio =[]

print("\n\nVocê pode escolher quantos recheios quiser.")

continuar = True
while  continuar == True:

    input_recheio = input('Entre com um recheio: ')
    lista_recheio.append(input_recheio)
    input_continuar = input('Deseja informar mais algum recheio? Informe NAO para parar e qualquer outra palavra para continuar: ')
    if input_continuar == 'NAO':
        continuar = False

print("Você escolheu esses recheios:",
lista_recheio[:])


import discord
from discord.ext import commands
import logging
import threading
from settings import TOKEN
from stats import stats as get_stats

description = '''Jeff's Discord Bot'''

bot = commands.Bot(command_prefix='.', description=description)

@bot.event
async def on_ready():
	print('We have logged in as {0.user}'.format(bot))

@bot.command()
async def stats(ctx, ign: str):
	esea_link = get_stats(ign)
	embed = discord.Embed(title="ESEA", description=(ign + " - " + esea_link), url=esea_link, inline=True)
	embed.set_thumbnail(url='https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Ftse4.mm.bing.net%2Fth%3Fid%3DOIP.5NSZleerSox2ncN8uNRYpAHaDd%26pid%3DApi&f=1')
	await ctx.send(embed=embed)
	# await ctx.send(ctx.author.created_at) make .register method

@bot.command()
async def register(ctx):
	# User check if already made
	return

logger = logging.getLogger('discord')
logger.setLevel(logging.DEBUG)
handler = logging.FileHandler(filename='discord.log', encoding='utf-8', mode='w')
handler.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s:%(name)s: %(message)s'))
logger.addHandler(handler)

bot.run(TOKEN)


import torch
import numpy as np
import random
import os
import os.path as osp
from torch.utils.tensorboard import SummaryWriter
from datetime import datetime

def print_loss_dict(loss_dict):
    plist = []
    for k, v in loss_dict.items():
        if 'loss' in k:
            plist.append(f'{k}:{v:.4f}\t')
        else:
            plist.append(f'loss_{k}:{v:.4f}\t')
    return ''.join(plist)

def get_time(format='%Y-%m-%d %H:%M:%S'):
    return datetime.strftime(datetime.now(), format=format)

def init_logger(cfg):
    """
    initialization the logger part; tensorboard, logger, save_dir
    Args:
        cfg: configs

    Returns:
        writer, logger, save_dir
    """
    cfg.desc = cfg.desc

    os.makedirs(osp.join(cfg.dir, cfg.desc, 'tb'), exist_ok=True)
    os.makedirs(osp.join(cfg.dir, cfg.desc, 'ckpt'), exist_ok=True)

    writer = SummaryWriter(osp.join(cfg.dir, cfg.desc, 'tb'))
    logger = Logger(osp.join(cfg.dir, cfg.desc, f'{cfg.desc}_log'))
    ckpt_dir = osp.join(osp.join(cfg.dir, cfg.desc, 'ckpt'))
    return writer, logger, ckpt_dir

class LossMeter():
    def __init__(self):
        self.loss = 0
        self.num = 0

    def add(self, loss, num):
        self.loss += loss * num
        self.num += num

    def avg(self):
        return self.loss / self.num

    def reset(self):
        self.loss = 0
        self.num = 0

def seed_everything(seed):
    torch.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)
    np.random.seed(seed)
    random.seed(seed)
    torch.backends.cudnn.deterministic = True

def z_save_model(model, opt, sch, epoch, save_path):
    save_dict = {
        'model': model.state_dict(),
        'optim': opt.state_dict(),
        'sch': sch.state_dict(),
        'epoch': epoch}
    torch.save(save_dict, save_path)

def z_load_model(model, opt, sch, save_path):
    save_dict = torch.load(save_path)
    model.load_state_dict(save_dict['model'])
    opt.load_state_dict(save_dict['optim'])
    sch.load_state_dict(save_dict['sch'])
    return save_dict['epoch']

if __name__ == '__main__':
    print(get_time())


import matplotlib.pyplot as plt

x_values = list(range(1, 5001))
y_values = [i**3 for i in range(1, 5001)]
plt.scatter(x_values, y_values, c=y_values, cmap=plt.cm.Blues,
            edgecolor='none', s=40)

plt.title("Practice", fontsize=24)
plt.xlabel("X Value", fontsize=14)
plt.ylabel("Y Value", fontsize=14)

plt.tick_params(axis='both', which='major', labelsize=14)

plt.show()


#!/usr/local/bin/python3
#
# arrange_pichus.py : arrange agents on a grid, avoiding conflicts
#
# Submitted by : [Yash Pratap Solanky]
#
# Based on skeleton code in CSCI B551, Fall 2021.

import sys

# Parse the map from a given filename
def parse_map(filename):
	with open(filename, "r") as f:
		return [[char for char in line] for line in f.read().rstrip("\n").split("\n")][3:]

# Count total # of pichus on house_map
def count_pichus(house_map):
    return sum([ row.count('p') for row in house_map ] )

# Return a string with the house_map rendered in a human-pichuly format
def printable_house_map(house_map):
    return "\n".join(["".join(row) for row in house_map])

# Add a pichu to the house_map at the given position, and return a new house_map (doesn't change original)
def add_pichu(house_map, row, col):
    return house_map[0:row] + [house_map[row][0:col] + ['p',] + house_map[row][col+1:]] + house_map[row+1:]

# Get list of successors of given house_map state
def successors(house_map):
    return [add_pichu(house_map, r, c) for r in range(0, len(house_map)) for c in range(0,len(house_map[0])) if house_map[r][c] == '.']

# check if house_map is a goal state
def is_goal(house_map, k):
    return count_pichus(house_map) == k

def is_pichu(house_map):
    pichu_loc = [(row_i, col_i) for col_i in range(len(house_map[0])) for row_i in range(len(house_map)) if house_map[row_i][col_i] == "p"] #Identifying location of 'p' on the map. Took this line of code from route_pichu.py
    count = 0 #I make use of a counter to not return True or False prematurely.

    for (i,j) in pichu_loc: #Looping through pichu_loc. It will contain coordinates of all "p" on the map.
        for (a,b) in pichu_loc:
            if i==a and j==b: #If they are the same, we can continue
                continue
            elif i < a and j == b: #If they are upwards of one another
                if is_wall(house_map,i,j,a,b) == True: #If there is a wall or @ in between them then we can continue
                    continue
                count =+ 1 #if there is no wall in between them then they can see one another. So we add to the count.
            elif i > a and j == b: #Downwards
                if is_wall(house_map,i,j,a,b) == True:
                    continue
                count =+ 1
            elif j > b and i == a: #Towards Right
                if is_wall(house_map,i,j,a,b) == True:
                    continue
                count =+ 1
            elif j < b and i == a: #Towards Left
                if is_wall(house_map,i,j,a,b) == True:
                    continue
                count =+ 1
            elif i<a and j>b and i-a==j-b: #left downwards diagonal
                if is_wall(house_map,i,j,a,b) == True:
                    continue
                count = + 1
            elif i<a and j<b and i-a== -(j-b): #right upwards diagonal
                if is_wall(house_map,i,j,a,b) == True:
                    continue
                count = + 1
            elif i>a and j<b and i-a== -(j-b):
                if is_wall(house_map,i,j,a,b) == True:
                    continue
                count = + 1
            elif i>a and j>b and i-a==j-b: #left upwards diagonal
                if is_wall(house_map,i,j,a,b) == True:
                    continue
                count = + 1

    if count > 0:
        return False #If count is increased for any condition that means that one pichu can see another pichu, so we return False
    else:
        return True #If count is still 0 like we initilaised then we return true, meaning that no pichu cans ee another pichu.

def is_wall(house_map,i,j,a,b): #Another function to check if there is a wall in between "p"
    obstacle = [(row_i, col_i) for col_i in range(len(house_map[0])) for row_i in range(len(house_map)) if house_map[row_i][col_i] in ["X","@"]] #As we have to treat "@" like a wall as well, we look for it along with "X"
    for c,d in obstacle: #If any of these conditions indicating a X or @ between p's is fulfiled we figure out that they cannot see one another.
        if i<c<a and j == b == d: #wall is in between 2 pichus on the same column
            return True
        elif a<c<i and j == b == d: #wall is in between 2 pichus on the same column
            return True
        elif b < d < j and i == c == a: #wall is in between 2 pichus on the same row
            return True
        elif j < d < b and i == c == a: #wall is in between 2 pichus on the same row
            return True
        elif i<c<a and j>d>b and i-a==j-b: #There is a wall in the diagonal of 2 pichus. Similarly, for the other 3 possible diagonals.
            return True
        elif i<c<a and j<d<b and i-a== -(j-b):
            return True
        elif i>c>a and j<d<b and i-a== -(j-b):
            return True
        elif i>c>a and j>d>b and i-a==j-b:
            return True

# Arrange agents on the map
# This function MUST take two parameters as input -- the house map and the value k --
# and return a tuple of the form (new_house_map, success), where:
# - new_house_map is a new version of the map with k agents,
# - success is True if a solution was found, and False otherwise.
#
def solve(initial_house_map,k):
    fringe = [initial_house_map]
    visited = [] #We make a visited set just to add each house map to it to avoid visiting same ones more times

    while len(fringe) > 0:
        for new_house_map in successors(fringe.pop(0)):#we again change pop() to pop(0) so as to perfrom BFS and not DFS.

            if is_pichu(new_house_map) == True and new_house_map not in visited: #Making sure this house map passes our is_pichu function and therfore passes is_wall function while we check if it in in visited list
                visited.append(new_house_map) #As its not already in the list, we add it to it.
                if is_goal(new_house_map,k):
                    return(new_house_map,True)
                fringe.append(new_house_map)
    return ['',False] #If the fringe is empty that means that we have searched all possible moves without returning the goal state. So we return False.

# Main Function
if __name__ == "__main__":
    house_map=parse_map(sys.argv[1])
    # This is k, the number of agents
    k = int(sys.argv[2])
    print ("Starting from initial house map:\n" + printable_house_map(house_map) + "\n\nLooking for solution...\n")
    solution = solve(house_map, k)
    print ("Here's what we found:")
    print (printable_house_map(solution[0]) if solution[1] else "False")


known_users = ["Alice","Bob","Claire","Dan","Emma","Fred","Goergie","Hanna"]

print(len(known_users))

while True:
    print("Hi! My name is Travis")
    name = input("What is your name?: ").strip().capitalize()

    if name in known_users:
        print("Hello {}!".format(name))
        remove = input("Would you like to be removed from the list y/n?: ").lower()

        if remove =='y':
            known_users.remove(name)
            print(known_users)
    else:
        print("Hmm i don't think i have met you {}".format(name))
        add_me = input("Would you like to be added (y/n)?: ").lower()
        if add_me == "y":
            known_users.append(name)
            print(known_users)


import os
import re
import torch
from torch_geometric.data import Dataset, Data
import torch.utils.data as torch_data

def read_edge_index(filehandle):
    edge_index=[[], []]
    edge_index[0] = [int(x) for x in filehandle.readline().split()]
    edge_index[1] = [int(x) for x in filehandle.readline().split()]
    edge_index = torch.tensor(edge_index)
    return edge_index

def folder_elements(folder_name):
    if not os.path.isdir(folder_name):
        return 0
    return (len([_ for _ in os.listdir(folder_name)]))

def alphanum_key(s):
    """ Turn a string into a list of string and number chunks.
        "z23a" -> ["z", 23, "a"]
    """
    def tryint(s):
        try:
            return int(s)
        except:
            return s
    return [ tryint(c) for c in re.split('([0-9]+)', s) ]

class GraphDatasetBase(Dataset):
    def __init__(self, root, device='cuda', split='train', transform=None, pre_transform=None, less_wired=False, probp=1, probq=4):
        self.device = device
        self.less_wired = less_wired
        self.probp = probp
        self.probq = probq
        lw = '_less_wired' if self.less_wired else ''
        proot = ''
        if not(probp == 1 and probq == 4):
            proot = '_'+str(probp)+'_'+str(probq)
        root += lw
        root += proot
        print("ROOT", root)
        assert split in ['train', 'val'] or 'test' in split
        self.split = split
        # print("INIT FIN")
        super(GraphDatasetBase, self).__init__(root, transform, pre_transform)
        print("PROCESSED", self.processed_dir)

    @property
    def raw_file_names(self):
        dirname = self.raw_dir+'/'+self.split
        raw_file_names = [self.split+'/'+str(x)+'.txt' for x in range(1, folder_elements(dirname)+1)]
        return raw_file_names

    @property
    def processed_file_names(self):
        # Raw dir below is not a typo
        dirname = self.raw_dir + '/' + self.split
        processed_file_names = [self.split+'/'+str(x)+'.pt' for x in range(0, folder_elements(self.processed_dir+'/'+self.split))]
        return processed_file_names

    def __len__(self):
        if not os.path.isdir('./' + self.raw_dir+ '/' + self.split):
            self.download()
        if not os.path.isdir('./' + self.processed_dir+ '/' + self.split):
            self.process()
        return (len([_ for _ in os.listdir(self.processed_dir+'/'+self.split)]))

    def process_augmenting_iteration(self, file_handle, s, n):
            metadata = {}
            metadata['weights'] = torch.tensor([float(x) for x in file_handle.readline().split()])
            metadata['capacities'] = torch.tensor([float(x) for x in file_handle.readline().split()])

            edge_attr = torch.cat((metadata['weights'].view(-1, 1), metadata['capacities'].view(-1, 1)), dim=1)

            bf = torch.tensor([float(x) for x in file_handle.readline().split()]).unsqueeze(1)
            pred = torch.tensor([float(x) for x in file_handle.readline().split()]).unsqueeze(1)
            features = torch.cat((bf, pred), dim=1).unsqueeze(1)
            target_features = None

            for i in range(s+n+1):
                target_bf = torch.tensor([float(x) for x in file_handle.readline().split()]).unsqueeze(1)
                target_pred = torch.tensor([float(x) for x in file_handle.readline().split()]).unsqueeze(1)
                y = torch.cat((target_bf, target_pred), dim=1)
                if target_features is None:
                    target_features = y.unsqueeze(1)
                else:
                    target_features = torch.cat((target_features, y.unsqueeze(1)), dim=1)

                if i != s+n-1:
                    features = torch.cat((features, y.unsqueeze(1)), dim=1)
            return edge_attr, features, target_features, metadata

    def process_graph(self, file_handle):
        s, n = [int(x) for x in file_handle.readline().split()]
        edge_index=[[], []]
        edge_index[0] = [int(x) for x in file_handle.readline().split()]
        edge_index[1] = [int(x) for x in file_handle.readline().split()]
        edge_index = torch.tensor(edge_index)
        return s, n, edge_index

    def preload(self):
        self.preloaded_data = []
        for path in self.processed_paths:
            print(path)
            self.preloaded_data.append(torch.load(path).to(self.device))

    def download(self):
        if not os.path.isdir(self.root+'/raw'):
            if not self.less_wired:
                os.system('./gen.sh 8 8 all_iter')
            else:
                os.system('./gen.sh 8 8 all_iter_less_wired'+' '+str(self.probp)+' '+str(self.probq))

    def get(self, idx):
        if not os.path.isdir(os.path.join(self.processed_dir+'/'+self.split)):
            if not os.path.isdir(os.path.join(self.raw_dir+'/'+self.split)):
                self.download()
            self.process()

        data = torch.load(os.path.join(self.processed_dir+'/'+self.split, '{}.pt'.format(idx))).to(self.device)
        return data

class SingleIterationDataset(GraphDatasetBase):
    def process(self):
        cnt = 0
        dirname = self.processed_dir+'/'+self.split
        print("PRP", self.raw_paths)
        for raw_path in sorted(self.raw_paths, key=alphanum_key):
            with open(raw_path, "r") as raw_file:
                s, n, edge_index = self.process_graph(raw_file)

                while True:
                    edge_attr, features, target_features, metadata = self.process_augmenting_iteration(raw_file, s, n)
                    if edge_attr.nelement() == 0:
                        break
                    metadata['reachability'] = target_features[:, :, 1] != -1

                    data = Data(features, edge_index, edge_attr, y=target_features, **metadata)
                    if not os.path.isdir(os.path.join(dirname)):
                        os.mkdir(os.path.join(dirname))
                    torch.save(data, os.path.join(dirname, '{}.pt'.format(cnt)))

                    cnt += 1

class BFSSingleIterationDataset(GraphDatasetBase):

    def __init__(self, root, device='cuda', split='train', transform=None, pre_transform=None, less_wired=False, probp=1, probq=4):
        super(BFSSingleIterationDataset, self).__init__(root, device, split, transform, pre_transform, less_wired, probp, probq)

    def process(self):
        cnt = 0
        dirname = self.processed_dir+'/'+self.split
        for raw_path in sorted(self.raw_paths, key=alphanum_key):
            with open(raw_path, "r") as raw_file:
                s, n, edge_index = self.process_graph(raw_file)

                while True:
                    edge_attr, features, target_features, metadata = self.process_augmenting_iteration(raw_file, s, n)
                    if edge_attr.nelement() == 0:
                        break
                    edge_attr[:, 1] = (metadata["capacities"] > 0).float()

                    features = (features[:, :, 1] != -1).float()
                    target_features = (target_features[:, :, 1] != -1).float()

                    data = Data(features, edge_index, edge_attr, y=target_features, **metadata)
                    if not os.path.isdir(os.path.join(dirname)):
                        os.mkdir(os.path.join(dirname))
                    torch.save(data, os.path.join(dirname, '{}.pt'.format(cnt)))

                    cnt += 1

class GraphOnlyDataset(GraphDatasetBase):

    def process(self):
        cnt = 0
        dirname = self.processed_dir+'/'+self.split
        for raw_path in sorted(self.raw_paths, key=alphanum_key):
            with open(raw_path, "r") as raw_file:
                s, n, edge_index = self.process_graph(raw_file)
                edge_attr, features, target_features, metadata = self.process_augmenting_iteration(raw_file, s, n)
                data = Data(features, edge_index, edge_attr, y=target_features, **metadata)
                if not os.path.isdir(os.path.join(dirname)):
                    os.mkdir(os.path.join(dirname))
                torch.save(data, os.path.join(dirname, '{}.pt'.format(cnt)))
                cnt += 1

class GraphOnlyDatasetBFS(GraphDatasetBase):

    def process(self):
        cnt = 0
        dirname = self.processed_dir+'/'+self.split
        for raw_path in sorted(self.raw_paths, key=alphanum_key):
            with open(raw_path, "r") as raw_file:
                s, n, edge_index = self.process_graph(raw_file)
                edge_attr, features, target_features, metadata = self.process_augmenting_iteration(raw_file, s, n)
                edge_attr[:, 1] = (metadata["capacities"] > 0).float()
                features = (features[:, :, 1] != -1).float()
                target_features = (target_features[:, :, 1] != -1).float()
                data = Data(features, edge_index, edge_attr, y=target_features, **metadata)
                if not os.path.isdir(os.path.join(dirname)):
                    os.mkdir(os.path.join(dirname))
                torch.save(data, os.path.join(dirname, '{}.pt'.format(cnt)))
                cnt += 1

if __name__ == '__main__':
    f = SingleIterationDataset('./all_iter', split='test', less_wired=True, device='cpu', probp=3, probq=4)
    print(f[0].x[:, 0])
    print(f[0].capacities)
    print(f[0].num_nodes)


import matplotlib.pyplot as plt
from stable_baselines3 import PPO
from stable_baselines3.common.monitor import Monitor
from stable_baselines3.common.evaluation import evaluate_policy
from snake_env import *

plt.style.use('bmh')

env = Monitor(SnakeGameEnv())
model = PPO.load("snake_game/ppo_snake_game_1000000x10")
n_eval_ep = 100
algo_name = 'PPO'
env_name = 'SnakeGameEnv'
is_render = False
is_plot = True

rewards, ep_lens = evaluate_policy(model, env,
                                   n_eval_episodes=n_eval_ep,
                                   deterministic=True,
                                   return_episode_rewards=True,
                                   render=is_render)

mean_rewards = np.mean(rewards)
std_rewards = np.std(rewards)

mean_ep_lens = np.mean(ep_lens)
std_ep_lens = np.std(ep_lens)

print(f"Rewards: {mean_rewards:.2f} +/- {std_rewards:.2f}")
print(f"Episode length: {mean_ep_lens:.2f} +/- {std_ep_lens:.2f}")

if is_plot:

    fig, ax = plt.subplots(2, 1, figsize=(12,8))

    ax[0].plot(rewards, color='tab:blue')
    ax[0].axhline(mean_rewards, 0, n_eval_ep, color='k', linestyle='--')

    ax[1].plot(ep_lens, color='tab:orange')
    ax[1].axhline(mean_ep_lens, 0, n_eval_ep, color='k', linestyle='--')

    fig.suptitle(f"{algo_name} | {env_name} | Evaluation",fontsize=20, fontweight='bold')
    ax[0].set_title(f"Rewards: {mean_rewards:.2f} +/- {std_rewards:.2f}")
    ax[1].set_title(f"Episode length: {mean_ep_lens:.2f} +/- {std_ep_lens:.2f}")

    plt.tight_layout()
    fig.savefig(f'./{algo_name}_{env_name}.png', dpi=200)


import numpy as np

def cluster_and_label(x_lbl,y_lbl,x_unlbl,*arg,**kwargs):
    num1,_=np.shape(x_lbl)
    num2,_=np.shape(x_unlbl)
    K=np.size(np.unique(y_lbl))
    X=np.vstack((x_lbl,x_unlbl))
    y_tmp=np.ones(num2)*np.inf
    def spectral(X,k):
        num,dim=np.shape(X)
        def similar(xi,xj):
            sig=kwargs['sigma']
            return np.exp(-(np.linalg.norm(xi-xj,axis=1)**2)/2*sig**2)
        def silhouette(X,Y,K):
            num,dim=np.shape(X)
            a=np.zeros((num,1))
            b=np.zeros((num,1))
            s=np.zeros((num,1))
            def dist(pt,xt):
                num,dim=np.shape(xt)
                pt=pt.reshape(1,dim)
                Xi=np.repeat(pt,num,axis=0)
                Xj=xt
                S=np.linalg.norm(Xi-Xj,axis=1)
                return np.sum(S)/(num)
            for i in range(num):
                p=X[i,:]
                #a
                ind_i=(Y[i]==Y)
                ind_i[i]=False
                xt=X[ind_i,:]
                a[i,0]=dist(p,xt)
                #b
                ttmp=[]
                for j in range(K):
                    if j==Y[i]:
                        continue
                    xt=X[j==Y,:]
                    tmp=dist(p,xt)
                    ttmp.append(tmp)
                b[i,0]=np.min(np.array(ttmp))
                #s
                if a[i,0]==b[i,0]:
                    s[i,0]=0
                if a[i,0]<=b[i,0]:
                    s[i,0]=1-a[i,0]/b[i,0]
                if a[i,0]>=b[i,0]:
                    s[i,0]=b[i,0]/a[i,0]-1
            #avg s
            s_avg=np.mean(s.flatten())
            return(s_avg)
        def kmean_pp(x,k):
            row,col=np.shape(x)
            itr=0
            D=np.empty((row,k))
            Cp=np.empty((k,col))
            #Step 1: Centroid intialisation
            def kpp(X,K):
                pts,dim=np.shape(X)
                #1 st centre
                c=np.zeros((K,dim))
                tmp=np.random.randint(0,pts)
                c[0,:]=X[int(tmp),:]
                #centres drawn from distributioin of normalised distance from neareat centre
                D=np.ones((pts,K-1))
                D=D*np.inf
                for i in range(1,K):
                    #distance matrix
                    D[:,i-1]=(np.linalg.norm(X-c[i-1,:],axis=1))**2
                    #nearest centre
                    D=np.sort(D,axis=1)
                    xt=D[:,0]
                    pdf=(xt)/np.sum(xt)
                    cdf=np.cumsum(pdf)
                    tmp=np.random.uniform(0,1,1)
                    tmp2=np.where(cdf>=tmp)[0][0]
                    c[i,:]=X[tmp2,:]
                return c
            big_score=0
            for i in range(20):
                C=kpp(x,k)
                while True:
                    if row<k:
                        print('Number of centroids exceeds the number of points')
                        break
                    itr=itr+1
                    #Step 2: Distance matrix
                    for i in range(row):
                        for j in range(k):
                            D[i,j]=np.linalg.norm(x[i,:]-C[j,:])
                    #Step 3: Cluster assignment
                    y=np.argmin(D,axis=1)
                    if np.size(np.unique(y))!=k:
                        itr=0
                        C=kpp(x,k)
                        continue
                    #Step 4: Update Centroid
                    Cp[:]=C[:]
                    for i in range(k):
                        cnd=(i*np.ones_like(y)==y)
                        xg=x[cnd,:]
                        C[i,:]=np.mean(xg,axis=0)
                    #Step 5: Stopping criterion
                    distm=np.linalg.norm(C-Cp,ord='fro')
                    if distm==0:
                        break
                score=silhouette(x,y,k)
                if score>=big_score:
                    big_score=score
                    Y=y
            return(Y)
        #step 1: Similarity matrix
        Xi=np.repeat(X,num,axis=0)
        Xj=np.tile(X,(num,1))
        S=similar(Xi,Xj).reshape(num,num)
        #step 2: Degree matrix
        D=np.identity(num)
        tS=np.sum(S,axis=1)
        D=D*tS
        #Step 3: Laplacian matrix
        if kwargs['laplacian']=='symmetric':
            tD=np.linalg.cholesky(D)
            tD=np.linalg.inv(tD)
            L=np.identity(num)-np.dot(tD,np.dot(S,tD))
        if kwargs['laplacian']=='random-walk':
            L=np.identity(num)-np.dot(np.linalg.inv(D),S)
        if kwargs['laplacian']=='unnormalised':
            L=D-S
        #Step 4: Eignvalues (Following steps reduce dimension, similar points comes closerr with this step)
        val,vec=np.linalg.eig(L)
        ind=np.argsort(val)
        val=val[ind]
        vec=vec[:,ind]
        #Step 5: first k eignvalues(smallest)
        V=vec[:,0:k]
        #Step 6: Kmean clsutering
        Y=kmean_pp(V,k)
        return(Y)
    def KNN(x_train,y_train,x_test,k,*args):
        n1,d=np.shape(x_train)
        n2,d=np.shape(x_test)
        y_test=np.zeros(n2)
        def mode(x):
            labels=np.unique(x)
            count_list=np.empty_like(labels)
            for i in range(labels.shape[0]):
                count=0
                for j in range(x.shape[0]):
                    if labels[i]==x[j]:
                        count+=1
                count_list[i]=count
            max_ind=np.argmax(count_list)
            return(labels[max_ind],count_list[max_ind])
        def cityblock(u,v):
            d=0
            for i in range(u.shape[0]):
                d=d+np.abs(u[i]-v[i])
            return d
        def minkowsky(u,v):
            dtmp=0
            for i in range(u.shape[0]):
                dtmp=dtmp+np.abs(u[i]-v[i])**2
            d=dtmp**0.5
            return d
        def hamming(u,v):
            c=0
            for i in range(u.shape[0]):
                if u[i]!=v[i]:
                    c+=1
            d=c/u.shape[0]
            return d
        def euclidean(u,v):
            dtmp=0
            for i in range(u.shape[0]):
                dtmp=dtmp+np.abs(u[i]-v[i])**2
            d=dtmp**0.5
            return d
        for i in range(n2):
            dist=np.zeros(n1)
            for j in range(n1):
                if args=='cityblock':
                    dist[j]=cityblock(x_test[i,:],x_train[j,:])
                elif args=='minkowsky':
                    dist[j]=minkowsky(x_test[i,:],x_train[j,:])
                elif args=='hamming':
                    dist[j]=hamming(x_test[i,:],x_train[j,:])
                else:
                    dist[j]=euclidean(x_test[i,:],x_train[j,:])
            dist=np.argsort(dist)
            tmp=dist[0:k]
            tmp2=y_train[tmp]
            temp3=mode(tmp2)
            y_test[i]=temp3[0]
        return y_test
    #Step 1: Cluster the data
    cls=spectral(X,K)
    Y=np.hstack((y_lbl,y_tmp))
    #Step 2: for each cluster predict the class
    for i in range(K):
        ind1=(i==cls)
        ind2=np.where(Y[ind1]!=np.inf)
        ind3=np.where(Y[ind1]==np.inf)
        Y[ind3]=KNN(X[ind2[0],:],Y[ind2[0]],X[ind3[0],:],K)
    #Step 3: Train classifier on the overall dataset and test on the unlabelled dataset
    Y_final=KNN(X,Y,x_unlbl,K)
    return(Y_final)


# -*- coding: utf-8 -*-
import json
import posix_ipc as ipc

from flask import Flask, jsonify, render_template
from flask_socketio import SocketIO, send, emit
from service.chartService import ChartService
from service.brewconfig import BrewConfig
from service.ipchelper import prepare_data, TYPE_CONTROL, CONTROL_NEXT

__author__ = 'oli@fesseler.info'
__version__ = ('0', '0', '1')

app = Flask(__name__)
app.config["JSON_SORT_KEY"] = False
app.config['SECRET_KEY'] = 'secret!braubar!mhh!BIER!'
socketio = SocketIO(app, async_mode='eventlet')
thread = None
cs = ChartService()

@app.route('/')
def index():
    recipe_file = open(BrewConfig.RECIPE_FILE)
    recipe = json.load(recipe_file)
    print(cs.status(brew_id))
    print(recipe)
    return render_template('index.html',
                           brew_id=brew_id,
                           brew_state=cs.status(brew_id),
                           brew_recipe=recipe)

@socketio.on("connected")
def handle_connected(connected_msg):
    emit("fullchart", cs.brew_chart(brew_id=brew_id))
    print(connected_msg)

@socketio.on("update chart")
def handle_update(update_msg):
    socketio.emit("update chart", json.dumps(cs.status(brew_id=brew_id)))
    print("emitted update chart after message: ", update_msg)

@socketio.on("next")
def next_state(next):
    msg = {"ok": False, "status": None}
    try:
        msg["status"] = cs.status(brew_id)
        print("status:", cs.status(brew_id))
        if write_to_queue(CONTROL_NEXT):
            print("write to queue worked")
            msg["ok"] = True
    except Exception as e:
        print("flask_app error:", e)
    finally:
        socketio.emit("next", json.dumps(msg))

@app.route('/start')
def brew_start():
    return "Not Implemented"

@app.route('/status')
def status():
    return jsonify(cs.status(brew_id))

@app.route('/status/brew')
def brew_state():
    return cs.brew_status(brew_id=brew_id)

@app.route('/status/system')
def system_state():
    return cs.system_status(brew_id=brew_id)

@app.route('/next')
def next_state():
    msg = {"ok": False, "status": None}
    try:
        msg["status"] = cs.status(brew_id)
        if write_to_queue(CONTROL_NEXT):
            msg["ok"] = True
    except Exception as e:
        print("error: ", e)

    finally:
        return jsonify(msg)

@app.route('/temp')
def temp():
    return "Not Implemented"

@app.route('/chart/data')
def chart_data():
    a = cs.brew_chart(brew_id=brew_id)
    print(a)
    return a

@app.route('/chart/last_row')
def last_row():
    return jsonify(cs.last_row(brew_id=brew_id))

def write_to_queue(control):
    try:
        msg = {"control": control}
        queue = ipc.MessageQueue(name=BrewConfig.BRAUBAR_QUEUE)
        queue.send(prepare_data(TYPE_CONTROL, msg).encode(encoding=BrewConfig.QUEUE_ENCODING), timeout=5)
    except ipc.ExistentialError as e:
        print("IPC Extential Error happened", e)
        queue.close()
        return False
    except ipc.BusyError as e:
        print("socket busy error: write_to_queue", e)
        queue.close()
        return False
    except Exception as e:
        print("error: ", e)

    return True

if __name__ == "__main__":
    import argparse

    # config.BrewConfig.CONFIG_FILE = "/home/oli/dev/braubar-pi/config/config.json"
    # config.BrewConfig.RECIPE_FILE = "/home/oli/dev/braubar-pi/config/recipe.json"

    parser = argparse.ArgumentParser(description="BrauBar webserver at your service.")
    parser.add_argument('--host', help="IP-Address to listen on. Default is 0.0.0.0", default="0.0.0.0")
    parser.add_argument('-i', '--id', help="brew_id to identify the current brew process. "
                                           "if no id is given, it shall return all brews")
    args = parser.parse_args()
    try:
        host = args.host
        brew_id = args.id
        # start app in debugmode
        app.debug = True
        socketio.run(app, host=host)
    finally:
        print("good beer, see ya")


import os
import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
from torch.utils.data import Dataset, DataLoader

import pandas as pd
import SimpleITK as sitk
from skimage.measure import label, regionprops
from scipy import signal
import math
import re
import pdb

class BrainDataset(Dataset):
    def __init__(self, csv_file, dataset_dir, label_dir, mode='train', sigma=5, z_size=40, heatmap_on=False, focus_on_small=False):

        self.mode = mode
        self.dataset_dir = dataset_dir
        self.label_dir = label_dir
        colnames = ['data', 'weight']
        self.csv = pd.read_csv(csv_file, header=None, names=colnames)
        self.data_index = self.csv.data.tolist()
        self.weightList = self.csv.weight.tolist()
        self.sigma = sigma
        self.z_slice = z_size
        self.heatmap_on = heatmap_on
        self.focus_on_small = focus_on_small

        self.dataList = []
        self.labelList = []

        print('start loading data')
        for i in range(len(self.data_index)):
            img = sitk.ReadImage(self.dataset_dir + self.data_index[i] + '_data.nii.gz')
            npImg = sitk.GetArrayFromImage(img)
            npImg = (npImg+100) / 1000

            lab = sitk.ReadImage(self.label_dir + self.data_index[i] + '_label.nii.gz')
            npLab = sitk.GetArrayFromImage(lab)

            npImg, npLab = self.init_pad(npImg, npLab)

            self.dataList.append(npImg)
            self.labelList.append(npLab)

        print('load done, length of dataset:', len(self.dataList))
        if self.heatmap_on:
            print('start generate heatmap')
            self.heatmapList = self._generate_heatmap(self.labelList)
            print('generate done')

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

    def __getitem__(self, idx):
        #with torch.cuda.device(1):
        image = self.dataList[idx]
        label = self.labelList[idx]
        tmp = self.weightList[idx]
        tmp = re.split('\.|\[|\]', tmp)
        while '' in tmp:
            tmp.remove('')
        weight = np.array(tmp).astype(np.float32)

        tensor_image = torch.from_numpy(image).cuda().float().unsqueeze(0).unsqueeze(0)
        tensor_label = torch.from_numpy(label).cuda().long().unsqueeze(0).unsqueeze(0)
        tensor_weight = torch.from_numpy(weight).cuda().float()
        if self.heatmap_on:
            tensor_heatmap = self.heatmapList[idx].cuda().float().unsqueeze(0)
        else:
            tensor_heatmap = None

        if self.mode == 'train':
            tensor_image, tensor_label, tensor_heatmap = self.random_zoom_rotate(tensor_image, tensor_label, tensor_heatmap)

        tensor_image, tensor_label, tensor_heatmap = self.randcrop(tensor_image, tensor_label, tensor_heatmap)
        assert tensor_image.shape == tensor_label.shape

        if self.heatmap_on:
            return tensor_image.float(), tensor_label.long(), tensor_weight.float(), tensor_heatmap.float()
        else:
            return tensor_image.float(), tensor_label.long(), tensor_weight.float()

    def randcrop(self, img, label, heatmap):
        _, _, D, H, W = img.shape

        diff_D = D - self.z_slice
        diff_H = H - 192
        diff_W = W - 192

        if self.mode == 'train':
            if self.focus_on_small:
                if np.random.random() > 0.1:
                    rand_z = np.random.randint(diff_D-10, diff_D)
                else:
                    rand_z = np.random.randint(0, diff_D)
            else:
                rand_z = np.random.randint(0, diff_D)
            rand_x = np.random.randint(0, diff_H)
            rand_y = np.random.randint(0, diff_W)

            croped_img = img[0, :, rand_z:rand_z+self.z_slice, rand_x:rand_x+192, rand_y:rand_y+192]
            croped_lab = label[0, :, rand_z:rand_z+self.z_slice, rand_x:rand_x+192, rand_y:rand_y+192]
            if heatmap is not None:
                croped_heatmap = heatmap[0, :, rand_z:rand_z+self.z_slice, rand_x:rand_x+192, rand_y:rand_y+192]

        else:
            if self.focus_on_small:
                if np.random.random() > 0.1:
                    rand_z = np.random.randint(diff_D-10, diff_D)
                else:
                    rand_z = np.random.randint(0, diff_D)
            else:
                rand_z = np.random.randint(0, diff_D)

            rand_x = np.random.randint(0, diff_H)
            rand_y = np.random.randint(0, diff_W)

            croped_img = img[0, :, rand_z:rand_z+self.z_slice, rand_x:rand_x+192, rand_y:rand_y+192]
            croped_lab = label[0, :, rand_z:rand_z+self.z_slice, rand_x:rand_x+192, rand_y:rand_y+192]
            if heatmap is not None:
                croped_heatmap = heatmap[0, :, rand_z:rand_z+self.z_slice, rand_x:rand_x+192, rand_y:rand_y+192]
        if heatmap is None:
            croped_heatmap = None

        return croped_img, croped_lab, croped_heatmap

    def random_zoom_rotate(self, img, label, heatmap):
        scale_z = np.random.random() * 0.2 + 0.9
        scale_x = np.random.random() * 0.2 + 0.9    # 0.6 0.7
        scale_y = np.random.random() * 0.2 + 0.9

        theta_scale = torch.tensor([[scale_z, 0, 0, 0],
                                    [0, scale_x, 0, 0],
                                    [0, 0, scale_y, 0],
                                    [0, 0, 0, 1]]).float().cuda()
        angle_z = (float(np.random.randint(-5, 5)) / 180.) * math.pi
        angle_x = (float(np.random.randint(-10, 10)) / 180.) * math.pi
        angle_y = (float(np.random.randint(-10, 10)) / 180.) * math.pi

        theta_rotate_z = torch.tensor( [[1, 0, 0, 0],
                                        [0, math.cos(angle_z), -math.sin(angle_z), 0],
                                        [0, math.sin(angle_z), math.cos(angle_z), 0],
                                        [0, 0, 0, 1]]).float().cuda()
        theta_rotate_x = torch.tensor( [[math.cos(angle_x), 0, math.sin(angle_x), 0],
                                        [0, 1, 0, 0],
                                        [-math.sin(angle_x), 0, math.cos(angle_x), 0],
                                        [0, 0, 0, 1]]).float().cuda()
        theta_rotate_y = torch.tensor( [[math.cos(angle_y), -math.sin(angle_y), 0, 0],
                                        [math.sin(angle_y), math.cos(angle_y), 0, 0],
                                        [0, 0, 1, 0],
                                        [0, 0, 0, 1]]).float().cuda()
        theta = torch.mm(theta_rotate_z, theta_rotate_x)
        theta = torch.mm(theta, theta_rotate_y)
        theta = torch.mm(theta, theta_scale)[0:3, :]

        theta = theta.unsqueeze(0)
        grid = F.affine_grid(theta, img.size()).cuda()
        img = F.grid_sample(img, grid, mode='bilinear', padding_mode='border')
        label = F.grid_sample(label.float(), grid, mode='nearest').long()
        if heatmap is not None:
            heatmap = F.grid_sample(heatmap, grid, mode='bilinear').float()

        return img, label, heatmap

    def init_pad(self, npImg, npLab):
        d, h, w = npImg.shape

        if d < 75:
            diff = 75 - d
            npImg = np.pad(npImg, ((diff, 0), (0, 0), (0,0)), mode='edge')
            npLab = np.pad(npLab, ((diff, 0), (0, 0), (0, 0)), mode='constant')

        return npImg, npLab

    def _generate_heatmap(self, labelList):

        center_map_list = []
        for label in labelList:
            D, H, W = label.shape
            center_map = np.zeros([3, D, H, W])
            region = regionprops(label)
            for i in range(len(region)):
                if region[i].label == 2:
                    (z, x, y) = region[i].centroid
                    z, x, y = int(round(z)), int(round(x)), int(round(y))
                    center_map[0, z, x, y] = 1
                if region[i].label == 4:
                    (z, x, y) = region[i].centroid
                    z, x, y = int(round(z)), int(round(x)), int(round(y))
                    center_map[1, z, x, y] = 1
                if region[i].label == 5:
                    (z, x, y) = region[i].centroid
                    z, x, y = int(round(z)), int(round(x)), int(round(y))
                    center_map[2, z, x, y] = 1
            center_map_list.append(center_map)

        heatmap_list = self._gaussian_map(center_map_list)

        return heatmap_list

    def _gaussian_map(self, center_map_list):
        heatmap_list = []

        for center_map in center_map_list:
            _, d, h, w = center_map.shape
            D1 = torch.linspace(1, d, d)
            H1 = torch.linspace(1, h, h)
            W1 = torch.linspace(1, w, w)
            [D, H, W] = torch.meshgrid(D1, H1, W1)
            z, x, y = np.where(center_map[0, :, :, :])
            DD = D - (z[0]+1)
            HH = H - x[0]
            WW = W - y[0]

            cube = DD*DD + HH*HH + WW*WW
            cube /= (2. * self.sigma * self.sigma)
            cube = torch.exp(-cube)
            cube[0:z[0]-1, :, :] = 0
            cube[z[0]+2:, :, :] = 0
            cube = cube.unsqueeze(0)

            for i in range(1, 3):
                z, x, y = np.where(center_map[i, :, :, :])
                DD = D - (z[0]+1)
                HH = H - x[0]
                WW = W - y[0]

                tmp_cube = DD*DD + HH*HH + WW*WW
                tmp_cube /= ( 2. * self.sigma * self.sigma)
                tmp_cube = torch.exp(-tmp_cube)
                tmp_cube[0:z[0]-1, :, :] = 0
                tmp_cube[z[0]+2:, :, :] = 0
                tmp_cube = tmp_cube.unsqueeze(0)
                cube = torch.cat((cube, tmp_cube), dim=0)

            cube[cube < 0.01] = 0
            heatmap_list.append(cube)
        return heatmap_list

if __name__ == '__main__':
    import matplotlib.pyplot as plt

    data_path = '/data/head/MICCAI2015/dataset/240dataset/'
    csv_file = '/data/head/MICCAI2015/dataset/new_test.csv'

    dataset = BrainDataset(csv_file, data_path, data_path, mode='train', heatmap_on=True)
    dataloader = DataLoader(dataset, batch_size=1, shuffle=True)

    for i, (img, label, weight, heatmap) in enumerate(dataloader):
        print(i, img.shape, label.shape, heatmap.shape, weight )
        if heatmap.max() == 0:
            continue
        for j in range(img.shape[2]):
            if heatmap[0, 0, j, :, :].max() < 0.1:
                continue
            else:
                print(heatmap[0, 0, j, :, :].max())
            plt.subplot(2,3,1)
            plt.imshow(img.cpu().numpy()[0, 0, j, :, :])
            plt.subplot(2,3,2)
            plt.imshow(label.cpu().numpy()[0, 0, j, :, :])
            plt.subplot(2,3,3)
            plt.imshow(heatmap.cpu().numpy()[0, 0, j, :, :])
            plt.subplot(2,3,4)
            plt.imshow(heatmap.cpu().numpy()[0, 1, j, :, :])
            plt.subplot(2,3,5)
            plt.imshow(heatmap.cpu().numpy()[0, 2, j, :, :])

            plt.subplot(2,3,6)
            plt.imshow(heatmap.cpu().numpy()[0, 0, j, :, :] + heatmap.cpu().numpy()[0, 1, j, :, :] + heatmap.cpu().numpy()[0, 2, j, :, :])

            plt.show()


# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from builtins import object
from django.conf import settings
from django.http import Http404
from django.db import transaction, OperationalError, IntegrityError
from django.db.models import Max
from django.apps import apps
from django.shortcuts import get_object_or_404
from django.core.exceptions import ObjectDoesNotExist

try:
	from django.core.exceptions import FieldDoesNotExist
except ImportError:
	from django.db.models.fields import FieldDoesNotExist

from e89_syncing.apps import E89SyncingConfig
from e89_syncing.syncing_utils import *
from e89_tools.tools import camelcase_underscore
import time
from rest_framework.exceptions import ValidationError

def saveNewData(user, timestamp, timestamps, device_id, data, files, platform = None, app_version = None):
	''' Percorre todos os SyncManagers solicitando que salvem os dados correspondentes.'''
	response = {}
	new_objects = {}
	for key in list(data.keys()):
		sync_manager = E89SyncingConfig.get_sync_manager(key)
		if sync_manager is not None:
			attempts = 0
			while attempts < 3:
				try:
					with transaction.atomic():
						manager_response,objects = sync_manager.saveNewData(user = user, device_id = device_id, data = data[key], files = files, platform = platform, app_version = app_version)
						break
				except OperationalError as e:
					attempts += 1
					time.sleep(0.2)
					if attempts == 3:
						raise e

			with transaction.atomic():
				response.update(manager_response)
				new_objects[sync_manager.getIdentifier()] = [o.id for o in objects if o is not None]

	new_data = getModifiedData(user = user,
							timestamp = timestamp,
							timestamps = timestamps,
							exclude = new_objects,
							platform = platform,
							app_version = app_version)
	response.update(new_data)

	return response

def getModifiedData(user, timestamps, timestamp = None, exclude = {}, platform = None, app_version = None):
	''' Percorre todos os SyncManagers solicitando que retornem quaisquer dados a serem
		enviados ao client correspondente. O parâmetro exclude é um dicionário
		de listas contendo ids que não devem ser buscados não query. Ex:

		exclude = {
					"identifier1":[1,2,3],
					"identifier2":[1,2],
					...
				  }
		'''
	data = {"timestamps":{}}
	coupled_sync_managers = []
	for sync_manager in E89SyncingConfig.get_sync_managers():
		identifier = sync_manager.getIdentifier()
		coupled = E89SyncingConfig.get_coupled_sync_managers(identifier)
		if timestamps:
			timestamp = timestamps.get(identifier, None)
			if timestamp is None and identifier not in coupled_sync_managers:
				continue
			else:
				if timestamp is None and identifier in coupled_sync_managers:
					for coupled_identifier in coupled:
						timestamp = timestamps.get(coupled_identifier, None)
						if timestamp is not None:
							break

				# coupled sync managers can send data in the same request
				for sm in coupled: coupled_sync_managers.append(sm)

		timestamp = timestamp_to_datetime(timestamp)
		manager_data,manager_parameters, new_timestamp = sync_manager.getModifiedData(user = user, timestamp = timestamp, exclude = exclude.get(identifier,[]), platform = platform, app_version = app_version)
		manager_parameters['data'] = manager_data
		data[identifier] = manager_parameters

		if new_timestamp is None:
			new_timestamp = timestamp

		# Synchronizing timestamps across coupled sync managers
		for sm in coupled:
			current_timestamp = data["timestamps"].get(sm)
			if current_timestamp is None:
				data["timestamps"][sm] = new_timestamp
			else:
				new_timestamp = max(new_timestamp, current_timestamp)
				data["timestamps"][sm] = new_timestamp

		data["timestamps"][identifier] = new_timestamp

	# Converting all timestamps to strings
	for key, value in list(data["timestamps"].items()):
		data["timestamps"][key] = datetime_to_timestamp(value)

	SyncLog = apps.get_model('e89_syncing','SyncLog')
	SyncLog.objects.store_timestamps(user, data["timestamps"])

	data["timestamp"] = get_new_timestamp() # Only to maintain compatibility
	return data

def getExpiredTokenResponse():
	''' Returns an empty response to all sync managers. Used when replying to a user that
		is not allowed to access data.'''

	data = {}
	for sync_manager in E89SyncingConfig.get_sync_managers():
		identifier = sync_manager.getIdentifier()
		data[identifier] = {'data':[]}

	expirable_token = getattr(settings, 'SYNC_EXPIRABLE_TOKEN', False)
	if expirable_token:
		data['expiredToken'] = {'data': [], 'expiredToken':True}
	else:
		data['logout'] = {'data':[],'logout':True}

	data["timestamp"] = get_new_timestamp() # Only to maintain compatibility
	data["timestamps"] = {}

	return data

def getModifiedDataForIdentifier(user, parameters, identifier, timestamps, platform = None, app_version = None):
	''' Busca dados especificamente para um identifier. Utilizado por clientes que
		implementam cache parcial. '''

	sync_manager = E89SyncingConfig.get_sync_manager(identifier)
	if sync_manager is None:
		raise Http404
	timestamp = timestamps.get(sync_manager.getIdentifier(), "")
	timestamp = timestamp_to_datetime(timestamp)
	manager_data,manager_parameters, new_timestamp = sync_manager.getModifiedData(user = user, timestamp = timestamp, parameters = parameters, platform = platform, app_version = app_version)
	manager_parameters['data'] = manager_data

	if new_timestamp is None:
		new_timestamp = timestamp

	data = {identifier:manager_parameters}
	if identifier in timestamps: # Not paginating, but updating
		coupled = E89SyncingConfig.get_coupled_sync_managers(identifier)
		if not coupled:
			data["timestamps"] = {identifier:datetime_to_timestamp(new_timestamp)}
		else:
			data["timestamps"] = {}
			for sm in coupled:
				coupled_sync_manager = E89SyncingConfig.get_sync_manager(sm)
				coupled_data,coupled_parameters, new_coupled_timestamp = coupled_sync_manager.getModifiedData(user = user, timestamp = timestamp, parameters = parameters, platform = platform, app_version = app_version)
				coupled_parameters['data'] = coupled_data
				data[sm] = coupled_parameters
				if new_coupled_timestamp is not None:
					new_timestamp = max(new_timestamp, new_coupled_timestamp)

				data["timestamps"][identifier] = new_timestamp
				data["timestamps"][sm] = new_timestamp

			# Converting all timestamps to strings
			for key, value in list(data["timestamps"].items()):
				data["timestamps"][key] = datetime_to_timestamp(value)

		SyncLog = apps.get_model('e89_syncing','SyncLog')
		SyncLog.objects.store_timestamps(user, data["timestamps"])
	return data

class BaseSyncManager(object):

	def getIdentifier(self):
		''' Retorna um identificador utilizado na comunicação JSON.
			Por exemplo, se o identificador for "teste", ao enviar dados ao client,
			o JSON criado será:
			{
				...
				"teste": [obj1, obj2, ...],
				...
			}

			'''
		if hasattr(self, "identifier"):
			return self.identifier
		else:
			raise NotImplementedError

	def getResponseIdentifier(self):
		''' Deve retornar um identificador para a resposta de recebimento de dados
			do client. Para'''
		if hasattr(self, "response_identifier"):
			return self.response_identifier
		else:
			raise NotImplementedError

	def getModifiedData(self, user, timestamp, parameters = None, exclude = [], platform = None, app_version = None):
		''' Searches for new data to be sent. Must return a list of serialized items and a dictionary
			containing parameters that should be passed back to the client.
			The exclude parameter is a list of object ids that must not be considered in the query.'''
		pass

	def saveNewData(self, user, device_id, data, files = None, platform = None, app_version = None):
		''' Saves new data received. Must return 2 objects:
			1. A dictionary that contains a list with data to be sent in response.
			   The key in the dictionary MUST be equal to the response identifier.
				For instance:
					{
						"news_id":[
							{"id":2,"id_client":1},
							...
						]
					}
			2. List with all the objects that were created
			'''

		response = []
		new_objects = []
		for object in data:
			object_response, new_object = self.saveObject(user = user, device_id = device_id, object = object, files = files, platform = platform, app_version = app_version)
			response.append(object_response)
			new_objects.append(new_object)

		return {self.getResponseIdentifier():response},new_objects

	def saveObject(self, user, device_id, object, files = None, platform = None, app_version = None):
		''' Saves an object in the database. Must return 2 objects:
			1. A dictionary containing data to be sent in response to the client.
			For example: {"id":1,"id_client":3}.
			2. The object that was saved in the database.'''

		pass

	def serializeObject(self, object):
		''' This method is responsible for transforming an object into a dictionary
			that will be converted to json later. It must return a dictionary. '''
		pass

	def check_has_field(self, Model, field_name):
		try:
			field = Model._meta.get_field(field_name)
			return True
		except FieldDoesNotExist:
			return False

class DefaultTimestampGenerator(object):
	timestamp_field = "timestamp"

	def __init__(self, timestamp_field = None):
		if timestamp_field is not None:
			self.timestamp_field = timestamp_field

	def getNewTimestamp(self, objects, user):
		return objects.values(self.timestamp_field).aggregate(new_timestamp=Max(self.timestamp_field))['new_timestamp']

class ModelToSendTimestampGenerator(DefaultTimestampGenerator):
	app_model = ''
	to_send_timestamp_field = "timestamp"
	user_field = "user"

	def getNewTimestamp(self, objects, user):
		default_timestamp = super(ModelToSendTimestampGenerator, self).getNewTimestamp(objects, user)

		ModelToSend = apps.get_model(self.app_model + 'ToSend')
		model_fk = camelcase_underscore(self.app_model.split('.')[1]) + '_id'

		fkargs = {
			"%s__in"%(model_fk): objects.values_list("id", flat=True),
			self.user_field: user
		}

		to_send_timestamp = ModelToSend.objects.filter(**fkargs).values(self.to_send_timestamp_field).aggregate(new_timestamp=Max(self.to_send_timestamp_field))['new_timestamp']

		if to_send_timestamp is not None and default_timestamp is not None:
			return max(default_timestamp, to_send_timestamp)
		else:
			return default_timestamp

class AbstractSyncManager(BaseSyncManager):
	app_model = ''
	page_size = 10
	serializer = None
	serializer_context_user_key = None
	prefetch_params = []
	allow_creation = False
	pagination_parameter = "max_date"
	extra_serializer_kwargs = {}
	timestamp_field = None
	timestamp_generator_class = DefaultTimestampGenerator

	def getModifiedData(self, user, timestamp, parameters = None, exclude = [], platform = None, app_version = None):
		''' Searches for new data to be sent. Must return a list of serialized items and a dictionary
			containing parameters that should be passed back to the client.
			The exclude parameter is a list of object ids that must not be considered in the query.'''

		# Total of 8 queries
		is_paginating_or_first_fetch = self._check_is_paginating(parameters) or timestamp == FIRST_TIMESTAMP
		if parameters is None:
			parameters = {}
		merged_exclude = set(exclude + parameters.pop('exclude',[]))

		# Loading models and getting user
		Model = apps.get_model(self.app_model)

		# Fetching objects and paginating
		objects = Model.objects.get_sync_items(user=user,timestamp=timestamp, **parameters).prefetch_related(*self.getPrefetchParams(user, timestamp, **parameters))
		new_timestamp = self.getNewTimestamp(objects, user=user)
		objects = objects.exclude(id__in=merged_exclude)

		response_parameters = {}
		if self.page_size is not None:
			response_parameters = self._get_pagination_response_parameters(objects, timestamp, parameters, is_paginating_or_first_fetch)

		if self.page_size is not None:
			objects = objects[:self.page_size]

		# Serialization
		user_key = self.serializer_context_user_key if self.serializer_context_user_key else "user"
		extra_serializer_kwargs = self.extra_serializer_kwargs or {}
		s = self.serializer(list(objects), context={user_key:user, 'timestamp': timestamp, 'platform': platform, 'app_version': app_version}, many=True, **extra_serializer_kwargs)
		serialized = s.data
		return serialized, response_parameters, new_timestamp

	def getPrefetchParams(self, user, timestamp, **kwargs):
		''' Must return an array of prefetch params. These may be Prefetch objects. '''
		return self.prefetch_params

	def getNewTimestamp(self, objects, user):
		return self.timestamp_generator_class(self.timestamp_field).getNewTimestamp(objects, user)

	def getExtraSerializerKwargs(self):
		return {}

	def _get_number_new_items(self, objects, timestamp, is_paginating_or_first_fetch):
		return len(objects) if type(objects) == type([]) else objects.count()

	def _get_pagination_response_parameters(self, objects, timestamp, request_params, is_paginating_or_first_fetch):
		''' Returns the pagination parameters necessary for the client to know what to do.
			It checks to see if there are more items in the server than the ones being sent
			and checks if there is a gap between the data the user has and what is in the server,
			in which case the client must delete all its cached items.'''

		response_parameters = {}
		number_items = self._get_number_new_items(objects, timestamp, is_paginating_or_first_fetch)
		if is_paginating_or_first_fetch:
			response_parameters['more'] = self.page_size < number_items
		else:
			response_parameters['deleteCache'] = number_items > self.page_size
			if response_parameters['deleteCache']:
				response_parameters['more'] = True
		return response_parameters

	def _check_is_paginating(self, parameters):
		return parameters is not None and self.pagination_parameter in parameters

	def saveNewData(self, user, device_id, data, files = None, platform = None, app_version = None):
		''' Saves new data received. Must return 2 objects:
			1. A dictionary that contains a list with data to be sent in response.
			   The key in the dictionary MUST be equal to the response identifier.
				For instance:
					{
						"news_id":[
							{"id":2,"id_client":1},
							...
						]
					}
			2. List with all the objects that were created
			3. The new timestamp, based on the items that were created
			'''
		response = []
		new_objects = []
		for object in data:
			try:
				object_response, new_object = self.saveObject(user = user, device_id = device_id, object = object, files = files, platform = platform, app_version = app_version)
				response.append(object_response)
				new_objects.append(new_object)
			except Http404:
				self.handleObjectNotFound(user = user, device_id = device_id, object = object, files = files, platform = platform, app_version = app_version)

		return {self.getResponseIdentifier():response},new_objects

	def isAllowed(self, user, device_id, object, files = None, platform = None, app_version = None):
		''' Returns True if the object can be created/updated or False otherwise.'''
		return True

	def saveObject(self, user, device_id, object, files = None, platform = None, app_version = None):
		''' Saves an object in the database. Must return 2 objects:
			1. A dictionary containing data to be sent in response to the client.
			For example: {"id":1,"id_client":3}.
			2. The object that was saved in the database.'''

		if not self.isAllowed(user=user, device_id=device_id, object=object, files=files, platform=platform, app_version=app_version):
			return {"idClient": object.get("idClient"), "id":-1}, None

		Model = apps.get_model(self.app_model)
		device_id = object.get("deviceId", device_id)
		if self.check_has_field(Model, 'idClient') and "idClient" in object and device_id is not None and Model.objects.filter(idClient=object['idClient'], deviceId=device_id).exists():
			instance = Model.objects.filter(idClient=object['idClient'], deviceId=device_id).first()
		elif "id" in object:
			instance = get_object_or_404(Model,id=object['id'])
		elif self.allow_creation:
			instance = None # Creating object
		else:
			raise Http404
		user_key = self.serializer_context_user_key if self.serializer_context_user_key else "user"

		if instance is None and self.check_has_field(Model, 'deviceId'):
			object['deviceId'] = device_id

		extra_serializer_kwargs = self.extra_serializer_kwargs or {}
		s = self.serializer(instance, data=object, context={user_key:user,'device_id':device_id, 'files':files}, **extra_serializer_kwargs)
		try:
			with transaction.atomic():
				s.is_valid(raise_exception=True)
				saved_obj = s.save(**object)
		except ValidationError as e:
			if self.allow_creation and "non_field_errors" in s._errors:
				try:
					saved_obj = Model.objects.get(idClient=object["idClient"], deviceId=device_id)
				except Model.DoesNotExist:
					raise e
			else:
				raise e
		except IntegrityError as e:
			try:
				saved_obj = Model.objects.get(idClient=object["idClient"], deviceId=device_id)
			except Model.DoesNotExist:
				raise e

		return {"id":saved_obj.id, "idClient":object.get("idClient", None)},saved_obj

	def serializeObject(self, object):
		''' This method is responsible for transforming an object into a dictionary
			that will be converted to json later. It must return a dictionary. '''

		return {}

	def handleObjectNotFound(self, user, device_id, object, files = None, platform = None, app_version = None):
		raise Http404

class ObjectDeletedSyncManager(BaseSyncManager):
	app_model = ''
	owner_attr = None

	def getModifiedData(self, user, timestamp, parameters = None, exclude = [], platform = None, app_version = None):
		''' Searches for new data to be sent. Must return a list of serialized items and a dictionary
			containing parameters that should be passed back to the client.
			The exclude parameter is a list of object ids that must not be considered in the query.'''

		# Loading models and getting employee
		employee = user
		try:
			ModelDeleted = apps.get_model(self.app_model + 'Deleted')
		except LookupError:
			ModelDeleted = None
		ModelToDelete = apps.get_model(self.app_model + 'ToDelete')
		fk_attr = camelcase_underscore(self.app_model.split('.')[1]) + '_id'

		if timestamp == FIRST_TIMESTAMP: # First fetch
			deleted = []
			new_timestamp = timestamp
		else:
			owner_attr = self.owner_attr if self.owner_attr else "user"
			owner_attr += "_id"
			fargs = {"timestamp__gt": timestamp}
			if self.check_has_field(ModelToDelete, owner_attr):
				fargs[owner_attr] = employee.id

			objects_to_delete = ModelToDelete.objects.filter(**fargs).values(fk_attr)
			new_timestamp = objects_to_delete.values('timestamp').aggregate(new_timestamp=Max('timestamp'))['new_timestamp']
			if new_timestamp is None:
				new_timestamp = timestamp
			deleted = list(objects_to_delete)
			if ModelDeleted:
				objects_deleted = ModelDeleted.objects.filter(timestamp__gt=timestamp).values(fk_attr)
				deleted += list(objects_deleted)
				new_timestamp2 = objects_deleted.values('timestamp').aggregate(new_timestamp=Max('timestamp'))['new_timestamp']
				if new_timestamp2 is not None:
					new_timestamp = max(new_timestamp, new_timestamp2)
			attr = camelcase_underscore(self.app_model.split('.')[1]) + '_id'
			deleted = list({v[attr]:v for v in deleted}.values())

		response_parameters = {}
		return deleted, response_parameters, new_timestamp

	def saveNewData(self, user, device_id, data, files = None, platform = None, app_version = None):
		''' Saves new data received. Must return 2 objects:
			1. A dictionary that contains a list with data to be sent in response.
			   The key in the dictionary MUST be equal to the response identifier.
				For instance:
					{
						"news_id":[
							{"id":2,"id_client":1},
							...
						]
					}
			2. List with all the objects that were created
			'''

		return {},[]

	def saveObject(self, user, device_id, object, files = None, platform = None, app_version = None):
		''' Saves an object in the database. Must return 2 objects:
			1. A dictionary containing data to be sent in response to the client.
			For example: {"id":1,"id_client":3}.
			2. The object that was saved in the database.'''

		return {},None

	def serializeObject(self, object):
		''' This method is responsible for transforming an object into a dictionary
			that will be converted to json later. It must return a dictionary. '''
		return {}

class ExpiredTokenException(Exception):
	pass


from __future__ import print_function
if __name__ == '__main__':
	import matplotlib
	matplotlib.use('Agg')

import sys
from math import pi

import numpy as np
import pylab as plt

from astrometry.util.sip import Tan
from astrometry.util.file import *

from sdsstractor import *

def makeTruth():
	W,H = 500,500
	ra,dec = 0,0
	width = 0.1

	wcs = Tan()
	wcs.crval[0] = ra
	wcs.crval[1] = dec
	wcs.crpix[0] = W/2.
	wcs.crpix[1] = H/2.
	scale = width / float(W)
	wcs.cd[0] = -scale
	wcs.cd[1] = 0
	wcs.cd[2] = 0
	wcs.cd[3] = -scale
	wcs.imagew = W
	wcs.imageh = H
	tanwcs1 = wcs
	wcs1 = FitsWcs(wcs)

	# rotate.
	W2 = int(W*np.sqrt(2.))
	H2 = W2
	rot = 30.
	cr = np.cos(np.deg2rad(rot))
	sr = np.sin(np.deg2rad(rot))
	wcs = Tan()
	wcs.crval[0] = ra
	wcs.crval[1] = dec
	wcs.crpix[0] = W2/2.
	wcs.crpix[1] = H2/2.
	wcs.cd[0] = -scale * cr
	wcs.cd[1] =  scale * sr
	wcs.cd[2] = -scale * sr
	wcs.cd[3] = -scale * cr
	wcs.imagew = W2
	wcs.imageh = H2
	wcs2 = FitsWcs(wcs)

	photocal = SdssPhotoCal(SdssPhotoCal.scale)
	psf = NCircularGaussianPSF([2.0], [1.0])
	sky = 0.
	skyobj = ConstantSky(sky)
	flux = SdssFlux(1.)

	# image 1
	image = np.zeros((H,W))
	invvar = np.zeros_like(image) + 1e-4
	img1 = Image(data=image, invvar=invvar, psf=psf, wcs=wcs1,
				 sky=skyobj, photocal=photocal, name='Grid1')
	# image 2
	image = np.zeros((H2,W2))
	invvar = np.zeros_like(image) + 1e-4
	img2 = Image(data=image, invvar=invvar, psf=psf, wcs=wcs2,
				 sky=skyobj, photocal=photocal, name='Grid2')

	tractor = SDSSTractor([img1, img2])

	np.random.seed(42)

	# arcsec
	#re = 10.
	#phi = 30.

	# grid: ra -- ab
	for i,(x,a) in enumerate(zip(np.linspace(50, W-50, 10),
								np.linspace(0.1, 1, 10))):
		#       dec -- phi
		#       dec -- r_e
		for j,(y,re) in enumerate(zip(np.linspace(50, H-50, 10),
									  exp(np.linspace(np.log(1), np.log(30.), 10)))):
									  #exp(np.linspace(np.log(0.1), np.log(20.), 10)))):
			#np.linspace(0, 90, 10, endpoint=False),
			ra,dec = tanwcs1.pixelxy2radec(x, y)
			pos = RaDecPos(ra, dec)
			phi = np.random.uniform(0, 360)
			#eg = ExpGalaxy(pos, flux, re, a, p)
			#eg = HoggExpGalaxy(pos, flux, re, a, phi)
			eg = HoggDevGalaxy(pos, flux, re, a, phi)
			tractor.catalog.append(eg)

	imgs = tractor.getModelImages()
	for i,img in enumerate(imgs):
		plt.clf()
		plt.imshow(img, interpolation='nearest', origin='lower')
		plt.colorbar()
		plt.savefig('grid%i.png' % i)

	for i,img in enumerate(imgs):
		timg = tractor.getImage(i)
		noise = (np.random.normal(size=timg.invvar.shape) *
				 np.sqrt(1. / timg.invvar))
		timg.data = img + noise

		plt.clf()
		plt.imshow(timg.getImage(),
				   interpolation='nearest', origin='lower')
		plt.colorbar()
		plt.savefig('grid%in.png' % i)

		pyfits.writeto('grid%in.fits' % i, timg.getImage(), clobber=True)

	return tractor.images

def main():
	from optparse import OptionParser
	parser = OptionParser()
	parser.add_option('-v', '--verbose', dest='verbose', action='count',
					  default=0, help='Make more verbose')
	opt,args = parser.parse_args()
	print('Opt.verbose = ', opt.verbose)
	if opt.verbose == 0:
		lvl = logging.INFO
	else: # opt.verbose == 1:
		lvl = logging.DEBUG
	logging.basicConfig(level=lvl, format='%(message)s',
						stream=sys.stdout)

	set_fp_err()

	print()
	print('makeTruth...')
	print()
	imgs = makeTruth()
	print()
	print('done makeTruth.')
	print()
	tractor = SDSSTractor(imgs)

	xyfn = 'grid0n.xy'
	if not os.path.exists(xyfn):
		print('Running image2xy...')
		cmd = 'image2xy %s -o %s' % (xyfn.replace('.xy', '.fits'), xyfn)
		print('Command:', cmd)
		os.system(cmd)
	assert(os.path.exists(xyfn))
	sxy = fits_table(xyfn)

	cat = tractor.getCatalog()
	for i in range(len(sxy)):
		# MAGIC -1: simplexy produces FITS-convention coords
		x = sxy.x[i] - 1.
		y = sxy.y[i] - 1.
		ix = int(round(x))
		iy = int(round(y))
		#src = tractor.createNewSource(imgs[0], x, y, sxy.flux[i])
		#src = tractor.createNewSource(imgs[0], x, y, sxy.flux[i])
		#cat.append(src)

		img = tractor.getImage(0)
		wcs = img.getWcs()
		pos = wcs.pixelToPosition(ix,iy)
		photocal = img.getPhotoCal()
		flux = photocal.countsToFlux(1e6) #sxy.flux[i])

		#cat.append(ExpGalaxy(pos, flux, 1., 0.5, 0.))
		#cat.append(HoggExpGalaxy(pos, flux, 1., 0.5, 0.))
		cat.append(HoggDevGalaxy(pos, flux, 1., 0.5, 0.))

	Nsteps = 30

	for i in range(Nsteps):
		html = ''
		html += '
Step %i ' % i
		if i > 0:
			html += ' Prev' % (i-1)
		html += ' Next' % (i+1)
		if i >= 5:
			html += ' -5' % (i-5)
		html += ' +5' % (i+5)
		html += '
'
		for j in range(2):
			html += '' % (i,j)
			html += '' % j
		html += ''
		write_file(html, 'grid%02i.html' % i)

	for step in range(Nsteps):
		imgs = tractor.getModelImages()
		for i,img in enumerate(imgs):
			plt.clf()
			plt.imshow(img, interpolation='nearest', origin='lower')
			fn = 'grid%02i-%in.png' % (step, i)
			plt.colorbar()
			plt.savefig(fn)
			print('saved', fn)

		#if step == 0:
		#	tractor.changeSourceTypes()
		#else:
		print()
		print('Step', step)
		print()
		for src in tractor.getCatalog():
			print(' ', src)
		tractor.optimizeCatalogAtFixedComplexityStep()

	sys.exit(0)

	(images, simplexys, rois, zrange, nziv, footradecs
	 ) = prepareTractor(False, False, rcfcut=[0])

	print('Creating tractor...')
	tractor = SDSSTractor(images, debugnew=False, debugchange=True)
	opt,args = parser.parse_args()

	src = DevGalaxy(pos, flux, 0.9, 0.75, -35.7)
	src.setParams([120.60275, 9.41350, 5.2767052, 22.8, 0.81, 5.0])
	tractor.catalog.append(src)

	def makePlots(tractor, fnpat, title1='', title2=''):
		mods = tractor.getModelImages()
		imgs = tractor.getImages()
		chis = tractor.getChiImages()
		for i,(mod,img,chi) in enumerate(zip(mods,imgs,chis)):
			zr = zrange[i]
			imargs = dict(interpolation='nearest', origin='lower',
						  vmin=zr[0], vmax=zr[1])
			srcpatch = src.getModelPatch(img)
			slc = srcpatch.getSlice(img)
			plt.clf()
			plt.subplot(2,2,1)
			plotimage(img.getImage()[slc], **imargs)
			plt.title(title1)
			plt.subplot(2,2,2)
			plotimage(mod[slc], **imargs)
			plt.title(title2)
			plt.subplot(2,2,3)
			plotimage(chi[slc], interpolation='nearest', origin='lower',
					  vmin=-5, vmax=5)
			plt.title('chi')
			#plt.subplot(2,2,4)
			#plotimage(img.getInvError()[slc],
			#		  interpolation='nearest', origin='lower',
			#		  vmin=0, vmax=0.1)
			#plt.title('inv err')
			fn = fnpat % i
			plt.savefig(fn)
			print('wrote', fn)

	makePlots(tractor, 'opt-s00-%02i.png', #'pre-%02i.png',
			  title2='re %.1f, ab %.2f, phi %.1f' % (src.re, src.ab, src.phi))

	for ostep in range(10):
		print()
		print('Optimizing...')
		#alphas = [1., 0.5, 0.25, 0.1, 0.01]
		alphas=None
		ppre = src.getParams()
		lnppre = tractor.getLogProb()
		dlnp,X,alpha = tractor.optimizeCatalogAtFixedComplexityStep(alphas=alphas)
		ppost = src.getParams()
		makePlots(tractor, 'opt-s%02i-%%02i.png' % (ostep+1),
				  title1='dlnp = %.1f' % dlnp,
				  title2='re %.1f, ab %.2f, phi %.1f' % (src.re, src.ab, src.phi))

		print()
		src.setParams(ppre)
		print('Pre :', src)

		src.setParams(ppost)
		print('Post:', src)

if __name__ == '__main__':
	import cProfile
	from datetime import tzinfo, timedelta, datetime
	cProfile.run('main()', 'prof-%s.dat' % (datetime.now().isoformat()))
	sys.exit(0)


from django.http import HttpResponse
from django.template import loader
from django.shortcuts import get_object_or_404, render, redirect
from PIL import Image
import itertools
import os, sys

from django.conf import settings

from .models import Genre, Product

def index(request):

    #this needs to just display all the products
    latest_prod_list = Product.objects.all()
    template = loader.get_template('catalog/index.html')
    context = {
        'latest_prod_list' : latest_prod_list
        }
    return render(request, 'catalog/index.html', context)

def detail(request, prod_id):
    #this will list the hierarchy and the breadcrumbs
    this_product = get_object_or_404(Product, pk=prod_id)

    breadcrumbs=getBreadcrumb(this_product.parent, [])

    hierarchy_list = getFullHierarchy()
    template = loader.get_template('catalog/detail.html')
    context = {
        'breadcrumbs' : breadcrumbs,
        'hierarchy_list' : hierarchy_list,
        'prod' : this_product
        }
    return render(request, 'catalog/detail.html', context)

def add(request):
    template = loader.get_template('catalog/add.html')
    return render(request, 'catalog/add.html',{})

def process(request):
    #check if item already is in database
    #build the adjacency list (genre model)
    media_object = Genre.objects.get(parent=None, genre_name=request.POST['media'])
    genre_objects = Genre.objects.filter(parent=media_object, genre_name=request.POST['genre'])
    if( not genre_objects.exists()):
       genre_objects = [makeGenre(request.POST['genre'], media_object)]
    parentG=genre_objects[0]
    if(request.POST['subgenre'] !=""):
        subgenre_objects = Genre.objects.filter(parent=parentG,
                                                genre_name=request.POST['subgenre'])
        if(not subgenre_objects.exists()):
            subgenre_objects=[makeGenre(request.POST['subgenre'], parentG)]
        parentG=subgenre_objects[0]

    #build the product model

    p = Product(media_type=request.POST['media'], parent=parentG,
                title=request.POST['title'], description=request.POST['description'],
                price=request.POST['price'])
    if 'pic' in request.FILES:
        img_path = handle_uploaded_file(request.FILES['pic'])
        p.image=request.FILES['pic'].name

    p.save()
    return redirect('catalog:index')

#returns relative path of file
def handle_uploaded_file(f):
    path = settings.MEDIA_ROOT+'/'+f.name
    with open(path, 'wb+') as destination:
        for chunk in f.chunks():
            destination.write(chunk)
    im = Image.open(path)
    new_size = 150, 150
    im.thumbnail(new_size, Image.ANTIALIAS)
    im.save(path)

def makeGenre(name, parentObject):
    g=Genre(parent=parentObject, genre_name=name)
    g.save()
    return g

def getBreadcrumb(genre_node, trail):
    if(genre_node.parent is None):
        return trail + [str(genre_node)]
    else:
        return getBreadcrumb(genre_node.parent, trail+[str(genre_node)])

#grabs the expanded hierarchy for a given media type, formatted for Django's unordered list
def getHierarchy(depth, parent_node, hierarchy):
    children_list = Genre.objects.filter(parent=parent_node)
    c_list=[]
    if not children_list:
       return hierarchy + [str(parent_node)]
    for child in children_list:
        c_list += getHierarchy(depth+1, child, hierarchy)
    return hierarchy + [str(parent_node), c_list]

def getFullHierarchy():
    full_list = []
    for choice in Genre.MEDIA_CHOICES:
        media = Genre.objects.get(genre_name=choice[0])
        full_list += getHierarchy(0, media, [])
    return full_list


'''
Dictionary Merger

'''

import collections
import argparse
import datetime
import os
import sys

from PIL import Image , TiffImagePlugin

def Worker(args):
	print("User Current Version:-", sys.version)
	# -- Arguments Definitions --------------------------------------------------------------------------------------------------------------
	parser = argparse.ArgumentParser(description='FileMan Link Generator')
	parser.add_argument('-d1', '--dictionary', type=str, default={'1':123, '2':234, '3':345, 'X':{'a':'abc', 'b':'bcd', 'c':'cde', }}, help='Dictionary to be updated')
	parser.add_argument('-d2', '--dictnew', type=str, default={'1':1234, '22':2234, '33':3345,  'X':{'aa':'aabc', 'bb':'bbcd', }}, help='New Dictionary to merge into the first one')

	# -- Variable Definitions --------------------------------------------------------------------------------------------------------------
	args = parser.parse_args()
	# -- Initial Setup
	jd1 = args.dictionary
	jd2 = args.dictnew

	#jd = {**jd1, **jd2}

	print(jd1)
	print(jd2)
	jd = DctMrg(jd1, jd2)

	print(dctcln(jd))

#------------------------------------------------------------------------------------
# Dict Clean up ---------------------------------------------------------------------
def dctcln(obj):
	if isinstance(obj, dict):
		for key, val in obj.items():
			obj[key] = dctcln(val)
		return obj
	elif isinstance(obj, tuple):
		return tuple(dctcln(val) for val in obj)
	elif isinstance(obj, TiffImagePlugin.IFDRational):
		return float(obj)
	elif isinstance(obj, bytes):
		#return  obj.decode("utf-8", "ignore")
		return  obj.decode(errors="replace")
	#elif isinstance(obj, list):
	#	return list(dctcln(val) for val in obj)
	else:
		#print("dctcln -> non defined tyte found:", type(obj), str(obj))
		return obj

#------------------------------------------------------------------------------------
# Dict Merger -----------------------------------------------------------------------
def DctMrg(dct='',dctnew=''):
	try:
		d=dct.copy()
	except:
		d=dct
	try:
		d2=dctnew.copy()
	except:
		d2=dctnew
	if isinstance(d, dict) and isinstance(d2, dict):
		for key, val in d2.items():
			if key in d:
				if isinstance(val, dict):
					d[key] = DctMrg(d[key], d2[key])
				else:
					d[key] = val
			else:
				d[key] = d2[key]
		return d
	elif not isinstance(d, dict) and isinstance(d2, dict):
		print('-d1 not a Dictionary: ', d)
		return d2
	elif not isinstance(d2, dict) and isinstance(d, dict):
		print('-d2 not a Dictionary: ', d2)
		return d
	else:
		return {}

#-------------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------------
if __name__ == '__main__':
	from sys import argv
	try:
		Worker(argv)
	except KeyboardInterrupt:
		pass
	exit()


from django_filters.rest_framework.backends import DjangoFilterBackend
from rest_framework import mixins
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import AllowAny
from rest_framework.viewsets import GenericViewSet

from base.auth.permissions.permission import IsSuperStaff, IsManager
from base.common.constant.view_action import BaseViewAction
from base.common.custom.pagination import CustomPagination
from base.common.utils.exceptions import PermissionDenied
from base.menu.models import Menu
from staff.menu.filters.menu import MenuListQueryFields
from staff.menu.serializers.menu import MenuListSlz, MenuRetrieveSlz, MenuCreateSlz, MenuUpdateSlz

class MenuViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, mixins.UpdateModelMixin, mixins.RetrieveModelMixin,
                  mixins.DestroyModelMixin, GenericViewSet):
    permission_classes = (AllowAny,)
    pagination_class = CustomPagination
    filter_backends = (DjangoFilterBackend, OrderingFilter, SearchFilter)
    serializer_class = MenuListSlz
    queryset = Menu.objects.all()
    search_fields = MenuListQueryFields.SEARCH_FIELDS
    ordering_fields = MenuListQueryFields.ORDER_FIELDS
    ordering = MenuListQueryFields.ORDER_DEFAULT_FIELD
    filterset_fields = MenuListQueryFields.FILTERSET_FIELDS

    def get_serializer_class(self):
        slz_switcher = {
            BaseViewAction.LIST: MenuListSlz,
            BaseViewAction.RETRIEVE: MenuRetrieveSlz,
            BaseViewAction.CREATE: MenuCreateSlz,
            BaseViewAction.UPDATE: MenuUpdateSlz,
        }
        slz = slz_switcher.get(self.action, self.serializer_class)
        return slz

    def get_permissions(self):
        perm_switcher = {
            BaseViewAction.LIST: (AllowAny,),
            BaseViewAction.RETRIEVE: (AllowAny,),
            BaseViewAction.CREATE: (IsManager | IsSuperStaff,),
            BaseViewAction.UPDATE: (IsManager | IsSuperStaff,),
            BaseViewAction.DESTROY: (IsSuperStaff,),
        }
        self.permission_classes = perm_switcher.get(self.action, self.permission_classes)
        if self.permission_classes is None:
            raise PermissionDenied()

        return super().get_permissions()


import psychopy.visual
import psychopy.event
import time
import numpy as np
from tqdm import tqdm

def run():
    # PARAMS
    repeats_per_orientation = 15
    orientations = [0, 45, 90]
    spatial_freq = 5.0 / 400.0
    n_frames_on = 45
    n_frames_off = 180
    speed = 5

    # CREATE STUFF
    white, black, gray = [1, 1, 1], [-1, -1, -1], [1, 1, 1]

    win = psychopy.visual.Window(
        pos=[50, 50],
        size=[1920, 1080],
        units="pix",
        fullscr=True,
        screen=1
    )

    square = psychopy.visual.Rect(
        win=win,
        pos=[-835, 415],
        width=250,
        height=250,
        units="pix",
        fillColor=black
    )

    grating_params = dict(
        win=win,
        units="pix",
        size=[8000, 8000]
    )

    grating = psychopy.visual.GratingStim(
        ori=orientations[0],
        **grating_params
    )
    grating.sf = spatial_freq

    # COMPUTE FRAMES
    orientations = np.repeat(orientations, repeats_per_orientation)

    square_frames = np.hstack(np.tile(np.array([np.ones(n_frames_on), np.zeros(n_frames_off)]), len(orientations)))
    ors = np.hstack([np.ones(n_frames_on+n_frames_off)*o for o in orientations])
    phases = np.hstack([np.hstack([np.linspace(0, speed, n_frames_on), np.zeros(n_frames_off)]) for o in orientations])

    if phases.shape != ors.shape or phases.shape != square_frames.shape:
        raise ValueError("Something went wrong with frames calculation")
    else:
        print("Total duration: {} stimuli over {}".format(len(orientations), phases.shape[0]))

    # Animate stimuli
    curr_orientation = orientations[0]
    for s, o, p in tqdm(zip(square_frames, ors, phases)):
        if s:
            square.color = white
        else:
            square.color = black

        if p==0:
            grating.opacity=0
        else:
            grating.opacity = 1

        if o != curr_orientation:
            grating = psychopy.visual.GratingStim(
                ori=o,
            **grating_params
            )
            grating.sf = spatial_freq

            curr_orientation = o
            print("\n\nStarting stim with orientation: {}".format(round(o)))

        grating.phase = p

        grating.draw()
        square.draw()
        win.flip()

    win.close()

if __name__ == "__main__":
    run()


# -*- coding: utf-8 -*-
import scrapy
import scrapy_splash
from scrapy_splash import SplashRequest
from stocks.items import StocksItem

from scrapy.utils.project import get_project_settings

class NSESpider(scrapy.Spider):
  name = "nse"

  def start_requests(self):
    urls = [
            'https://www.nseindia.com/',
            #'http://www.bseindia.com/'
           ]
    for url in urls:
      #yield scrapy.Request(url=url, callback=self.parse)
      yield SplashRequest(url, self.parse,
                          args= {
                            'wait': 0.5,
                            'timeout' : 120, #Timeout to render (default 30 sec)
                            #'url': Prefilled by plugin
                            #'baseurl': Base HTML content, relative resources on page referenced acc. to this.,
                            #'resource_timeout': #Individual resource request timeout value
                            # 'http_method', 'body',
                            #'js', 'js_source', 'filters', 'allowed_domains', 'allowed_content_types',
                            #'forbidden_content_types', 'viewport', 'images', 'headers', 'save_args',
                            #'load_args'
                          },
                          endpoint = 'render.html', #optional; could be render.json, render.png
                          #splash_url = SPLASH_URL, #optional; overrides SPLASH_URL
                          slot_policy=scrapy_splash.SlotPolicy.PER_DOMAIN, #optional
                          )

  def parse(self, response):
    page = response.url
    filename = 'nsepage.html'
    with open(filename, 'wb') as f:
      f.write(response.body)
    self.log("Saved file %s" %filename)


import requests,os,openpyxl
from datetime import date

def dataScraper(u_name):

    headers = {
        'accept-encoding': 'gzip, deflate, br',
        'accept-language': 'en-US,en;q=0.9',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36',
        'accept': '*/*',
        'referer': 'https://www.instagram.com',
        'Connection': 'keep-alive',
    }

    url ='https://www.instagram.com/'+u_name

    params = {
        '__a': '1'

    }

    r = requests.get(url=url, headers=headers,params= params )

    global p_id
    global username
    global fullname
    global bio
    global posts
    global followers
    global following
    global profpic
    global status
    global s_data
    global t_date

    data = r.json()
    p_id = data["graphql"]["user"]["id"]
    username= data["graphql"]["user"]["username"]
    fullname= data["graphql"]["user"]["full_name"]
    bio = data["graphql"]["user"]["biography"]
    posts = data["graphql"]["user"]["edge_owner_to_timeline_media"]["count"]
    followers = data["graphql"]["user"][ "edge_followed_by"]["count"]
    following = data["graphql"]["user"]["edge_follow"]["count"]
    profpic = data["graphql"]["user"]["profile_pic_url_hd"]

    get_status = data["graphql"]["user"]["is_private"]
    if get_status == True:
        status='Private'
    else :
        status ='Public'

    t_day =date.today()

    s_data= [fullname,username,p_id,posts,followers,following,status,profpic,t_day]
    return s_data
    # print(fullname,username,p_id,posts,followers,following,status,profpic)

def extractData(s_data):
    global wb
    title_data=['Full Name','Username','ID','Posts','Followers','Following','Status','Profile Pic']
    os.chdir('C:\\Users\\Shaun\\Desktop\\python practrice') #change the directory to your folder
    wb = openpyxl.load_workbook('data.xlsx')   #devnote create a excel file in the directory you are using
    sheet = wb.active
    sheet.title = 'StalkerData'
    sheet['A1']. value = 'Full Name'
    sheet['B1']. value = 'Username'
    sheet['C1']. value = 'ID'
    sheet['D1']. value = 'Posts'
    sheet['E1']. value = 'Followers'
    sheet['F1']. value = 'Following'
    sheet['G1']. value = 'Status'
    sheet['H1']. value = 'Profile Pic'
    sheet['I1']. value = 'TimeStamp'
    sheet.append(s_data)
    wb.save('data.xlsx')
    wb.close()

ulist = ['_shaunnyboi_'] #add your friends username in this list

print("Data Extracted!...Saving Data Please Wait!...")
for u_name in ulist:
    dataScraper(u_name)

    # print(fullname,username,p_id,posts,followers,following,status,profpic)
    # print(s_data)
    extractData(s_data)
print("Data Saved...")