from django.core.paginator import Paginator
from django.shortcuts import get_object_or_404, render

from .models import News, Tag

def page_list(set, request):
    paginator = Paginator(set, 10)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    return page_obj

# Главная страница
def index(request):
    post_list = News.objects.all()
    page_obj = page_list(post_list, request)
    template = 'news/index.html'
    context = {
        'page_obj': page_obj,
    }
    return render(request, template, context)

# Страница со списком новостей по тегу
def news_tag(request, slug):
    tag = get_object_or_404(Tag, slug=slug)
    news = News.objects.filter(tag=tag)
    page_obj = page_list(news, request)
    template = 'news/news_tag.html'
    context = {
        'page_obj': page_obj,
        'tag': tag,
    }
    return render(request, template, context)

def news_detail(request, pk):
    new = get_object_or_404(News, pk=pk)
    context = {
        'new': new,
    }
    return render(request, 'news/news_detail.html', context)


from fastai.vision.widgets import *
from fastai.vision.all import *
from pathlib import Path
import PIL
from PIL import Image
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import color

file_name='style.pkl'
learn_inference = load_learner(Path()/file_name)

#defining wallpaper class for testing
class Wallpaper():
    def __init__(self, id, color, style):
        #path to wallpaper
        self.id = id
        #color of wallpaper
        self.color = color
        #style of wallpaper
        self.style = style

categories = ['texture', 'geometric', 'stripe', 'nature']

#sample list of wallpapers
wallpapers = [Wallpaper("26", "green", "texture"), Wallpaper("24", "darkblue", "stripe"), Wallpaper("30", "gray", "texture"), Wallpaper("7", "darkblue", "geometric"), Wallpaper("31", "darkblue", "nature"), Wallpaper("22", "gray", "nature")]

def give_recommendation(image_path):
    #loading image
    location = image_path
    image = open(location, 'rb')

    #classifying style of image
    pred, pred_idx, probs = learn_inference.predict(PILImage.create(image))
    style = pred

    #classifying color of image
    image_color = color.compare(image_path)

    matches = []

    #checking if there are wallpapers with the same color and style
    for wallpaper in wallpapers:
        if wallpaper.color == image_color and wallpaper.style == style:
            matches.append(wallpaper)
        if len(matches) == 6:
            return matches

    #if there are not enough wallpapers with the same color and style, return wallpapers with the same style
    if len(matches) < 6:
        for wallpaper in wallpapers:
            if wallpaper.style == style:
                matches.append(wallpaper)
            if len(matches) == 6:
                return matches

    return matches

#test
print(give_recommendation("/Users/Leah/boho/images/test/1.jpg"))


import numpy as np
import chainer
import argparse
import csv

import chainer.functions as F
import chainer.links as L
from chainer import cuda
from chainer import serializers

from fix_data import OneDimSensorData

"""
    LSTMを書いて, 訓練するクラス
"""
class LSTM(chainer.Chain):
    def __init__(self):
        super().__init__(
            l1=L.Linear(1, 5),
            l2=L.LSTM(5, 30),
            l3=L.Linear(30, 1),
            l4=L.Linear(1, 2)
        )

    def predictor(self, x):
        # テストデータでの評価用途
        self.l2.reset_state()
        row = x.shape[0]
        col = x.shape[1]
        for i in range(col):
            h = self.l1(xp.array(x[:, i].reshape(row, 1), dtype=xp.float32))
            h = self.l2(h)
            h = self.l3(h)
            h = self.l4(h)
        return [0 if data[0] > data[1] else 1 for data in h.data] # WATCH: あとでmapできるようにかきかえる

    def __call__(self, x, t):
        # ひとつのデータごとに誤差を計算する
        self.l2.reset_state()
        row = x.shape[0]
        col = x.shape[1]
        accum_loss = None
        for i in range(col):
            h = self.l1(xp.array(x[:, i].reshape(row, 1), dtype=xp.float32))
            h = self.l2(h)
            h = self.l3(h)
            if i != col-1:
                loss = F.mean_squared_error(h, xp.array(x[:, i+1].reshape(row, 1), dtype=xp.float32))
                accum_loss = loss if accum_loss is None else accum_loss + loss
            h = self.l4(h)
        accum_loss += F.softmax_cross_entropy(h, xp.array(t, dtype=xp.int32))
        # print(loss.data)

        return accum_loss

# gpu
parser = argparse.ArgumentParser()
parser.add_argument('--gpu', '-g', default=-1, type=int,
                    help='GPU ID')
args = parser.parse_args()

# 学習データとテストデータ
one_dim_sensor = OneDimSensorData()
one_dim_sensor.load_csv()
one_dim_sensor.shuffle()
train, train_label, test, test_label, one_label_counts = one_dim_sensor.divide_train_and_test()

# model
model = LSTM()
optimizer = chainer.optimizers.Adam()
optimizer.setup(model)

# for cuda
xp = cuda.cupy if args.gpu >= 0 else np
if args.gpu >= 0:
    cuda.get_device(args.gpu).use()
    model.to_gpu()

# training loop
display = 1000
total_loss = 0
epoch = 500
n_size = len(train)
batch_size = 1000
# question_num = len(test)

loss_plt_ary = []
accuracy_plt_ary = []
recall_plt_ary = []

for i in range(epoch):
    sffindx = np.random.permutation(n_size)
    for j in range(0, n_size, batch_size):
        x = train[sffindx[j:(j+batch_size) if (j+batch_size) < n_size else n_size]]
        y = train_label[sffindx[j:(j+batch_size) if (j+batch_size) < n_size else n_size]]
        loss = model(x, y)
        # print(loss.data)
        model.zerograds()
        loss.backward()
        optimizer.update()
        if j%display == 0:
            print("{} epoch {} number, loss {}".format(i, j, loss.data))
        last_loss = loss.data

    # テストデータでチェック
    answer_num = 0
    recall = 0
    for t_d, t_l in zip(test, test_label):
        answers = model.predictor(t_d)
        bool_ans = (answers==t_l)
        for bool in bool_ans:
            if bool:
                answer_num += 1
        for answer, tl in zip(answers, t_l):
            if answer == tl and answer:
                recall += 1
    print('main/loss {}, accuracy rate {}, recall rate {}, one_counts {}'.format(last_loss, answer_num/7410, recall/one_label_counts, one_label_counts))
    loss_plt_ary.append(last_loss)
    accuracy_plt_ary.append(answer_num/7410)
    recall_plt_ary.append(recall/one_label_counts)

serializers.save_npz("fixed_lstm_model_2", model)

def write_csv(path, ary):
    with open('results/lstm_fixed_result/%s.csv' % path, 'w') as f:
        writer = csv.writer(f, lineterminator='\n')
        writer.writerow(ary)

write_csv('loss', loss_plt_ary)
write_csv('accuracy', accuracy_plt_ary)
write_csv('recall', recall_plt_ary)

# csvにデータを書き込み
with open('results/lstm_fixed_result/loss.csv', 'w') as f:
    writer = csv.writer(f, lineterminator='\n')
    writer


# -*- coding: utf-8 -*-
# NOTES
# ALl mask related mathematics happens assuming (and only after conversion to) the mask image as a 2D array [... x ...]
# No channels=1 are used for the mask. Ofcourse while reading, it is read as [.. x .. x 1];

import os, cv2, pickle as pk, numpy as np
import params
from clustering import dominant_clusters

###########################################################################################################
def simply_erode_opencv(inp_mask, adj_labels_to_erode):
    mask = inp_mask.copy();
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
    for label in adj_labels_to_erode:
        # print(label)
        # Pick the partial_mask
        partial_mask = np.zeros(mask.shape); partial_mask[mask==label] = 1;
        mask[mask==label] = 0;
        er_partial_mask = cv2.erode(partial_mask, kernel, iterations = 2);
        mask[er_partial_mask==1] = label;
    return mask;
def get_bw_mask(mask_path, k_gap_erode=4):
    ###############################################################
    # Collects all masks from the org folder and erodes any two
    # masks thata re close by.
    ###############################################################
    mask_files = os.listdir(mask_path);
    mask, partial_mask_label = [], 1;
    adj_labels_to_erode, k_gap = [], k_gap_erode;
    for mask_file in mask_files:
        partial_mask = cv2.imread(os.path.join(mask_path,mask_file), cv2.IMREAD_GRAYSCALE);
        partial_mask[partial_mask>0] = partial_mask_label;
        partial_mask_inds = np.where(partial_mask==partial_mask_label)
        try:
            mask+=partial_mask;
        except:
            mask = partial_mask;
        found_something_close_by = 0;
        for p in range(partial_mask_inds[0].shape[0]):
            row = partial_mask_inds[0][p]; col = partial_mask_inds[1][p];
            if row-k_gap>=0 and row+k_gap<partial_mask.shape[0] and col-k_gap>=0 and col+k_gap<partial_mask.shape[1]:
                window = mask[row-k_gap:row+k_gap, col-k_gap:col+k_gap];
                other_labels = window[(window>0) & (window!=partial_mask_label)]
                for label in other_labels:
                    if label not in adj_labels_to_erode:
                        #print(partial_mask_label, label, row, col);
                        adj_labels_to_erode.append(label);
                        found_something_close_by = 1;
        if found_something_close_by:
            #print(partial_mask_label);
            adj_labels_to_erode.append(partial_mask_label);
        # Continue adding more partial_masks
        partial_mask_label+=1;
    for ind, lab in enumerate(adj_labels_to_erode):
        adj_labels_to_erode[ind] = int(lab)
    # Simply erode these label clusters
    new_mask = simply_erode_opencv(mask, adj_labels_to_erode);
    # bw_mask =  cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY);
    bw_mask = new_mask.copy(); bw_mask[bw_mask>0] = 255;
    if len(adj_labels_to_erode)>0:
        print('These many masks were found closeby; Eroded Brutally!!', len(adj_labels_to_erode));
    return bw_mask
#############################################################################################################
def thisPatch(image, bw_mask, curr_row, curr_col, base_name, vertical_flip, horizontal_flip, rotation_90s, zoomIn):
    # Desired values
    row_length, col_length, channels = params.image_patch_rows, params.image_patch_cols, params.image_patch_channels;
    # make new images
    new_image = image[curr_row:curr_row+row_length,curr_col:curr_col+col_length,:channels].copy();
    new_mask = bw_mask[curr_row:curr_row+row_length,curr_col:curr_col+col_length].copy();
    new_name = base_name;
    # Random Operations
    if vertical_flip and np.random.uniform(0,1)>=0.5:
        new_image = np.flip(new_image,axis=0);
        new_mask = np.flip(new_mask,axis=0);
        new_name = new_name+'_vflip';
    if horizontal_flip and np.random.uniform(0,1)>=0.5:
        new_image = np.flip(new_image,axis=1);
        new_mask = np.flip(new_mask,axis=1);
        new_name = new_name+'_hflip';
    if rotation_90s and np.random.uniform(0,1)>=0.5 and new_image.shape[0]==new_image.shape[1]:
        # Using OpenCV, input must be SQUARE else bizzare results can be seen
        rows,cols,_ = new_image.shape
        M = cv2.getRotationMatrix2D((cols/2,rows/2),90*(np.random.randint(3)+1),1)
        new_image = cv2.warpAffine(new_image,M,(cols,rows))
        new_mask = cv2.warpAffine(new_mask,M,(cols,rows))
        new_name = new_name+'_r90';
    if zoomIn and np.random.uniform(0,1)>=0.5:
        # Up-Size the image and do rotation and capture 256*256 size
        new_image_big = cv2.resize(new_image, (2*new_image.shape[1], 2*new_image.shape[0]), interpolation = cv2.INTER_LINEAR)
        new_mask_big = cv2.resize(new_mask, (2*new_mask.shape[1], 2*new_mask.shape[0]), interpolation = cv2.INTER_LINEAR)
        start_row = np.random.randint(new_image_big.shape[0]-row_length)
        start_col = np.random.randint(new_image_big.shape[1]-col_length)
        new_image = new_image_big[start_row:start_row+row_length,start_col:start_col+col_length,:];
        new_mask = new_mask_big[start_row:start_row+row_length,start_col:start_col+col_length];
        new_name = new_name+'_zoomin';
    return new_image, new_mask, new_name
def extract_patches_and_save(item, image, bw_mask, vertical_flip, horizontal_flip, rotation_90s, zoomIn):
    # Desired values
    row_length, col_length = params.image_patch_rows, params.image_patch_cols;
    # Other Initializations
    extracted_images, extracted_masks, extracted_names = [], [], [];
    img_rows, img_cols, img_channels = image.shape;
    # raise Exception('Channels<Desired Channels') if(img_channels<channels) else print('Shapes of Input Read: ', image.shape, bw_mask.shape)
    # Generate
    curr_gen_count=1;
    curr_row = 0;
    while(curr_row+row_length<=img_rows):
        curr_col = 0;
        while(curr_col+col_length<=img_cols):
            base_name = str(item)+'_'+str(row_length)+'x'+str(col_length)+'_'+str(curr_gen_count);
            new_image, new_mask, new_gen_name = thisPatch(image, bw_mask, curr_row, curr_col, base_name, vertical_flip, horizontal_flip, rotation_90s, zoomIn);
            if (np.sum(new_mask==0)/(new_mask.shape[0]*new_mask.shape[1]))<params.max_non_mask_pixel_percent or len(extracted_names)<1:
                extracted_images.append(new_image); extracted_masks.append(new_mask); extracted_names.append(new_gen_name);
                curr_gen_count+=1;
            curr_col+=params.win_shift_cols;
        # Saving a last patch in the given set of fixed rows and varying col number
        if curr_col>0 and curr_col<img_cols and curr_col+col_length>img_cols and (img_cols-col_length)%params.win_shift_cols!=0: #Dont go to one of earlier indices
            curr_col = img_cols-col_length;
            base_name = str(item)+'_'+str(row_length)+'x'+str(col_length)+'_'+str(curr_gen_count);
            new_image, new_mask, new_gen_name = thisPatch(image, bw_mask, curr_row, curr_col, base_name, vertical_flip, horizontal_flip, rotation_90s, zoomIn);
            if (np.sum(new_mask==0)/(new_mask.shape[0]*new_mask.shape[1]))<params.max_non_mask_pixel_percent or len(extracted_names)<1:
                extracted_images.append(new_image); extracted_masks.append(new_mask); extracted_names.append(new_gen_name);
                curr_gen_count+=1;
            curr_col+=params.win_shift_cols;
        curr_row+=params.win_shift_rows;
    # Saving a last patch in the given set of varying row number and varying col number
    if curr_row>0 and curr_row<img_rows and curr_row+row_length>img_rows and (img_rows-row_length)%params.win_shift_rows!=0: #Dont go to one of earlier indices
        curr_row = img_rows-row_length;
        curr_col = 0;
        while(curr_col+col_length<=img_cols):
            base_name = str(item)+'_'+str(row_length)+'x'+str(col_length)+'_'+str(curr_gen_count);
            new_image, new_mask, new_gen_name = thisPatch(image, bw_mask, curr_row, curr_col, base_name, vertical_flip, horizontal_flip, rotation_90s, zoomIn);
            if (np.sum(new_mask==0)/(new_mask.shape[0]*new_mask.shape[1]))<params.max_non_mask_pixel_percent or len(extracted_names)<1:
                extracted_images.append(new_image); extracted_masks.append(new_mask); extracted_names.append(new_gen_name);
                curr_gen_count+=1;
            curr_col+=params.win_shift_cols;
        # Saving a last patch in the given set of fixed rows and varying col number
        if curr_col>0 and curr_col<img_cols and curr_col+col_length>img_cols and (img_cols-col_length)%params.win_shift_cols!=0: #Dont go to one of earlier indices
            curr_col = img_cols-col_length;
            base_name = str(item)+'_'+str(row_length)+'x'+str(col_length)+'_'+str(curr_gen_count);
            new_image, new_mask, new_gen_name = thisPatch(image, bw_mask, curr_row, curr_col, base_name, vertical_flip, horizontal_flip, rotation_90s, zoomIn);
            if (np.sum(new_mask==0)/(new_mask.shape[0]*new_mask.shape[1]))<params.max_non_mask_pixel_percent or len(extracted_names)<1:
                extracted_images.append(new_image); extracted_masks.append(new_mask); extracted_names.append(new_gen_name);
                curr_gen_count+=1;
            curr_col+=params.win_shift_cols;
    return extracted_images, extracted_masks, extracted_names
#############################################################################################################
def generate_train_data_with_augmentation(target_folder): # Patches with FLIPS, ROTATIONS, ZOOMIN
    # Sanity check for files of requirement
    with open(params.hsv_clustering_data,'rb') as openFile:
        hsv_clustering = pk.load(openFile);
        clt_model = hsv_clustering['clt']
        print("HSV Cluster Centers: ", np.array(hsv_clustering['cluster_centers_'], dtype='int'));
        del hsv_clustering;
    # Other initializations
    org_names, gen_names, gen_names_ind, gen_names_ind_cnt = [], [], [], []; #gen_names_individual
    for item in os.listdir(params.train_folder_org):
        # Get Paths & Load image,masks
        org_names+=[item]; print(len(org_names));
        image_org_path = os.path.join(params.train_folder_org,item+'/images');
        mask_org_path = os.path.join(params.train_folder_org,item+'/masks');
        image = cv2.imread(os.path.join(image_org_path,os.listdir(image_org_path)[0]));
        bw_mask = get_bw_mask(mask_org_path);
        # Know to which clustre this image belongs to!
        hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV);
        thisCenter, _, _ = dominant_clusters(hsv_image, n_clusters=1);
        centerMapped = clt_model.predict(thisCenter);
        n_iters = 1; vertical_flip=True; horizontal_flip=True; rotation_90s=True; zoomIn=False;
        if centerMapped==1 or centerMapped==3:
            n_iters = 4; zoomIn=True;
        for _ in range(n_iters):
            # Patches with FLIPS, ROTATIONS, ZOOMIN
            extracted_images, extracted_masks, extracted_names = extract_patches_and_save(item, image, bw_mask,
                                                                                vertical_flip, horizontal_flip, rotation_90s, zoomIn);
            # Write images to folder of interest
            print('No.of Files Generated: {}'.format(len(extracted_names)))
            for ind, name in enumerate(extracted_names):
                cv2.imwrite(os.path.join(target_folder, name+'.png'), extracted_images[ind]);
                cv2.imwrite(os.path.join(target_folder, name+'_mask.png'), extracted_masks[ind]);
            # Save data for future reference and proceed
            gen_names+=extracted_names;
            gen_names_ind+=[extracted_names];
            gen_names_ind_cnt+=[len(extracted_names)];
    with open(os.path.join(target_folder,'org_names.pickle'),'wb') as opfile:
        pk.dump(org_names, opfile); opfile.close();
    with open(os.path.join(target_folder,'gen_names.pickle'),'wb') as opfile:
        pk.dump(gen_names, opfile); opfile.close();
    print('Training Data generated success...');
    return org_names, gen_names, gen_names_ind, gen_names_ind_cnt
def generate_train_data_only_resize(target_folder): # Rotations+Patches
    org_names, gen_names = [], []; #gen_names_individual
    for item in os.listdir(params.train_folder_org):
        # Get Paths & Load image,masks
        org_names+=[item]; print(len(org_names));
        image_org_path = os.path.join(params.train_folder_org,item+'/images');
        mask_org_path = os.path.join(params.train_folder_org,item+'/masks');
        image = cv2.imread(os.path.join(image_org_path,os.listdir(image_org_path)[0]));
        bw_mask = get_bw_mask(mask_org_path);
        # Desired values
        row_length, col_length = params.image_patch_rows, params.image_patch_cols;
        # Resize to desired size
        image = cv2.resize(image, (col_length, row_length), interpolation = cv2.INTER_LINEAR);
        bw_mask = cv2.resize(bw_mask, (col_length, row_length), interpolation = cv2.INTER_LINEAR);
        for _ in range(2):
            # Do FLIPS, ROTATIONS, ZOOMIN
            new_image, new_mask, new_name = thisPatch(image, bw_mask, 0, 0, item);
            # Write images to folder of interest
            cv2.imwrite(os.path.join(target_folder, new_name+'.png'), new_image);
            cv2.imwrite(os.path.join(target_folder, new_name+'_mask.png'), new_mask);
            # Save data for future reference and proceed
            gen_names+=[new_name];
    with open(os.path.join(target_folder,'org_names.pickle'),'wb') as opfile:
        pk.dump(org_names, opfile); opfile.close();
    with open(os.path.join(target_folder,'gen_names.pickle'),'wb') as opfile:
        pk.dump(gen_names, opfile); opfile.close();
    print('Training Data generated success...');
    return org_names, gen_names
############################################################################################################
def load_train_list_with_augmentation(target_folder):
    with open(os.path.join(target_folder,'gen_names.pickle'),'rb') as opfile:
        tr_list = pk.load(opfile);
        opfile.close();
    return tr_list
def load_test_list(target_folder):
    with open(os.path.join(target_folder,'org_names.pickle'),'rb') as opfile:
        ts_list = pk.load(opfile);
        opfile.close();
    return ts_list
############################################################################################################
def generate_original_copies_train_data(source_folder, target_folder):
    org_names = [];
    for item in os.listdir(source_folder):
        org_names+=[item]; print(len(org_names));
        # Get Path and load image
        image_path = os.path.join(source_folder,item+'/images');
        image_file = os.listdir(image_path)[0];
        image = cv2.imread(os.path.join(image_path,image_file));
        cv2.imwrite(os.path.join(target_folder, item+'.png'), image);
    with open(os.path.join(target_folder,'org_names.pickle'),'wb') as opfile:
        pk.dump(org_names, opfile); opfile.close();
    print('Training Data generated success...');
    return org_names
def generate_original_copies_test_data(source_folder, target_folder):
    org_names = [];
    for item in os.listdir(source_folder):
        org_names+=[item]; print(len(org_names));
        # Get Path and load image
        image_path = os.path.join(source_folder,item+'/images');
        image_file = os.listdir(image_path)[0];
        image = cv2.imread(os.path.join(image_path,image_file));
        cv2.imwrite(os.path.join(target_folder, item+'.png'), image);
    with open(os.path.join(target_folder,'org_names.pickle'),'wb') as opfile:
        pk.dump(org_names, opfile); opfile.close();
    print('Training Data generated success...');
    return org_names
############################################################################################################
#from train_m3 import prep_image_to_unet
#def make_patches_and_predict(model, bgr_image, threshold_type='global', print_images=False): #'global','otsu','adap+otsu'
#    # Create patch->Predict->Save in Mask->Increment each_pixel_cnt for resp. patch
#    img_rows, img_cols, channels = bgr_image.shape;
#    row_length, col_length = params.image_patch_rows, params.image_patch_cols; # Desired values
#    cnt_matrix = np.zeros((bgr_image.shape[0],bgr_image.shape[1],1));
#    mask_matrix = np.zeros((bgr_image.shape[0],bgr_image.shape[1],1));
#    if(channels<3):
#        raise Exception('Channels<Desired Channels')
#    curr_gen_count =  1;
#    #Patches
#    curr_row = 0;
#    while(curr_row+row_length<=img_rows):
#        curr_col = 0;
#        while(curr_col+col_length<=img_cols):
#            # newImage and predict\
#            #new_bgr_image = bgr_image[curr_row:curr_row+row_length,curr_col:curr_col+col_length,:channels].copy();
#            new_bgr_image = bgr_image;
#            new_bgr_image, new_ycrcb_image = prep_image_to_unet(None, new_bgr_image);
#            new_bgr_image = np.expand_dims(new_bgr_image, axis=0);
#            new_ycrcb_image = np.expand_dims(new_ycrcb_image, axis=0)
#            pred_mask = model.predict([new_ycrcb_image,new_bgr_image])[0];
#            # save details
#            mask_matrix[curr_row:curr_row+row_length,curr_col:curr_col+col_length,:1]+= pred_mask;
#            cnt_matrix[curr_row:curr_row+row_length,curr_col:curr_col+col_length,:1]+= 1;
#            # Increment count and continue
#            curr_gen_count+=1;
#            curr_col+=params.win_shift_cols;
#        # Saving a last patch in the given set of fixed rows and varying col number
#        if curr_col>0 and curr_col<img_cols and curr_col+col_length>img_cols and (img_cols-col_length)%params.win_shift_cols!=0: #Dont go to one of earlier indices
#            curr_col = img_cols-col_length;
#            # newImage and predict\
#            new_bgr_image = bgr_image[curr_row:curr_row+row_length,curr_col:curr_col+col_length,:channels].copy();
#            new_bgr_image, new_ycrcb_image = prep_image_to_unet(None, new_bgr_image);
#            new_bgr_image = np.expand_dims(new_bgr_image, axis=0);
#            new_ycrcb_image = np.expand_dims(new_ycrcb_image, axis=0)
#            pred_mask = model.predict([new_ycrcb_image,new_bgr_image])[0];
#            # save details
#            mask_matrix[curr_row:curr_row+row_length,curr_col:curr_col+col_length,:1]+= pred_mask;
#            cnt_matrix[curr_row:curr_row+row_length,curr_col:curr_col+col_length,:1]+= 1;
#            # Increment count and continue
#            curr_gen_count+=1;
#        curr_row+=params.win_shift_rows;
#    # Saving a last patch in the given set of varying row number and varying col number
#    if curr_row>0 and curr_row<img_rows and curr_row+row_length>img_rows and (img_rows-row_length)%params.win_shift_rows!=0: #Dont go to one of earlier indices
#        curr_row = img_rows-row_length;
#        curr_col = 0;
#        while(curr_col+col_length<=img_cols):
#            # newImage and predict\
#            new_bgr_image = bgr_image[curr_row:curr_row+row_length,curr_col:curr_col+col_length,:channels].copy();
#            new_bgr_image, new_ycrcb_image = prep_image_to_unet(None, new_bgr_image);
#            new_bgr_image = np.expand_dims(new_bgr_image, axis=0);
#            new_ycrcb_image = np.expand_dims(new_ycrcb_image, axis=0)
#            pred_mask = model.predict([new_ycrcb_image,new_bgr_image])[0];
#            # save details
#            mask_matrix[curr_row:curr_row+row_length,curr_col:curr_col+col_length,:1]+= pred_mask;
#            cnt_matrix[curr_row:curr_row+row_length,curr_col:curr_col+col_length,:1]+= 1;
#            # Increment count and continue
#            curr_gen_count+=1;
#            curr_col+=params.win_shift_cols;
#        # Saving a last patch in the given set of fixed rows and varying col number
#        if curr_col>0 and curr_col<img_cols and curr_col+col_length>img_cols and (img_cols-col_length)%params.win_shift_cols!=0: #Dont go to one of earlier indices
#            curr_col = img_cols-col_length;
#            # newImage and predict\
#            new_bgr_image = bgr_image[curr_row:curr_row+row_length,curr_col:curr_col+col_length,:channels].copy();
#            new_bgr_image, new_ycrcb_image = prep_image_to_unet(None, new_bgr_image);
#            new_bgr_image = np.expand_dims(new_bgr_image, axis=0);
#            new_ycrcb_image = np.expand_dims(new_ycrcb_image, axis=0)
#            pred_mask = model.predict([new_ycrcb_image,new_bgr_image])[0];
#            # save details
#            mask_matrix[curr_row:curr_row+row_length,curr_col:curr_col+col_length,:1]+= pred_mask;
#            cnt_matrix[curr_row:curr_row+row_length,curr_col:curr_col+col_length,:1]+= 1;
#            # Increment count and continue
#            curr_gen_count+=1;
#    if np.min(cnt_matrix)==0: # Safe Check
#        raise Exception('At least one pixel is not in any of the patches! Use np.where() to find it.')
#    # Threshold the pixels
#    mask_matrix/=cnt_matrix; # Average ##### mask_matrix = (mask_matrix > 0.5).astype(np.uint8) ######
#    if threshold_type=='global':
#        temp = mask_matrix.copy();
#        pred_image_thres = 255*(temp > 0.5);
#        pred_image_thres = pred_image_thres.astype(np.uint8);
#    elif threshold_type=='otsu':
#        temp = mask_matrix.copy();
#        pred_image_255 = 255*temp;
#        pred_image_255_uint8 = pred_image_255.astype(np.uint8)
#        _ , pred_image_thres = cv2.threshold(pred_image_255_uint8, 127, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
#    elif threshold_type=='adap+otsu':
#        #OTSU
#        temp = mask_matrix.copy();
#        pred_image_255 = 255*temp;
#        pred_image_255_uint8 = pred_image_255.astype(np.uint8)
#        _ , pred_image_thres1 = cv2.threshold(pred_image_255_uint8, 127, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
#        # Adaptive Thresholding
#        temp = mask_matrix.copy();
#        pred_image_255 = 255*temp;
#        pred_image_255_uint8 = pred_image_255.astype(np.uint8)
#        pred_image_thres2 = cv2.adaptiveThreshold(pred_image_255_uint8, 255,
#                                                  adaptiveMethod=cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
#                                                  thresholdType=cv2.THRESH_BINARY, blockSize=13, C=0)
#        # Global Thresholding AND Adaptive Thresholding
#        pred_image_thres = np.logical_or(pred_image_thres1==255,pred_image_thres2==255);
#        pred_image_thres = pred_image_thres.astype(np.uint8)
#        pred_image_thres = 255*pred_image_thres;
#    else:
#        print('Required threshold_type unavailable!');
#    # Print thye images
#    if print_images:
#        cv2.imshow( "{0}".format('ThisImage'), bgr_image);
#        cv2.imshow( "{0}".format('ThisMask'), pred_image_thres);
#        cv2.waitKey(0);
#        cv2.destroyAllWindows();
#    return pred_image_thres #, mask_matrix

if __name__=="__main__":
    #generate_original_copies_train_data(params.train_folder_org, params.train_folder_gen);
    #generate_original_copies_test_data(params.test_folder_org, params.test_folder_gen);
    #generate_original_copies_test_data(params.test2_folder_org, params.test2_folder_gen);

    #org_names, gen_names, gen_names_ind, gen_names_ind_cnt = generate_train_data_with_augmentation(params.train_folder_gen_m3); #Uses global variable
    #org_names, gen_names = generate_train_data_only_resize(params.train_folder_gen_resize)

    #tr_list = load_train_list_with_augmentation(params.train_folder_gen);
    #ts_list = load_test_list(params.test_folder_gen)
    print('Execution Complete. Please check respective folders as mentioned in params.')


import os

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from mpl_toolkits.mplot3d.art3d import Poly3DCollection, pathpatch_2d_to_3d
import seaborn as sns
from scipy import spatial

from utils import update_matplotlib_rc_parameters
from utils import sph2cart
from utils import sph_normals

def main():
	# averaging surface configuration
	edge_length = 0.02  # in m
	target_area_origin = (-edge_length/2, -edge_length/2)
	N = 11  # number of grid points

	# control evaluation plane coordinates
	x = np.linspace(-edge_length/2, edge_length/2, N)
	y = 0
	z = np.linspace(-edge_length/2, edge_length/2, N)
	Xt, Zt = np.meshgrid(x, z)
	x_pln = Xt.ravel()
	z_pln = Zt.ravel()

	# spherical averaging surface coordinates
	r = 0.05  # in m
	alpha = 2 * np.arcsin(edge_length/2/r)  # angle from secant
	theta = np.linspace(np.pi/2-alpha/2, np.pi/2+alpha/2, N)
	phi = np.linspace(np.pi-alpha/2, np.pi+alpha/2, N)
	Theta, Phi = np.meshgrid(theta, phi)
	y_sph, x_sph, z_sph = sph2cart(r, Theta.ravel(), Phi.ravel())
	y_sph -= y_sph.min() + y_sph.ptp() / 2
	ny_sph, nx_sph, nz_sph = sph_normals(r, Theta.ravel(), Phi.ravel())

	# visualize
	update_matplotlib_rc_parameters(is_3d=True)
	cs = sns.color_palette('rocket', 2)
	fig = plt.figure()
	ax = plt.axes(projection ='3d')
	plane = Rectangle(target_area_origin,
					  width=edge_length, height=edge_length,
					  ec=cs[0], fc=cs[1], alpha=0.25,
					  label='control evaluation plane')
	ax.add_patch(plane)
	pathpatch_2d_to_3d(plane, z=y, zdir='y')
	ax.scatter(x_sph, y_sph, z_sph, color=cs[0], depthshade=True,
		       label='integration grid')
	ax.quiver(x_sph, y_sph, z_sph,
		      nx_sph, ny_sph, nz_sph,
			  normalize=True, arrow_length_ratio=0.33, length=0.75/1000,
			  lw=1.25, color=cs[0], label='unit normal vector')
	ax.set_box_aspect([1, 1, 1])
	ax.set(xlabel='$x$ [mm]', ylabel='$y$ [mm]', zlabel='$z$ [mm]',
		   xticks=[x_pln.min(), 0.0, x_pln.max()],
		   yticks=[y_sph.min(), 0.0, y_sph.max()],
		   zticks=[z_pln.min(), 0.0, z_pln.max()],
		   xticklabels=[round(x_pln.min()*1000), 0, round(x_pln.max()*1000)],
		   yticklabels=[round(y_sph.min()*1000, 2), 0, round(y_sph.max()*1000, 2)],
		   zticklabels=[round(z_pln.min()*1000), 0, round(z_pln.max()*1000)],
		   xlim=[x_pln.min()*1.5, x_pln.max()*1.5],
		   ylim=[y_sph.min()-abs(y_sph.max()*0.5),
				 y_sph.max()+abs(y_sph.max()*0.5)],
		   zlim=[z_pln.min()*1.5, z_pln.max()*1.5]
		   )
	ax.xaxis.pane.fill = False
	ax.yaxis.pane.fill = False
	ax.zaxis.pane.fill = False
	ax.view_init(20, -70)
	fig.legend()
	fig.tight_layout()
	# fig.savefig(os.path.join(
	#     os.pardir, 'artwork', 'spherical_surface.pdf'
	#     ))
	plt.show()

if __name__ == '__main__':
	main()


from flask import Flask, request, render_template
from selenium import webdriver
from bs4 import BeautifulSoup
import pandas as pd
from utils import scroll_to_page_end, extract_videos_data

app = Flask(__name__)

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

@app.route("/result", methods=["POST"])
def result():
    url = request.form["url"]
    if "/videos" not in url:
        url = url.rstrip("/") + "/videos"
    driver = webdriver.Chrome()
    driver.get(url)
    scroll_to_page_end(driver)
    html = driver.page_source
    soup = BeautifulSoup(html, "html.parser")
    data = extract_videos_data(soup)
    channel_name = url.split("/")[-2].replace("@", "")
    df = pd.DataFrame(data)
    videos = df.to_dict("records")
    return render_template("result.html", videos=videos)

if __name__ == "__main__":
    app.run(debug=True)


import fileinput
from multiprocessing import Process
import os
import shutil
import sys

from node import Node
from observer import Observer
from utils import pipeName, Pipes

def createNode(node_id, money):
    n = Node(node_id, money)
    n.listen()

def createObserver():
    obs = Observer()
    obs.listen()
    pass

class Master:
    def __init__(self):
        self.nodes = dict()
        self.pipes = Pipes()
        self.observer = None

    def startMaster(self):
        # Setup pipes
        shutil.rmtree('./pipes', ignore_errors=True)
        os.mkdir('./pipes')

        # Create pipe between master and observer
        os.mkfifo(pipeName('master', 'observer'))
        os.mkfifo(pipeName('observer', 'master'))
        self.pipes.createPipe('master', 'observer', write=True, blocking=True)
        self.pipes.createPipe('observer', 'master', write=False, blocking=True)

        # Start observer
        self.observer = Process(target=createObserver)
        self.observer.start()

    def killAll(self):
        self.observer.terminate()
        for node in self.nodes.values():
            node.terminate()
        shutil.rmtree('./pipes', ignore_errors=True)
        sys.exit()

    def createNode(self, node_id, money):
        # Create pipe between master and node
        os.mkfifo(pipeName('master', node_id))
        os.mkfifo(pipeName(node_id, 'master'))
        self.pipes.createPipe('master', node_id, write=True, blocking=True)
        self.pipes.createPipe(node_id, 'master', write=False, blocking=True)

        # Create pipe from observer to node
        os.mkfifo(pipeName('observer', node_id))
        os.mkfifo(pipeName(node_id, 'observer')) # TODO not needed but need to change createPipe to be asymmetric

        # Start process
        p = Process(target=createNode, args=(node_id, money))
        p.start()

        # Create inter-node pipes
        msg = 'CreateNode {}'.format(node_id)
        self.pipes.sendMessage('master', 'observer', msg)

        response = self.pipes.receiveMessage('observer', 'master')
        if (response != 'ack'):
            raise RuntimeError('Expected \'ack\', received {}'.format(response))

        for neighbor_id in self.nodes.keys():
            os.mkfifo(pipeName(node_id, neighbor_id))
            os.mkfifo(pipeName(neighbor_id, node_id))

            msg = 'CreateNode {}'.format(node_id)
            self.pipes.sendMessage('master', neighbor_id, msg)

            response = self.pipes.receiveMessage(neighbor_id, 'master')
            if (response != 'ack'):
                raise RuntimeError('Expected \'ack\', received {}'.format(response))

            msg = 'CreateNode {}'.format(neighbor_id)
            self.pipes.sendMessage('master', node_id, msg)

            response = self.pipes.receiveMessage(node_id, 'master')
            if (response != 'ack'):
                raise RuntimeError('Expected \'ack\', received {}'.format(response))

        self.nodes[node_id] = p

    def send(self, send_id, recv_id, val):
        msg = 'Send {} {}'.format(recv_id, val)
        self.pipes.sendMessage('master', send_id, msg)

        response = self.pipes.receiveMessage(send_id, 'master')
        if (response != 'ack'):
            raise RuntimeError('Expected \'ack\', received {}'.format(response))

    def receive(self, recv_id, send_id=''):
        msg = 'Receive {}'.format(send_id)
        self.pipes.sendMessage('master', recv_id, msg)

        response = self.pipes.receiveMessage(recv_id, 'master')
        if (response != 'ack'):
            raise RuntimeError('Expected \'ack\', received {}'.format(response))

    def receiveAll(self):
        msg = 'ReceiveAll'
        received = True
        while received:
            received = False
            for node_id in sorted(self.nodes.keys()):
                self.pipes.sendMessage('master', node_id, msg)
                response = self.pipes.receiveMessage(node_id, 'master')

                if ('ack' not in response):
                    raise RuntimeError('Expected \'ack\', received {}'.format(response))
                if 'True' in response:
                    received = True

    def beginSnapshot(self, node_id):
        msg = 'BeginSnapshot {}'.format(node_id)
        self.pipes.sendMessage('master', 'observer', msg)

        response = self.pipes.receiveMessage('observer', 'master')
        if (response != 'ack'):
            raise RuntimeError('Expected \'ack\', received {}'.format(response))

        self.receive(node_id, send_id='observer')

    def collectState(self):
        msg = 'CollectState'
        self.pipes.sendMessage('master', 'observer', msg)

        # TODO sort?
        for node_id in sorted(self.nodes.keys()):
            response = self.pipes.receiveMessage('observer', 'master')
            if (response != f'ack {node_id}'):
                raise RuntimeError('Expected \'ack {}\', received {}'.format(node_id, response))
            self.receive(node_id, send_id='observer')

        response = self.pipes.receiveMessage('observer', 'master')
        if (response != 'ack'):
            raise RuntimeError('Expected \'ack\', received {}'.format(response))

    def printSnapshot(self):
        msg = 'PrintSnapshot'
        self.pipes.sendMessage('master', 'observer', msg)

        response = self.pipes.receiveMessage('observer', 'master')
        if (response != 'ack'):
            raise RuntimeError('Expected \'ack\', received {}'.format(response))

def run(master):
    for line in fileinput.input():
        args = line.split()
        cmd = args[0]
        for idx in range(1, len(args)):
            args[idx] = int(args[idx])

        if cmd == 'StartMaster':
            master.startMaster()
        elif cmd == 'KillAll':
            master.killAll()
        elif cmd == 'CreateNode':
            node_id = args[1]
            money = args[2]
            master.createNode(node_id, money)
        elif cmd == 'Send':
            send_id = args[1]
            recv_id = args[2]
            money = args[3]
            master.send(send_id, recv_id, money)
        elif cmd == 'Receive':
            recv_id = args[1]
            send_id = args[2] if len(args) > 2 else ''
            master.receive(recv_id, send_id)
        elif cmd == 'ReceiveAll':
            master.receiveAll()
        elif cmd == 'BeginSnapshot':
            node_id = args[1]
            master.beginSnapshot(node_id)
        elif cmd == 'CollectState':
            master.collectState()
        elif cmd == 'PrintSnapshot':
            master.printSnapshot()
        else:
            raise ValueError('Command not supported: ' + line)

if __name__ == '__main__':
    master = Master()
    run(master)


from re import M
from pyrailbaron.map.svg import MapSvg, transform_lcc, transform_dxf
from pyrailbaron.map.datamodel import Map, Coordinate
from pyrailbaron.map.states import get_border_data

from pathlib import Path
from typing import List

ROOT_DIR = (Path(__file__) / '../../..').resolve()
border_data = get_border_data(ROOT_DIR / 'data')

BORDERS_TO_DRAW = [
    [["MINNESOTA",0,[175,0]],
     ["M",[49,-98]],
     ["M",[49,-99]],
     ["M",[49,-100]],
     ["M",[49,-101]],
     ["M",[49,-102]],
     ["M",[40.5,-102]],
     ["M",[40.5,-108]],
     ["M",[37,-108]],
     ["COLORADO",0,[65,45]],
     ["OKLAHOMA",0,[200,33]],
     ["ARKANSAS",0,[0,8]],
     ["M",[36.5,-92.5]],
     ["M",[40.6,-92.5]],
     ["IOWA",0,[124,25]],
     ["WISCONSIN",0,[265,-1]]],
    [["M",[40.5,-108]],
    ["M",[40.5,-109]],
    ["M",[40.5,-110]],
    ["M",[40.5,-111]],
    ["M",[40.5,-112]],
     ["M",[40.5,-113]],
     ["M",[40.5,-114]],
    ["NEVADA",0,[12,0]],
    ["NEVADA",0,[-1,173]],
    ["CALIFORNIA",0,[15,0]],
    ["CALIFORNIA",0,[-1,158]],
    ["ARIZONA",0,[154,113]],
    ["NEW MEXICO",0,[65,52]],
    ["TEXAS",0,[700,606]],
    ["OKLAHOMA",0,[196,200]],
    ["COLORADO",0,[45,65]],
    ["M",[37,-108]]],
   [["TEXAS",0,[606,172]],
    ["LOUISIANA",0,[470,100]],
    ["MISSISSIPPI",0,[70,40]],
            ["M", [32.97, -88.47]],
        ["M", [32.97, -85.50]],
        ["KENTUCKY", 0, [263,150]],
        ["MISSOURI",0,[105,173]],
        ["OKLAHOMA",0,[33,196]]]
]

with (ROOT_DIR/'output/map.json').open('rt') as map_json:
    map: Map = Map.from_json(map_json.read())
(ROOT_DIR / 'output/border_test.svg').unlink(missing_ok=True)
svg = MapSvg(ROOT_DIR / 'output/border_test.svg')
svg.transforms = [transform_lcc, map.map_transform, transform_dxf]

colors = ['black', 'red', 'blue']
l = svg.layer('main')
for row_idx, rows in enumerate(BORDERS_TO_DRAW):
    pts: List[Coordinate] = []
    for i, row in enumerate(rows):
        if row[0] == 'M':
            pts.append(row[1])
            print(f'  Added point {pts[-1]}')
        else:
            state, border_idx, range = row
            border = border_data[state][border_idx]
            print(f'BORDER {state} #{border_idx} = {len(border)} points')
            segment = None
            if range == 'all':
                segment = border
            elif isinstance(range, list):
                start, end = range
                do_reverse = False
                if (end >= 0 and start > end) or start < 0:
                    start, end = end, start
                    do_reverse = True
                if end == -1:
                    segment = border[start:]
                else:
                    segment = border[start:(end + 1)]
            if segment:
                if do_reverse:
                    segment = segment.copy()
                    segment.reverse()
                if len(pts) == 0:
                    l.circle(segment[0], 2, fill='black')
                    l.text('start', segment[0])
                pts += segment
                l.circle(pts[-1], 2, fill='black')
                l.text(str(i), pts[-1])
                print(f'  Added segment from {segment[0]} to {segment[-1]}')
    pts.append(pts[0])
    l.path(pts, stroke=colors[row_idx % 3], stroke_width=0.5, fill='none')

svg.save()


import numpy as np
import cv2
from scipy.misc import imresize
from imageio import imread
from tensorflow.keras.preprocessing import image
from keras.applications import imagenet_utils
import os
def get_bounding_box_coordinates(projection):
    combined_channels = np.sum(projection[0], axis=2)

    arg_positions = np.argwhere(combined_channels)
    (xstart, ystart), (xstop, ystop) = arg_positions.min(0), arg_positions.max(0)

    return (ystart, ystop, xstart, xstop)

def draw_bounding_box_cv2(image, bounding_boxes):
    count = 0
    for xstart,xstop,ystart,ystop in bounding_boxes:
        count += 1
        cv2.rectangle(image, (xstart,ystart), (xstop,ystop), (255, 0, 0), 1 )
        cv2.putText(image, "b%d"%(count), (xstart+10,ystart+10), 1, 1, (255, 0, 0), 1)
    return image

def get_strongest_filter(activation_img):

    # Make sure that dimensions 2 and 3 are spacial (Image is square)
    assert activation_img.shape[1] == activation_img.shape[2], "Index ordering incorrect"

    # Find maximum activation for each filter for a given image
    activation_img = np.nanmax(activation_img, axis=2)
    activation_img = np.nanmax(activation_img, axis=1)

    # Remove batch size dimension
    assert activation_img.shape[0] == 1
    activation_img = activation_img.sum(0)

    # Make activations 1-based indexing
    activation_img = np.insert(activation_img, 0, 0.0)

    #  activation_image is now a vector of length equal to number of filters (plus one for one-based indexing)
    #  each entry corresponds to the maximum/summed activation of each filter for a given image

    return activation_img.argmax()

def get_strongest_filters(activation_img, N=2):

    # Make sure that dimensions 2 and 3 are spacial (Image is square)
    assert activation_img.shape[1] == activation_img.shape[2], "Index ordering incorrect"

    # Find maximum activation for each filter for a given image
    # Find maximum activation for each filter for a given image
    activation_img = np.nanmax(activation_img, axis=2)
    activation_img = np.nanmax(activation_img, axis=1)

    # Remove batch size dimension
    assert activation_img.shape[0] == 1
    activation_img = activation_img.sum(0)

    # Make activations 1-based indexing
    activation_img = np.insert(activation_img, 0, 0.0)

    #  activation_image is now a vector of length equal to number of filters (plus one for one-based indexing)
    #  each entry corresponds to the maximum/summed activation of each filter for a given image

    return activation_img.argsort()[-N:][::-1]

def preprocess_image_batch(image_paths, img_size=(256, 256), crop_size=(224, 224), color_mode="rgb", out=None):
    """
    Resize, crop and normalize colors of images
    to make them suitable for alexnet_model (if default parameter values are chosen)

    This function is also from
    https://github.com/heuritech/convnets-keras/blob/master/convnetskeras/convnets.py
    with only some minor changes
    """

    # Make function callable with single image instead of list
    if type(image_paths) is str:
        image_paths = [image_paths]

    img_list = []
    for im_path in image_paths:
        img = imread(im_path, mode='RGB')
        img = imresize(img, img_size)

        img = img.astype('float32')
        # Normalize the colors (in RGB space) with the empirical means on the training set
        img[:, :, 0] -= 123.68
        img[:, :, 1] -= 116.779
        img[:, :, 2] -= 103.939
        # We permute the colors to get them in the BGR order
        if color_mode == "bgr":
            img[:, :, [0, 1, 2]] = img[:, :, [2, 1, 0]]
        img = img.transpose((2, 0, 1))

        if crop_size:
            img = img[:, (img_size[0] - crop_size[0]) // 2:(img_size[0] + crop_size[0]) // 2
            , (img_size[1] - crop_size[1]) // 2:(img_size[1] + crop_size[1]) // 2]

        img_list.append(img)

    try:
        img_batch = np.stack(img_list, axis=0)
    except:
        raise ValueError('when img_size and crop_size are None, images'
                         ' in image_paths must have the same shapes.')

    if out is not None and hasattr(out, 'append'):
        out.append(img_batch)
    else:
        return img_batch

def grey_square(img, x, y, radius = 10):

    h = img.shape[1]
    w = img.shape[2]
    assert radius <= x < h - radius
    assert radius <= y < w - radius
    #square size = 2*radius + 1
    img[:, x-radius:x+radius, y-radius:y+radius, :] = 0
    return img

def set_zero_except_maximum(filter, x):
    assert filter >= 1
    # Set other layers to zero
    new_array = np.zeros_like(x)
    new_array[0, :, :, filter - 1] = x[0, :, :, filter - 1]
    # Set other activations in same layer to zero
    max_index_flat = np.nanargmax(new_array)
    max_index = np.unravel_index(max_index_flat, new_array.shape)
    out = np.zeros_like(new_array)
    out[max_index] = new_array[max_index]
    return out

def get_path_from_id(img_id):
    '''
    used for imagenet data
    :param img_id:
    :return:
    '''
    img_id_str = str(img_id)
    while len(img_id_str) < 5:
        img_id_str = '0' + img_id_str
    folder = 'D:\data\imagenet-data\ILSVRC2012_img_val\\'
    file = 'ILSVRC2012_val_000' + img_id_str + '.JPEG'
    path = folder + file
    return path

def load_image(img_path):
    img = image.load_img(img_path, target_size=(224, 224))
    x = image.img_to_array(img)
    x = np.expand_dims(x, axis=0)
    x = imagenet_utils.preprocess_input(x)
    return x

def deprocess_image(x, format = 'cl'):
    '''
    Same normalization as in:
    https://github.com/fchollet/keras/blob/master/examples/conv_filter_visualization.py
    '''
    if np.ndim(x) > 3:
        x = np.squeeze(x)
    # normalize tensor: center on 0., ensure std is 0.1
    x -= x.mean()
    x /= (x.std() + 1e-5)
    x *= 0.1

    # clip to [0, 1]
    x += 0.5
    x = np.clip(x, 0, 1)

    # convert to RGB array
    x *= 255
    if format == 'cf':
        x = x.transpose((1, 2, 0))
    x = np.clip(x, 0, 255).astype('uint8')
    return x

def to_small_pitch(path, pitch_size=(50,50), input_shape=(224,224,3)):
    img = image.load_img(path, target_size = pitch_size)
    x = image.img_to_array(img)
    out = np.zeros(input_shape)
    out[50:50+pitch_size[0],50:50+pitch_size[1],:] = x
    fname = os.path.basename(path)
    image.save_img("small_pitch_{}".format(fname), out)

if __name__ == '__main__':
    to_small_pitch('D:\data\imagenet-data\ILSVRC2012_img_val\ILSVRC2012_val_00000003.JPEG',pitch_size=(100,100))


from size_based_ecosystem import *
import matplotlib.animation as animation
tableau20 = [(31, 119, 180), (174, 199, 232), (255, 127, 14), (255, 187, 120),
             (44, 160, 44), (152, 223, 138), (214, 39, 40), (255, 152, 150),
             (148, 103, 189), (197, 176, 213), (140, 86, 75), (196, 156, 148),
             (227, 119, 194), (247, 182, 210), (127, 127, 127), (199, 199, 199),
             (188, 189, 34), (219, 219, 141), (23, 190, 207), (158, 218, 229)]

# Scale the RGB values to the [0, 1] range, which is the format matplotlib accepts.
for i in range(len(tableau20)):
    r, g, b = tableau20[i]
    tableau20[i] = (r / 255., g / 255., b / 255.)

from size_based_ecosystem import *
import copy as copy
import scipy.stats as stats
import pickle as pkl

depth = 20
layers = 100
size_classes = 1
lam = 1
simulate = True
verbose = False
daily_cycle = 365*2*np.pi

obj = spectral_method(depth, layers-1) #This is the old off-by-one error... Now we have added another fucked up error!
#norm_dist = stats.norm.pdf(obj.x, loc = 3, scale = 3)
#print(norm_dist)
norm_dist = stats.norm.pdf(obj.x, loc = 3)
res_start = 3*norm_dist #0.1*(1-obj.x/depth)
res_max = 10*norm_dist

water_start = water_column(obj, res_start, layers = layers, resource_max = res_max, replacement = lam, advection = 0, diffusion = 0)
list_of_sizes = np.array([20, 8000]) #, 1, 400, 1600, 40000])

l2 = False
size_classes = 2
m_v_t = list_of_sizes #list_of_sizes[0:size_classes]
params = ecosystem_parameters(m_v_t, obj)
eco = ecosystem_optimization(m_v_t, layers, params, obj, water_start, l2 = l2, output_level = 5, movement_cost = 1)
#OG_layered_attack = np.copy(eco.parameters.layered_attack)
eco.population_setter(np.array([20, 0.1]) )#, 1, 1, 1, 0.1]))
eco.parameters.handling_times = 0 * eco.parameters.handling_times
OG_layered_attack = np.copy(params.layered_attack)
frozen_ecos = []

stability = False
time_step = 10**(-4)
#max_err = time_step*1/10
x_res = sequential_nash(eco, verbose=True, l2=l2, max_its_seq = 20)
eco.strategy_setter(x_res)

for i in range(2):
    plt.plot(obj.x, x_res[i]@eco.heat_kernels[i])
plt.show()

for i in range(100):
    eco.population_setter(np.array([20, 0.1+0.01*(i+1)]) )#, 1, 1, 1, 0.1]))
    x_res = sequential_nash(eco, verbose=True, l2=l2, max_its_seq=20)
    eco.strategy_setter(x_res)
    print("Current iteration", i)


import os
import sys
import difflib
import unittest
import subprocess
import distutils.file_util

import getnose
import nose.plugins
import nose.plugins.builtin
import makeloadertests

class JsTest(nose.plugins.Plugin):
    def options(self, parser, env=os.environ):
        nose.plugins.Plugin.options(self, parser, env)
        parser.add_option("--revalidate-logs", action="store_true",
                          dest="revalidate_logs",
                          default=False,
                          help="For all tests run, makes their logs "
                          "the expected, or canonical, log file to "
                          "which all future runs of the tests are "
                          "compared to.")

    def configure(self, options, config):
        nose.plugins.Plugin.configure(self, options, config)
        self.revalidate_logs = options.revalidate_logs

    def wantFile(self, file):
        basename = os.path.basename(file)
        ext = os.path.splitext(file)[1]
        if (basename.startswith("test_") and ext == ".js"):
            return True
        # Oddly enough, if we return 'False' here instead of 'None',
        # none of the other plugins get a chance to test the file.
        return None

    def loadTestsFromFile(self, filename):
        return [JsTestCase(filename, self.revalidate_logs)]

class JsTestCase(unittest.TestCase):
    def __init__(self, test, revalidate_logs):
        self.__test = test
        self.__revalidate_logs = revalidate_logs
        unittest.TestCase.__init__(self)

    def shortDescription(self):
        return os.path.basename(os.path.splitext(self.__test)[0])

    def runTest(self):
        test = self.__test
        dirname = os.path.dirname(test)
        testname = os.path.splitext(os.path.basename(test))[0]
        result = subprocess.call(
            ["make",
             "-C", dirname,
             "-f", "../harness/Makefile",
             testname],
            stdout = subprocess.PIPE,
            stderr = subprocess.STDOUT
            )
        logfile_name = os.path.join(dirname, testname + ".log")
        if result != 0:
            self.fail(open(logfile_name, "r").read())
        else:
            expected_logfile_name = logfile_name + ".expected"
            if self.__revalidate_logs:
                distutils.file_util.copy_file(logfile_name,
                                              expected_logfile_name)
            if os.path.exists(expected_logfile_name):
                expected = open(expected_logfile_name, "r").read()
                actual = open(logfile_name, "r").read()
                if expected != actual:
                    diff = "Expected results differ from actual results.\n\n"
                    diff += "\n".join(difflib.unified_diff(
                        expected.splitlines(), actual.splitlines(),
                        "expected results", "actual results"
                        ))
                    diff += ("\n\nIf you believe that these changes are valid "
                             "(i.e., that they don't represent malfunctioning "
                             "code), you may want to re-validate the expected "
                             "results by running the following command:\n\n")
                    diff += "python %s %s --revalidate-logs\n" % (
                        sys.argv[0],
                        self.__test
                        )
                    self.fail(diff)

if __name__ == "__main__":
    makeloadertests.remove_old_loader_tests()
    makeloadertests.make_loader_tests()

    sys.argv.append("--with-jstest")
    nose.main(defaultTest=["scripts",
                           "tests/unit",
                           "tests/system"],
              plugins=[JsTest()])


from PIL import Image
import numpy as np
import pandas as pd
from shutil import copyfile
import os

# Add instructions to copy .csv to test/train directory
if not os.path.isdir("./data/"):
    print('Creating Data Directory')
    os.mkdir("./data/")
if os.path.isdir("./data/smiles_valset/"):
    print("You already have raw test images, so I'm using those\n")
else:
    print("Downloading Raw Test Images\n")
    os.system('gsutil -m cp -r gs://cs229-gap-data/RawData/smiles_valset ./data/')
    print("Raw Training Test Downloaded\n")
print("Processing Test Images")
source_csv_path = "./"
source_img_path = "./data/smiles_valset/"
file_name = "gender_fex_valset.csv"
dest_csv_path = "data/test_face/"
if not os.path.isdir("./data/test_face"):
    os.mkdir("./data/test_face")
train_data = pd.read_csv(source_csv_path+file_name,header=0)
img_names = np.array(train_data.ix[:,0:1])
copyfile(source_csv_path+file_name, dest_csv_path+file_name)

for img_name in img_names:
    img = Image.open(source_img_path+img_name[0])
    img = img.resize((256,256), Image.ANTIALIAS)
    img.save(dest_csv_path+img_name[0])

for img_name in img_names:
    img = np.array(Image.open(dest_csv_path+img_name[0]))
    if(img.shape!=(256,256,3)):
        img = np.stack((img,)*3,axis=2)
        img = Image.fromarray(img)
        img.save(dest_csv_path+img_name[0])

if os.path.isdir("./data/smiles_trset/"):
    print("You already have raw training images, so I'm using those\n")
else:
    print("Downloading Raw Training Images\n")
    os.system('gsutil -m cp -r gs://cs229-gap-data/RawData/smiles_trset ./data/')
    print("Raw Training Training Downloaded\n")
print("Processing Training Images")
source_csv_path = "./"
source_img_path = "./data/smiles_trset/"
file_name = "gender_fex_trset.csv"
dest_csv_path = "data/train_face/"
if not os.path.isdir("./data/train_face"):
    os.mkdir("./data/train_face")
train_data = pd.read_csv(source_csv_path+file_name,header=0)
img_names = np.array(train_data.ix[:,0:1])
copyfile(source_csv_path+file_name, dest_csv_path+file_name)

for img_name in img_names:
    img = Image.open(source_img_path+img_name[0])
    img = img.resize((256,256), Image.ANTIALIAS)
    img.save(dest_csv_path+img_name[0])

for img_name in img_names:
    img = np.array(Image.open(dest_csv_path+img_name[0]))
    if(img.shape!=(256,256,3)):
        img = np.stack((img,)*3,axis=2)
        img = Image.fromarray(img)
        img.save(dest_csv_path+img_name[0])


from __future__ import annotations
import json
import os
import requests
from typing import Tuple
from .common import *
from .jws import sign, rsa, x509

INTERACTIVE_PAYMENT = "interactive_payment"
AUTOMATED_PAYMENT = "automated_payment"
EXPECTED_PAYMENT = "expected_payment"

class PayinDebtor:
    """The debtor (origin) of a payin with the following fields:

    - name: The name of the debtor (optional)
    - identification: The ID of the debtor (optional)
    - financial_institution: The financial institution of the debtor (optional)
    - account: The account of the debtor (optional)
    - account_type: The type of account of the debtor (optional)
    - email: The email of the debtor (optional)
    """

    def __init__(
        self,
        name: str = None,
        identification: PersonId = None,
        financial_institution: FinancialInstitution = None,
        account: str = None,
        account_type: str = None,
        email: str = None,
    ) -> None:
        self.name = name
        self.identification = identification
        self.financial_institution = financial_institution
        self.account = account
        self.account_type = account_type
        self.email = email

class PayinCreditor:
    """The creditor (destination) of a payin with:

    - name: The name of the creditor
    - identification: The ID of the creditor
    - financial_institution: The financial institution of the creditor
    - account: The account of the creditor
    - account_type: The type of account of the creditor
    - email: The email of the creditor
    """

    def __init__(
        self,
        name: str,
        identification: PersonId,
        financial_institution: FinancialInstitution,
        account: str,
        account_type: str,
        email: str,
    ) -> None:
        self.name = name
        self.identification = identification
        self.financial_institution = financial_institution
        self.account = account
        self.account_type = account_type
        self.email = email

class PayinTransaction:
    """A payin transaction with:

    - payin_type: Either "interactive_payment" or "automated_payment" or "expected_payment"
    - interactive_payment_provider: The provider of the interactive payment (optional)
    - interactive_payment_success_redirect_url: The URL to redirect to after a successful interactive payment (only required for interactive payments)
    - interactive_payment_failure_redirect_url: The URL to redirect to after a failed interactive payment (only required for interactive payments)
    - transaction_id: The ID of the transaction (UUID string)
    - currency: The currency of the transaction
    - amount: The amount of the transaction (string) (optional)
    - description: The description of the transaction
    - expiration_date: The last date the transaction can be executed, after which the payment will be considered as failed (optional)
    - debtor: The debtor of the transaction
    - creditor: The creditor of the transaction
    """

    def __init__(
        self,
        payin_type: str,
        currency: str,
        creditor: PayinCreditor,
        interactive_payment_provider: str = None,
        interactive_payment_success_redirect_url: str = None,
        interactive_payment_failure_redirect_url: str = None,
        transaction_id: str = None,
        amount: str = None,
        description: str = None,
        expiration_date: str = None,
        debtor: PayinDebtor = None,
    ) -> None:
        self.transaction_type = "payin"
        self.payin_type = payin_type
        self.interactive_payment_provider = interactive_payment_provider
        self.interactive_payment_success_redirect_url = (
            interactive_payment_success_redirect_url
        )
        self.interactive_payment_failure_redirect_url = (
            interactive_payment_failure_redirect_url
        )
        self.transaction_id = transaction_id or random_uuid()
        self.currency = currency
        self.amount = amount
        self.description = description
        self.expiration_date = expiration_date
        self.debtor = debtor
        self.creditor = creditor

class PayinHttpResponseError:
    """An error in the payin sync response with:

    - error_code: The error code
    - error_message: Human-readable error message
    """

    def __init__(self, error_code: str, error_message: str) -> None:
        self.error_code = error_code
        self.error_message = error_message

    def __str__(self) -> str:
        return f"{self.error_code} ({self.error_message})"

    def __repr__(self) -> str:
        return f"PayinHttpResponseError({self.error_code}, {self.error_message})"

class PayinHttpResponse:
    """The http response received right after posting a payin message, with:
    - http_status_code: The HTTP code of the response
    - transaction ids: A dict mapping transaction ids to Shinkansen's transaction id
    - interactive_payment_urls: A dict mapping transaction ids to interactive payment URLs
    - errors: A list of `PayinHttpResponseError`s
    """

    def __init__(
        self,
        http_status_code: int,
        transaction_ids: dict[str, str],
        interactive_payment_urls: dict[str, str],
        errors: list[PayinHttpResponseError],
    ) -> None:
        self.http_status_code = http_status_code
        self.transaction_ids = transaction_ids
        self.interactive_payment_urls = interactive_payment_urls
        self.errors = errors

    def __str__(self) -> str:
        return f"{self.http_status_code} transaction_ids={self.transaction_ids} interactive_payment_urls={self.interactive_payment_urls} errors={self.errors}"

    def __repr__(self) -> str:
        return f"PayinHttpResponse({self.http_status_code}, {self.transaction_ids}, {self.interactive_payment_urls} {self.errors})"

    @classmethod
    def from_http_response(cls, response: requests.Response) -> PayinHttpResponse:
        """Return a PayinHttpResponse from a HTTP response"""
        if response.status_code in (200, 409):
            return PayinHttpResponse(
                http_status_code=response.status_code,
                errors=[],
                transaction_ids={
                    t["transaction_id"]: t["shinkansen_transaction_id"]
                    for t in response.json()["transactions"]
                },
                interactive_payment_urls={
                    t["transaction_id"]: t["interactive_payment_url"]
                    for t in response.json()["transactions"]
                    if "interactive_payment_url" in t
                },
            )
        elif response.status_code == 400:
            try:
                return PayinHttpResponse(
                    http_status_code=response.status_code,
                    transaction_ids={},
                    interactive_payment_urls={},
                    errors=[
                        PayinHttpResponseError(e["error_code"], e["error_message"])
                        for e in response.json()["errors"]
                    ],
                )
            except requests.exceptions.JSONDecodeError:
                pass  # go to the catch-all at the end
        # Catch all:
        return PayinHttpResponse(
            http_status_code=response.status_code,
            transaction_ids={},
            interactive_payment_urls={},
            errors=[],
        )

class PayinMessage:
    """A payin message with:

    - header: The header of the message
    - transactions: A list of transactions contained in the message
    """

    def __init__(
        self, header: MessageHeader, transactions: list[PayinTransaction]
    ) -> None:
        self.header = header
        self.transactions = transactions

    def as_json(self) -> str:
        """Returns the message as a JSON object"""
        return json.dumps(
            {"document": self},
            default=lambda o: {k: v for (k, v) in o.__dict__.items() if v is not None},
        )

    @classmethod
    def from_json(cls, json_string: str) -> "PayinMessage":
        """Return a message from a JSON string"""
        json_dict = json.loads(json_string)
        return cls(
            header=MessageHeader.from_json_dict(json_dict["document"]["header"]),
            transactions=[
                PayinTransaction(
                    payin_type=t["payin_type"],
                    interactive_payment_provider=t.get("interactive_payment_provider"),
                    interactive_payment_success_redirect_url=t.get(
                        "interactive_payment_success_redirect_url"
                    ),
                    interactive_payment_failure_redirect_url=t.get(
                        "interactive_payment_failure_redirect_url"
                    ),
                    transaction_id=t["transaction_id"],
                    currency=t["currency"],
                    amount=t.get("amount"),
                    description=t.get("description"),
                    expiration_date=t.get("expiration_date"),
                    debtor=t.get("debtor")
                    and PayinDebtor(
                        name=t["debtor"].get("name"),
                        identification=t["debtor"].get("identification")
                        and PersonId(
                            id_schema=t["debtor"]["identification"]["id_schema"],
                            id=t["debtor"]["identification"]["id"],
                        ),
                        financial_institution=t["debtor"].get("financial_institution")
                        and FinancialInstitution(
                            fin_id_schema=t["debtor"]["financial_institution"][
                                "fin_id_schema"
                            ],
                            fin_id=t["debtor"]["financial_institution"]["fin_id"],
                        ),
                        account=t["debtor"].get("account"),
                        account_type=t["debtor"].get("account_type"),
                        email=t["debtor"].get("email"),
                    ),
                    creditor=PayinCreditor(
                        name=t["creditor"]["name"],
                        identification=PersonId(
                            id_schema=t["creditor"]["identification"]["id_schema"],
                            id=t["creditor"]["identification"]["id"],
                        ),
                        financial_institution=FinancialInstitution(
                            fin_id_schema=t["creditor"]["financial_institution"][
                                "fin_id_schema"
                            ],
                            fin_id=t["creditor"]["financial_institution"]["fin_id"],
                        ),
                        account=t["creditor"]["account"],
                        account_type=t["creditor"]["account_type"],
                        email=t["creditor"]["email"],
                    ),
                )
                for t in json_dict["document"]["transactions"]
            ],
        )

    @property
    def id(self) -> str:
        """Returns the ID of the message"""
        return self.header.message_id

    def signature(
        self,
        certificate_private_key: rsa.RSAPrivateKey,
        certificate: x509.Certificate,
    ) -> str:
        return sign(self.as_json(), certificate_private_key, certificate)

    def sign_and_send(
        self,
        certificate_private_key: rsa.RSAPrivateKey,
        certificate: x509.Certificate,
        api_key: str = None,
        base_url: str = None,
    ) -> Tuple[str, PayinHttpResponse]:
        """Signs the message and sends it to the Shinkansen API"""
        signature = self.signature(certificate_private_key, certificate)
        return (signature, self.send(signature, api_key, base_url))

    def send(
        self, signature: str, api_key: str = None, base_url: str = None
    ) -> PayinHttpResponse:
        """Sends the message to the Shinkansen API"""
        base_url = base_url or SHINKANSEN_API_V1_BASE_URL
        api_key = api_key or os.environ.get("SHINKANSEN_API_KEY")
        if not api_key:
            raise ShinkansenException(
                "No api_key argument and SHINKANSEN_API_KEY not found in env"
            )
        response = requests.post(
            url=f"{base_url}/messages/payins",
            data=self.as_json(),
            headers={
                "Content-Type": "application/json",
                "Shinkansen-Api-Key": api_key,
                "Shinkansen-JWS-Signature": signature,
            },
        )
        return PayinHttpResponse.from_http_response(response)


import os
import re
import shutil
import tempfile
import unittest

from cupy import testing

from example_tests import example_test

os.environ['MPLBACKEND'] = 'Agg'

@testing.with_requires('matplotlib')
class TestKmeans(unittest.TestCase):

    def test_default(self):
        output = example_test.run_example(
            'kmeans/kmeans.py', '-m', '1', '--num', '10')
        assert re.search(
            r' CPU :  [0-9\.]+ sec\s+GPU :  [0-9\.]+ sec',
            output.decode('utf-8'),
        )

    def test_custom_kernel(self):
        output = example_test.run_example(
            'kmeans/kmeans.py', '-m', '1', '--num', '10',
            '--use-custom-kernel')
        assert re.search(
            r' CPU :  [0-9\.]+ sec\s+GPU :  [0-9\.]+ sec',
            output.decode('utf-8'),
        )

    def test_result_image(self):
        dir_path = tempfile.mkdtemp()
        try:
            image_path = os.path.join(dir_path, 'kmeans.png')
            example_test.run_example(
                'kmeans/kmeans.py', '-m', '1', '--num', '10', '-o', image_path)
            assert os.path.exists(image_path)
        finally:
            shutil.rmtree(dir_path, ignore_errors=True)


# -*- coding: UTF-8 -*-
from flask import Flask, jsonify, current_app, render_template, request

import os
import sys
import json             # http query responses handled as json
                        # (in python requests/grequests and ajax calls)
import requests         # for http get/post calls
from time import time   # to measure elapsed time for debugging purpose

''' 'yelp2' module is my contribution for extracting photos (biz-photos) '''
from yelp2.url_params import Url_Params     # set up parameters to use Yelp search API
from yelp2.config import DEFAULT_TERM       # term/category for yelp search query in case term input field is empty
from yelp2.config import DEFAULT_LOCATION   # default location for yelp search query
from yelp2.visual_yelp import Visual_Yelp # wrapper for yelp client object
import logging
from logging.handlers import RotatingFileHandler

app = Flask(__name__)

IS_PRODUCTION = (os.getenv('PYTHON_ENV', False) == "production")
if not IS_PRODUCTION:
    app.debug = True

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

''' "visual" presentation of yelp search results '''
@app.route('/yelp')
def yelp():
    # business photos (biz-photos) are extracted from yelp search results,
    # and displayed one business per row.

    # biz-photos are found on each business' photo-box page. Formatted results
    # are appended to "search-results" div tag in body.

    # Yelp query string is '/yelp/?term=category&location=region'
    # business term or category and location are taken from input fields

    # visitor first sees yelp results with default term/category and
    # ip-obtained geolocation displayed on page

    # browser ip used to obtain geolocation
    client_ip = request.environ.get('HTTP_X_REAL_IP', request.remote_addr)

    # util functions to generate search query parameters
    # in case of error default term/category & location values used
    util = Url_Params()

    location = util.get_location(client_ip)

    # pass location info to yelp page
    return render_template('yelp.html', term=DEFAULT_TERM, loc=location)

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

# @app.route('/home')
# def home():
#      link_id_1 = 'YelpPhotos'
#      link_url_1 = '/yelp/'
#      link_id_2 = 'LinkedIn'
#      link_url_2 = 'https://www.linkedin.com/in/gilkwak'
#      return render_template('indexhtml.html',
#                              link_id_1=link_id_1,
#                              link_url_1=link_url_1,
#                              link_id_2=link_id_2,
#                              link_url_2=link_url_2)

""" Displays results of Yelp http get request """
@app.route("/search/", methods=["GET"])
def main():
    # decorator for Yelp client for search query & process response for
    # visual display of results (biz-photos for each businesses)
    yelp = Visual_Yelp()

    biz_photos = yelp.biz_photos()

    # json containing status, html for biz-photos,
    # longitudes and latitudes of businesses for google map
    return biz_photos

''' for google map '''
@app.route('/googlemap/')
def googlemap():
    return render_template('googlemap.html')

if __name__ == "__main__":
    # handler = RotatingFileHandler('foo.log', maxBytes=10000, backupCount=1)
    # handler.setLevel(logging.INFO)
    # app.logger.addHandler(handler)
    if app.debug:
        app.run(
            host=os.getenv('IP', '0.0.0.0'),
            port=int(os.getenv('PORT', '8080'))
        )
    else:
        app.run()